文章目录
-
- 一、环境准备与架构概览
-
- [1.1 架构示意图](#1.1 架构示意图)
- [1.2 工作流](#1.2 工作流)
- [1.3 安装依赖](#1.3 安装依赖)
- [二、实战代码:构建 DeepSeek 天气助手](#二、实战代码:构建 DeepSeek 天气助手)
- 三、执行结果全流程解析
-
- [3.1 第一轮:纯对话(记忆写入)](#3.1 第一轮:纯对话(记忆写入))
- [3.2 第二轮:ReAct 模式(工具调用与推理)](#3.2 第二轮:ReAct 模式(工具调用与推理))
-
- [阶段 A:思考与行动 (Agent Action)](#阶段 A:思考与行动 (Agent Action))
- [阶段 B:工具执行与观察 (Observation)](#阶段 B:工具执行与观察 (Observation))
- [阶段 C:最终响应 (Final Answer)](#阶段 C:最终响应 (Final Answer))
- [四、底层原理:ReAct 循环与记忆机制](#四、底层原理:ReAct 循环与记忆机制)
-
- [4.1 ReAct 交互时序图](#4.1 ReAct 交互时序图)
- [4.2 核心组件详解](#4.2 核心组件详解)
在人工智能应用开发中,单一的大语言模型(LLM)往往面临两大痛点:知识时效性滞后 (不知道今天的天气)和缺乏长期记忆(记不住上一句话)。
Agent(智能体) 是解决这些问题的终极方案。它不仅是"大脑"(LLM),还拥有"双手"(Tools)和"笔记本"(Memory)。本文将基于 LangGraph 和 DeepSeek 模型,带你从零构建一个具备联网搜索 能力和对话记忆的智能 Agent。
一、环境准备与架构概览
在开始编写代码之前,我们需要理解 Agent 的核心架构组成:
- 核心逻辑/控制器 (Controller/Orchestrator):负责驱动整个 Agent 的运行流程(如 ReAct 循环)。
- 规划模块 (Planner):LLM 思考如何分解任务、制定计划。
- 工具集 (Tool Set):定义 Agent 可以使用的工具,并提供调用接口。
- 记忆模块 (Memory Module):短期记忆(如对话历史)、长期记忆(如知识库)。
- 行动执行器 (Action Executor):实际执行 LLM 决定的动作。
1.1 架构示意图

不仅仅是语⾔模型,⽽是具备感知、规划、决策、执⾏、反思能⼒的智能体。
1.2 工作流
以使用Deepseek为例,工作流如下:
- ⽤户指令输⼊: 接收⽤户的任务需求。
- 意图理解与规划 (LLM核⼼):
a. DeepSeek 模型分析⽤户意图,将其分解为⼀系列可执⾏的⼦任务。
b. ⽣成初步的执⾏计划和步骤。 - ⼯具选择与调⽤:
a. 根据规划的⼦任务,智能选择最合适的外部⼯具 (Function Calling)。
b. 构造⼯具调⽤参数,并执⾏。 - 结果观察与反思:
a. 接收⼯具执⾏结果 (Observation)。
b. DeepSeek 模型对结果进⾏评估和分析:是否达到预期?是否有新的信息?是否需要调整计划? - 循环与迭代:
a. 基于反思结果,修正计划。
b. 再次进⼊⼯具选择与调⽤阶段,直⾄任务完成或达到终⽌条件。 - 最终输出: 将任务结果以⽤户可理解的⽅式呈现。
1.3 安装依赖
请确保安装了以下核心库:
bash
pip install langchain langchain-openai langchain-tavily langgraph python-dotenv
我们需要准备两个 API Key:
- DeepSeek API Key: 用于驱动 LLM。
- Tavily API Key: 专为 LLM 设计的搜索引擎。
二、实战代码:构建 DeepSeek 天气助手
以下是完整的 Python 实现代码。我们使用 ChatOpenAI 接口来调用兼容 OpenAI 协议的 DeepSeek 模型,并使用 MemorySaver 来持久化对话状态。
python
from langchain_tavily import TavilySearch
from langchain_core.messages import HumanMessage
from langgraph.checkpoint.memory import MemorySaver
from langgraph.prebuilt import create_react_agent
from langchain_openai import ChatOpenAI
import os
# 1. 配置 LLM (使用 DeepSeek)
# 注意:DeepSeek 兼容 OpenAI SDK,需配置 base_url
memory = MemorySaver()
model = ChatOpenAI(
model_name="deepseek-chat",
temperature=0.7,
max_tokens=2000,
api_key=os.environ["DS_AI_API_KEY"],
base_url="https://api.deepseek.com/v1",
)
# 2. 配置工具 (Tools)
# Tavily 是一个强大的 AI 搜索引擎工具
search = TavilySearch(max_results=2)
tools = [search]
# 3. 创建 Agent 执行器
# create_react_agent 自动编排了模型调用和工具执行的循环
agent_executor = create_react_agent(model, tools, checkpointer=memory)
# 4. 执行对话
# 配置 thread_id 以启用记忆功能
config = {"configurable": {"thread_id": "abc123"}}
print("--- Round 1: 自我介绍 ---")
for chunk in agent_executor.stream(
{"messages": [HumanMessage(content="hi im bob! and i live in sf")]}, config
):
print(chunk)
print("----")
print("\n--- Round 2: 询问天气 (触发工具调用) ---")
for chunk in agent_executor.stream(
{"messages": [HumanMessage(content="whats the weather where I live?")]}, config
):
print(chunk)
print("----")
三、执行结果全流程解析
Agent 的执行过程非常精彩,它展示了 LLM 如何"思考"并决定"行动"。让我们逐步拆解输出日志。
3.1 第一轮:纯对话(记忆写入)
用户输入 :"hi im bob! and i live in sf"
执行日志:
json
{
'agent': {
'messages': [
AIMessage(content="Hi Bob! It's great to meet you. San Francisco is an amazing city... What brings you here today? ...")
]
}
}
解析:
- 此时不需要调用工具。
- 关键点 :LLM 记住了用户的名字是 Bob ,居住地是 SF (San Francisco) 。这些信息被存储在
MemorySaver中关联的thread_id="abc123"下。
3.2 第二轮:ReAct 模式(工具调用与推理)
用户输入 :"whats the weather where I live?"
注意:用户没有说"旧金山",只说了"我住的地方"。
执行日志拆解:
阶段 A:思考与行动 (Agent Action)
json
{
'agent': {
'messages': [
AIMessage(content='', additional_kwargs={'tool_calls': [{
'function': {
'arguments': '{"query":"current weather in San Francisco"...}',
'name': 'tavily_search'
},
'type': 'function'
}]})
]
}
}
解析 :LLM 读取记忆,知道"我住的地方"="San Francisco"。它判断需要实时数据,因此生成了一个调用
tavily_search的指令,查询词自动填充为"current weather in San Francisco"。
阶段 B:工具执行与观察 (Observation)
json
{
'tools': {
'messages': [
ToolMessage(content='{"location": "San Francisco", "current": {"temp_c": 14.4, "condition": "Partly cloudy"...}}', name='tavily_search')
]
}
}
解析:Tavily 接口被调用,返回了 JSON 格式的旧金山实时天气数据(温度 14.4°C,部分多云)。
阶段 C:最终响应 (Final Answer)
json
{
'agent': {
'messages': [
AIMessage(content="Here's the current weather in San Francisco:\n\n- **Temperature**: 57.9°F (14.4°C)\n- **Condition**: Partly cloudy...")
]
}
}
解析:LLM 接收到工具返回的 JSON 数据,将其转化为自然语言,友好地回答了用户。
四、底层原理:ReAct 循环与记忆机制
为什么上面的代码能工作?核心在于 ReAct (Reasoning + Acting) 模式与 LangGraph 的状态管理。
4.1 ReAct 交互时序图
下面的时序图展示了 Agent 在处理第二轮问题时的内部流转:
Tavily Search DeepSeek LLM Memory Agent Executor User Tavily Search DeepSeek LLM Memory Agent Executor User 上下文加载 决策: 需调用 Search 参数: "weather in SF" loop [ReAct Loop] 状态保存 "What's the weather where I live?" 获取 thread_id="abc123" 历史 返回: "User is Bob, lives in SF" 输入: 历史 + 新问题 + 可用工具定义 输出: 思考(Thought) + 工具调用(Action) 执行 TavilySearch 返回: 🌤️ 14.4°C, Cloudy (Observation) 输入: 历史 + 工具返回结果 输出: 最终自然语言回答 "SF当前天气是14.4度,多云..." 更新对话历史
4.2 核心组件详解
-
MemorySaver (记忆):
- 在 LangGraph 中,
checkpointer负责保存 Agent 的状态(State)。 - 每次交互前,Agent 会根据
thread_id拉取之前的messages列表。 - 这就是为什么 Agent 能理解 "where I live" 指的是上一轮提到的 "sf"。
- 在 LangGraph 中,
-
Tools (工具绑定):
- LLM 本身无法联网。我们将
TavilySearch封装成函数描述(Function Calling/Tool Calling 格式)传给 LLM。 - DeepSeek 模型识别到需要外部信息时,不会瞎编,而是返回一个特殊的
tool_calls结构。
- LLM 本身无法联网。我们将
-
Create React Agent (编排器):
create_react_agent是 LangGraph 预构建的一个图(Graph)。- 它定义了节点流转逻辑:
Start->Call Model->Has Tool Call?-> (Yes) ->Execute Tool->Call Model-> ... -> (No) ->End。
通过本文的实战,我们成功构建了一个具备以下能力的 Agent:
- ✅ 基于 DeepSeek 大模型:利用高性价比模型进行逻辑推理。
- ✅ 长短期记忆 :通过
MemorySaver记住用户偏好和上下文。 - ✅ 工具使用能力 :通过
Tavily获取实时外部数据。