LangChain从入门到精通(2)

上篇回顾:LangChain从入门到精通(上):基础实战篇

目录

  1. LangGraph工作流编排
  2. 多智能体协作(Multi-Agent)
  3. MCP模型上下文协议
  4. 实战案例:AI私厨
  5. 总结

1. LangGraph工作流编排

在上篇中,我们通过 create_agent 快速构建了具备检索和工具调用能力的Agent。你可能已经注意到,Agent内部的执行路径并非线性的------它可能多次调用工具、反复调用模型,甚至陷入循环。这就是为什么从LangChain 1.x开始,Agent底层已全面迁移至LangGraph。

LangGraph的核心价值:让开发者精确控制Agent的每一步执行,在保持自主性的同时大幅提升稳定性。

1.1 LangGraph三要素

LangGraph基于图(Graph)来编排AI工作流,其核心抽象仅三个:

要素 类比 职责
State(状态) 共享工作笔记本 定义所有节点共享的数据结构
Node(节点) 执行单元 处理State并返回更新
Edge(边) 控制流 决定执行顺序(普通边/条件边)

基础示例------简单的笑话生成器:

python 复制代码
from typing import TypedDict
from langgraph.graph import StateGraph, START, END

class JokeState(TypedDict):
    topic: str
    joke: str

def generate_joke(state: JokeState):
    msg = llm.invoke(f"写一个关于 {state['topic']} 的笑话")
    return {"joke": msg.content}

graph = (
    StateGraph(JokeState)
    .add_node("generate", generate_joke)
    .add_edge(START, "generate")
    .add_edge("generate", END)
    .compile()
)

1.2 七种核心编排模式

LangGraph将常见的AI工作流归纳为七种模式,覆盖了从简单到复杂的全部场景:

模式一:顺序执行(Prompt Chaining)

前一个LLM的输出作为后一个LLM的输入,类似流水线。可以在节点间加入验证门控------质量不达标时退回重做。

典型场景:写作流程(大纲→初稿→润色)、翻译+校对

模式二:并行执行(Parallelization)

多个节点同时执行,有两种实现方式:

  • 任务拆分:将一个大任务拆为多个子任务并行处理,最后汇总
  • 冗余投票:多个LLM运行相同任务,合并优化结果(提高准确率)
python 复制代码
# 三个节点从START并行出发
builder.add_edge(START, "joke")
builder.add_edge(START, "story")
builder.add_edge(START, "poem")
# 汇聚到聚合节点
builder.add_edge("joke", "aggregator")
builder.add_edge("story", "aggregator")
builder.add_edge("poem", "aggregator")
模式三:路由(Routing)

根据输入内容将请求分发到不同的处理节点,是实现Agent决策的核心机制。

典型场景:智能客服(售前/退款/退货路由)、按领域分类的知识问答

模式四:编排器-工作者(Orchestrator-Worker)

编排器(Orchestrator)动态将复杂任务拆解为多个子任务,通过 Send API 分发给工作节点(Worker)并行执行,最后合成器汇总结果。

与普通并行的本质区别:子任务数量是动态的、不确定的

python 复制代码
from langgraph.types import Send

def orchestrator(state: State):
    """为每个章节创建一个Worker"""
    return [Send("worker", {"section": section}) for section in state["sections"]]

典型场景:深度研究报告生成、批量文档处理

模式五:评估-优化循环(Evaluator-Optimizer)

生成器产出内容,评估器打分给出反馈,不达标则带着反馈重返生成器。形成"生成-评估-反馈-优化"的闭环。

与普通循环的区别:自带终止条件,仅在质量不达标时重复。

典型场景:文案优化、代码审查、翻译质量提升

模式六:子图嵌套(Subgraphs)

将复杂图拆分为多层子图,降低单个图的复杂度:

方式 说明
直接嵌入 子图作为父图节点,State自动映射
包装调用 在普通节点内手动调用子图,灵活控制State映射
python 复制代码
parent_graph.add_node("analysis_subgraph", compiled_subgraph)

典型场景:大规模工作流的模块化拆分、团队协作开发

模式选择指南
业务需求 推荐模式
步骤确定,前后依赖 Prompt Chaining
不同领域的分支处理 Routing
多个独立任务需要加速 Parallelization
复杂任务动态拆解 Orchestrator-Worker
需要迭代优化质量 Evaluator-Optimizer
流程过长需要拆解 Subgraphs

1.3 Think In LangGraph:客户支持Agent完整案例

上篇我们学会了用 create_agent 快速构建Agent,但面对分支路径、人工审核、多步操作等复杂场景时,我们需要LangGraph的精细控制。本节从零构建一个自动处理客服邮件的Agent,展示完整的LangGraph思维框架。

需求分析

假设我们需要处理的邮件场景:

场景 类型 处理策略
密码重置 简单问题(question) 查询文档 → 自动回复
PDF导出崩溃 Bug报告(bug) 创建工单 → 人工审核
重复扣款 紧急账单(billing) 直接人工处理
暗黑模式功能 功能请求(feature) 查文档 → 标记功能
API间歇性504 复杂技术(complex) 直接人工处理

核心观察:不同的问题走不同的处理路径------这正是需要**图(Graph)**而非链(Chain)的原因。

第一阶段:设计工作流

首先梳理业务流程,确定节点:

节点 职责 类型 决策?
读取邮件 解析邮件内容和发件人 Data节点
意图识别 LLM分类意图+紧急度,决定下一步路径 LLM节点
文档搜索 搜索知识库 Data节点
BUG跟踪 创建/更新Bug工单 Action节点
生成草稿 LLM生成回复草稿 LLM节点
人工审核 暂停等待人工审批 Human节点
发送 发送邮件回复 Action节点
第二阶段:设计State

State是所有节点共享的工作笔记本 。判断字段是否入State的原则:如果下游节点需要用它做决策或处理,就入State;如果能从其他字段推导出来,就不存。

python 复制代码
from typing import TypedDict, Literal

class EmailClassification(TypedDict):
    intent: Literal["question", "bug", "billing", "feature", "complex"]
    urgency: Literal["low", "medium", "high", "critical"]
    topic: str
    summary: str

class EmailAgentState(TypedDict):
    email_content: str
    sender_email: str
    email_id: str
    classification: EmailClassification | None
    search_results: list[str] | None
    customer_history: dict | None
    draft_response: str | None
第三阶段:构建Node

在LangGraph中,Node内部通过 Command 声明路由,避免了复杂的外部条件边:

python 复制代码
from langgraph.graph import StateGraph, START, END
from langgraph.types import Command, RetryPolicy

# 意图识别节点------内部决策路由
def classify_intent(state: EmailAgentState) -> Command[Literal["search_documentation", "bug_tracking", "draft_response"]]:
    classification = classifier_llm.invoke(f"""
        分析这封客户邮件并分类:
        邮件: {state['email_content']}
        发件人: {state['sender_email']}
        提供 intent(question/bug/billing/feature/complex)、urgency、topic、summary。
    """)

    if classification['intent'] in ['question', 'feature']:
        goto = "search_documentation"
    elif classification['intent'] == 'bug':
        goto = "bug_tracking"
    else:  # billing / complex → 生成草稿(后续判断是否人工审核)
        goto = "draft_response"

    return Command(update={"classification": classification}, goto=goto)

# 生成草稿节点------判断是否需要人工审核
def draft_response(state: EmailAgentState) -> Command[Literal["human_review", "send_reply"]]:
    # ... 调用LLM生成草稿 ...
    needs_review = (
        classification.get('urgency') in ['high', 'critical'] or
        classification.get('intent') in ['complex', 'billing']
    )
    goto = "human_review" if needs_review else "send_reply"
    return Command(update={"draft_response": response.content}, goto=goto)

异常处理策略------不同节点类型有不同的容错方案:

错误类型 谁来修复 策略
网络超时、限流 系统自修复 重试(RetryPolicy)
工具执行失败 LLM 错误信息写入State,重新调用LLM处理
输入信息缺失 用户 interrupt() 暂停,人工修复
重试耗尽 开发者 error_handler 兜底
第四阶段:构建图

由于节点内部已通过 Command 声明路由,图的边只需定义固定路径:

python 复制代码
workflow = StateGraph(EmailAgentState)
workflow.add_node("read_email", read_email)
workflow.add_node("classify_intent", classify_intent)
workflow.add_node("search_documentation", search_documentation,
                  retry=RetryPolicy(max_attempts=3))
workflow.add_node("bug_tracking", bug_tracking)
workflow.add_node("draft_response", draft_response)
workflow.add_node("human_review", human_review)
workflow.add_node("send_reply", send_reply)

# 最小边原则------只定义固定路径
workflow.add_edge(START, "read_email")
workflow.add_edge("read_email", "classify_intent")
workflow.add_edge("human_review", "send_reply")
workflow.add_edge("send_reply", END)

app = workflow.compile(checkpointer=InMemorySaver())

设计哲学小结:LangGraph的"最小边原则"------尽可能在Node内部用Command做路由决策,Graph层面只保留固定的串行边。这使图的拓扑结构极度简洁,将复杂的路由逻辑留给LLM去处理。


2. 多智能体协作(Multi-Agent)

在上篇中,我们构建的单Agent配合适量工具和精心设计的提示词,足以解决大部分问题。但当工具数量膨胀到10+、涉及多个领域时,单Agent的上下文窗口将不堪重负。此时就需要引入多Agent协作。

2.1 何时使用多Agent

当出现以下信号时,可考虑引入多Agent:

  1. 上下文膨胀:工具数量过多(如10+),单Agent上下文窗口难以容纳
  2. 职能分离:不同团队维护不同Agent(如机票组、酒店组)
  3. 效率需求:多个独立子任务需要并行执行

2.2 常见协作模式

模式 原理 特点
Subagents 主Agent将子Agent作为Tool协调调用 支持分布式开发、并行、多跳
Handoffs 随任务执行切换Agent,各Agent可直接与用户交互 灵活切换,适合多轮交互
Skills 单Agent按需加载不同技能/知识 上下文可控,避免膨胀
Router 路由Agent分类请求后导向专用Agent 天然并行,适合分流

这些模式并非互斥,实际开发中可灵活组合。

2.3 实战案例:婚礼策划多Agent

以婚礼策划为例,展示Subagents模式的具体实现。

需求梳理

婚礼策划Agent需完成三项核心任务:机票搜索(Travel)、场地搜索(Venue)、歌单策划(Playlist)。

选择多Agent而非单Agent的决策依据:

  • 工具过多:航班+场地+音乐数据库,上下文难以承受
  • 可并行:三个任务彼此独立,可同时执行提高效率
  • 便于扩展:未来新增"餐饮""摄影"等Agent不影响现有逻辑
实现方案

Step 1:定义三个子Agent

python 复制代码
# Travel Agent(调用MCP工具查询航班)
travel_agent = create_agent(
    model="deepseek-chat",
    tools=[flights_tool, time_tool],
    system_prompt="你是旅行规划专家..."
)

# Venue Agent(基于Tavily搜索场地)
venue_agent = create_agent(
    model="deepseek-chat",
    tools=[web_search],
    system_prompt="你是婚礼场地专家..."
)

# Playlist Agent(查询SQLite数据库)
playlist_agent = create_agent(
    model="deepseek-chat",
    tools=[query_playlist_db],
    system_prompt="你是音乐策划专家..."
)

Step 2:定义主Agent(Coordinator)

主Agent通过Tool调用子Agent,实现协调和汇总:

python 复制代码
from langchain.agents import AgentState

class WeddingState(AgentState):
    origin: str
    destination: str
    guest_count: str
    genre: str

# 将子Agent封装为Tool
@tool
async def search_flights(runtime: ToolRuntime) -> str:
    """搜索前往目的地的航班"""
    origin = runtime.state["origin"]
    destination = runtime.state["destination"]
    response = await travel_agent.ainvoke({
        "messages": [HumanMessage(content=f"从{origin}到{destination}的航班")]
    })
    return response['messages'][-1].content

@tool
def search_venues(runtime: ToolRuntime) -> str:
    """搜索婚礼场地"""
    query = f"在{ runtime.state['destination'] }适合{ runtime.state['guest_count'] }人的婚礼场地"
    response = venue_agent.invoke({"messages": [HumanMessage(content=query)]})
    return response['messages'][-1].content

# 主Agent------婚礼策划协调者
coordinator = create_agent(
    model="deepseek-chat",
    tools=[search_flights, search_venues, suggest_playlist, update_state],
    state_schema=WeddingState,
    system_prompt="你是婚礼策划协调员..."
)

Step 3:执行验证

运行后,主Agent先通过对话收集婚礼需求,更新State,然后并行调用三个子Agent:

复制代码
用户:我来自伦敦,想在巴黎举办100人的婚礼,爵士风格

1. update_state → origin=伦敦, destination=巴黎, guest_count=100, genre=爵士
2. 并行调用:
   → search_flights(查询伦敦→巴黎航班)
   → search_venues(搜索巴黎婚礼场地)
   → suggest_playlist(策划爵士歌单)
3. 汇总输出完整的婚礼策划方案

三个子Agent互不依赖,可并行执行,这是Subagents模式相较于串行处理的核心效率优势。


3. MCP模型上下文协议

多Agent协同需要接入多种外部服务------航班查询、时间获取、数据库操作等。在传统模式下,每接入一个服务都需要手动编写Tool代码,不仅工作量大,而且难以复用。MCP(Model Context Protocol)正是为解决这一问题而生。

3.1 什么是MCP

MCP是由Anthropic推出的开放标准,可理解为 "AI世界的USB接口协议"

在没有MCP的时代,每次接入外部服务都需要手动定义Tool,存在两个根本问题:

  • 复用性差:不同Agent有相同的工具需求,每次都重复定义
  • 协议不统一:千家服务接口各异,集成成本极高

MCP的解决思路是标准化

  • 外部服务遵循MCP协议提供接口(MCP Server)
  • AI应用(MCP Host)通过MCP Client统一对接,无需手动定义Tool

核心概念:

概念 职责 类比
MCP Server 提供MCP服务的应用(远程/本地) USB设备
MCP Client 连接Server,获取Tool信息供Host使用 USB驱动
MCP Host 协调多个Client的AI应用(如LangChain Agent) 操作系统

通信方式:

方式 延迟 适用场景
stdio 无网络延迟 本地MCP服务器
SSE(HTTP) 有网络延迟 远程MCP服务

3.2 连接外部MCP服务

LangChain通过 MultiServerMCPClient 统一管理多个MCP连接:

Time MCP(stdio方式------本地进程通信):

python 复制代码
from langchain_mcp_adapters.client import MultiServerMCPClient

client = MultiServerMCPClient({
    "time": {
        "transport": "stdio",
        "command": "uvx",
        "args": ["mcp-server-time", "--local-timezone=Asia/Shanghai"]
    }
})
tools = await client.get_tools()
# tools 包含: get_current_time, convert_time

agent = create_agent("deepseek-chat", tools)
response = await agent.ainvoke({
    "messages": [HumanMessage("现在几点了?")]
})

Kiwi MCP(SSE方式------远程HTTP通信):

python 复制代码
client = MultiServerMCPClient({
    "kiwi-com-flight-search": {
        "transport": "http",
        "url": "https://mcp.kiwi.com"
    }
})
tools = await client.get_tools()

agent = create_agent(
    model="deepseek-chat",
    tools=tools,
    system_prompt="You are a travel agent. If the user uses Chinese, use zh-cn as locale."
)

说明 :Kiwi擅长国际航班,国内航班可选用 VariFlight(飞友AI) 等MCP服务。

3.3 自定义MCP服务

团队内部也可以将自己的服务封装为MCP Server。使用FastMCP框架可以快速创建:

python 复制代码
from fastmcp import FastMCP

mcp = FastMCP("Math")

@mcp.tool()
def add(a: float, b: float) -> float:
    """Add two numbers"""
    return a + b

@mcp.tool()
def multiply(a: float, b: float) -> float:
    """Multiply two numbers"""
    return a * b

if __name__ == "__main__":
    mcp.run(transport="stdio")

LangChain侧连接自定义MCP:

python 复制代码
client = MultiServerMCPClient({
    "math": {
        "transport": "stdio",
        "command": "python",
        "args": ["math_mcp_server.py"]
    }
})
tools = await client.get_tools()

agent = create_agent("deepseek-chat", tools,
    system_prompt="使用数学工具回答问题。")
response = await agent.ainvoke({
    "messages": [HumanMessage("467和529的平方根之和是多少?")]
})

MCP使用流程小结:

复制代码
配置MultiServerMCPClient → 调用get_tools()获取工具 → 创建Agent并调用

自定义MCP Server可提供三类资源:

装饰器 用途 推荐场景
@mcp.tool() 工具 必备,实现核心功能
@mcp.resource() 静态资源 可选,类似知识库
@mcp.prompt() 预设提示词 可选,方便下游使用

4. 实战案例:AI私厨

现在,让我们通过一个完整的实战案例,将上、下篇的所有知识串联起来。

4.1 项目概述

AI私厨是一个基于LangChain多模态AI的食谱推荐应用:

  • 用户上传冰箱/食材照片
  • AI自动识别图片中的食材
  • 根据食材搜索相关食谱
  • 多维度评估排序(营养、难度、口味)
  • 输出结构化的食谱推荐报告

4.2 技术选型

组件 选型 说明
多模态模型 qwen3.5-plus 支持图片理解
搜索工具 TavilySearch Web搜索引擎
记忆持久化 SQLite + SqliteSaver 对话历史管理与中断恢复
后端框架 FastAPI 提供RESTful API和文件上传
文件存储 阿里云OSS 图片上传和URL获取

4.3 核心代码

python 复制代码
from langchain.chat_models import init_chat_model
from langchain_tavily import TavilySearch
from langchain.agents import create_agent
from langgraph.checkpoint.sqlite import SqliteSaver

# 1. 初始化搜索工具
web_search = TavilySearch(max_results=5, topic="general")

# 2. 初始化多模态模型
model = init_chat_model(
    model="qwen3.5-plus",
    model_provider="openai",
    base_url=os.getenv("DASHSCOPE_BASE_URL"),
    api_key=os.getenv("DASHSCOPE_API_KEY")
)

# 3. 初始化记忆
checkpointer = SqliteSaver(
    sqlite3.connect("db/personal_chief.db", check_same_thread=False)
)
checkpointer.setup()

# 4. 系统提示词
system_prompt = """你是一名私人厨师。收到食材照片或清单后:
1. 识别和评估食材
2. 调用web_search搜索对应食谱
3. 从营养和难度两个维度打分排序
4. 输出结构化的食谱推荐报告(含步骤、配料、预估时间)"""

# 5. 创建Agent
agent = create_agent(
    model=model,
    tools=[web_search],
    checkpointer=checkpointer,
    system_prompt=system_prompt
)

4.4 多模态消息处理

python 复制代码
from langchain.messages import HumanMessage

# 推荐使用OSS URL而非base64,避免请求体过大
message = HumanMessage(content=[
    {"type": "image", "url": oss_image_url},
    {"type": "text", "text": "帮我看看这些食材能做些什么?"}
])

response = agent.invoke(
    {"messages": [message]},
    config={"configurable": {"thread_id": "chef-001"}}
)

4.5 部署方案

方案一------LangGraph CLI部署:

创建 langgraph.json 配置文件,执行 langgraph dev 一键启动,自带RESTful API和可视化调试界面。

方案二------自定义FastAPI服务:

提供更灵活的控制,包含对话接口、会话管理接口和文件上传接口,适合与现有系统集成。


5. 总结

5.1 技术栈全景图

复制代码
LangChain生态全景

├── LangChain Core(核心框架)
│   ├── 模型调用(ChatModels + with_structured_output)
│   ├── 工具系统(Tools + MCP)
│   ├── 消息系统(Messages + 多模态)
│   ├── 记忆管理(Checkpointer)
│   └── 中间件(Middleware + HITL)
│
├── RAG(检索增强生成)
│   ├── 知识库构建(加载 → 切分 → 向量化 → 存储)
│   ├── 检索优化(HyDE / Multi-Hop / 多路召回 + RRF)
│   ├── 重排序(Cross-Encoder / MMR)
│   └── 评估体系(RAGAS:Faithfulness / Precision / Recall)
│
├── LangGraph(工作流编排)
│   ├── 三要素(State / Node / Edge)
│   ├── 七种编排模式(Chaining / Parallel / Routing 等)
│   └── 最小边原则(Command内部路由)
│
├── Multi-Agent(多智能体协作)
│   ├── Subagents / Handoffs / Skills / Router
│   └── 实战:婚礼策划协调者模式
│
└── 工具链
    ├── LangSmith(调试 / 监控 / 部署)
    ├── MCP协议(Time / Kiwi / 自定义Math Server)
    ├── FastAPI(后端服务)
    └── LangGraph CLI(一键部署)

5.2 实践

  1. 从简单开始,渐进式演化:优先使用单Agent + 适量Tool。仅当上下文膨胀或需要函数分离时,才引入多Agent或LangGraph。过度设计是AI应用工程化的常见陷阱。

  2. 善用中间件构建企业级能力:PII脱敏是数据合规的硬性要求;模型降级是生产环境可用性的保证;HITL(人工审核)在高风险场景中不可或缺。

  3. RAG优化要体系化:Demo级RAG只需"加载→切分→检索"三步,但工业级RAG需要查询优化(重写/HyDE)、多路召回(稠密+稀疏)、RRF融合和Cross-Encoder重排序的完整链路。

  4. 多模态用URL而非base64:大尺寸图片的base64编码会占用大量Token,显著增加成本和延迟。优先使用对象存储URL。

  5. 尽早接入LangSmith:从开发第一天就启用链路追踪。当Agent行为不符合预期时,LangSmith的执行详情页是debug的首要入口。

  6. 选择正确的编排模式:根据业务特性选择LangGraph编排模式。大多数场景下,传统Chain + Routing就足够,不必追求Evaluator-Optimizer等高级模式。

  7. 用MCP拥抱标准化:新项目优先考虑MCP协议接入外部服务,而非手动编写Tool。这既降低维护成本,也为未来的可移植性做好准备。

LangChain生态仍在快速演进,以下方向值得持续关注:

  • Agentic RAG的深化:从"检索→生成"的固定模式,演进为Agent自主决定检索时机、检索策略和结果利用方式,使RAG系统真正具备"思考能力"。

  • MCP协议的生态化:随着越来越多服务商提供MCP接口,"AI应用连接一切"的开发成本将大幅降低,标准化的Tool市场正在形成。

  • Multi-Agent编排的成熟:从手动编写协调逻辑,演进为框架级的多Agent编排方案,支持Agent间更灵活的消息传递和任务协调。

  • 生产级可观测性:LangSmith等平台将持续深化,从Trace级别演进为融合Metrics、Logging、Alerting的完整可观测性体系。

上篇回顾:LangChain从入门到精通(上):基础实战篇

相关推荐
kishu_iOS&AI2 小时前
LLM —— LangChain
人工智能·langchain
老梁agent3 小时前
Agent 返回 JSON 而不是闲聊:LangChain4j 结构化输出实战
物联网·langchain
打小就很皮...4 小时前
基于 Python + LangChain + React 实现智能发票识别与验真系统实战
前端·react.js·langchain·ocr·发票识别
颜酱17 小时前
让 Agent 不再失忆:LangChain 短期记忆实战
langchain·agent
装不满的克莱因瓶19 小时前
了解 LangChain 中的 LLM 与 ChatModel 的差异
人工智能·python·ai·langchain·llm·agent·chatmodel
颜酱20 小时前
LangChain 工具调用:从原理、入门到落地
langchain·llm
swipe20 小时前
别再把关系库和向量库拆开了:PostgreSQL 搭建 AI 长期记忆层实战
面试·langchain·llm
喵叔哟1 天前
Week 3 -- Day 1:LangGraph 入门
langchain
wuhen_n1 天前
RAG 实战:语义检索 + 大模型生成精准问答
前端·langchain·ai编程