解释器为代理在代理循环内提供了一个可编程的 内存中 工作区。代理编写代码来完成任务,运行时执行代码并仅返回相关结果。中间结果不会成为模型上下文的一部分。 如果说沙箱是作用于环境(例如运行命令、安装依赖项和编辑文件)的代码优先方式,那么解释器则是组合工具、保留状态以及决定哪些信息应返回给模型的代码优先方式。
解释器处于 测试版。API 和生命周期行为可能在版本之间发生变化。
解释器需要 @langchain/quickjs。

为何使用解释器?

大多数代理工作在模型推理和工具调用之间交替进行。模型可以在一个回合中发出多个工具调用,但该批次在发出时就已确定。在没有另一个模型回合的情况下,无法进行循环、根据结果分支、重试失败或将一次调用的输出馈送到下一次调用,并且每个结果都会返回到模型的上下文中。模型还决定发出多少次调用,因此要求它在数百个项目上调度工作是不可靠的,并且它倾向于覆盖样本而不是每个项目。 解释器将这种编排转移到代码中,以便模型推理 要做什么,而不是每个中间步骤。

程序化工具调用 (PTC)

从解释器代码中调用选定的工具,包括循环、重试、分支和并行批次。

动态子代理

从代码中分派子代理,用于对大型输入进行扇出、验证和递归工作流。

有状态工作

将中间值保存在运行时状态中,而不会使模型上下文过载。

确定性转换

对结构化数据进行排序、分组、解析、验证、评分和聚合,无需另一个模型回合。

选择模式

将解释器用于代理循环内的代码:组合工具、保留状态以及控制返回给模型的内容。 将沙箱用于作用于环境的代码:shell 命令、包安装、测试、文件系统编辑和操作系统级执行。

快速入门

安装 QuickJS 中间件包,然后使用 createDeepAgent 上的 middleware 参数传递解释器中间件。

解释器如何工作

该中间件向代理添加了一个 eval 工具。当有用时,代理编写 JavaScript 并调用 eval;您不会直接调用解释器。该工具在 QuickJS 上下文中运行代码,其变量可以在 eval 调用之间持续存在,具体取决于持久化 mode。它捕获 console.log、console.warn 和 console.error,并返回最后一个表达式的结果。 代理可以编写如下代码:
代码在 QuickJS 上运行,这是一个轻量级 JavaScript 运行时。默认情况下,解释器代码无法访问主机文件系统、网络、shell、包管理器或时钟。它可以计算、保存状态并写入 console.log、console.warn 或 console.error,仅此而已。 两个显式桥接扩展了其访问范围:
  • 工具,通过程序化工具调用 (PTC)。在 tools 命名空间下提供一个工具列表作为异步函数。这些可以是代理自己的工具或您定义并传入的独立工具。
  • 子代理,通过动态子代理。当代理配置了子代理时,解释器会暴露一个 task() 全局函数,用于从代码中分派它们。
程序化工具调用在您启用它之前是关闭的。只要代理有子代理,通过 task() 进行的子代理分派就默认开启,您可以将其关闭。除此之外,没有其他内容会跨越 QuickJS 边界。

程序化工具调用 (PTC)

程序化工具调用 (PTC) 在解释器内部全局 tools 命名空间下暴露选定的代理工具。代理可以编写代码,通过循环、分支、重试或并行批次调用工具,而不是要求模型发出一次工具调用、等待结果,然后再决定下一次调用。 当中间结果仅作为下一步的输入时,这很有帮助:解释器在任何内容返回给模型之前对其进行过滤或聚合,从而使多步骤工作流保持令牌效率。它是模型无关的,由中间件实现,而不是特定于提供商的工具调用 API。 中间件将每个列入允许列表的工具暴露为 tools 下的一个异步函数。代理使用 await 调用它,在代码中处理结果,模型只看到最终的解释器输出,而不是每个中间值。工具名称被转换为 camelCase,而输入对象仍遵循工具的 schema,因此名为 web_search 的工具变为 tools.webSearch(...):

启用 PTC

使用显式允许列表启用 PTC:
启用 PTC 后,代理可以从解释器代码中调用列入允许列表的工具。此示例并行搜索多个主题,并在返回给模型之前合并结果:
PTC 调用目前通过解释器桥接执行,不经过正常的工具调用路径。因此,interruptOn 审批工作流不会针对每个 PTC 调用的工具调用强制执行。

动态子代理

以下概述涵盖了何时使用动态子代理以及一个最小的 task() 模式。有关配置、编排示例、工作流触发器和安全注意事项,请参阅动态子代理。 动态子代理允许解释器使用内置的 task() 全局函数从代码中分派已配置的子代理。一个跨越许多独立单元的任务(例如审阅目录中的每个文件或分流一批工单)变成了一个循环,该循环扇出工作并综合结果。 将动态子代理用于:
  • 扇出与综合:在许多项目上并行运行相同类型的工作,然后合并结果。
  • 验证:将发现结果发送给独立的验证子代理,并仅保留已确认的结果。
  • 递归工作流:在解释器变量中保留工作集,选择切片,调用子代理,并细化结果。

安全

解释器使用 QuickJS 以严格的默认隔离来运行不受信任的 JavaScript。将其视为一个作用域受限的解释器运行时,而不是一个完整的生产沙箱后端。 您通过 PTC 暴露的每个工具都是解释器代码可以使用的外部能力。将 PTC 允许列表视为一个权限边界:仅暴露代理需要的工具,并避免桥接可以访问敏感系统、花费资金、修改数据或调用无限制网络的广泛工具,除非该行为是有意的。
代码执行如何工作解释器代码通过 QuickJS-Emscripten 在 WASM 沙箱化的 QuickJS 运行时中运行,而不是在主机 Node.js 进程中。将解释器视为一个能力范围受限的执行层:仅桥接代理需要的工具和子代理,并保持 PTC 允许列表狭窄。

配置

createCodeInterpreterMiddleware 接受以下选项: