‹ 博客列表

LangChain 1.2 入门(二十三):Agent 是什么——create_agent 与第一张图

Agent 的五项关键能力与四类组件,0.x 碎片化 API 与 1.x 单入口 create_agent 的对比,两种传模型方式,以及 invoke 的输入输出与 Agent 的图结构。

LangChain 1.2 入门(二十三):Agent 是什么——create_agent 与第一张图

前六章分别解决了输入(消息、提示词)、能力(工具)、输出(结构化输出)三个问题。这一章把它们装到一起:谁来决定「先调哪个工具、再怎么做」——答案是 Agent。LangChain 1.x 把这条路收敛成一个函数:create_agent()。

23.1 Agent 到底是什么

在大模型应用里,智能体通常指这样一种软件系统:以大语言模型为推理与决策核心,结合记忆、工具调用与环境交互能力,能够规划决策并执行复杂任务以达成目标。

拆开看,它要解决五个问题:理解用户问题、把任务拆成步骤、判断是否需要工具、决定调用哪个工具、以及如何利用工具结果推进任务并生成回答。这也是它区别于「一次问答」的地方——它自己决定下一步做什么。

关于架构要素,有个很实用的排序:

  • 必须有的:行动(Action),没有动作就只是聊天;
  • 几乎总是有的:工具(Tool),行动的落点;
  • 有条件才有的:规划决策(Planning);
  • 最容易被省略的:记忆(Memory),早期应用基本靠外部消息列表代替。

所以别被「智能体」这个词吓到:一个能调用工具的循环,就已经是 Agent 了。

23.2 从 0.x 到 1.x:从一堆函数变成一个入口

LangChain 0.x 时代的思路是「针对场景设计特定 Agent」,想要思维链就用 create_react_agent,要结构化输出就用 create_structured_chat_agent,要工具调用就用 create_tool_calling_agent。代码长这样:

from langchain_openai import ChatOpenAI
from langchain.agents import AgentExecutor, create_react_agent
from langchain_core.prompts import PromptTemplate

model = ChatOpenAI(model="gpt-4o-mini")

prompt = PromptTemplate.from_template("""
You are a helpful assistant.
Tools: {tools}
Tool Names: {tool_names}
{agent_scratchpad}
""")

agent = create_react_agent(llm=model, tools=tools, prompt=prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
result = executor.invoke({"input": "问题"})

灵活,但带来三个问题:每种 Agent 都要单独记 API 与参数,心智负担高;多个 Agent 之间无法统一调度,可组合性差;不同模块难以复用,生态碎片化。

1.0 之后 LangChain 做了一次彻底重构,把所有创建方式收敛成一个入口 create_agent(),底层通过「中间件机制」和统一的 invoke / stream 接口实现全局一致:

from langchain.chat_models import init_chat_model
from langchain.agents import create_agent

# 1. 初始化模型
model = init_chat_model("gpt-4o-mini", model_provider="openai")

# 2. 创建 agent(一步完成)
agent = create_agent(
    model=model,
    tools=[tool1, tool2],
    system_prompt="Agent 的行为指令",   # 可选
)

# 3. 调用
result = agent.invoke({"messages": [{"role": "user", "content": "问题"}]})

create_agent 的完整签名(节选):

create_agent(
    model: str | BaseChatModel,             # 必需:聊天模型
    tools: List[BaseTool],                  # 必需:工具列表
    *,
    system_prompt: str = "",                # 系统提示词
    middleware: Sequence[AgentMiddleware] = (),   # 中间件
    interrupt_before: List[str] = None,     # 在某些工具前暂停(人机协作)
    interrupt_after: List[str] = None,      # 在某些工具后暂停
    debug: bool = False,                    # 调试模式
    name: str | None = None,                # Agent 名称
)

23.3 模型怎么传:字符串还是对象

模型是 Agent 的「大脑」。传法有两种。

方式 1:传模型字符串,Agent 自己创建模型对象。

from langchain.agents import create_agent
from dotenv import load_dotenv

load_dotenv(override=True)
agent = create_agent("deepseek-v4-flash")
print(type(agent))
# <class 'langgraph.graph.state.CompiledStateGraph'>

方式 2:传模型对象,能完全控制 provider、key、base_url。

from langchain.chat_models import init_chat_model
from langchain.agents import create_agent
import os

model = init_chat_model(
    model="gpt-5.4-mini",
    model_provider="openai",
    api_key=os.getenv("CLOSEAI_API_KEY"),
    base_url=os.getenv("CLOSEAI_BASE_URL"),
)
agent = create_agent(model)
print(type(agent))
# <class 'langgraph.graph.state.CompiledStateGraph'>

注意返回类型:Agent 本质上是 LangGraph 的 CompiledStateGraph 实例,底层是一张图。没有任何工具时,这张图就是一条直线:

只有模型、没有工具时的 Agent 图结构:__start__ 节点指向 model 节点,再指向 __end__ 节点

把这张图打出来很简单:agent.get_graph().draw_mermaid_png()。后面加了工具,图就会多出一个 tools 节点,那时才是真正的 Agent。

23.4 怎么调用:输入是消息列表,输出也是

agent.invoke() 是最基本的同步调用,会阻塞到返回最终结果。

  • 输入:字典,通过 messages 字段传消息列表,形如 {"messages": [{"role": "user", "content": "..."}]};也可以直接传字符串列表,默认当 HumanMessage。
  • 输出:同样是字典,messages 里是完整的消息列表——中间可能经历多轮工具调用,所以不止两条。
response = agent.invoke({"messages": ["你好"]})
print(type(response))        # <class 'dict'>

# 结构大致是:
# {
#   "messages": [
#       HumanMessage(...),   # 用户问题
#       AIMessage(...),      # 可能要调工具
#       ToolMessage(...),    # 工具结果
#       AIMessage(...),      # 最终回答 ← 通常取这个
#   ]
# }

final_answer = response["messages"][-1].content

想更细地看过程,就把消息挨个 pretty_print()。这也是排查 Agent 问题最有效的手段:它到底调没调工具、参数对不对、模型怎么理解结果,全在这几条消息里。

另外,输入里可以放 system 角色来定义行为:

resp = agent.invoke({
    "messages": [
        {"role": "system", "content": "你是一个小学数学老师,耐心,幽默,讲解深入浅出"},
        {"role": "user", "content": "100 加上 50 等于多少?"},
    ]
})
print(resp["messages"][-1].content)

这种「每次调用塞一条 system」的写法适合临时试;线上更推荐用 create_agent(system_prompt=...) 固定下来,见下一篇。

23.5 小结

Agent 是「模型 + 工具 + 循环」的组合,1.x 里统一由 create_agent() 创建,返回一张 LangGraph 图;模型可传字符串或对象;调用输入输出都是 {"messages": [...]},最终答案取 [-1].content。

但光有模型只是个直连的问答机。下一篇接入工具,才会看到 start → model → tools → model → end 那张真正的图,以及工具调用、重试和那一堆「为什么它没调我的工具」的问题。

上一篇:TypedDict、JSON Schema 与 @dataclass——轻量结构的代价;系列第一篇:为什么需要 LangChain。

本文根据公开课程课件整理,并结合 LangChain 官方文档核对与补充。

本文来自 https://aimock.cn/blog,站内重新编排。
内容仅供学习交流,转载请注明出处。