跳到主要内容

161 篇博文 含有标签「agents」

查看所有标签

面试模式与任务模式:你的智能体不断打破的无形契约

· 阅读需 12 分钟
Tian Pan
Software Engineer

打开任何智能体 (Agent) 的用户反馈渠道,你都会发现两类抱怨,它们声音宏大、普遍存在,且都被归咎于模型。第一种听起来像是:“它在干活前问的问题太多了。”第二种听起来像是:“它不跟我确认就自顾自地跑去乱做一气。”产品团队将这两者视为截然相反的问题,并发布了相反的修复方案——收紧系统提示词以减少提问,然后在下一季度因另一种抱怨声变大而再次放开。这两种改变都无法长久奏效,因为这两类抱怨的核心并不在于提问或行动本身,而在于用户默默选定了一份契约,而智能体未能履行。

与智能体的每一次对话都运行在两种隐性模式之一中。访谈模式 (Interview mode) 是一种契约,用户期望智能体在采取任何实质性行动之前先提取需求——澄清性提问是受欢迎的,过早执行则是失败。任务模式 (Task mode) 则是另一种契约,用户已经完成了思考,心中已有具体计划,并期望智能体根据现有上下文直接执行,仅在真正受阻时才提问——提问是阻力,半生不熟的执行则是失败。

用户不会宣布他们处于哪种模式。他们期望智能体能从消息、对话历史和情境中读懂模式,并在智能体搞错时给予严厉的抨击。针对“问题太多”和“问得不够”的修复方案是同一个:将“模式”作为一个一等公民的概念引入你的智能体,从你可以实际观察到的信号中检测它,并在不确定时向用户明示。

飞行中转向:无需重启即可重定向长时运行的智能体

· 阅读需 11 分钟
Tian Pan
Software Engineer

观察一个开发者使用代理型 IDE 二十分钟,你会看到同样的小剧场上演三次。代理开始了一个长任务。在两次工具调用后,用户意识到他们想要一个函数式组件而不是类,或者想要 v2 接口而不是 v1,亦或是想用 Vitest 而不是 Jest 编写测试。他们手中只有一个杠杆:红色的停止按钮。他们按了下去。代理在编辑中途阵亡。他们复制并粘贴上一个提示词,加上修正,然后为前八分钟的工作支付了两次费用。

中止按钮是错误的交互设计。它将“我想调整计划”和“我想丢弃这次运行”视为同一种动作。在实践中,它们就像方向盘和弹射座椅一样迥异,而将两者混为一谈,正是为什么许多代理产品在任务耗时超过一屏输出时就显得脆弱不堪的原因。

评估通过,但工具全是 Mock 的:为什么你的 Agent 最棘手的生产故障从未进入测试框架

· 阅读需 11 分钟
Tian Pan
Software Engineer

你的智能体在评估测试集上达到了 94% 的准确率。然而你的轮值告警却响个不停。房间里没人撒谎,这两个数字都是真实的。实际情况是,测试框架(harness)在测试提示词(prompt),而生产环境在测试智能体(agent),这是两个完全不同的产物,只是恰好共享了权重。

Mock 工具的评估通常是产生这种差距的原因。你用预设的 JSON 存根(stub)了 search_orderscharge_cardsend_email,给模型输入一个用户回合,并对最终响应进行断言。这种运行方式成本低、具有确定性且可复现——这些都是 CI 系统喜欢的特性。但它对工具选择、延迟、速率限制(rate limits)、部分失败和重试行为保持沉默,也就是说,它忽略了那些在事故回顾中占主导地位的失败因素。

重试放大:2% 的工具错误率如何演变成 20% 的智能体故障

· 阅读需 15 分钟
Tian Pan
Software Engineer

在值班文档的表格上,搜索工具的错误率为 2%。事故审查报告称,在三个小时的时间窗口内,Agent 平台的故障率为 20%。没人对这两个数字有异议。搜索团队没有过错。平台团队也没有发布 Bug。这两个数字之间的差距就是故事的全部,而这是一个关于算术的故事,而不是工程能力的平庸。

重试逻辑是 Agent 系统中最常被借用且最少针对性调整的模式之一。团队从他们的 REST 客户端复制 tenacity 装饰器,将它们堆叠在 SDK、网关和 Agent 循环中,然后直接上线。每一层单独看都是合理的。但这种组合就像是一件指向集群中最不稳定依赖项的攻城武器,而且它恰恰在那个依赖项最需要降低负载的时刻开火最猛烈。

本篇文章将探讨这种数学逻辑是如何运作的,为什么 Agent 循环比请求-响应系统更剧烈地放大错误,以及如何通过重试规范防止瞬时波动演变成印着你自己公司 Logo 的关联性宕机事故。

Agent Trace 中的采样偏差:为什么你的调试数据集在悄悄排除你最关心的失败案例

· 阅读需 11 分钟
Tian Pan
Software Engineer

你团队每个周一盯着看的调试语料库并不是生产环境的代表性样本。它具有明显的偏差,而且偏差的方向完全错误。1% 的头部采样在保留一个罕见的灾难性轨迹之前,会先保留一百次中位数请求——大多数团队只有在某种静默循环了数月的失败模式最终导致退款或停机,并试图在追踪存储(trace store)中寻找示例却一无所获时,才会发现这一点。

这并不是什么罕见的边缘情况。这是所有专为无状态 Web 服务设计、随后又被用于长时程(long-horizon)Agent 的可观测性栈的默认行为。同样的采样算法在处理 HTTP 请求追踪时表现良好,但在处理 Agent 时却会系统性地抹除那些最重要的轨迹——因为在这里,每个“请求”都是一个包含三十个步骤的计划,可能会调用数十个工具,重新生成三个子计划,并在第 27 步发生细微错误之前消耗数万个 token。

解决方法不是“增加采样”。增加采样只会让账单爆炸,而不会改变偏差——你只会得到更多已经过剩的普通数据。解决方法是改变你采样的对象,以只有在轨迹结束后才能获知的预测结果为基准。这需要抛弃基于头部的默认设置,并围绕尾部信号、异常权重以及能在 Agent 执行的长尾效应中存续的有界蓄水池(bounded reservoirs)重新构建保留层。

规范先行(Spec-First)智能体:为什么契约必须先于提示词落实

· 阅读需 13 分钟
Tian Pan
Software Engineer

我接手时,我们客服智能体的提示词已经达到了 2,400 个 token,而编写它的工程师已经离职了。其中的每一条指令对于某些生产行为来说都是“承重的”,但没人能告诉我哪些才是关键。一条关于“在回答之前务必先复述用户问题”的条目看起来像是凑数的,直到我们删掉它后,CSAT(客户满意度)在一周内下降了四个百分点。事实证明,提示词就是规范(specification)。它既是实现(implementation),也是测试套件(test suite)——它是隐性的、未记录的,仅存在于那位已经离职的工程师脑中。

这就是“提示词即规范”的终局。提示词既是智能体应该做什么,也是它如何做,一旦提示词规模超过了单个作者的掌握范围,两者就会变得无法区分。你无法重构它,因为你不知道哪些行编码了需求,哪些行仅仅是暗示。你无法评审变更,因为没有可以与之对比的基准产物。你无法让任何人接手并负责它,因为负责意味着“最近阅读过全文并记得每一项条款存在的原因”,这是一项没人愿意批准的、长达六个月的投资。

“规范优先”颠覆了这种顺序。契约(contract)——输入、输出、不变量、错误情况、拒绝语义、升级触发条件——是一个先于提示词并约束每次修订的一等产物(first-class artifact)。对提示词的修改变成了针对规范的补丁(diff),而不是对规范本身的重写。这种转变听起来很官僚,直到你看到它所释放的潜力:评估(evals)源自规范而非反之,评审只需几分钟而非整个下午,最终能让新工程师在没有六个月学徒期的情况下直接接手整个模块。

你的工具描述是提示词,而非 API 文档

· 阅读需 12 分钟
Tian Pan
Software Engineer

工具描述不是文档。它是模型在每一轮对话中都会读取的 prompt,用于决定该工具是否触发以及如何触发。你不是在为对接该工具的开发者编写内容——开发者已经在 PR 中看到了 schema、类型和示例。你是在为一个从未见过这个代码库的随机读者编写内容,它在同一个上下文窗口中还拿着另外二十个工具描述,并且必须在下一次前向传播中选出一个。

大多数团队并没有意识到这一点。他们把 OpenAPI 摘要粘贴到 description 字段中,把 JSON Schema 贴在下面,然后就发布了。结果,agent 调用工具的次数过少,或者自信地调用了错误的邻近工具,又或者用了任何读过 schema 的人类都会觉得“显而易见”是错误的参数来调用正确的工具。团队责备模型,但模型读取的正是一字不差的你写的内容。

工具 Schema 弃用:为什么你不能直接重命名参数

· 阅读需 13 分钟
Tian Pan
Software Engineer

你在一个工具 schema 中将 query 重命名为 search_query。变更日志写着:“非破坏性更名:更清晰的命名”。PR 通过了评审。三天后,你的支持队列里塞满了关于助手“搜索结果为空”的报告。发生的事情并不是讨论帖里任何人会告诉你的。智能体(Agent)并没有失败。它们提交了旧的字段名称,你的工具服务器忽略了未知的 key,将 search_query 默认设置为空字符串,并返回了零条结果。模型看到一个看起来很正常的空响应,便自信地向用户解释为什么他们的查询没有返回任何相关内容。

这是智能体工程(Agent Engineering)中不符合从 REST API 版本管理借鉴来的心理模型的部分。发送已重命名字段的 REST 客户端会收到 400 错误和清晰的报错——该字段要么存在于验证器中,要么不存在。而发送已重命名字段的智能体得到的则是静默接受、一个毫无意义的结果以及一段幻觉式的合理解释。失败不在于线路传输(the wire);而在于运行时 schema 与模型关于工具外观的上下文心理模型(in-context mental model)之间的脱节。

工具 schema 存在于两个地方。第一个是运行时规范(runtime spec)——即你发布到 MCP 服务器或函数调用注册表的 JSON schema。第二个是该规范在模型中的上下文表示,它通过系统提示词(system prompt)中的 few-shot 示例、智能体在多轮任务中看到的序列化工具历史记录,以及模型在预训练期间已经吸收的关于你 API 的知识来在每一轮对话中不断强化。你可以原子化地更新前者,但你无法原子化地更新后者。这种不对称性就是问题的核心,这也是为什么“仅限添加,永久保留”——protobuf 和 GraphQL 运营商在十年前就已经内化的原则——现在需要迁移到工具 schema 层了。

语音智能体并非带麦克风的聊天机器人:半双工税

· 阅读需 12 分钟
Tian Pan
Software Engineer

一个在所有转写层级基准测试(benchmark)中得分完美的语音智能体,在实际通话中可能仍然让人感觉有些微妙的不对劲。文字没错,推理也没错。仪表盘上的端到端延迟显示为 520ms,这正是预期的目标。然而,电话另一端的人却不断卡顿、抢话、重说,甚至提前挂断。团队发布了更好的模型,数据提升了,但体感依然没有改善。

究其原因,与模型说了什么几乎无关,而与它何时说话几乎全盘相关。语音并非仅仅是附带了音频的文本。人类的对话运行在一个严密的半双工(half-duplex)协议之上,包含插话(barge-in)、反馈信号(backchannel)和重叠语音,其时间预算是以毫秒计算的。大多数语音智能体的问题,在解决了第一周的幻觉修复后,本质上都是轮次协商(turn-negotiation)问题。而轮次协商是架构层面的问题——你无法通过提示词工程(prompting)来解决它。

在写第一个 Prompt 之前,先设计好你的 Agent 状态机

· 阅读需 11 分钟
Tian Pan
Software Engineer

大多数工程师在构建第一个 LLM agent 时,都会遵循相同的流程:写一个系统提示词,添加一个调用模型的循环,撒上一些工具调用逻辑,然后看着它在简单的测试用例上运行。六周后,这个 agent 变成了一团难以理解的嵌套条件、粘贴在 f-string 里的 prompt 片段,以及散落在三个文件中的重试逻辑。添加一个功能需要通读整个代码。遇到生产 bug 就得盯着一个上千 token 的上下文窗口,试图重建模型当时在"想"什么。

这就是"意大利面式 agent"问题,在以 prompt 为起点而非设计为起点的团队中几乎普遍存在。解决方案不是更好的提示技巧,也不是换一个框架,而是一种纪律:在写第一个 prompt 之前,先设计好状态机

AI智能体的CAP定理:当LLM成为瓶颈时,选择一致性还是可用性

· 阅读需 11 分钟
Tian Pan
Software Engineer

每个部署过分布式系统的工程师都曾直面CAP定理并做出抉择:当网络分区时,你是继续提供陈旧数据(可用性),还是拒绝服务直到获得一致的答案(一致性)?该定理告诉你,二者不可兼得。

AI智能体面临着同样的权衡,然而几乎没有人在明确地做出这一选择。当你的LLM调用超时、工具返回垃圾数据、下游API不可用时——你的智能体会怎么做?在大多数生产系统中,答案是:它会猜测。悄无声息地。信心满满地。而且往往是错的。

故障模式并不戏剧化。日志中没有异常。智能体"回答"了用户。两周后才有人问起,为什么系统订了错误的航班、提取了错误的实体,或者自信地告诉客户一个已不存在的价格。

复合精度问题:为什么你的 95% 精确率 Agent 会失败 40% 的时间

· 阅读需 12 分钟
Tian Pan
Software Engineer

你的 Agent 在隔离测试中表现完美。你对每个步骤都做了基准测试,测量得到每步精确率为 95%。向利益相关者演示时效果很好。然后你上线了,用户反映几乎有一半时间它都会失败。

这个失败不是任何单个组件的 bug,而是数学。