LangGraph 基础小项目:构建一个带状态的搜索助手 Agent
·
引言:为什么“搜索助手”是最适合入门 LangGraph 的项目?
前面我们已经学习了:
- State(状态管理)
- Node(节点)
- Edge(边)
- Conditional Edge(条件分支)
- ReAct 循环
- Studio 调试
但很多人学完概念后,还是会卡在:
真正项目到底怎么组合?
所以这一篇,我们做一个:
完整 LangGraph 小项目
目标:
构建一个“带状态”的搜索助手 Agent。
它可以:
- 接收用户问题
- 判断是否需要搜索
- 调用搜索 Tool
- 记住上下文
- 根据搜索结果继续回答
这会是你第一个:
真正完整的 LangGraph Agent
一、项目效果演示
用户输入
OpenAI 最近有什么新闻?
Agent 执行流程
START
↓
Agent Node
↓
判断是否需要搜索
↓
Search Tool
↓
Agent Node
↓
Final Answer
输出示例
OpenAI 最近发布了新的 GPT 模型,并加强了 Agent 平台能力。
二、项目结构设计
这个项目会包含:
| 模块 | 作用 |
|---|---|
| State | 保存 messages / search_results |
| Agent Node | 负责推理 |
| Search Tool Node | 执行搜索 |
| Conditional Edge | 判断是否需要搜索 |
| MemorySaver | 保存多轮上下文 |
三、安装依赖
pip install langgraph langchain-openai tavily-python
四、定义 State(非常重要)
from typing import TypedDict, Annotated, List
from langgraph.graph.message import add_messages
from langchain_core.messages import BaseMessage
class AgentState(TypedDict):
messages: Annotated[List[BaseMessage], add_messages]
search_results: str
为什么需要 search_results?
因为:
搜索结果需要在 Node 之间传递
这就是 State 的价值。
五、初始化模型
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="gpt-4o-mini",
temperature=0
)
六、定义搜索 Tool
这里为了简单,我们模拟搜索。
实际项目可以接:
- Tavily
- SerpAPI
- DuckDuckGo
- 企业搜索
Search Tool Node
def search_node(state: AgentState):
last_message = state["messages"][-1].content
# 模拟搜索结果
result = f"搜索结果:关于 {last_message} 的最新新闻。"
return {
"search_results": result,
"messages": [
{
"role": "tool",
"content": result
}
]
}
七、定义 Agent Node
Agent 的职责:
决定:
- 是否需要搜索
- 如何基于搜索结果回答
Agent Node 代码
def agent_node(state: AgentState):
messages = state["messages"]
response = llm.invoke(messages)
return {
"messages": [response]
}
八、定义 Conditional Edge(核心)
这是整个项目最关键的部分。
简化版判断
def should_search(state: AgentState):
last_message = state["messages"][-1]
# 教学简化版
if "新闻" in str(last_message):
return "search"
return END
工程推荐版(真实项目)
生产环境建议:
if last_message.tool_calls:
而不是关键词判断。
九、构建 Graph
from langgraph.graph import StateGraph, END
builder = StateGraph(AgentState)
builder.add_node("agent", agent_node)
builder.add_node("search", search_node)
builder.set_entry_point("agent")
builder.add_conditional_edges(
"agent",
should_search,
{
"search": "search",
END: END
}
)
builder.add_edge("search", "agent")
十、加入状态持久化(MemorySaver)
from langgraph.checkpoint.memory import MemorySaver
memory = MemorySaver()
graph = builder.compile(
checkpointer=memory
)
为什么需要 MemorySaver?
这样 Agent 才能:
记住用户之前问过什么
十一、运行完整项目
from langchain_core.messages import HumanMessage
config = {
"configurable": {
"thread_id": "user_1"
}
}
result = graph.invoke(
{
"messages": [
HumanMessage(content="OpenAI 最近有什么新闻?")
]
},
config
)
print(result["messages"][-1].content)
十二、完整执行流程解析
第一步:用户输入
OpenAI 最近有什么新闻?
第二步:Agent Node
模型判断:
这是实时信息,需要搜索
第三步:Conditional Edge
→ search Node
第四步:Search Node
执行搜索:
搜索结果:OpenAI 发布了新模型...
第五步:返回 Agent Node
模型基于搜索结果总结回答。
十三、Graph 流程图
START
↓
Agent
↓
Conditional Edge
↓ ↓
Search END
↓
Agent
十四、这个项目已经具备哪些 Agent 能力?
虽然这是一个基础项目,但已经具备:
✔ 状态管理
✔ Tool 调用
✔ ReAct 循环
✔ Conditional Edge
✔ 多轮记忆
✔ 状态持久化
这已经是一个真正的 Agent 雏形。
十五、常见问题(非常重要)
问题1:无限循环
原因:
if "新闻" in str(last_message)
搜索结果里也有“新闻”。
正确方式
if last_message.tool_calls:
问题2:messages 被覆盖
原因:
没有使用 Annotated + add_messages
问题3:上下文丢失
原因:
没有使用 MemorySaver
十六、如何升级这个项目(进阶方向)
你可以继续扩展:
1. 接入真实搜索 API
例如:
- Tavily
- SerpAPI
- DuckDuckGo
2. 多 Tool 协作
增加:
- calculator
- database
- weather
3. 增加 Summary Memory
避免 messages 无限增长。
4. 接入 LangSmith
分析:
- Token
- Latency
- Tool 调用
5. 增加 Human-in-the-loop
例如:
搜索结果需要人工确认后再继续
十七、这个项目真正重要的地方
很多人会觉得:
这不就是一个搜索机器人吗?
但真正重要的不是“搜索”。
而是:
你已经完成了一个完整 Agent 系统的最小闭环。
包括:
State
Node
Edge
Tool
Memory
Conditional Routing
这才是 LangGraph 真正的核心。
结语
一句话总结:
LangGraph 的真正价值,不是“调用模型”,而是“组织模型如何工作”。
这一篇你已经完成了:
- 带状态的 Agent
- 搜索 Tool
- ReAct 循环
- 多轮记忆
- Graph 编排
你已经正式进入:
Agent 工程开发阶段
更多推荐




所有评论(0)