第一篇我们打印过
create_agent的内部结构:两个节点model和tools,一条条件边,一条回边。经过前三篇,State、Reducer、条件边、循环都已经讲过,这张图里已经没有陌生的部件了。这一篇就亲手把它搭出来——不是为了替代create_agent,而是为了在需要定制时知道该改哪里。后半篇转向工程问题:节点怎么拿到"这一次调用"的配置(比如当前用户是谁),以及怎样让调用外部服务的节点更经得起折腾。
一、先拆解:Agent 循环需要哪些部件#
回顾 LangChain 系列第五篇讲过的工具调用流程:模型并不会自己执行工具,它只是返回一条"工具调用指令",由代码去执行,再把结果交回给模型。把这个流程按第一篇的方法拆一遍:
拆步骤:调用模型、执行工具,两步。
定数据:整个过程就是一串消息——用户的问题、模型的回复(可能带工具调用指令)、工具的执行结果……所以 State 只需要一个消息列表,而且要用上一篇讲的 add_messages 让它不断追加。现成的 MessagesState 正好合适。
连线:调用模型之后要做一个判断——回复里有工具调用,就去执行工具;没有,说明模型已经给出了最终答案,结束。执行完工具,总是回到模型。
flowchart LR
S([开始]) --> M[model:调用模型]
M -.->|有工具调用| T[tools:执行工具]
T --> M
M -.->|没有工具调用| E([结束])三个部件都有现成的积木:State 用 MessagesState,"执行工具"用 LangGraph 提供的 ToolNode,"有没有工具调用"的判断用 tools_condition。
二、动手搭建#
2.1 模型节点#
模型节点做的事很简单:把消息历史交给绑定了工具的模型,把它的回复作为新消息交回去。
from langchain.chat_models import init_chat_model
from langgraph.graph import MessagesState
model = init_chat_model("openai:gpt-4o-mini").bind_tools([get_weather])
def call_model(state: MessagesState):
reply = model.invoke(state["messages"])
return {"messages": [reply]}
bind_tools 把工具的说明一起发给模型,模型才知道有哪些工具可以用。get_weather 就是用 @tool 定义的普通工具,和 LangChain 系列里的写法完全一样。
2.2 工具节点:ToolNode#
工具节点要做的事情稍多:从最后一条 AI 消息里取出工具调用指令,找到对应的工具执行,再把结果包装成 ToolMessage(带上对应的调用 ID,模型才知道哪个结果对应哪次调用)。如果模型一次要求调用多个工具,还应该并行执行。
这些琐碎的工作,ToolNode 已经全部做好:


还没有公开留言,成为第一个写下回声的人。