LangChain与LangGraph深度解析:从智能体搭建到工作流编排
前言
随着大语言模型(LLM)技术的快速发展,AI智能体(Agent)已成为构建复杂AI应用的核心范式。LangChain作为最流行的LLM应用开发框架,提供了从基础模型调用到复杂智能体构建的全套工具链。而LangGraph作为其工作流编排引擎,进一步将智能体开发推向工程化、可控化的新高度。本文将深入探讨LangChain的核心架构、智能体搭建过程,以及如何通过LangGraph实现复杂工作流编排,并分析其与Harness Engineering的相似性。
一、LangChain:从基础调用到智能体构建
1.1 LangChain的层次化架构
LangChain采用层次化设计,从最底层的API调用到最高层的智能体应用,提供了不同抽象级别的接口:
# 最底层:原始API调用("砖块")
client = openai.OpenAI(api_key="sk-...")
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "1+1等于几?"}]
)
# 中间层:模型封装类("预制砖墙")
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(api_key="sk-...", model="gpt-4o-mini")
response = llm.invoke("1+1等于几?")
# 高层:统一工厂函数("施工队长")
from langchain.chat_models import init_chat_model
llm = init_chat_model("openai:gpt-4o-mini") # 切换模型只需改字符串
# 最高层:智能体构建("设计师")
from langchain.agents import create_agent
agent = create_agent(model=llm, tools=[search_tool])
1.2 智能体的核心能力
一个完整的AI智能体通常具备三大核心能力:
| 能力 | 说明 | 类比 |
|---|---|---|
| 感知(Perception) | 获取环境信息和反馈 | 眼睛、耳朵 |
| 决策(Decision) | 思考做什么、怎么做 | 大脑 |
| 行动(Action) | 执行具体操作 | 手、脚 |
与传统LLM相比,AI智能体具有显著优势:
| 特性 | 普通 LLM | AI Agent |
|---|---|---|
| 交互模式 | 一问一答,用户驱动 | 自主执行,目标驱动 |
| 能力边界 | 只有模型内置能力 | 可通过工具扩展能力 |
| 记忆 | 会话上下文(有限) | 短期 + 长期记忆 |
| 规划 | 无(或需用户引导) | 自主任务分解与规划 |
| 反馈循环 | 无(单次生成) | 观察-思考-行动循环 |
1.3 智能体搭建实战:客服机器人示例
以下是一个完整的LangChain智能客服机器人实现:
import os
from dotenv import load_dotenv
from typing import Annotated
from langchain.tools import tool
from langchain.agents import create_agent
from langchain.agents.middleware import before_model, after_model
from langchain.chat_models import init_chat_model
from langchain.messages import HumanMessage
from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langgraph.checkpoint.sqlite import SqliteSaver
# ========== 1. 准备知识库 ==========
knowledge_base = [
"菜鸟教程 RUNOOB 创立于 2013 年,是国内领先的免费编程学习平台。",
"平台提供 300+ 套教程,涵盖 Python、Java、HTML、CSS、JavaScript 等。",
"Python3 基础教程共 30 章,累计学习人次超 500 万。课程完全免费。",
"VIP 会员费用为 ¥99/月,¥799/年,包含视频课程和一对一答疑服务。",
"退款政策:购买 7 天内且在 3 节课以内可全额退款。",
"平台支持在线编程环境,无需安装任何软件即可编写运行代码。",
"客服工作时间:周一至周五 9:00-18:00,周末 10:00-16:00。",
]
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
chunks = RecursiveCharacterTextSplitter(
chunk_size=200, chunk_overlap=30
).create_documents(knowledge_base)
vector_store = Chroma.from_documents(chunks, embeddings)
retriever = vector_store.as_retriever(search_kwargs={"k": 3})
# ========== 2. 定义工具 ==========
@tool
def search_kb(query: str) -> str:
"""搜索菜鸟教程知识库,获取关于平台、课程、政策等官方信息。"""
docs = retriever.invoke(query)
if not docs:
return "未找到相关信息,建议转接人工客服。"
return "\n".join(f"- {doc.page_content}" for doc in docs)
@tool
def query_order(order_id: str) -> str:
"""根据订单号查询订单状态和详情。"""
orders_db = {
"ORD-2024-001": {"user": "小明", "item": "VIP 年费会员",
"amount": 799, "status": "已完成", "date": "2024-01-15"},
"ORD-2024-002": {"user": "小明", "item": "Python 实战课程",
"amount": 199, "status": "配送中", "date": "2024-03-20"},
}
order = orders_db.get(order_id.upper())
if not order:
return f"未找到订单 {order_id}。请确认订单号是否正确。"
return (f"订单 {order_id}:{order['item']} | "
f"金额 ¥{order['amount']} | "
f"状态 {order['status']} | "
f"日期 {order['date']}")
@tool
def transfer_to_human(reason: str) -> str:
"""将用户转接给人工客服。"""
from langgraph.types import interrupt
approval = interrupt({
"action": "transfer_to_human",
"reason": reason,
"message": f"用户请求转接人工客服,原因:{reason}。是否转接?"
})
if approval.get("confirmed"):
return (f"已为您转接人工客服,预计等待 {approval.get('wait_time', 3)} 分钟。"
f"工单号:TK-{approval.get('ticket_id', 'N/A')}")
return "转接已取消,我继续为您服务。"
# ========== 3. 定义 Middleware ==========
@before_model
def content_guard(state, runtime):
"""过滤用户输入中的不当内容"""
last_msg = state["messages"][-1] if state.get("messages") else None
if not last_msg:
return None
content = str(getattr(last_msg, 'content', ''))
blocked = ["黄X", "X博", "违法"]
for word in blocked:
if word in content:
return {
"jump_to": "end",
"messages": [HumanMessage(content="抱歉,我不能处理这个请求。")]
}
return None
@after_model
def auto_signature(state, runtime):
"""自动追加客服签名"""
msgs = state.get("messages", [])
if not msgs:
return None
last = msgs[-1]
if last.type == "ai" and last.content and not (
hasattr(last, 'tool_calls') and last.tool_calls
):
from langchain.messages import AIMessage
return {"messages": [AIMessage(
content=last.content
+ "\n\n---\n菜鸟教程 RUNOOB 客服中心 | 工作时间 9:00-18:00"
)]}
return None
# ========== 4. 创建 Agent ==========
checkpointer = SqliteSaver.from_conn_string("customer_service.db")
model = init_chat_model("deepseek:deepseek-v4-flash", temperature=0)
agent = create_agent(
model=model,
tools=[search_kb, query_order, transfer_to_human],
middleware=[content_guard, auto_signature],
checkpointer=checkpointer,
system_prompt="""你是菜鸟教程 RUNOOB 的智能客服"小菜"。
## 你的职责
1. 热情接待每一位用户,用"您"称呼
2. 关于平台信息、课程内容、政策等问题,使用 search_kb 查询
3. 关于订单查询,使用 query_order 工具
4. 遇到无法解决的问题,使用 transfer_to_human 转接人工
## 行为准则
- 回答简洁,每次 2-3 句话
- 不知道的就查询知识库,查不到就诚实告知
- 保持友好亲切的语气""",
)
# ========== 5. 对话接口 ==========
def chat(thread_id: str, message: str) -> str:
"""处理用户消息并返回回复"""
config = {"configurable": {"thread_id": thread_id}}
result = agent.invoke(
{"messages": [HumanMessage(content=message)]},
config=config,
)
state = agent.get_state(config)
if state.tasks and state.tasks[0].interrupts:
interrupt_info = state.tasks[0].interrupts[0].value
return f"[需要审批] {interrupt_info.get('message', '')}"
return result["messages"][-1].content
二、LangGraph:工作流编排的工程化框架
2.1 LangGraph的核心价值
LangGraph 的核心价值,就是为"大模型调用智能体"这个充满不确定性的过程,套上了一层工程化的稳定外壳,让它从一次"危险的跳跃",变成一次"可控的飞行"。本质上就是一个让"大模型调用智能体"这个过程变得可控、稳定、可观测的工程化框架。
| 特性 | 传统 LLM Chain | LangGraph |
|---|---|---|
| 工作流结构 | 线性,单向执行 | 图结构,支持循环 |
| 状态管理 | 需手动管理 | 内置状态持久化 |
| 条件路由 | 实现复杂 | 原生支持 |
| 人机协作 | 需要额外开发 | 内置支持 interrupt |
| 多 Agent 协调 | 实现困难 | 一流支持 |
| 调试工具 | 有限 | LangGraph Studio |
2.2 LangGraph核心概念
Graph(图)
Graph 是整个工作流的蓝图,定义了 Agent 的完整逻辑结构。它由节点(Nodes)和边(Edges)组成。
State(状态)
State 是贯穿整个图的共享数据结构。每个节点可以读取和更新 State,更新后的 State 会传递给下一个节点。
Nodes(节点)
节点是普通的 Python 函数,接收当前 State,返回更新后的 State(部分字段)。
Edges(边)
边定义节点之间的流转方式,支持条件路由和并行执行。
2.3 基础LangGraph示例
from langgraph.graph import StateGraph, START, END
from typing import TypedDict
# Step 1: 定义 State
class SimpleState(TypedDict):
message: str
processed: bool
# Step 2: 定义节点函数
def greet_node(state: SimpleState) -> dict:
"""欢迎节点:生成问候语"""
print(f"[greet_node] 收到消息: {state['message']}")
return {"message": f"你好!{state['message']}"}
def process_node(state: SimpleState) -> dict:
"""处理节点:标记为已处理"""
print(f"[process_node] 处理消息: {state['message']}")
return {"processed": True}
# Step 3: 构建图
builder = StateGraph(SimpleState)
# 添加节点
builder.add_node("greet", greet_node)
builder.add_node("process", process_node)
# 添加边,指定顺序
builder.add_edge(START, "greet")
builder.add_edge("greet", "process")
builder.add_edge("process", END)
# Step 4: 编译图
graph = builder.compile()
# Step 5: 运行
result = graph.invoke({
"message": "世界",
"processed": False
})
print(f"\n最终结果: {result}")
2.4 高级特性:条件路由与工具调用
from langgraph.graph import StateGraph, MessagesState
from langgraph.prebuilt import ToolNode, tools_condition
from typing import Annotated
from langgraph.graph.message import add_messages
# 定义状态
class AgentState(TypedDict):
messages: Annotated[list, add_messages]
user_id: str
session_id: str
error: str | None
retry_count: Annotated[int, lambda x, y: x + y]
# 定义工具
@tool
def search_weather(city: str) -> str:
"""查询城市天气"""
return f"{city}的天气:晴,25°C"
@tool
def search_stock(code: str) -> str:
"""查询股票信息"""
return f"{code}当前价格:100元"
# 构建智能体工作流
builder = StateGraph(AgentState)
# 添加LLM节点
def llm_node(state: AgentState) -> dict:
"""调用LLM决定下一步行动"""
# 实际实现中会调用大模型
last_msg = state["messages"][-1].content if state["messages"] else ""
if "天气" in last_msg:
return {"messages": [{"role": "assistant", "content": f"调用天气工具查询{last_msg}"}]}
elif "股票" in last_msg:
return {"messages": [{"role": "assistant", "content": f"调用股票工具查询{last_msg}"}]}
else:
return {"messages": [{"role": "assistant", "content": "我无法处理这个问题"}]}
# 添加工具节点
tools = [search_weather, search_stock]
builder.add_node("llm", llm_node)
builder.add_node("tools", ToolNode(tools))
# 添加条件边
builder.add_edge(START, "llm")
builder.add_conditional_edges(
"llm",
tools_condition, # 内置路由函数
{
"tools": "tools", # 有工具调用 -> 执行工具
END: END # 无工具调用 -> 结束
}
)
builder.add_edge("tools", "llm") # 工具执行后返回LLM节点
graph = builder.compile()
2.5 LangGraph Studio:可视化调试
LangGraph Studio 是官方提供的可视化开发环境,让你实时查看 Agent 的执行过程:
# 安装 LangGraph CLI
pip install langgraph-cli -i https://mirrors.aliyun.com/pypi/simple/
# 创建项目配置文件 langgraph.json
{
"dependencies": ["."],
"graphs": {
"my_agent": "./my_agent.py:graph"
},
"env": ".env"
}
# 启动开发服务器
langgraph dev
启动后访问 http://localhost:8123 即可在浏览器中使用 LangGraph Studio,主要功能包括:
- 实时可视化:图形化展示节点执行过程
- 状态检查:在任意节点暂停查看当前 State
- 时间旅行:回放历史执行步骤
- 热重载:修改代码后自动更新图结构
三、LangGraph与Harness Engineering的相似性
3.1 工程化思维的一致性
LangGraph 与 Harness Engineering 在核心理念上高度相似,都强调将复杂、不确定的过程转化为可控、可观测的工程化系统:
| 维度 | LangGraph | Harness Engineering |
|---|---|---|
| 核心目标 | 将大模型调用过程工程化 | 将软件交付过程工程化 |
| 不确定性处理 | 通过图结构管理LLM不确定性 | 通过流水线管理部署不确定性 |
| 状态管理 | 内置状态持久化与检查点 | 部署状态追踪与回滚 |
| 可视化 | LangGraph Studio 可视化调试 | Harness UI 可视化流水线 |
| 可观测性 | 执行轨迹追踪与监控 | 部署过程监控与告警 |
| 人机协作 | 内置 interrupt 机制 | 人工审批节点 |
3.2 工作流编排的类比
3.3 关键相似点分析
1. 图结构的工作流定义
- LangGraph:使用节点和边定义智能体执行流程
- Harness:使用阶段和步骤定义部署流水线
- 共同点:都将复杂流程分解为可组合、可重用的单元
2. 状态管理与持久化
- LangGraph:
SqliteSaver、RedisSaver等检查点机制 - Harness:部署状态数据库、执行历史记录
更多推荐

所有评论(0)