LangGraph 入门笔记

基于 LangChain + LangGraph 构建 AI Agent 的核心概念总结


一、第一次 LLM 调用

LangChain 提供统一的模型接口,可以无缝切换 OpenAI、Anthropic 等不同提供商:

from langchain.chat_models import init_chat_model

model = init_chat_model("openai:gpt-4o-mini")

response = model.invoke("什么是 LangGraph?")
response.pretty_print()  # 格式化输出模型回复

要点:

  • init_chat_model("provider:model_name") 统一入口,无厂商锁定
  • .invoke() 发送请求,返回 AIMessage 对象
  • .pretty_print() 格式化显示内容,比直接 print 更易读

二、消息(Messages)

消息是 LangChain 中对话的基本单元,分为四种类型:

类型 说明
SystemMessage 设置模型行为的指令
HumanMessage 用户输入
AIMessage 模型回复
ToolMessage 工具执行结果
from langchain.messages import HumanMessage, SystemMessage

messages = [
    SystemMessage(content="你是一个简洁的技术助手。"),
    HumanMessage(content="什么是 Agent?"),
]

response = model.invoke(messages)

# 多轮对话:把回复追加到历史,继续提问
messages.append(response)
messages.append(HumanMessage(content="举个例子?"))
response2 = model.invoke(messages)

要点: 把消息列表不断追加,就实现了多轮对话(模型能记住上下文)。


三、工具(Tools)

LLM 本身无法访问外部数据,@tool 装饰器让普通 Python 函数变成 LLM 可调用的工具:

from langchain_core.tools import tool

@tool
def get_weather(latitude: float, longitude: float) -> str:
    """获取指定坐标的天气信息。"""
    # 调用天气 API...
    return "晴天,22°C"

@tool
def search_movies(genre: str) -> str:
    """按类型搜索电影。"""
    return "星际穿越, 降临, 银翼杀手2049"

将工具绑定给模型,模型会决定何时调用:

model_with_tools = model.bind_tools([get_weather, search_movies])

response = model_with_tools.invoke("北京天气怎么样?")
print(response.tool_calls)  # 模型返回想调用的工具名+参数

工具调用完整流程:

用户提问
  → 模型返回 tool_calls(工具名 + 参数)
  → 执行工具获取结果
  → 把结果包装成 ToolMessage 传回模型
  → 模型综合输出最终回答

四、Agent:自动化工具调用循环

手动处理工具调用循环很繁琐,create_agent() 约 10 行代码搞定:

from langchain.agents import create_agent

agent = create_agent(
    model=model,
    tools=[get_weather, search_movies],
    system_prompt="你是一个能查天气、推荐电影的助手。"
)

result = agent.invoke({
    "messages": [HumanMessage(content="北京天气?推荐几部科幻电影。")]
})

for msg in result["messages"]:
    msg.pretty_print()

Agent 自动完成:分析请求 → 并行调用多个工具 → 综合结果输出。

create_agent() vs 自定义 LangGraph:

create_agent() 自定义 LangGraph
代码量 ~10 行 30+ 行
流程 固定 ReAct 循环 完全自定义
适用场景 快速原型、简单问答 审批流、多 Agent、复杂业务

五、记忆(Memory)

默认每次调用都是独立的,加 checkpointer 实现跨轮记忆:

from langgraph.checkpoint.memory import MemorySaver
import uuid

checkpointer = MemorySaver()

agent_with_memory = create_agent(
    model=model,
    tools=[get_weather, search_movies],
    system_prompt="你是一个有用的助手。",
    checkpointer=checkpointer
)

# 用 thread_id 标识同一段对话
config = {"configurable": {"thread_id": str(uuid.uuid4())}}

# 第一轮
agent_with_memory.invoke({"messages": [{"role": "user", "content": "我叫 Alice,喜欢科幻片。"}]}, config=config)

# 第二轮(Agent 记得上文)
result = agent_with_memory.invoke({"messages": [{"role": "user", "content": "我叫什么名字?"}]}, config=config)

要点:

  • 同一个 thread_id = 同一段对话,共享记忆
  • 不同 thread_id = 不同对话,互相隔离
  • thread_id 可以用 uuid.uuid4() 或任意唯一字符串

六、流式输出(Streaming)

# 查看每个 Agent 步骤(适合调试)
for chunk in agent.stream({"messages": [...]}, stream_mode="updates"):
    for node_name, data in chunk.items():
        print(f"步骤: {node_name}")

# 逐 Token 流式输出(类似 ChatGPT 打字效果)
for token, metadata in agent.stream({"messages": [...]}, stream_mode="messages"):
    if metadata.get("langgraph_node") == "model":
        for block in token.content_blocks:
            if block.get("type") == "text":
                print(block["text"], end="", flush=True)

七、从零构建 ReAct Agent

理解 LangGraph 三大原语:State(状态)、Node(节点)、Edge(边)

State — 对话数据容器

from typing_extensions import TypedDict
from typing import Annotated, List
from langgraph.graph.message import AnyMessage, add_messages

class State(TypedDict):
    # add_messages 是 reducer,表示新消息追加而非覆盖
    messages: Annotated[List[AnyMessage], add_messages]

继承 TypedDict 的原因:LangGraph 需要读取字段定义和 reducer 来管理状态更新。

Node — 处理逻辑单元

from langgraph.prebuilt import ToolNode
from langchain.messages import SystemMessage

# 工具节点:自动根据函数名匹配并执行工具
tools = [search_movies, get_weather]
tool_node = ToolNode(tools)  # 内部建立 {"get_weather": fn, ...} 字典,按名字匹配执行

# 主助手节点
def assistant(state: State):
    system_prompt = "你是一个能查天气、推荐电影的助手。"
    all_messages = [SystemMessage(system_prompt)] + state["messages"]
    response = model_with_tools.invoke(all_messages)
    return {"messages": [response]}

Edge — 控制流转

def should_continue(state: State):
    last_message = state["messages"][-1]
    if last_message.tool_calls:
        return "continue"  # 有工具调用 → 去执行工具
    else:
        return "end"       # 直接回答 → 结束

编译图

from langgraph.graph import StateGraph, START, END

builder = StateGraph(State)

# 添加节点
builder.add_node("assistant", assistant)
builder.add_node("tool_node", tool_node)

# 添加边
builder.add_edge(START, "assistant")
builder.add_conditional_edges(
    "assistant",
    should_continue,
    {
        "continue": "tool_node",  # should_continue 返回 "continue" → 去 tool_node
        "end": END,               # should_continue 返回 "end" → 结束
    }
)
builder.add_edge("tool_node", "assistant")  # 工具执行后返回 LLM

agent = builder.compile(name="agent")

执行流程:

START → assistant → (有工具调用?) → tool_node → assistant → ... → END
                  ↘ (直接回答)  → END

小结

概念 作用
init_chat_model 统一模型接口,支持多提供商
Messages 对话历史的基本单元
@tool 把 Python 函数变为 LLM 可调用工具
create_agent() 快速创建 ReAct Agent
MemorySaver 基于 thread_id 的对话记忆
StateGraph 自定义 Agent 的有向图框架
ToolNode 自动匹配执行工具的预构建节点
条件边 根据运行时状态动态路由流程
posted @ 2026-05-18 16:55  江鸟Dev  阅读(8)  评论(0)    收藏  举报