进二 Agent Loop:心脏手术
02.1 你的 Agent 为什么"卡"半天才吐字
你问一句,它三五秒才冒第一个字。不是模型慢,是流式响应的工程真相:
模型是一个 token 一个 token 往外吐的。首字延迟(TTFT)取决于:系统提示有多长、检索了几轮、工具跑了几秒。后面的字是边生成边推(SSE / WebSocket)。
| 阶段 | 占用时间 | 你能做的 |
|---|---|---|
| 拼上下文 | 常最大头 | 压缩系统提示、上缓存(进四 04) |
| 首轮推理 | 中 | 用快模型打初稿 |
| 工具往返 | 看外部 | 设超时、并行调用 |
| 流式输出 | 用户可见 | 已是最优,别优化 |
核心建议:用户觉得"卡",多半是首包太慢。先砍系统提示和检索轮数,比换模型管用。
02.2 模型 API 挂了怎么办?容错不是加个 try-catch
生产环境,API 一定会挂。新手写:
try:
r = call_model(prompt)
except:
r = "出错了" # ← 这等于把锅甩给用户
生产级要做四件事:
- 重试 + 退避:失败隔 1s、2s、4s 再试,别瞬间狂轰。
- 熔断:某模型连挂,先停用,别拖垮全链路。
- 降级:主模型挂,切备用模型(弱一点但活着)。
- 幂等:重试不能让"发两次邮件"。
经验:容错的目标不是"不报错",是"用户无感"。
02.3 死循环、重复犯错、Token 烧穿:三个保险丝
呼应 §09.4 的停止条件,我把它们叫 Loop 的三道保险丝:
| 保险丝 | 干什么 | 不装的后果 |
|---|---|---|
| 步骤上限 | 跑 N 步强制停 | 原地空转一整晚 |
| Token/成本预算 | 超预算即停 | 账单爆炸 |
| 连续失败即停 | 工具连错 K 次停 | 同一个错反复犯 |
for step in range(MAX_STEPS): # 保险丝① 步骤
if ctx.cost > BUDGET: break # 保险丝② 成本
if ctx.tool_fail_streak >= 3: break # 保险丝③ 失败
...
注意:模型越强,越要紧边界。不是换更强模型,是装更牢的保险丝。