开场
大家好,感谢各位来听这场分享。我知道今天已经接近尾声了,大家吃过午饭,可能也有些累了,所以特别感谢你们的耐心。你们已经听了我们 Arize AI 团队不少内容;如果刚才在场,可能还听了 Sophia 的演讲。再次谢谢大家。我叫 Fuad,昨天也做了一场分享,如果你当时没来过的话。我在 Arize AI 做产品,也就是大家说的 AI 产品经理,稍后我会聊聊这和交付智能体有什么关系。
今天我想谈谈过去两年里,我们如何把产品内的生产级智能体交付出去,以及一路学到的一些经验。希望这些内容能给正在真实环境中构建智能体的你们一些有用启发。
智能体层层嵌套
好,开始之前先聊点元话题,希望大家都跟得上。这页幻灯片是用智能体做的,没错。我们有编程智能体,它们会和 Alex、Signal 以及产品里的其他部分协作,而那些部分本身也都是智能体。
Signal 是一个读取追踪数据的智能体,它会分析我们智能体的 traces。也就是说,一个智能体在读另一个智能体的运行轨迹。Alex 则是产品内的智能体,你可以把它想成 AI 工程领域的 Cursor。今天我要讲的就是这个智能体。我们实际上会用 Alex 来调试 Alex,所以话题会有点套娃。希望你们能从中了解 Alex 如何帮助你们评估自己的智能体,也能借鉴一些设计模式,把它们用到自己的智能体上。总之,就是“龟中有龟”,智能体也是一层套一层。如果你分不清我们现在说的是哪个智能体,我会尽量讲清楚。
接下来会介绍 Alex 是如何发展到今天的。我准备了一些 2023 年的怀旧截图,感觉已经是很久以前了,可以看看 Alex 当时的样子:那时它只是一个在技能工具调用循环上做路由的组件。然后我会讲讲我们如何改变它,以及一路上最难做的一些决定:计划由谁掌管、如何结束一轮、智能体的记忆怎么处理、该用一个智能体还是多个子智能体、默认选什么模型,以及怎么测试。
像我刚才说的,这个话题有点元:我们用 Alex 调试 Alex,现在还有 Signal。接下来会讲 Signal 如何发现 Alex 的重试循环,以及我们用 Signal 找到的一些真实问题。还有一个重要问题:哪些事情仍然需要人来做?人的判断力在哪里发挥价值,AI 产品经理又如何参与?最后也会谈谈 Alex 的架构几经重建后,哪些决定一直保留了下来。
Alex 的功能
Alex 是 Arize X 里的智能体。它可以读取你的追踪数据,把发现转成测试,也就是替你构建评估、数据集和实验。它还能规划工作、执行多步骤任务,并根据你的追踪数据生成合成数据,能做的事情很多。
这是我们一位资深工程师对 2023 年底第一个原型的评价。当时用的是 GPT-3.5 这类模型,大约有 50% 的内容是在幻觉。你们也能看到,随着模型变好,情况有所改善。
这里用前后对比的画面给大家一个直观印象。你可以把存放在 Arize 里的提示词交给它,让它帮忙优化。现在的流程深入得多,也有更漂亮的界面;Alex 会解释自己正在做什么,对任务的推理也更扎实。比如这里,我让它优化 Alex 自己的系统提示词,它会制定计划,检查应用周边的资源。这个窗口会出现在 Arize 里,你可以用它调试追踪数据。
从 2023 到 2026 的演进
我们是怎么走到今天的?快速回顾一下时间线。我们在 2023 年底启动了原型,当时用的是 GPT-3.5 这类模型。很快我们就决定把大量数学计算从模型中移到 harness 代码里。你们还记得那时让智能体做数学题是什么样吧?如今它们能解决 Navier–Stokes 方程级别的问题了,但当时可没那么擅长数学。
随后我们正式发布,当时把它叫作 Copilot,那个年代大家还都把产品叫 Copilot。它是一个技能集合的路由器,配有决策树和一些护栏。2025 年 8 月,我们大幅重写了它;加入了迭代式工具调用和待办工具,让智能体可以自己规划要做的事。2026 年 2 月,我们大规模重新发布 Alex 2.0,Sonar 4.5 成为默认模型,稍后会讲我们如何测试模型。6 月刚发布的 One Alex 则把原先的专家智能体合并成一个智能体,由它按需加载技能。
我们还加入了长期记忆。用户在一个会话过程中与 Alex 互动时,智能体会持续了解这位用户的历史记录,并在后台把它写下来。
当然,这些模型不是我们训练的。我们重建的东西都是 harness 代码。我觉得这让我对工程领域仍有很多有趣问题可解更有信心:事情并非全由模型决定,也不能只运行一个前沿模型,就指望它替你把一切做好。模型确实按自己的节奏不断进步,我们也围绕这一点做了一些选择,但我们构建的几乎所有东西都是 harness 代码。我们没有使用智能体框架;循环、计划、停止规则和记忆全是我们自己做的。这让我们有很大的掌控力,也让我们一路学到了很多。
计划由谁掌管?
第一个问题是计划和待办清单。我在幻灯片上准备了不少内容,不过关于规划,我想到一个比喻。假设你想让孩子做些家务——我自己没有孩子,可能在座有人能体会——你可以给孩子一张家务清单,让他们做完一项就勾掉一项。也可以一直盯着孩子,由你自己拿着清单,但不把整张清单告诉他们,只告诉他们下一项任务。这是另一种模式。每种做法都有取舍。
一开始,我们只是把待办清单交给模型。结果发现,它大部分时间都花在勾清单上:调用了很多次语言模型,却几乎没做任何有用的工作,只是在更新待办事项。我们还发现,经过多次工具调用后,它容易失去焦点;光是在待办工具上就能迭代二十多次。于是我们把待办工具作为它工具箱里的一个额外工具。
后来我们逐步把计划移进 harness。首先加入了“进行中”状态,避免模型忘了自己做到哪一步。接着,我们把计划作为一条消息,让 harness 在每次模型调用时都把计划渲染给模型;规则和数据放在一起,模型就更容易判断当前进度。后来我们又删掉“进行中”标记,因为那等于为了同一件事多调用一次模型:只要任务还没完成,按优先级排列的下一项自然就是接下来要做的事。
现在我们也在测试完全不使用待办工具的方式,只把所有状态完整保存在消息里。由 harness 维护状态并检查是否完成,模型读取这些内容,然后继续做下一件事。给正在构建待办流程的各位一个经验:模型可能会非常积极地使用清单。
怎样才算结束一轮?
“完成”后来成了由 harness 强制执行的一道门槛。我们最初试过把“没有工具调用的文本”当作完成信号,但遇到一种模型就会出问题:它在一轮里宣布要执行某个步骤,下一轮才真正调用工具。
更换模型时,很快就会发现有些假设会导致故障。在 Arize X 里,我们允许用户选择自己的模型提供商,因此不可能保证把用户可能尝试的每个模型都测一遍。我们在这里做的很多设计,都是为了防住这类情况。是的,我们会运行回归测试,用多种不同模型做检查和基准测试。我们对默认模型有自己的看法,但有些客户只用 Anthropic,另一些客户只用 OpenAI。为了让他们能用自己的模型,我们不得不针对各种可用模型来设计。
现在我们有一个明确的 finish 调用:如果计划里还有未完成的项目,它最多会被退回三次;在达到迭代上限前一步会发出警告,之后还会强制结束。
把大型结果当作文件处理
记忆是个很好的话题,这里其实有好几个问题。我喜欢打比方,再用一个比方吧:想象你坐在办公桌前,桌上放来一本很厚的书。一本书还好,你可以打开它、翻查内容。但书越来越厚,就会变得没什么用,因为你会把所有时间都花在读它上面。这就像一个工具返回了很大的结果,大到你根本读不过来。
再想想,桌上可能不止一本书。最后不只是每本书都太长,桌面也会被书堆满。处理办法有很多:你可以把书收起来,只在桌面留一个指向它的索引。我们对工具结果做的就像这样:桌上留一张便笺,写明书在哪里、大致包含什么。需要读的时候,查一下便笺,再到书架上把书找出来。桌面就清爽了一些。
Alex 可以帮你分析追踪数据,其中可能包含其他智能体的大量运行信息。如果工具返回一个很大的 JSON 数据块,就会撑爆上下文窗口,让你几乎无法继续做有用的工作。我们的做法是在 JSON 中截断内容;如果需要完整上下文,就让智能体代码用 jq 去查找。
智能体很擅长写代码,也很擅长使用类似代码的工具来推断信息,所以我们尽量利用这一点。智能体自身的执行轨迹也会超过一定窗口。现在 harness 会让模型写一个检查点,然后丢弃被检查点取代的旧内容。我们为历史记录设定固定的 token 预算。至于跨会话的长期记忆,基本做法是让后台任务为每位用户编辑一个小文件。稍后我还会讲我们为什么选择这种长期记忆方案。
一个小文件胜过知识图谱
总结一下:把巨大的结果当成文件处理,存起来就好,不要把所有内容都倒进上下文,也不必一开始就搞得很复杂。长期记忆方面,一个小文件实际效果胜过一整套图谱。我们试过向量检索、情景记忆和语义存储、时序知识图谱等等,最后采用的方案是每位用户一个 Markdown 文件,最多 8,000 个字符。
这里有个教训:工程师喜欢构建东西,做起来也很有意思,但有时会把事情弄复杂,反而碍手碍脚。每次完整请求都会载入这个文件。会话结束后,后台任务负责写入。文件小而精确,易于载入,不会挤爆上下文,人也很容易审查。可以让人工标注人员检查这些记忆文件,确认保存的内容是否正确,并调整后台任务的编辑指令。
而且在会话末尾只运行一个后台任务,也很容易做好安全保护,确保不会把其他用户的记忆写进这份文件。所以,这是一个关于不要过度设计问题的好教训。
专家智能体还是一个通用智能体?
简单说一下专家智能体。2025 年一开始,我们只有一个做追踪分析的智能体。后来发展出 10 个专家智能体,每个页面都有自己的专家:比如在数据集页面,就有一个专门的子智能体,可以为你生成合成数据,并检查、分析你的所有数据集。
后来我们又把这种做法收了回来,改成一个智能体,由它按需加载技能说明和工具,让它自己决定要调用哪些工具。这既是模型能力演进的结果,我认为也是一种简化。
最新模型未必总是最好
说到模型能力,我们也坚持认为,默认使用最新模型未必总是最佳选择。有时候我们确实会默认升级模型,我们对此有自己的判断。但“什么模型最好”是个非常主观的问题。在通用前沿能力上表现最好的模型,和最适合你正在构建、或我们正在构建的东西的模型,可能完全不同。
通常我们会默认选择速度快、效果够用的模型,把更多精力花在 harness 上。现在我们开始探索自动路由,也就是针对不同任务选择不同模型;还会训练自己的模型,比如在非常狭窄的应用场景上做小型后训练 SLM。有些场景甚至完全不需要循环,单次模型调用就够了。比如 AI 筛选器。和过去生成 SQL 相比,现在用非常小的模型生成筛选条件已经很容易。所以在这类场景里,也许根本不需要整个智能体循环,否则又是在过度设计。
把生产会话变成测试
很好的经验。现在讲讲生产会话如何成为我们的测试用例,也会多介绍一点 Arize 平台。追踪所有运行非常重要。你看,这些就是这个智能体的追踪数据,话题又绕回来了:每次你向 Alex 提问,我们都会留下 Alex 的追踪记录。我们仍然把它叫作 Copilot prod。这些是工具实时传回来的追踪数据。
有了这些数据,就很容易添加回归数据集,记录不同的用户查询,之后反复测试、迭代。生产会话会逐渐成为我们的测试用例和持续生长的样本;遇到新的错误情况时,它们也会不断增加、变化。现在我们还能把整个会话存成数据集,需要时让智能体重放其中某一轮。整个过程中我们也会使用 Arize 实验,对 harness 的改动做 A/B 测试。
我还想请大家记住一点:智能体里的 bug 很少会以明确报错的形式出现。传统软件的情况不太一样——我不确定是不是更简单,但确实不同。现在我们需要做定性判断:状态显示正常,可如果同一轮里出现 43 次相同的工具调用,那大概就是我们应该修复的问题。
延迟这类软件指标也是如此。大家大概都同意,等 227 秒才收到回复实在太久;但究竟多长才算太久,真的取决于使用场景。我们现在大量使用 Signal 来自动发现这些问题,人工读追踪数据的次数越来越少,我们的资深工程师对此很感激。不过我们仍然需要人的专业判断,稍后会讲到。
修复方案也可以是下一个方框里的东西。因此回归数据集非常重要,希望大家记住这一点。评估器需要有人类基准,这就是人类任务发挥作用的地方。我们要校准评估器,并确保评判器确实能反映工程师的判断,这非常重要。
哪些事仍需要人来做?
我认为仍有很多事情要由人来负责。那些黄金标签、供评判器使用的黄金数据集,都来自人类。
速度和质量之间如何取舍,是需要人来判断的。我不认为整个技术栈上存在一个统一答案,能告诉你什么时候应该更快一些、什么时候可以接受质量下降。即使我们掌握了相关指标——比如更换模型会让延迟增加 X、让回答质量提高 Y——这仍然是人的判断。假如我们所有地方都用 Astra,这会是正确决定吗?我认为这依然要由人来判断。指标能为决策提供依据,但最终还是得由我们作出选择。
几次重建后保留下来的东西
下面是几次重建之后一直保留下来的六件事。第一,追踪我们自己的产品——我们当然仍会追踪 Alex 做的每一件事。第二,数学和数据交给代码处理:由代码计算聚合结果,再由模型推理和解释;然后把这些能力作为工具提供给模型。我们不会把纯文本数学题直接丢给模型,而是让它调用代码去完成。
第三,在持续集成中使用黄金数据集;第四,错误要有明确的修复办法;第五,支持流式输出和持久化;第六,使用技能。我们给“技能”换过不同名字,比如路由器、工具等等,但本质上是给模型提供围绕外部系统的能力。
你们会遇到很多类似的决策,这些是我们的选择。请拍下这页幻灯片:计划由谁掌管?怎样才算结束一轮?工具输出大到超出上下文时怎么办?谁来写长期记忆,要不要长期记忆?应该用一个智能体还是多个子智能体?什么模型既够好又够快?又由谁来检查智能体自己做出的修复?
以上就是我。屏幕右下角有我的 LinkedIn 和 X 账号。我们的口号是:每天我们都用 Alex 来构建 Alex。我们也写了不少文章,深入介绍这套系统的技术实现。欢迎大家联系我。也要特别感谢 Alex 团队和参与构建它的工程师们,谢谢。