这周的工作日志其实挺有意思的。周一还在调一个 agent 的上下文压缩策略周二被 token 刷新问题折腾到半夜周三又在评估新模型要不要上生产周五复盘时发现这一周刚好能串成一句话更少 token、更强模型、更难管的 agent。这句话不只是本周的观感也是最近做 AI 工程最真实的体感。很多刚接触 AI 工程的朋友会以为模型变强了工程会变简单。实际恰好相反。模型能力越强token 成本越敏感agent 的自主行为越难约束工程复杂度反而在往上走。这篇文章就把我这周的实操、踩坑和思考完整记录下来不绕弯子全是能直接用上的东西。1. 更少 tokenAI 工程的第一道成本题1.1 token 用量为什么是工程第一痛点先给不了解背景的朋友补个基础。现在的大模型基本按 token 计费一个 token 大约是 0.75 个英文单词中文因为分词方式不同一个汉字大概对应 1 到 2 个 token。听起来简单但工程上一算就知道吓人一个 2000 字的业务文档光输入就要吃掉三千多 token如果系统里有 50 份这样的文档单次请求的输入就可能超过 15 万 token。更要命的是token 不只是“花钱”的问题它直接拖慢响应速度。我在一个 RAG 问答服务里做过压测上下文从 2 万 token 涨到 8 万 token首字延迟从 900 毫秒涨到 3.2 秒翻了三倍多。原因是模型在生成每个新 token 时都要重新处理一遍已有的上下文长上下文的注意力计算是二次复杂度数据一多显存和算力都扛不住。所以“更少 token”不是抠门是既省钱又保体验的硬指标。1.2 三条省钱路线上下文压缩、缓存复用、提示词瘦身先说上下文压缩。我现在的做法是给长文档建立“摘要层”文档进来之后先用一个轻量模型抽取关键信息生成结构化的摘要真正问答时只把摘要加上相关片段送进大模型。这周测试了一个合同审查场景原始合同 5 万字压缩后有效上下文只有 9000 token回答准确率从 82% 提到 91%。为什么准确率反而提升了因为无关信息少了模型注意力更集中被干扰的概率下降。第二招是缓存复用。很多服务都是同一套系统提示词加少量动态内容比如客服机器人只有用户问题在变。这种情况下可以用前缀缓存把不变的部分缓存起来重复请求时直接复用已计算的 KV 状态。实测下来缓存命中时单次请求的 token 成本能降 50% 到 70%前提是缓存前缀足够长且顺序稳定。这里有个细节动态内容要放在缓存区之后不要穿插在固定提示词中间否则每次都会触发整段重新计算。第三招是提示词瘦身。我见过很多人的 prompt 恨不得把所有规则、示例、历史对话全塞进去结果模型反而抓不住重点。合理的做法是只保留当前步骤真正需要的约束示例控制在 2 到 3 个并且每个示例都明确标注“这是正确做法”和“这是错误做法”的对比。这周我重构了一个审批 agent 的 prompt从 3200 token 压到 1100 token工具调用准确率从 89% 升到 94%。删掉的不只是字数是模型需要“消化”的噪音。1.3 滑动窗口与上下文水位管理这周做一个流式日志分析 agent 时我借用了滑动窗口滤波的思路来管理上下文。滑动窗口滤波是信号处理里的经典方法只保留最近一段时间的采样数据平滑噪声同时跟踪趋势。把同样的逻辑搬到 LLM 上下文里不是所有历史消息都该永远留在上下文里而是维护一个小窗口里面放最近几轮对话和当前任务状态更早的内容要么丢弃要么压缩成摘要。实际配置参数可以这样理解窗口大小决定了“记忆”长度摘要间隔决定了压缩频率。我做的是 6 轮对话窗口每 10 轮触发一次摘要合并把早期对话提炼成一句状态描述。效果很明显一个连续会话的 token 消耗从线性增长变成平台型曲线并且模型在长会话末尾的“失忆”问题也缓解了——因为它只关注当前窗口不会被几个回合前的细节带偏。2. 更强模型能力红利与工程反噬2.1 新模型带来红利也带来新的麻烦这周我评估了两款新模型一个在函数调用上进步明显一个在长上下文理解上很强。表面看都是利好但一到工程侧问题就来了行为漂移。原先针对旧模型精心设计的提示词换到新模型上反而可能触发多余动作。典型例子是旧模型按格式返回 JSON 很稳定新模型可能“太聪明”自己加字段、改枚举值导致下游解析崩掉。所以我的原则是模型升级不是改个 base_url 就完事必须配套做回归验证。这周三我搭了一个最小验证集里面包含 30 个典型请求覆盖工具调用、格式要求、拒绝回答三类场景每次切换模型先跑一遍对比输出结构完整率和语义正确率。没有这个验证集直接上生产大概率会翻车。2.2 模型选型别只看榜单要看交互模式很多人选模型喜欢看排行榜但工程场景里榜单分数参考价值有限。榜单测的是静态问答能力而生产系统看重的是指令遵循稳定性、上下文窗口利用率、工具调用格式一致性。比如 embedding 模型的选择排行榜上第一名的模型不一定适合你的检索场景因为检索质量取决于向量空间与你的文档分布是否匹配。我做过一个测试同一批技术文档在两个 embedding 模型上召回率差了 8 个百分点而这两者在榜单上只差 0.2 分。我的选型维度大致是这样维度具体关注点我常用的验证方法工具调用稳定度是否严格按 schema 返回参数连续调用 50 次统计失败率上下文利用率长文档中关键信息是否被正确引用构造 10 万字文档做定点查找格式一致性输出是否始终是合法 JSON批量跑 100 次解析错误率延迟与成本p95 延迟、单次请求成本用真实流量回放压测这里有个容易忽略的点长上下文模型不等于“可以随便往里塞东西”。即便模型支持 200k 上下文超过一定量后注意力会大幅退化这在 Transformer 架构里是天然存在的现象。所以就算换了强模型我仍然坚持 1.2 里的上下文管理策略只是把“窗口”上限调大了而不是取消窗口。2.3 提示词工程与上下文工程的边界最近圈子里的讨论从“提示词工程”转向“上下文工程”我完全认同。提示词的职责是告诉模型“怎么答”上下文工程的职责是决定模型“看到什么”。后者对结果的影响往往更大。拿这周做的专利检索辅助小工具来说初始版本的提示词写得很详细但效果一直不稳定。后来我把精力放到上下文构建上先做文档切分再按检索相关度排序最后只把 top 5 段落拼进上下文。提示词反而退回简单水平——“基于以下材料回答”。结果准确率从 76% 升到 88%。这个例子说明强模型时代提示词的作用在下降工程重点已经转移到数据的组织方式上。谁的上下文更干净、更相关、更紧凑谁的效果就好。这也是“更少 token”和“更强模型”两个趋势的交汇点模型越强越不需要在 prompt 里啰嗦把位置让给真正相关的数据就够了。3. 更难管的 agent不确定性的治理实验3.1 agent 为什么到了生产环境就变“刺头”这周遇到最多的报错来自 agent 执行链路。单独调一个 agent 的某个功能是好的但把它放进生产流程后各种意外层出不穷工具返回了预期外的格式agent 没有按计划调用下一步甚至出现循环重试同一个工具直到超时。我在排查一个“agent execution terminated due to error”问题时发现根因是 agent 在一个外部 API 返回 500 错误后没有退避而是疯狂重试——这不是 bug是 agent 自主决策带来的不稳定性。业内常说 agent 是最难做的工程问题这话不夸张。普通 API 调用是确定性行为输入相同、输出必相同。agent 图例的每一步都可能调用不同模型、不同工具输出分布天然发散。这意味着不能用传统软件工程的“单元测试”思路来保证正确性只能靠约束、监控和容错机制把它圈在安全边界内。3.2 受控的 agent框架选型与工程护栏做 agent 工程时我最看重的是“可终止性”和“可控性”这比模型聪明更重要。框架选择上我倾向编排式而非完全自主式编排式把任务流程拆成固定节点每个节点允许 agent 在限定范围内做决策完全自主式则把全部决策权交给 agent看起来美好但生产失控概率极高。实操中我给每个 agent 都套上了五层护栏最大步数限制比如一个任务最多执行 20 步超过即终止并报错。工具权限白名单只暴露这个任务真正需要的工具避免 agent 链式调用其他外部服务。预算上限累计消耗 token 超过设定值就强制停止防止死循环烧钱。关键操作确认涉及删除、写库、发送消息等操作必须先返回用户确认。超时熔断单次工具调用超过 30 秒就标记失败并切换备用路径。这里有个教训护栏不是越多越好。这周二我一度加了 8 层限制结果 agent 频繁触发防御逻辑任务完成率反而下降。后来我减到 5 层把相互冲突的规则合并完成率从 67% 回升到 86%。护栏的目标是框住风险而不是把 agent 绑死。3.3 让 agent 扛住并发隔离、限流与幂等关于“AI agent 怎么扛并发”是我这周被问得最多的问题。先说结论agent 不适合用传统 API 那种彻底并行的方式直接怼因为它的链路复杂、耗时长、资源占用不可预测。我给生产环境设计的方案是任务队列加并发池请求先进入队列由 worker 逐个领取执行并发池大小根据底层模型 QPS 和工具服务容量动态调整。并发池的大小的选择参考底层 API 的速率限制。如果模型接口限制是每分钟 600 次调用而单个 agent 任务平均要调 3 次模型接口那并发池调到 60 就超过限制。实际我把并发设成 40留出 30% 余量给重试和突发。这个数字不是拍脑袋是拿真实流量压测出来的并发 40 时平均任务耗时 28 秒并发 80 时升到 51 秒且错误率暴增因为底层 API 开始限流。另一个必须处理的点是幂等。agent 因为超时重试时如果工具调用不是幂等的就会出现重复扣款、重复建单。这周我踩了一个大坑某个支付回调工具不支持幂等agent 超时后自动重试结果用户被扣了两笔钱。修复方案是给每个工具调用加上全局唯一的请求 ID服务端记录已处理 ID重复请求直接返回“已处理”状态。这个机制应该作为 agent 工具层的基本要求而不是事后补。3.4 agent 的可观测性没有 trace 就没有治理这周排查 agent 问题时最痛的一点是可观测性不足。传统后端的日志是一条直线的请求链路agent 的执行过程则是一棵分支树一次任务会派生出多个子任务、多次工具调用还可能自我纠错重来。用普通日志根本拼不出完整执行过程。我现在强制要求所有 agent 动作都打结构化 trace记录关键字段任务 ID、当前步骤、目标、输入摘要、调用的工具、返回结果摘要、耗时、token 消耗。集中在类似 trace 面板里查看。这周在定位一个“为什么 agent 总在处理无关信息”的问题时就是靠 trace 发现它被一个残留的会话上下文干扰清理后立刻恢复正常。agent 的可观测性还包含成本审计。每个任务的 token 消耗都要能追溯到具体步骤否则月末账单出来都不知道钱花哪了。我习惯在 trace 里加一个“cost”字段由底层调用统一记录这样能做按任务、按用户、按维度的成本报表。4. 认证令牌另一条 token 战线上的坑4.1 从 LLM token 到认证令牌的思维切换标题里的“更少 token”在工程里其实有两条线。一条是上文讲的模型 token 消耗另一条是系统认证里的 token 治理。这周我被后者折腾得不轻登录接口报sign-in could not be completed token exchange failed刷新 token 又返回401排查到最后发现是 refresh token 生命周期策略和网关配置不一致。很多 AI 工程师会把认证 token 当成“登录的小事”忽略但它恰恰是 agent 系统里最致命的一环。agent 要调外部服务、要跨系统交换身份每一步都在使用 token。一旦 token 提前失效或交换失败整个链路直接瘫痪而且错误信息往往只在日志深处出现。4.2 JWT 失效与续签的工程方案给不熟悉的朋友简述一下 JWT 的经典模型登录成功后服务端签发一个 access token 和一个 refresh token。前者短期有效用于访问资源后者长期有效用于在 access token 过期后换取新的。流程图不做直接说关键参数。我目前的生产配置是access token 有效期 30 分钟refresh token 有效期 7 天refresh token 每次使用后轮换并且只允许使用一次。轮换意味着每次刷新时旧 refresh token 立即作废签发新的这样即使某个 refresh token 泄露它也只能用一次风险窗口大幅缩小。这里必须特别注意一个细节refresh token 轮换后如果客户端并发请求同时用同一个 refresh token 去刷新会产生竞态条件——一个请求成功了另一个请求拿着已经失效的旧 token 会失败。解决方式是在服务端做 token 家族管理记录同一家族的 refresh token只要家族内有任意一个 token 被使用且通过了校验就视为合法并签发新 token 给当前请求同时作废整个家族的旧 token。4.3 本周实际的 token 报错排查周报里已经有一张表了我直接复述下表里的高频现象报错现象常见根因修复方向token exchange failed授权码/refresh token 不匹配或已过期检查 token 版本与过期时间统一时钟源refresh_token 为空字符串前端或 SDK 未正确存储 refresh token核对存储方案确认是否存在跨域丢 Cookie403 forbidden网关地域策略或来源白名单限制检查网关层 ACL 配置invalid refresh token轮换后使用了旧 token前端必须用最新 refresh token避免并发刷新那个刷新 token 返回空字符串的错误根因很滑稽sdk 在刷新前用localStorage.getItem(refreshToken)而刷新过期后 token 被清理拿到的是空串SDK 又没做空值校验就直接发请求。修复只需要加一个前置判断拿不到 refresh token 时直接引导用户重新登录而不是发一个注定失败的请求。5. 本周问题排查谢实报错背后的工程真相5.1 案例一token 刷新失败导致定时任务链断开背景是一个定时触发的 AI 分析 agent它需要周期性地调用本系统的报告 API。某天开始连续报错错误信息是sign-in could not be completed token exchange failed: token endpoint returned status 403。初看以为是权限问题查服务端日志后发现定时任务用的 service account 登录流程里授权请求走的是旧的 token endpoint 配置而网关已经升级到新的 endpoint旧路径被安全策略拦截。排查顺序是先看错误发生的组件边界再对比最近变更记录。最终定位是配置文件里 endpoint 地址没有随服务升级同步更新。这个案例的启示是token 报错不要第一时间怀疑认证算法先检查组件交互边界和配置文件版本。5.2 案例二agent 并发打满配额后的连环雪崩现象某个时段 agent 任务失败率突然从 3% 飙升到 47%并且所有失败都集中在同一个外部 OCR 服务。排查 trace 发现并发池配置在高峰期给某个长耗时任务开了后台并行子任务一下子把 OCR 服务的 QPS 配额打满后续请求全被限流然后 agent 在限流后不断重试形成雪崩。修复分三步第一步在并发池外围加限流器限制每秒最多 20 个 Agent 任务进入第二步给 OCR 调用单独加一层退避策略收到限流码后等待 1 秒、2 秒、4 秒指数退避第三步给长耗时任务设置并行子任务上限限制最大并行 3 个。修复后失败率回落到 1.8%而且 OCR 服务恢复正常响应。这个案例再次印证了一件事agent 工程里流量控制不能只依赖底层模型服务的限流每个外部依赖都要有自己的保护层因为 agent 会以不可预测的方式发起调用。6. 观察与体会工程复杂度正在向上移动这一整周下来我的核心感受是AI 工程的门槛不在“调用模型”而在“治理不确定性”。更少 token 是成本与性能的治理更强模型是能力与风险的治理更难管的 agent 是行为与并发的治理。三者本质上都在做同一件事把模型的概率行为约束在确定性的工程边界里。还在老项目里挣扎的时候我觉得 prompt 写得好就是高手。现在回头看prompt 只是最外层的手段。真正拉开差距的是你怎么设计上下文结构、怎么配置缓存、怎么给 agent 套护栏、怎么做 trace 和幂等。每一个词条背后都是一堆细节问题而这些细节恰恰是传统文档不会写的。最后分享一个小技巧这周我把 agent 的每次调用都统一封装成一个入口函数无论是调模型、调工具还是调外部 API都会自动做三件事——记录耗时和 token、生成 trace、检查是否超出预算。这个封装让我在排查问题时能直接从统一入口看全局而不是翻好几份日志。这个习惯我强烈建议每个做 AI 工程的人都尽早养成因为它省下的是深夜排查问题时最宝贵的睡眠。