首页> 软件教程> 手把手搭建DeepAgents项目:从基础到进阶

手把手搭建DeepAgents项目:从基础到进阶

作者:佚名 时间:2026-03-17 10:28:01

作者 | 崔皓

审校 | 重楼

在AI开发场景中,很多开发者都有过这样的困扰:普通智能体只能处理简单的单步指令,面对多步骤、长周期的复杂任务时,要么杂乱无章,要么记忆过载,很难达到实际应用需求。而DeepAgents的出现,让智能体从“能执行”升级为“能组织”,成为具备统筹能力的“智能管理者”。更重要的是,借助LangChain和LangGraph工具,我们可以循序渐进地搭建一个属于自己的DeepAgents项目,从基础工具调用到进阶的子智能体协同,每一步都清晰可落地。

先搞懂:普通智能体的“痛点”,就是DeepAgents的“突破口”

在动手搭建项目前,我们先明确核心需求——为什么需要DeepAgents?普通智能体的三大痛点,正是我们搭建项目时需要重点解决的问题,也是DeepAgents的核心价值所在。

日常开发中,我们接触的普通智能体,处理“查天气”“转文本”这类单步任务时毫无压力,但如果让它完成“调研竞品并生成分析报告”这类复杂任务,就会暴露明显短板:

一是缺乏规划能力,拿到任务后“走一步看一步”,步骤混乱易遗漏,比如生成竞品报告时,一会儿查功能、一会儿查份额,无法形成有序流程;二是记忆过载,多步任务的中间结果、工具调用记录会撑满模型上下文,不仅增加Token成本,还会导致推理混乱(即“上下文污染”);三是能力单一,一个智能体包揽所有工作,既做调研又做编程,结果往往样样不精,且不同任务的数据相互干扰。

而我们要搭建的DeepAgents项目,核心就是解决这三大痛点,通过“任务规划+外部记忆+子智能体协同”的架构,让智能体具备“管理能力”。接下来,我们从基础到进阶,一步步完成项目搭建。

第一步:环境准备与基础搭建,实现简单工具调用

搭建DeepAgents项目的前提,是准备好基础开发环境,核心依赖LangChain和LangGraph——这两个工具能帮我们快速实现智能体的核心逻辑,无需从零开发。

首先执行安装命令,安装所需依赖(这是项目搭建的第一步,也是后续所有功能实现的基础):

pip install langchain langgraph openai python-dotenv  # 核心依赖,openai可替换为其他LLM库
  • 1.

安装完成后,我们从最基础的功能入手:实现一个能自主调用工具的文本处理智能体,这是DeepAgents项目的“入门操作”,也是后续复杂功能的基础。

核心思路是:用@tool装饰器将普通Python函数转换为LangChain可识别的工具,再通过create_agent函数,将LLM(大脑)、工具(能力)和系统提示词(行为准则)封装成可执行的智能体。关键代码如下:

from langchain.agents import create_agent, AgentExecutor
from langchain.agents.tools import tool
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
import os

# 加载环境变量(存储LLM API Key)
load_dotenv()
llm = ChatOpenAI(model="gpt-3.5-turbo", api_key=os.getenv("OPENAI_API_KEY"))

# 1. 用@tool装饰器定义基础工具
@tool
def count_words(text: str) -> int:
    """统计输入文本的字数,返回整数结果。"""
    return len(text.strip().split())

@tool
def convert_case(text: str, case: str = "upper") -> str:
    """将文本转换为大写或小写,case参数可选'upper'(默认)或'lower'。"""
    if case == "upper":
        return text.upper()
    elif case == "lower":
        return text.lower()
    else:
        return "参数错误,case只能为'upper'或'lower'"

# 2. 组装工具列表
tools = [count_words, convert_case]

# 3. 系统提示词(指导智能体行为)
system_prompt = """你是一个文本处理智能体,可调用提供的工具完成任务,严格按照工具参数要求调用,无需额外多余操作。"""

# 4. 构建智能体并执行
agent = create_agent(llm, tools, system_prompt)
agent_executor = AgentExecutor(agent=agent, verbose=True)

# 测试调用
result = agent_executor.invoke({"input": "统计'Hello DeepAgents'的字数,并将其转换为大写"})
print(result["output"])
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.

比如,我们可以定义统计字数、转换大小写、提取关键词三个基础工具,用@tool装饰器标注后,LLM会自动识别工具的用途和参数。之后通过create_agent函数组装智能体,调用.invoke()方法即可运行——当用户输入“提取这段文字的关键词并转换为大写”时,智能体能自主选择对应的工具,完成任务后返回结果。

这一步的核心是掌握“工具定义”和“智能体构建”的基本逻辑:@tool装饰器的关键是清晰的文档字符串(docstring),它直接决定LLM能否正确调用工具;create_agent函数则是智能体的“组装器”,三大核心组件(LLM、Tools、System Prompt)缺一不可。

第二步:添加状态管理,让智能体拥有“记忆”

基础工具调用实现后,我们需要给智能体添加“记忆”——让它能记住任务列表和操作历史,这是实现复杂任务规划的关键。这一步,我们需要自定义智能体状态,解决普通智能体“记不住事”的痛点。

具体实现的核心,是继承LangGraph的基础AgentState,扩展自定义状态字段。我们可以定义一个状态类,继承AgentState(默认包含对话历史messages字段),再添加todos(任务列表)和files(虚拟文件系统,为后续进阶功能预留)两个字段。关键代码如下:

from langgraph.graph import AgentState
from typing import List, Dict, Annotated
from langchain_core.messages import BaseMessage
from langgraph.utils import Reducer

# 1. 自定义Reducer函数,合并任务历史
def merge_history(left: List[str], right: List[str]) -> List[str]:
    """合并操作历史,避免覆盖"""
    return left + right

# 2. 扩展智能体状态
class DeepAgentState(AgentState):
    # 任务列表:可选字段,每个任务包含content(描述)和status(状态)
    todos: List[Dict[str, str]] = []
    # 虚拟文件系统:用Reducer合并,避免覆盖文件
    files: Annotated[Dict[str, str], Reducer(merge_history)] = {}
    # 操作历史:记录所有工具调用记录
    history: Annotated[List[str], Reducer(merge_history)] = []
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

其中,todos字段用于存储任务列表,我们可以用字典列表的形式,每个字典包含任务描述(content)和任务状态(status,可选待处理、进行中、已完成);为了让任务状态能持续累积,我们会用Annotated标注字段,并搭配Reducer函数——当不同节点更新任务列表时,不会直接覆盖,而是合并新旧内容。

同时,我们需要实现两个核心工具:write_todos(创建/更新任务列表)和read_todos(读取当前任务列表)。write_todos工具通过InjectedState注入当前智能体状态,验证任务结构后,通过Command对象更新状态;read_todos工具则只读取状态,不作修改,直接返回任务列表。关键代码如下:

from langgraph.graph import InjectedState, Command

# 1. 写入/更新任务列表工具
@tool
def write_todos(todos: List[Dict[str, str]], state: InjectedState[DeepAgentState]) -> Command:
    """创建或全量更新任务列表,每个任务需包含content和status字段(status可选pending/in_progress/completed)"""
    # 验证任务结构
    for todo in todos:
        if not all(key in todo for key in ["content", "status"]):
            return Command(update={"messages": [f"任务格式错误,需包含content和status字段"]})
        if todo["status"] not in ["pending", "in_progress", "completed"]:
            return Command(update={"messages": [f"状态错误,只能是pending/in_progress/completed"]})
    # 更新状态:全量覆盖todos,追加操作历史
    return Command(
        update={
            "todos": todos,
            "history": [f"更新任务列表:{todos}"],
            "messages": [f"任务列表已更新,共{len(todos)}个任务"]
        }
    )

# 2. 读取任务列表工具
@tool
def read_todos(state: InjectedState[DeepAgentState]) -> List[Dict[str, str]]:
    """读取当前所有任务列表,返回任务详情"""
    return state.get("todos", [])

# 测试工具(需结合智能体状态)
test_state = DeepAgentState(todos=[{"content": "搜索MCP的定义", "status": "pending"}])
print(read_todos(test_state))  # 输出:[{"content": "搜索MCP的定义", "status": "pending"}]
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.

举个例子,当用户输入“调研MCP并总结”时,智能体会通过write_todos工具生成任务列表(“搜索MCP的定义”“整理MCP的核心功能”“总结MCP的应用场景”),并实时更新任务状态;执行过程中,智能体可以通过read_todos工具查看当前进度,确保任务有序推进。这一步,我们正式解决了普通智能体“缺乏规划”的痛点。

第三步:实现并行工具调用,提升多任务处理效率

当智能体拥有“记忆”后,我们可以进一步优化效率——实现并行工具调用,让智能体能够同时处理多个独立任务,解决普通智能体“串行执行效率低”的问题。

这一步的实现无需额外新增复杂工具,核心是利用LangGraph的原生能力:当LLM判断多个任务之间没有依赖关系时,会在一次响应中生成多个tool_call,而create_agent函数能自动识别这种情况,并行执行这些工具调用,而非串行等待。

比如,用户输入“同时查询北京和上海的天气,以及美元和欧元的汇率”,智能体无需先查完北京天气,再查上海天气,而是会并行发起四个查询请求,同时获取结果,大幅缩短任务执行时间。

这里需要注意的是,并行调用的关键的是LLM的决策能力——我们需要在系统提示词中明确指导模型,当遇到多个独立任务时,可发起多个工具调用。到这一步,我们的DeepAgents项目已经具备了“规划能力”和“高效执行能力”,能应对中等复杂度的任务。

第四步:引入虚拟文件系统,实现上下文卸载

随着任务复杂度提升,我们会遇到新的问题:处理大文件、长日志时,大量内容会撑爆LLM的上下文窗口,导致任务失败。这时候,我们需要给项目添加“虚拟文件系统”,实现上下文卸载,解决普通智能体“记忆过载”的痛点。

上下文卸载的核心逻辑很简单:不再把所有中间结果、大篇幅内容塞进对话上下文,而是将其写入虚拟文件系统,对话历史中只保留“文件路径+预览”,需要时再通过工具读取。这就像我们整理电脑文件,把大文件存入硬盘,桌面只留快捷方式,既节省空间,又能快速调取。

具体实现上,我们基于之前定义的DeepAgentState,完善files字段(字典类型,key为文件路径,value为文件内容),并实现三个核心工具:ls(列出所有文件路径)、read_file(分页读取文件内容)、write_file(写入/覆盖文件)。关键代码如下:

from langgraph.graph import InjectedState, Command

# 1. 列出所有文件(ls工具)
@tool
def ls(state: InjectedState[DeepAgentState]) -> List[str]:
    """列出虚拟文件系统中所有文件的路径"""
    files = state.get("files", {})
    return list(files.keys()) if files else ["当前无任何文件"]

# 2. 分页读取文件(read_file工具)
@tool
def read_file(file_path: str, offset: int = 0, limit: int = 10, state: InjectedState[DeepAgentState]) -> str:
    """分页读取文件内容,offset为起始行号,limit为最大读取行数"""
    files = state.get("files", {})
    if file_path not in files:
        return f"文件不存在:{file_path}"
    # 按行分割,分页返回
    lines = files[file_path].splitlines()
    end = offset + limit
    paginated_lines = lines[offset:end]
    # 添加行号,便于查看
    return "n".join([f"{offset+i+1}: {line}" for i, line in enumerate(paginated_lines)])

# 3. 写入/覆盖文件(write_file工具)
@tool
def write_file(file_path: str, content: str, state: InjectedState[DeepAgentState]) -> Command:
    """写入或覆盖文件,file_path为文件路径,content为文件内容"""
    current_files = state.get("files", {})
    # 覆盖或新增文件
    current_files[file_path] = content
    return Command(
        update={
            "files": current_files,
            "history": [f"写入文件:{file_path},内容长度:{len(content)}字符"],
            "messages": [f"文件{file_path}已成功写入"]
        }
    )

# 测试文件工具
test_state = DeepAgentState(files={})
# 写入文件
write_cmd = write_file("search_results.txt", "MCP是智能体相关的核心概念...", test_state)
test_state.update(write_cmd.update)
# 列出文件
print(ls(test_state))  # 输出:["search_results.txt"]
# 读取文件
print(read_file("search_results.txt", 0, 5, test_state))
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.

其中,read_file工具支持offset(起始行号)和limit(读取行数)参数,避免一次性读取大文件撑爆上下文;write_file工具通过Command对象更新文件系统,并在对话历史中追加文件更新提示;ls工具则用于查看当前所有文件,方便智能体和用户了解文件存储情况。

比如,我们处理大篇幅的调研数据时,智能体会通过write_file工具将数据写入“search_results.txt”文件,后续分析时,通过read_file工具分页读取内容,既避免了上下文过载,又能灵活处理大文件。这一步,我们彻底解决了普通智能体“记忆过载”的痛点,让项目能应对长周期、大内容的复杂任务。

第五步:添加子智能体委托,实现专业分工协同

当项目需要处理更复杂的任务(如行业研究、多领域调研)时,单一智能体的能力仍有局限。这时候,我们需要给项目添加“子智能体委托”功能,让主智能体能够分派任务,实现专业分工,解决普通智能体“能力单一”的痛点。

核心实现分为三步:定义子智能体配置、实现task工具、组装主监督智能体。

首先,用TypedDict定义SubAgent配置,相当于给子智能体编写“岗位说明书”,包含name(唯一标识,如“research-agent”)、description(功能描述,供主智能体决策)、prompt(系统提示词,指导子智能体工作)、tools(子智能体可使用的工具,如调研类子智能体只允许使用搜索工具)。关键代码如下:

from typing import TypedDict, List
from langchain.agents import create_agent
from langchain_core.tools import BaseTool

# 1. 定义子智能体配置(TypedDict)
class SubAgent(TypedDict):
    name: str  # 子智能体唯一标识
    description: str  # 子智能体功能描述(供主智能体决策)
    prompt: str  # 子智能体系统提示词
    tools: List[BaseTool]  # 子智能体可使用的工具

# 2. 定义调研类子智能体配置(示例)
research_agent_config: SubAgent = {
    "name": "research-agent",
    "description": "专注于行业调研、信息搜索,擅长通过搜索工具获取精准信息并整理",
    "prompt": "你是调研子智能体,仅使用web_search工具获取信息,整理后以简洁明了的格式返回,不添加多余内容",
    "tools": [web_search]  # web_search为之前实现的搜索工具(可替换为Tavily API)
}

# 3. 实现create_task_tool函数,把子智能体转为可调用工具
def create_task_tool(subagents: List[SubAgent], llm) -> BaseTool:
    @tool
    def task(description: str, subagent_type: str, state: InjectedState[DeepAgentState]) -> Command:
        """
        委托子智能体执行任务,description为任务描述,subagent_type为子智能体名称(对应SubAgent的name)
        """
        # 找到指定子智能体
        subagent = next((sa for sa in subagents if sa["name"] == subagent_type), None)
        if not subagent:
            return Command(update={"messages": [f"未找到子智能体:{subagent_type}"]})
        
        # 创建隔离上下文(仅包含任务描述和文件,不包含主智能体历史)
        isolated_state = DeepAgentState(
            messages=[{"role": "user", "content": description}],
            files=state.get("files", {})
        )
        
        # 构建子智能体并执行
        sub_agent = create_agent(llm, subagent["tools"], subagent["prompt"])
        sub_agent_executor = AgentExecutor(agent=sub_agent, verbose=True)
        result = sub_agent_executor.invoke(isolated_state)
        
        # 把子智能体结果汇回主智能体
        return Command(
            update={
                "messages": [f"子智能体{subagent_type}执行结果:{result['output']}"],
                "history": [f"委托子智能体{subagent_type}执行任务:{description}"]
            }
        )
    return task
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.

在技术落地时,我们选择Tavily API作为搜索工具(专为AI设计,结果质量高,免费额度1000次/月,适合快速落地),并自定义行业研究框架,让智能体能够按“市场规模-发展历程-竞争格局-发展趋势”的维度,自动规划任务、调用工具、存储数据、生成报告。关键代码如下:

from tavily import TavilyClient
from dotenv import load_dotenv
import os

# 1. 初始化Tavily搜索工具
load_dotenv()
tavily = TavilyClient(api_key=os.getenv("TAVILY_API_KEY"))

@tool
def web_search(query: str) -> str:
    """使用Tavily API搜索信息,返回简洁的搜索结果摘要"""
    response = tavily.search(query, max_results=3)
    return "n".join([f"来源:{res['url']}n内容:{res['content'][:200]}..." for res in response["results"]])

# 2. 自定义行业研究框架
RESEARCH_FRAMEWORK = {
    "market_size": {
        "name": "市场规模",
        "search_queries": ["{industry}市场规模 2024-2025", "{industry}市场增长率"],
        "output_template": "# {industry}市场规模n## 市场体量n{market_volume}n## 增长率n{growth_rate}"
    },
    "competition": {
        "name": "竞争格局",
        "search_queries": ["{industry}主要企业及市场份额", "{industry}核心竞品分析"],
        "output_template": "# {industry}竞争格局n## 主要企业n{companies}n## 市场份额n{market_share}"
    }
}

# 3. 组装主智能体,落地行业研究助手
def create_industry_research_agent(llm):
    # 子智能体配置
    subagents = [research_agent_config]
    # 创建task工具
    task_tool = create_task_tool(subagents, llm)
    # 基础工具列表
    base_tools = [write_todos, read_todos, ls, read_file, write_file, task_tool, web_search]
    # 系统提示词(指导主智能体按框架调研)
    system_prompt = f"""你是AI行业研究助手,需按以下框架完成调研:{RESEARCH_FRAMEWORK}
步骤:1. 生成调研任务列表;2. 委托research-agent执行搜索;3. 写入文件;4. 整合生成报告。"""
    # 构建主智能体
    agent = create_agent(llm, base_tools, system_prompt, state_schema=DeepAgentState)
    return AgentExecutor(agent=agent, verbose=True)

# 测试行业研究助手
agent_executor = create_industry_research_agent(llm)
result = agent_executor.invoke({"input": "调研AI生成式内容行业"})
print(result["output"])
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.

其次,通过create_task_tool函数,把子智能体变成可调用的工具。这个工具的核心作用是:主智能体调用task(description, subagent_type)时,会创建一个隔离的上下文(只包含任务描述和必要文件,不包含主智能体的完整对话历史),启动对应的子智能体执行任务,完成后将结果封装成ToolMessage汇回主智能体。

最后,通过create_supervisor_agent函数组装主智能体,将task工具和其他基础工具注入,主智能体负责制定战略、拆解任务、验收子智能体的结果,不直接执行具体操作。

举个例子,当主智能体需要完成“AI行业研究报告”时,会将任务拆分为“市场规模调研”“竞争格局分析”“发展趋势预测”三个子任务,分别委托给三个不同的子智能体(research-agent),三个子智能体并行执行,完成后将结果汇总给主智能体,主智能体再整合生成最终报告。这种模式既保证了专业性,又提升了效率。

此外,我们还可以添加一个think_tool工具,让主智能体在拿到子智能体结果后,显式记录思考过程,反思已掌握的信息、缺失的内容,规划下一步动作,确保任务整体可控。

项目落地:搭建AI行业研究助手,检验DeepAgents能力

当我们完成了以上五步搭建后,就可以将项目落地为一个实用的AI行业研究助手,检验DeepAgents的核心能力。这个助手适用于投资人、产品经理、求职者等各类人群,能帮助用户快速了解陌生行业。

整体架构如下:

在技术落地时,我们选择Tavily API作为搜索工具(专为AI设计,结果质量高,免费额度1000次/月,适合快速落地),并自定义行业研究框架,让智能体能够按“市场规模-发展历程-竞争格局-发展趋势”的维度,自动规划任务、调用工具、存储数据、生成报告。

具体流程如下:用户输入目标行业(如“AI生成式内容行业”),主智能体通过write_todos工具生成调研任务列表;之后,主智能体委托子智能体,通过Tavily API搜索各维度信息,将搜索结果通过write_file工具存入虚拟文件系统;最后,主智能体整合文件中的信息,生成结构清晰的行业研究报告,全程无需用户手动干预。

同时,我们可以添加流式输出功能,让用户实时看到任务进度和报告生成过程;通过状态同步函数,实现任务状态的实时更新,用户随时可以查看当前调研进度。

关键技术选型

组件

技术选择

选择理由

大模型

DeepSeek

中文能力强,推理成本低,适合复杂任务规划。

搜索引擎

Tavily API

专为 AI 设计的搜索 API,结果质量高,免费额度 1000 次/月,适合快速落地。

智能体框架

LangGraph

提供状态管理和流程控制,支持复杂工作流编排。

Web 框架

Streamlit

快速构建数据应用,自带响应式布局和组件系统。

状态管理

LangGraph State

通过状态注解实现跨工具的状态共享和持久化。

核心功能实现

智能体首先使用 write_todos 工具将复杂的研究任务分解为可执行的子任务:

# 用户输入:新能源汽车行业
# 智能体自动生成的任务列表
todos = [
    {"content": "研究新能源汽车行业概述", "status": "pending"},
    {"content": "研究新能源汽车竞争格局", "status": "pending"},
    {"content": "研究新能源汽车发展趋势", "status": "pending"},
    {"content": "整合分析并生成报告", "status": "pending"}
]
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

每个任务都有明确的状态:pending(待处理)、in_progress(进行中)、completed(已完成),通过 update_todo_status 工具实时更新。这种结构化的任务管理方式,让用户能够清晰看到研究进度。

智能体根据任务列表,自动进行多维度的信息收集:

# 搜索工具调用示例
web_search("新能源汽车市场规模和增长趋势")
web_search("新能源汽车主要企业和竞争格局")
web_search("新能源汽车技术发展趋势")
web_search("新能源汽车政策环境和未来展望")
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

每次搜索后,智能体会使用 think 工具进行反思:

  • “我找到了什么关键信息?”
  • “这些信息是否足够回答用户的问题?”
  • “还需要搜索哪些补充信息?”

这种反思-决策机制,确保了搜索的针对性和信息收集的完整性。

所有研究结果被实时存储在虚拟文件系统中,通过 write_file 工具写入:

# 文件写入示例
write_file("行业概述.md", "# 新能源汽车行业概述n...")
write_file("竞争格局.md", "# 新能源汽车竞争格局n...")
write_file("发展趋势.md", "# 新能源汽车发展趋势n...")
  • 1.
  • 2.
  • 3.
  • 4.

这个虚拟文件系统有以下优点:

  • 隔离性:每次研究都有独立的文件空间,避免数据混乱。
  • 持久性:通过 LangGraph 的状态管理,文件在研究过程中持续保存。
  • 可扩展:支持任意数量和类型的文件,适合存储不同维度的研究结果。

最后,主智能体整合所有文件中的信息,生成结构清晰的行业研究报告:

# 最终报告生成
report = generate_report(
    overview=read_file("行业概述.md"),
    competition=read_file("竞争格局.md"),
    trends=read_file("发展趋势.md")
)
write_file("研究报告.md", report)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

报告自动包含摘要、核心发现、详细分析、结论建议等部分,完全符合专业研究报告的格式要求。

关键代码解析

我们扩展了 LangGraph 的 AgentState,增加了任务列表和文件系统:

class DeepAgentState(AgentState):
    """
    深度智能体状态
    包含:
    - messages: 消息历史(继承自 AgentState)
    - todos: TODO 任务列表
    - files: 虚拟文件系统
    """
    todos: NotRequired[list[dict]]
    files: Annotated[NotRequired[dict[str, str]], file_reducer]
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

这里的 file_reducer 是一个自定义的合并函数,用于在状态更新时正确合并新旧文件:

def file_reducer(left: dict, right: dict) -> dict:
    """文件系统合并函数"""
    if left is None:
        return right
    elif right is None:
        return left
    else:
        return {**left, **right}  # 新文件覆盖旧文件
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

通过 LangGraph 的状态注入机制,工具可以安全地访问和修改状态:

@tool
def write_file(
    file_path: str,
    content: str,
    state: Annotated[dict, InjectedState] = None,  # 注入状态
    tool_call_id: Annotated[str, InjectedToolCallId] = None,  # 注入工具调用ID
) -> Command:
    """向虚拟文件系统写入内容"""
    files = state.get("files", {})
    files[file_path] = content

    # 返回 Command 对象更新状态
    return Command(
        update={
            "files": files,
            "messages": [
                ToolMessage(
                    content=f"已成功写入文件: {file_path}",
                    tool_call_id=tool_call_id,
                )
            ],
        }
    )
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.

这种设计保证了工具之间的解耦和状态的统一管理。

智能体的创建过程清晰地体现了 DeepAgents 的设计理念:

def create_research_agent(
    model_name: str = None,
    temperature: float = None,
    max_results: int = None,
    search_depth: str = None,
):
    """创建行业研究智能体"""

    # 1. 初始化大模型
    llm = ChatDeepSeek(
        model=actual_model_name,
        temperature=actual_temperature,
        api_key=settings.DEEPSEEK_API_KEY,
    )

    # 2. 创建工具集
    tools = [
        web_search,      # 搜索工具
        ls, read_file, write_file,  # 文件工具
        write_todos, read_todos, update_todo_status,  # 任务工具
        think,           # 思考工具
    ]

    # 3. 创建智能体
    agent = create_agent(
        llm,
        tools=tools,
        system_prompt=SYSTEM_PROMPT,
        state_schema=DeepAgentState,
    )

    return agent
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.

项目亮点

for chunk in agent.stream(
    {"messages": [HumanMessage(content=prompt)]},
    config=config,
    stream_mode="values",
):
    # 实时更新进度和日志
    if "todos" in chunk:
        st.session_state.todos = chunk["todos"]
        update_progress(calculate_progress(chunk["todos"]))
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

这种实时反馈机制,大大提升了用户体验,让用户能够信任智能体的工作过程。

项目实现了完善的状态同步和容错机制:

def run_real_research(industry: str):
    """使用真实智能体进行研究"""
    try:
        # 尝试使用真实智能体
        agent = create_research_agent()
        # ... 智能体运行逻辑
    except Exception as e:
        # 出错时自动切换到模拟模式
        add_log("info", f"❌ 研究出错: {str(e)}")
        add_log("info", "切换到模拟模式...")
        simulate_research(industry)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

这种设计保证了服务的稳定性,即使在 API 限流或网络故障的情况下,用户仍然可以得到模拟结果。

项目支持研究历史记录和报告导出:

# 保存到历史记录
history_record = {
    "industry": industry,
    "time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
    "files": dict(st.session_state.research_files),
    "result": st.session_state.research_result,
    "todos": list(st.session_state.todos),
}
st.session_state.research_history.append(history_record)

# 只保留最近 10 条历史
if len(st.session_state.research_history) > 10:
    st.session_state.research_history = st.session_state.research_history[-10:]
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

项目价值与能力检验

验证了 DeepAgents 的几项核心能力:

能力维度

验证方式

结果体现

任务规划能力

自动生成结构化任务列表

从“新能源汽车”自动分解为概述、格局、趋势、报告四个任务

工具协调能力

多工具协同完成复杂任务

搜索→思考→存储→报告的完整流程自动化

状态管理能力

维护多维度中间状态

任务进度、文件系统、研究日志的一致性管理

错误恢复能力

异常情况下的降级服务

API 故障时自动切换模拟模式,保证用户体验

用户体验

流式输出与实时反馈

用户能看到智能体的思考过程,建立信任感

总结:循序渐进,从入门到精通DeepAgents项目搭建

我们搭建DeepAgents项目的过程,正是解决普通智能体痛点的过程:从基础的工具调用,到状态管理实现任务规划,再到并行调用提升效率,最后通过虚拟文件系统和子智能体委托,实现复杂任务的高效处理,每一步都循序渐进、可落地。

整个项目的核心逻辑,是让智能体从“被动执行”升级为“主动管理”——通过“规划-分解-委托-整合”的闭环架构,让智能体能够调度资源、管理记忆、分工协作。对于开发者而言,借助LangChain和LangGraph,我们无需从零开发核心逻辑,只需按步骤完善功能,就能快速搭建出具备DeepAgents能力的智能体。

未来,我们还可以基于这个项目进一步优化:将虚拟文件系统与持久化存储(如Postgres)结合,实现跨会话的长期记忆;优化子智能体的配置,支持更多专业场景;添加UI界面,让非技术用户也能轻松使用。相信随着技术的迭代,DeepAgents将在更多场景中落地,成为我们工作中的“智能伙伴”。

作者介绍

崔皓,51CTO社区编辑,资深架构师,拥有18年的软件开发和架构经验,10年分布式架构经验。

责任编辑:庞桂玉 来源: 51CTO

相关阅读

人气下载推荐