← 返回信息流

精选LangChain新闻

LangSmith Engine:我们如何构建一个用于改进智能体的智能体

langchain.com教程产品AI评分:70/100

LangSmith 团队分享了其 Engine 的技术实现,该引擎通过大规模分析追踪数据,将重复出现的失败转化为可操作的问题,并自动提出评估器和修复建议,从而帮助开发者改进 AI 智能体。

上周我们发布了 LangSmith Engine。Engine 是一个智能体,它基于你的智能体追踪数据,发现反复出现的问题,并建议下一步该怎么做。

这篇文章将深入介绍我们构建它的技术细节:为什么我们要构建 Engine,它处理哪些输入和输出,以及让它能够分析海量追踪数据的架构决策。

为什么我们要构建 Engine

LangSmith 是智能体改进闭环的核心平台。构建、测试、部署和监控是这个闭环的四大支柱,支撑着智能体的开发。

随着你部署的智能体数量不断增长,它们产生的追踪数据也在不断增加。因此,你需要花费越来越多的时间来筛选追踪记录,找出智能体出错的地方。

基本的工具错误相对容易发现。整体运行轨迹也可以从追踪视图中看到。但许多智能体问题要难检测得多,除非你以细粒度的方式检查每条追踪记录:

  • 智能体在相同的工具调用中循环往复
  • 它使用了不正确的工具参数
  • 它执行效率低下
  • 它遗漏了本应使用的工具
  • 它在不同运行中反复出现同一类型的请求失败

在 LangChain 内部遇到这个问题后,我们着手构建了 LangSmith Engine。

Engine 有三项任务:

  1. 在追踪数据中发现反复出现的失败。
  2. 将这些失败转化为可操作的问题。
  3. 将这些问题转化为持久的改进:评估器、数据集示例和修复方案。

Engine 本身就是一个智能体:一个编排器,使用专门的组件端到端地运行改进闭环。它拉取追踪数据,在连接了代码仓库时读取代码,将失败归类为问题,提出评估器和数据集示例建议,并随着时间的推移不断更新对你智能体的理解。

Engine 产出什么:问题

Engine 的核心功能是识别问题。

一个问题是一种反复出现的失败模式,有证据追踪作为支撑,并附带建议的后续行动。问题会呈现在用户的 Issue Board(问题看板)中:即 Engine 在追踪项目中发现的问题列表。

一个问题由以下部分组成:

  • 名称:问题的标题
  • 描述:对问题的段落式描述
  • 类别:预定义的智能体失败类别之一
  • 严重程度:低、中或高
  • 追踪记录:相关的追踪记录,为问题发生的位置提供证据
  • 建议行动:防止问题再次发生的建议后续步骤
  • 标签:用于驱动后续工作流的元数据,例如 needs_fix
  • 建议的在线评估器:一个评估器,如果问题再次发生,能够将其标记出来
  • 建议的数据集示例:对离线数据集的补充,能够代表该问题
  • 建议的修复方案:修复根本问题的代码或提示词更改

重要的一点是,Engine 不仅仅是指出一个有问题的追踪记录。它试图将生产环境中的失败转化为你的团队未来可以采取行动并加以测试的东西。

Engine 消费什么

Engine 接收或能够获取四种主要输入。

Engine 由 Agent Overview(智能体概览)引导。这类似于 AGENTS.md 文件:一份动态更新的描述,说明你的智能体做什么、应该期望什么样的追踪结构、需要关注哪些失败模式,以及你的团队表达了哪些偏好。

首次运行基于引导问答和项目上下文进行引导。在初次运行期间,Engine 会分析追踪数据,并利用所学到的内容创建第一版 Agent Overview。在后续运行中,Agent Overview 成为 Engine 读取和更新的持久化输入。

你也可以随时手动编辑 Agent Overview。

Engine 通过 LangSmith CLI 从相关的 LangSmith 追踪项目中拉取追踪数据。

一条完整的追踪记录包含一次智能体运行的消息和轨迹。为了应对规模问题,Engine 并不总是从加载每条追踪记录的完整内容开始。它通常从紧凑的轨迹摘要开始,然后在需要深入调查某条追踪记录时,有选择地加载完整的追踪内容。

Engine 会获取当前的 Issue Board,包括未关闭的问题和之前已关闭的问题。

这让 Engine 能够掌握项目的当前状态。它可以避免重复提交已知问题,为现有问题补充证据,并了解哪些问题已经解决或关闭。

你可以选择将 Engine 连接到你的代码库。这样 Engine 就能更精确地诊断问题,并让独立的修复代理能够提出修改建议。

如果连接了代码库,该仓库会被安装到沙箱中。在设置过程中,你可以指定 Engine 应使用哪个分支或子目录。

Engine 会更新什么

Engine 在运行过程中可以更新多种输出。

Engine 的主要职责是更新 Issue Board。它可以创建新问题、更新现有问题、附加证据轨迹、修改问题元数据。

对于每个问题,Engine 可以提出一个评估器,用于在未来的轨迹中捕获相同的模式。它还可以从证据轨迹中提出回归示例,这样生产中观察到的故障就能转化为离线测试覆盖。它还可以建议提示词或代码修改来修复根本问题。

Engine 可以记录其发现的内容,并更新 Agent Overview 以供后续运行使用。

这就是 Engine 随时间记住项目特定信息的方式:常见故障模式、轨迹模式、工具行为和用户偏好。

高层架构

Engine 构建在 Deep Agents 之上,并连接到一个沙箱,在沙箱中它可以写入文件、检查轨迹、执行代码,以及操作已检出的仓库。

  • 系统提示和指令:包括 Agent Overview
  • 沙箱:Engine 工作的环境
  • LangSmith CLI:Engine 用于从 LangSmith 获取数据并将更新推送回去的主要接口
  • 自定义工具:尤其是用于测试评估器和提出回归示例的工具
  • 子代理:用于筛选轨迹和调查可能的问题,而不会让主代理的上下文溢出
  • 记忆:通过 Agent Overview 维护,并根据用户操作进行更新
  1. 准备代理的上下文。
  2. 大规模筛选轨迹。
  3. 调查可能的问题。
  4. 创建问题、评估器和数据集示例。
  5. 在需要时将修复移交给单独的代理。
  6. 更新记忆以供下次运行使用。
  1. 准备代理的上下文

在 Engine 分析轨迹之前,它需要一个可以工作的环境,以及足够的上下文来理解它所检查的代理。

沙箱设置

Engine 在连接沙箱的状态下运行。我们为此使用 LangSmith Sandboxes。

在运行 Engine 之前,我们先设置代理的环境。首先,我们拉取基础 Engine Docker 镜像。该镜像包含所需的库和 LangSmith CLI,Engine 通过它来与 LangSmith 数据交互。

如果 Engine 连接了 GitHub 仓库,我们还会拉取相关的代码工件。用户可以在设置过程中指定使用哪个分支或子目录。

沙箱很重要,因为 Engine 经常需要检查轨迹数据、写入中间文件、测试评估器代码,并对提出的输出进行迭代。给代理一个受控的工作环境会让整个工作流程可靠得多。

Agent Overview

Agent Overview 既是一个指令文件,也是一个记忆层。

当你设置 Engine 时,你需要回答一组基础的引导问题。Engine 会利用这些回答,加上它在首次运行期间发现的内容,来创建初始的 Agent Overview。

  • 你的代理是做什么的
  • 预期会看到什么样的轨迹结构
  • 需要注意的常见陷阱
  • 项目特定的上下文
  • 用户偏好

Engine 会在后续运行中读取并更新这个文件。

LangSmith CLI

Engine 与 LangSmith 交互的主要方式是通过 LangSmith CLI。

在大多数情况下,我们更倾向于使用它,而不是为每个 LangSmith 操作都创建自定义工具。CLI 为 Engine 提供了一个通用接口,用于拉取轨迹、查询问题、创建问题、附加轨迹、更新问题元数据以及提出工件。

这也让 Engine 更易于调试和复现。CLI 是同一个可下载的接口,也可以提供给本地的编码代理使用。如果 Engine 通过 CLI 执行了某项操作,通常也可以在该系统之外理解和复现该操作。

  1. 大规模筛选追踪记录

构建 Engine 时最大的架构挑战是追踪记录的数量。

让一个代理一次调查和整理 50 条追踪记录相对容易。但一旦我们将系统接入生产环境的代理,在这个规模下有效的技术就开始失效。生产项目在回溯窗口内可能有数千甚至数万条追踪记录。

将所有完整追踪内容加载到主代理的上下文中是不可行的。即使是来自长时间运行代理的 10 条追踪记录,也可能包含数百次工具调用和消息。

  1. 一个广泛的筛选阶段,用于快速识别可疑的追踪记录。
  2. 一个更深入的调查阶段,只加载可能重要的追踪记录的完整上下文。

轨迹格式

为了实现筛选,我们需要对每条追踪记录进行压缩表示。

如何在压缩追踪记录中信息的同时,保留回溯到其中所需的信息?

答案是代理轨迹:追踪记录的紧凑骨架。

一条轨迹每个回合有一个条目,包含角色、可选的工具名称、延迟和内容大小。它不包含完整内容。

{ role: "human", chars: 142 }{ role: "ai", latency_ms: 1820, chars: 89 }{ role: "tool", tool_name: "search_db", latency_ms: 340, chars: 2100 }{ role: "tool", tool_name: "search_db", latency_ms: 312, chars: 1980 }{ role: "tool", tool_name: "search_db", latency_ms: 298, chars: 2040 }{ role: "ai", latency_ms: 2100, chars: 210 }

轨迹充当导航工具。它让筛选器能够快速发现可疑的模式,然后在完整追踪记录中搜索,只将所需的信息加载到上下文中。

优先处理带反馈的追踪记录

追踪记录可能已经关联了反馈。这些反馈可以来自人工标注、LLM-as-a-judge 评分,或终端用户的反馈(点赞/点踩)。

Engine 将追踪记录上的反馈视为可能存在问题的优先信号。

Engine 拉取的初始追踪记录集合包含反馈统计信息。Engine 被指示查找带反馈的追踪记录,并优先对其进行分类处理。

反馈不会自动成为问题。它会提高筛选和调查的优先级。代理仍然需要判断该追踪记录是否属于真实问题的一部分。

筛选子代理

给定这条追踪记录,其中是否存在值得进一步调查的问题?

Engine 为此使用一个专门的筛选子代理。该筛选器是一个基于 Haiku 的子代理,主代理将其分派到大约 20 条追踪记录一组的多组中。

筛选器的职责刻意保持狭窄。它不创建问题,不诊断根本原因。它只在表面层面判断一条追踪记录是干净的还是可能包含问题。

筛选器向主代理返回结构化响应。响应中每条被标记的追踪记录占一行,包含追踪记录 ID、类别和简短原因,随后是干净追踪记录的数量。

这一步缩小了搜索空间。我们不是让主代理对每条追踪记录进行完整推理,而是使用并行筛选器来识别值得更深入关注的追踪记录。

  1. 调查可能的问题

筛选之后,主代理读取筛选器的输出,并分派更深入的调查。

调查子代理

调查器接收被标记的追踪记录,拉取完整的追踪内容,在可用时阅读代码库,并对潜在问题进行更深入的分析。

我们鼓励主代理使用子代理来完成这项工作,因为完整的追踪内容可能很大。将多条完整追踪记录和相关代码加载到主代理的上下文窗口中会很快导致溢出。

与筛查器不同,调查器并非一个拥有固定系统提示词的专用子代理,而是由主代理针对具体调查任务进行提示的通用子代理。这赋予了主代理灵活性:不同类型的问题可能需要不同的调查策略。

调查器的职责是判断被标记的轨迹是否代表真实问题、轨迹是否应被归组,以及应在问题上记录哪些内容。

问题类别

Engine 为每个问题都引入了类别概念。

我们识别出了一组预定义的常见代理失败模式,并提示 Engine 主要查找这些类型的问题。该列表包括:

  • pii_leak
  • agent_looping
  • incorrect_tool_args
  • missing_tool

将 Engine 限制在已知类别中,有助于我们控制其发现的问题范围,并在将这些类型引入客户之前对其进行评估。这也使输出更易于用户理解。

用户仍可通过 Agent Overview 自定义 Engine 应重点关注的内容。如果某个团队关心特定问题类型,他们可以在那里描述这些优先级。

随着我们不断识别和验证新的反复出现的代理失败模式,我们正在积极扩展这一类别列表。

  1. 创建问题、评估器和数据集示例

一旦 Engine 识别出真实问题,主代理就会创建或更新问题,并附上证据轨迹。

主代理负责问题创建以及围绕问题的评估产物,但不负责直接修复底层代码或提示词。

  1. 问题本身及其证据轨迹。
  2. 一个建议的评估器。
  3. 建议的回归示例。
  4. 一个 needs_fix 标签,用于指示是否应启动单独的修复代理。

评估器

Engine 被提示为每个问题提出一个评估器。

思路很简单:一旦发现某种失败模式,你就需要一个检查器,能在未来的轨迹中捕获相同的模式。

Engine 支持两种评估器类型。

代码评估器是检查轨迹结构的 JavaScript 函数——字段值、工具输出、步骤数、错误模式。当失败无需阅读内容即可检测到时,它们是合适的选择。

LLM-as-judge 评估器则处理需要理解力的场景:幻觉、接地失败、无帮助的拒绝、错误建议。

代理根据问题类型选择评估器。结构性失败使用代码评估器,语义性失败使用 judge 评估器。

在 Engine 呈现建议的评估器之前,它会调用 test_evaluator 工具。

test_evaluator 工具

test_evaluator 工具允许 Engine 在向用户建议评估器之前,先在证据轨迹上测试建议的评估器。

这一点很重要,因为一个评估器可能看起来合理,却无法捕获实际问题。Engine 调用该工具时传入评估器定义以及它想要运行评估器的轨迹。该工具执行评估器并返回从轨迹 ID 到结果的映射。

如果评估器未能捕获正确的轨迹,Engine 可以迭代代码或提示词。目标是交付最能捕获证据轨迹所代表的失败模式的版本。

回归示例和断言

每当创建问题或向问题添加新轨迹时,Engine 都会被指示对每条证据轨迹调用一次 propose_regression_example。

这会为该轨迹创建一个建议的回归示例。该示例由代理的原始输入以及对预期输出的断言组成。

我们建议使用断言而非完整的标准答案输出,因为断言更简单、更灵活。一个正确的回答可以有多种表述方式。关键在于它是否满足轨迹所隐含的关键主张。

  • key:反馈标识符,以短横线式 slug 形式书写
  • comment:一句人类可读的陈述,说明正确回答应满足什么条件

提出的示例会显示在前端的问题(issue)中。审阅者随后可以将它们提升为数据集。

这就闭环了从生产故障到离线测试覆盖的流程。

  1. 将修复工作移交给独立的智能体

一个关键的设计决策是将问题创建与修复生成分开。

在早期版本中,我们尝试让主智能体既识别问题,又提出提示词或代码修复方案。这让智能体的任务过于宽泛。它必须扫描轨迹、判断哪些内容重要、对故障进行分组、创建问题、生成评估器、提出数据集示例,同时还要推理正确的修复方案。

我们发现,当所有这些都在一次运行中完成时,主智能体很难可靠地做出修复。

  1. 主 Engine 智能体识别并记录问题。
  2. 它创建数据集和评估器工件。
  3. 如果问题需要修复,它会留下一个 needs_fix 标签。
  4. 一个独立的修复智能体被启动,负责提出实际的代码或提示词修改。

这让主智能体更加简单,也让修复智能体的任务更加聚焦。修复智能体可以从问题、证据轨迹和关联的仓库上下文出发,而无需同时执行完整的轨迹筛选工作流。

  1. 为下一次运行更新记忆

Engine 不会每次都从零开始。

Agent Overview 不仅由 Engine 的调查更新,也由用户操作更新。当你解决问题、关闭问题或创建评估器时,该操作就会成为信号。

Engine 可以通过 LangSmith CLI 拉取近期事件,从这些事件中归纳观察结果,并更新 Agent Overview。

它被特别提示要维护一个“用户偏好”(User Preferences)部分。该部分记录 Engine 从观察用户与问题交互方式中学到的内容。

每个团队关心的是一组不同的问题。Agent Overview 就是 Engine 随着时间推移,根据这些偏好调整其分析的方式。

架构决策与经验教训

有几个架构决策最终被证明尤为重要。

将 CLI 作为主要的 LangSmith 接口

Engine 所做的大部分工作都是通过 LangSmith CLI 完成的。与为每个操作创建狭窄的自定义工具相比,这使系统更加灵活。这也让 Engine 的行为更容易复现和调试。

在读取轨迹之前先进行压缩

在生产规模下,完整轨迹太大,无法全部筛选。Trajectories 让 Engine 能够对大量轨迹的形态进行推理,然后有选择地加载重要的细节。

将筛选与调查分开

筛选器针对规模进行优化。调查器针对更深入的分析进行优化。

这种拆分让 Engine 能够处理大量的轨迹,而无需让每条轨迹都经过昂贵的完整调查流程。

使用专用筛选器,但使用灵活的调查器

筛选器的工作是狭窄且可重复的,因此它受益于专用的提示词和结构。

调查则更加多样化。有些需要阅读代码,有些需要理解评估器失败的原因,有些需要比较轨迹。因此,我们使用通用的调查子智能体,由主智能体动态提示它们。

约束问题类别

让智能体随意发明问题类别会使输出更难评估、更难信任。预定义的分类法让我们能够控制质量、衡量性能,并有意识地扩展覆盖范围。

优先使用断言而非完整的预期输出

对于回归示例,断言通常比完整的参考答案更合适。它们捕捉了必须为真的条件,而不会过度约束正确回答的确切措辞。

让主智能体专注于问题本身

主代理仅负责创建问题及关联的数据集/评估器工件,不会直接尝试修复提示词或代码。

当某个问题需要修复时,主代理会为其标记 needs_fix。随后由独立的修复代理处理修复提案。

这种分工源于我们的观察:当同一个代理需要在同一轮中既识别问题又提出修复方案时,往往难以兼顾。

结论

Engine 是我们为自动化更多代理改进循环所做的尝试。

代理可观测性的难点不仅在于查看单条追踪中发生了什么,更在于跨大量追踪发现重复出现的模式、判断哪些模式值得关注,并将这些模式转化为问题、评估器、数据集示例和修复方案。

该架构正是对这一循环的体现。Engine 准备上下文、大规模筛选追踪、调查可疑问题、创建问题工件、在需要时将修复工作移交给独立代理,并更新自身记忆以供下一轮运行使用。

它已经改变了我们内部改进自身代理的方式。我们不再需要手动翻查追踪记录并单独编写评估,而是可以直接将生产环境中的行为转化为问题、修复方案和测试。

你可以在 LangSmith 追踪项目的 Issues 标签页中找到 Engine。连接代码仓库即可获得具备代码感知的修复提案,或者仅从追踪开始,看看 Engine 能发现哪些重复模式。

了解你的代理真实行为

LangSmith 是我们的代理工程平台,可帮助开发者调试每一个代理决策、评估变更,并一键部署。

译文已达到本站中文翻译的字数上限,剩余内容请查看原文。

阅读原文