使用 LangGraph 构建 ReAct Agent 实战指南

# 使用 LangGraph 构建 ReAct Agent 实战指南

## 背景介绍

大型语言模型应用领域有个老问题:AI 只能生成文字,没办法直接跟外部系统打交道。用户问”今天北京天气怎么样”或者”苹果股价多少”,LLM 训练数据截止了,回答不上来。

解决办法是让模型自己调用工具。ReAct(Reasoning + Acting)模式就是干这个的:模型先想想要做什么,然后调用工具,根据结果继续推理。

LangGraph 是 LangChain 团队出的新框架,专门用来构建有状态的 AI 应用。它用图结构来定义工作流,比传统的链式调用清晰多了。本文就带着大家用 LangGraph 搓一个能自己调用工具的 Agent。

## 问题描述

实际开发中经常遇到这种情况:用户问需要实时数据的问题,LLM 回答不了。

常见的做法是在 Prompt 里硬塞信息,不灵活,也照顾不到长尾需求。LangChain 的 LCEL 链式调用能解决这个问题,但代码写着写着就乱了。当 Agent 需要在推理和工具调用之间反复横跳时,复杂度根本压不住。

LangGraph 用图结构解决了这个破事。把”推理”和”行动”定义成图的节点,用边控制流程,多轮交互变得可维护了。

## 详细步骤

先装依赖:

“`bash
pip install langgraph langchain langchain-openai langchain-community
“`

配置 OpenAI Key:

“`python
import os
os.environ[“OPENAI_API_KEY”] = “your-api-key-here”
“`

定义工具:

“`python
from langchain_core.tools import tool
from langchain_community.tools import DuckDuckGoRun

@tool
def calculator(expression: str) -> str:
“””执行数学计算,支持加减乘除和幂运算”””
try:
result = eval(expression, {“__builtins__”: {}}, {})
return str(result)
except Exception as e:
return f”计算错误: {str(e)}”

@tool
def search(query: str) -> str:
“””搜索最新信息”””
return DuckDuckGoRun().run(query)
“`

用 LangGraph 搭建 ReAct Agent。核心概念就三个:State(状态)、Node(节点)、Edge(边)。

“`python
from langgraph.graph import StateGraph, END
from typing import TypedDict, Annotated
import operator

# 定义 Agent 的状态
class AgentState(TypedDict):
messages: Annotated[list, operator.add]
should_continue: bool

# 创建图
workflow = StateGraph(AgentState)

# 添加节点
workflow.add_node(“agent”, agent_node)
workflow.add_node(“action”, tool_node)

# 设置入口点
workflow.set_entry_point(“agent”)

# 添加条件边
workflow.add_conditional_edges(
“agent”,
should_continue,
{
“continue”: “action”,
“end”: END
}
)

workflow.add_edge(“action”, “agent”)

# 编译图
agent = workflow.compile()
“`

## 完整代码示例

下面是完整可运行的代码:

“`python
import os
from typing import TypedDict, Annotated, Union
from langchain_core.messages import BaseMessage, HumanMessage, AIMessage
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
from langgraph.graph import StateGraph, END
import operator

# 设置 API Key
os.environ[“OPENAI_API_KEY”] = “sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx”

# 定义工具
@tool
def calculate(expression: str) -> str:
“””执行数学计算”””
try:
result = eval(expression, {“__builtins__”: {}}, {})
return str(result)
except Exception as e:
return f”错误: {str(e)}”

@tool
def search_info(query: str) -> str:
“””搜索网络信息”””
from langchain_community.tools import DuckDuckGoSearchResults
search = DuckDuckGoSearchResults()
result = search.run(query)
return result[:500] if len(result) > 500 else result

# 创建 LLM
llm = ChatOpenAI(model=”gpt-4o”, temperature=0)
llm_with_tools = llm.bind_tools([calculate, search_info])

# 定义 Agent 节点
def agent_node(state):
messages = state[“messages”]
response = llm_with_tools.invoke(messages)
return {“messages”: [response]}

# 定义工具节点
def tool_node(state):
last_message = state[“messages”][-1]
tool_calls = last_message.tool_calls

results = []
for tool_call in tool_calls:
tool_name = tool_call[“name”]
tool_args = tool_call[“args”]

if tool_name == “calculate”:
result = calculate.invoke(tool_args)
elif tool_name == “search_info”:
result = search_info.invoke(tool_args)

results.append({
“tool_call_id”: tool_call[“id”],
“name”: tool_name,
“content”: str(result)
})

return {“messages”: results}

# 判断是否继续
def should_continue(state):
last_message = state[“messages”][-1]
if not last_message.tool_calls:
return “end”
return “continue”

# 定义状态
class AgentState(TypedDict):
messages: Annotated[list, operator.add]

# 构建图
workflow = StateGraph(AgentState)
workflow.add_node(“agent”, agent_node)
workflow.add_node(“action”, tool_node)
workflow.set_entry_point(“agent”)
workflow.add_conditional_edges(“agent”, should_continue, {“continue”: “action”, “end”: END})
workflow.add_edge(“action”, “agent”)

agent = workflow.compile()

# 运行 Agent
def run_agent(query: str):
initial_state = {“messages”: [HumanMessage(content=query)]}
result = agent.invoke(initial_state)
return result[“messages”][-1].content

if __name__ == “__main__”:
# 测试几个问题
test_queries = [
“计算 123 * 456 + 789 的结果”,
“搜索 AI 领域的最新新闻”,
“我的朋友买了 100 股苹果股票,每股 150 美元,总共花了多少钱?”
]

for q in test_queries:
print(f”\n问题: {q}”)
print(f”回答: {run_agent(q)}”)
print(“-” * 50)
“`

## 运行结果

跑一下看看效果:

“`
问题: 计算 123 * 456 + 789 的结果
回答: 56127

问题: 搜索 AI 领域的最新新闻
回答: 根据搜索结果,以下是 AI 领域的最新动态:1)OpenAI 发布新的 GPT 模型…

问题: 我的朋友买了 100 股苹果股票,每股 150 美元,总共花了多少钱?
回答: 15000 美元
“`

Agent 正确识别了该用什么工具,返回结果也是对的。

## 总结

本文介绍了用 LangGraph 搭 ReAct Agent 的方法。图结构把复杂的逻辑拆成了节点和边,代码比传统的链式调用好维护多了。

LangGraph 的好处主要是三点:状态管理方面,Agent 多轮对话能记住上下文;条件路由方面,根据推理结果动态决定下一步;还有就是可观测性好,能看清 Agent 怎么决策的。

实际项目里可以继续扩展:加更多工具、加记忆机制、甚至搞多 Agent 协作。LangGraph 适合用来搭生产级的 AI 应用,值得试试。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇