Sunday 的面试指南

LangChain createAgent 源码(中):Middleware 与图编译

《Agent 大模型 0 到 1 系统课》 · 程序员 Sunday

你正在阅读本节的免费试读。完整课程 ¥499,可在文末添加作者微信购买。

上一小节最后,咱们顺着 createAgent() 一直追到了 ReactAgent,并且看到了下面这段代码:

const workflow = new StateGraph(state, {
	input,
	output,
	context: this.options.contextSchema
})

state、input、output 和 context 分别负责什么,前面已经讲过了。

但是!

代码执行到这里以后,Agent 其实还不能运行。

因为 new StateGraph() 只是创建了一个 Graph Builder。他更像是先准备好一张空白的流程图,并且规定这张图里的数据应该长什么样。

至于流程图里有哪些 Node、Node 之间怎么连接、模型什么时候调用 Tool、Tool 执行完以后又回到哪里,现在都还没有确定。

所以,ReactAgent 构造函数接下来还需要完成三件事:

  • 把模型、Tool 和 Middleware 加入 Graph
  • 为这些 Node 连接 Edge 和 Conditional Edge
  • 调用 compile(),把 Graph Builder 编译成可执行 Graph

这一小节,咱们就继续沿着 ReactAgent.ts 往下看,把这三件事捋清楚。

先看看最终要构建出什么

暂时先不看源码,咱们想一下一个最基础的 Agent 应该怎样运行。

模型收到用户问题以后,可能直接给出最终回答,也可能返回 Tool Call。

如果返回 Tool Call,应用程序就执行 Tool,再把 Tool Result 交还给模型。模型拿到结果以后继续判断,直到不再调用 Tool 为止。

因此,最基础的 Graph 其实就长这样:

LangChain createAgent 源码(中):Middleware 与图编译 配图 1

这里的 model_request 负责调用模型,tools 负责执行 Tool。

从 model_request 出发有两个方向,所以这里不能写死一条普通 Edge,而是需要根据模型返回的结果动态选择路径。

这个地方用到的,就是第 07 小节讲过的 Conditional Edge。

不过,真实 Agent 里还可能加入 Middleware。

例如咱们第 06 小节使用过下面这些 Hook:

LangChain createAgent 源码(中):Middleware 与图编译 配图 2

这些 Hook 加进来以后,Graph 还是不是刚才那张图?

答案是:不一定。

有些 Middleware Hook 会直接变成 Graph Node,有些则只是包住模型或者 Tool 的调用过程,根本不会出现在 Graph 里。

这就是接下来阅读源码时,最需要弄明白的第一件事。

Middleware 是怎么进入 Graph 的

继续打开上一小节已经定位到的文件:libs/langchain/src/agents/ReactAgent.ts

LangChain createAgent 源码(中):Middleware 与图编译 配图 3

找到刚才的 new StateGraph(),然后继续往下看。

紧接着会看到几个数组:

LangChain createAgent 源码(中):Middleware 与图编译 配图 4

这里先不要管源码里的泛型,只看变量名就可以了。

简化之后的代码,大概就是这样:

// 为有钩子的中间件节点生成节点名
const beforeAgentNodes = []
const beforeModelNodes = []
const afterModelNodes = []
const afterAgentNodes = []

const wrapModelCallHookMiddleware = []

前四个数组负责记录生命周期 Hook 对应的 Graph Node,最后一个数组则专门保存实现了 wrapModelCall 的 Middleware。

然后,源码会遍历咱们传给 createAgent() 的全部 Middleware:

const middleware = this.options.middleware ?? []

for (let i = 0; i < middleware.length; i++) {
	const m = middleware[i]

	if (m.beforeAgent) {
		const node = new BeforeAgentNode(m)
		const name = `${m.name}.before_agent`

		beforeAgentNodes.push({ index: i, name })

本节试读已结束

继续学习,解锁完整课程

购买《Agent 大模型 0 到 1 系统课》,
继续阅读本节剩余内容与后续课程。

扫码添加作者微信,备注「Agent 课程」

添加作者微信 · 购买完整课程

解锁完整课程 ¥499

《Agent 大模型 0 到 1 系统课》
扫码添加微信,备注「Agent 课程」,购买后由 Sunday 提供完整内容的学习方式。

扫码添加作者微信 LGD_Sunday,购买 499 元 Agent 课程

微信昵称:LGD_Sunday
手机上可长按保存二维码,再用微信扫一扫识别。

保存微信二维码