DeepSeek + LangGraph: 探讨并评测推理模型在Agent应用上的能力与表现|深度

DeepSeek火爆出圈,特别是对标Open o1的R1模型,其更低的提示门槛与深度推理能力加速了AI应用的普及。不过,相对于个人应用侧的狂热,我们还需要更客观与科学的关注其在商业领域的生产力应用上的能力与表现。

DeepSeek-R1擅长深度“思考”,那么在更需要自主规划能力的Agent应用中,它是否有更好的表现呢?本文将以最常见的ReAct范式的Agent来探讨这个问题,不过,结果可能会颠覆你的预期。

01 什么是ReAct Agent?

ReAct(Reasoning + Acting)是一种结合推理(Reasoning)行动(Acting)的 AI 智能体范式。其核心理念是让 AI 先进行思考推理,再据此采取行动,如调用外部工具;经过多次这样循环,直到任务完成。

在这里插入图片描述

简单的说就是:

给Agent安上手脚(Tools)和大脑(LLM),让它自己思考,并借助手脚完成任务。

所以,ReAct Agent的特点是:

  • 自主规划能力: 自行推理多子任务步骤,并在过程中动态调整

  • 工具使用: 支持与API、数据库、搜索引擎等交互,以完成任务

  • 更高的灵活性:相对于有固定流程的Workflows,任务更灵活

  • 存在不可控性: LLM输出的不确定性可能会带来一定不可控性

Anthropic在《Build effective agents》中将Agentic系统分成了有着预定流程的Workflows与自主规划的Agents,很显然ReAct Agents属于后者。

02 ReAct Agent需要哪些推理能力

ReAct Agent是一种高度依赖于LLM的智能体,其需要的推理能力包括:

* 多任务步骤的规划与推理

  • 根据输入任务与工具等信息推理出子任务,并合理安排顺序

  • 理解推理历史与观察工具结果,动态规划,调整决策,避免冗余等

比如这样的任务:

“了解公司新品的网络评价,如果偏负面,则发送邮件到产品经理。”

这个任务需要LLM最终能够规划出类似下面的任务步骤,注意这个规划是要在过程中动态完成的,因为你无法事先得知网络评价的结果:

在这里插入图片描述

* 工具使用的推理

能够推理子任务需要使用的工具,及其结构化的输入参数。这通常借助LLM的Function Calling特性或者提示工程(Prompt)来实现。

* 协助子任务的执行

除了任务步骤的推理,当然LLM也可以用来协助完成某个具体任务。比如在一个研究智能体中,辅助生成论文提纲等。

我们重点关注前两种推理能力,这是体现Agent自主能力的核心。

03 手搓支持DeepSeek-R1的ReAct Agent

一个典型的ReAct Agent的Graph图表示如下:

在这里插入图片描述

在LangGraph中构建ReAct Agent最快捷的方法是使用官方提供的prebuilt函数:

在这里插入图片描述

但这个方法对我们并不适用。因为这个方法有一个强制要求:

大模型必须支持Function Calling(函数调用),因为其内部实现需要借助LLM的Function Calling功能来推理下一个步骤与工具!而目前的推理模型都不支持函数调用。

所以,我们必须要使用LangGraph来自行实现这个Agent,这需要使用提示工程来要求LLM进行任务步骤推理。这里仅展示核心过程:

1. 提示词

设计ReAct范式的Prompt如下:

...  
  
# ReAct 提示格式   
REACT_PROMPT = '''  
你被设计用于帮助完成各种输入任务,包括回答问题、内容创作、自动化处理等。  
  
## 工具  
你可以使用各种工具,并且需要自行决定使用工具的顺序,以完成当前任务。  
这可能需要将任务拆分为多个子任务,并使用不同的工具来完成各个子任务。  
你可以使用以下工具:  
  
{tools_desc}  
  
## 输出格式  
如果本次需要使用工具完成某个子任务,请按照以下格式输出:  

Thought: 我需要使用一个工具来帮助回答这个问题。  
Action: 工具名称 (从 {tool_names} 中选择一个工具),如果需要使用工具的话。  
Action Input: 传递给工具的输入,使用 JSON 格式表示参数(例如:{
    
    {"query": "你好"}})。  

注意:  
* 始终以“Thought”开头。  
* 绝对不要在你的响应外部使用 Markdown 代码标记,但如果在你的回答中需要,你可以在适当的位置使用代码标记。  
* 请使用有效的JSON 格式作为Action Input。不要使用类似 {
    
    {'input': '你好世界', 'num_beams': 5}} 这种错误格式。  
* 一次响应最多只能使用一个工具以完成一个子任务。不要在一次响应中出现多个Action。  
  
如果你已经获得足够的信息而来输出最终回答,则必须使用以下两种格式之一来输出最后答案:  

Thought: 我可以在不使用更多工具的情况下回答问题。  
Answer: [你的回答 (与用户问题的语言相同)]  

Thought: 我无法使用提供的工具回答该问题。  
Answer: [你的回答 (与用户问题的语言相同)]  

注意:  
* 确保所有子任务都完成后才输出最终答案  
* 最终回答尽量涵盖用户任务的所有方面  
  
  
## 当前对话  
以下是当前的对话历史, 由人类、AI的消息交替组成。  
  
'''

2. 准备Tools

准备几个简单的模拟Tool,交给Agent使用:

  • 网络搜索(network_search)

  • 计算器(caculator)

  • 文本摘要与总结(document_summarizer)

  • 电子邮件发送(Email)

代码大致如下(省略了内部逻辑):

...  
  
# 定义4个模拟工具  
@tool  
def network_search(query: str) -> str:  
    """  
    用于执行网络搜索并返回搜索结果  
    Args:  
        query (str): 要进行网络搜索的关键词  
    """  
    print_colored(f'调用tool: network_search, 输入: {
      
      query}', 'green')  
    try:  
        # 调用 TavilySearchResults 来执行搜索,模拟返回结果  
        results = TavilySearchResults(max_results=2).invoke({
    
    "query": query})  
        return f"搜索结果: {
      
      results}"  
    except Exception as e:  
        return f"搜索错误: {
      
      str(e)}"  
      
@tool  
def calculator(query: str) -> str:  
    """  
    用来执行加减乘除计算  
    Args:  
        query (str): 要计算的表达式,如1+2*3  
    """  
  ...  
  
@tool  
def document_summarizer(text: str) -> str:  
    """  
    用来提炼与总结文本的核心内容,形成摘要  
    Args:  
        text (str): 要总结的文本内容  
    """  
  ...  
@tool  
def email(recipient, subject, body) -> str:  
    """  
    用于发送电子邮件  
    Args:  
        recipient (str): 收件人的电子邮件地址  
        subject (str): 电子邮件的主题  
        body (str): 电子邮件的正文  
    """  
...

3. 实现核心推理逻辑(借助LLM)

这个是整个流程的核心部分,主要职责是调用LLM进行任务推理:

  1. 通过提示词与对话历史让LLM推理下一步行动

  2. 如果需要调用工具,则给出结构化的调用信息

  3. 如果无需再调用工具,则输出LLM给出的答案

  4. 如果达到最大迭代次数仍未完成任务,则报错

实现如下(代码中的llm将在后面测试中使用不同模型如Deepseek-R1来替换):

...  
llm = ChatOpenAI(model='gpt-4o-mini')  
tools = [network_search,calculator,document_summarizer,email]  
  
async def call_model(  
    state: State, config: RunnableConfig  
) -> Dict[str, List[AIMessage]]:  
      
    # 生成工具描述  
    tools_desc = "\n".join([  
        f"- {
      
      tool.name}: {
      
      tool.description}\n"   
        for tool in tools  
    ])  
  
    tool_names = [tool.name for tool in tools]  
  
    # 生成 ReAct 提示  
    system_prompt = REACT_PROMPT.format(  
        tools_desc=tools_desc,  
        tool_names=tool_names  
    )  
  
    # 这一步需要根据不同模型增加或注释  
    state.messages = [HumanMessage(content=msg.content) if "ToolMessage" in msg.__class__.__name__ else msg for msg in state.messages]  
  
    # 调用 LLM,输入提示词(system_prompt)和对话历史(messages)  
    response = await llm.ainvoke([SystemMessage(content=system_prompt)] + state.messages)  
    content = response.content  
      
    print_colored("\n===========================Reasoning================================", 'magenta')  
    print_colored(f'{
      
      content}', 'magenta')  
    print_colored("=========================Reasoning End================================\n", 'magenta')  
  
    if "Action:" in content and "Action Input:" in content:  
  
        # 提取工具调用信息  
        action_lines = [line for line in content.split('\n') if line.startswith('Action:') or line.startswith('Action Input:')]  
        tool_name = action_lines[0].replace('Action:', '').strip()  
        tool_input = action_lines[1].replace('Action Input:', '').replace("'",'"').strip()  
        tool_input = tool_input.replace('\\', '\\\\')  
          
        response.tool_calls = [{
    
      
            "id": "call_1",  
            "type": "function",  
            "name": tool_name,  
            "args": json.loads(tool_input)  
            }  
        ]  
  
    if state.is_last_step and response.tool_calls:  
        return {
    
      
            "messages": [  
                AIMessage(  
                    content="对不起,我在指定的步骤数内无法找到问题的答案。"  
                )  
            ]  
        }  
  
    return {
    
    "messages": [response]}

4. 创建Graph

完成了核心的推理节点,就可以创建这个Graph(Tools调用借助官方ToolNode组件即可):

@dataclass  
class InputState:  
    messages: Annotated[Sequence[AnyMessage], add_messages] = field(  
        default_factory=list  
    )  
  
@dataclass  
class State(InputState):  
  
    is_last_step: IsLastStep = field(default=False)  
  
builder = StateGraph(State, input=InputState)  
builder.add_node(call_model)  
builder.add_node("tools", ToolNode(tools))  
builder.add_edge("__start__", "call_model")  
  
# 定义一个函数,根据模型输出的内容来决定下一个节点;如果有工具调用,则转向tools  
def route_model_output(state: State) -> Literal["__end__", "tools"]:  
    last_message = state.messages[-1]  
    if not isinstance(last_message, AIMessage):  
        raise ValueError(  
            f"Expected AIMessage in output edges, but got {
      
      type(last_message).__name__}"  
        )  
      
    if not last_message.tool_calls:  
        return "__end__"  
      
    return "tools"  
  
# 添加条件边  
builder.add_conditional_edges(  
    "call_model",  
    route_model_output,  
)  
builder.add_edge("tools", "call_model")  
  
# 编译  
graph = builder.compile()  
graph.name = "ReAct Agent"

5. 验证可用性

现在你可以使用graph.invoke方法来输入任务,以测试这个ReAct Agent。按照预期,它应该能够理解你的自然语言输入任务,并使用已有的四个工具(搜索、计算器、摘要、邮件发送)来完成。为了更好的观察,我们加入一些跟踪信息,以展示LLM的推理过程。

这里先用一个简单任务看下效果(模型gpt-4o-mini):

可以看到,第一次推理,LLM认为需要使用搜索工具;第二次推理,因为观察到工具返回(这里未打印),LLM已经可以正确回答问题了!

04 不同模型的ReAct Agent评测

现在我们使用不同难度的任务来考察类似DeepSeek- R1这样的推理模型,在ReAct Agent中的多任务步骤推理时的表现,并同通用模型做对比。

测试任务(从简单到复杂)

  • “搜索《哪吒2》的最新票房数据”,

  • “搜索《哪吒2》的详细剧情介绍,并发送到[email protected]”,

  • “搜索《哪吒2》的最新票房,如果超过50亿,再帮我搜索《哪吒3》的上映时间; 如果没有超过50亿,则创作一段加油的文字。最后把结果发邮件到[email protected]

对比模型:

  • gpt-4o-mini

  • doubao-1.5-32k

  • deepseek-v3(官方)

  • deepseek-r1(官方)

  • deepseek-r1:7b(开源)

  • qwen-2.5:7b(开源)

测试方法:

  • 在不改变其他代码与提示的情况下,切换不同的模型

  • 依次输入3个测试任务,每个任务测试多次,观察结果

  • 确保每次任务是独立的,不记忆之前的任务历史

测试结果:


任务一 任务二
任务三
gpt-4o-mini
Yes
Yes Yes
doubao-1.5-32k yes yes yes
deepseek-v3
yes yes yes
deepseek-r1
yes yes *  no
deepseek-r1:7b yes no *
no
qwen-2.5:7b yes yes
no
  • yes: 全部成功,且推理过程输出符合预期

  • no:全部失败,未获得期望结果甚至异常

  • yes*: 代表大部分成功,偶尔失败;或者结果成功,但推理过程不符预期

  • no*: 代表大部分失败,偶尔成功

DeepSeek-R1失败的主要现象:

1. 不遵循逐步推理的指令。 即一次性返回包含多个Thought-Action行动步骤的完整任务过程(尽管这个过程可能是正确的)。如这次:

在这里插入图片描述

2. 基于假设(幻觉)推理。 在第一步的子任务推理后,有时候会自作主张的“假设”一个工具调用结果,并据此做后续步骤推理(r1:7b模型)。

3. 遗漏某个任务步骤。 比如某一次任务3的测试中,未推理与执行“发送邮件”这一步骤,但最终却有如下“貌似完美”的输出:

在这里插入图片描述

4. 输出格式不能稳定遵循指令要求。 比如下图中,自行添加了’json’标记,当然格式的问题有时候可以通过代码来容错,但也可能会直接异常:

在这里插入图片描述

我们来看一下最复杂的任务3的成功输出,推理过程应该类似下图:

在这里插入图片描述

05 思考与总结

尽管从直觉上你可能会认为“自带Cot(思维链)”的推理模型Deepseek- R1应该更擅长自主的多步骤任务规划与推理,但是事实恰恰相反:

目前的推理模型(DeepSeek-R1、OpenAI的o1等)在Agent需要的自主、多步骤、动态的任务规划能力上还缺乏足够的可用性

下面是我们的一些具体思考与总结:

1. 目前o1,r1这样的推理模型的确擅长step by step的思考问题,但输入任务应该更直接。即复杂性体现在问题本身,而不能是提示词与上下文。 比如:

  • 根据需求描述生成复杂的代码

  • 解决一道复杂的数学问题

  • 进行一项科学计算与研究

  • 根据主题生成有深度的论文

而以下类型的任务它目前并不擅长:

  • 基于复杂上下文与对话历史的推理任务

  • 有严格的指令遵循与结构化输出要求的任务

  • 依赖于Function Calling功能的智能体任务

这里的结构化输出可以借助辅助LLM来完善;Function Calling也可以借助提示词来获得,但是第一个问题则需要等待模型进化。

2. 具体到AI Agent应用,特别是ReAct Agent,由于其更依赖于LLM的多任务步骤推理能力。我们建议:

  • 在任务步骤的动态规划与推理上,通用模型目前更适合,比如GPT-4o,DeepSeek-v3;且参数越大的模型越稳定

  • 推理模型,包括满血的DeepSeek-R1,以及开源的1.5b等蒸馏版本,都不建议用作Agent的任务步骤推理;但是可以作为一个Tool来完成某个子任务,比如根据搜索结果编写一份有深度的报告

  1. 推理模型在Agent中应用的另一个问题是响应性能,由于其深度思考的特点,其响应时间普遍较长,这是制约其在企业级应用的另一个问题。

以上的一些结论刚好也验证了DeepSeek-R1官方技术报告揭示的自身“能力缺陷”,包括不支持function calling、不擅长多轮对话、结构化输出较弱、提示词与复杂上下文敏感等,我们也期待下一个版本的R1在这些能力上取得突破!


如何系统学习掌握AI大模型?

AI大模型作为人工智能领域的重要技术突破,正成为推动各行各业创新和转型的关键力量。抓住AI大模型的风口,掌握AI大模型的知识和技能将变得越来越重要。

学习AI大模型是一个系统的过程,需要从基础开始,逐步深入到更高级的技术。

这里给大家精心整理了一份全面的AI大模型学习资源,包括:AI大模型全套学习路线图(从入门到实战)、精品AI大模型学习书籍手册、视频教程、实战学习、面试题等,资料免费分享

在这里插入图片描述

1. 成长路线图&学习规划

要学习一门新的技术,作为新手一定要先学习成长路线图方向不对,努力白费

这里,我们为新手和想要进一步提升的专业人士准备了一份详细的学习成长路线图和规划。可以说是最科学最系统的学习成长路线。
在这里插入图片描述

2. 大模型经典PDF书籍

书籍和学习文档资料是学习大模型过程中必不可少的,我们精选了一系列深入探讨大模型技术的书籍和学习文档,它们由领域内的顶尖专家撰写,内容全面、深入、详尽,为你学习大模型提供坚实的理论基础(书籍含电子版PDF)

在这里插入图片描述

3. 大模型视频教程

对于很多自学或者没有基础的同学来说,书籍这些纯文字类的学习教材会觉得比较晦涩难以理解,因此,我们提供了丰富的大模型视频教程,以动态、形象的方式展示技术概念,帮助你更快、更轻松地掌握核心知识

在这里插入图片描述

4. 2024行业报告

行业分析主要包括对不同行业的现状、趋势、问题、机会等进行系统地调研和评估,以了解哪些行业更适合引入大模型的技术和应用,以及在哪些方面可以发挥大模型的优势。

在这里插入图片描述

5. 大模型项目实战

学以致用 ,当你的理论知识积累到一定程度,就需要通过项目实战,在实际操作中检验和巩固你所学到的知识,同时为你找工作和职业发展打下坚实的基础。

在这里插入图片描述

6. 大模型面试题

面试不仅是技术的较量,更需要充分的准备。

在你已经掌握了大模型技术之后,就需要开始准备面试,我们将提供精心整理的大模型面试题库,涵盖当前面试中可能遇到的各种技术问题,让你在面试中游刃有余。

在这里插入图片描述

全套的AI大模型学习资源已经整理打包,有需要的小伙伴可以微信扫描下方CSDN官方认证二维码,免费领取【保证100%免费

在这里插入图片描述