LangChain / LangGraph 开发智能体工具导致幻觉?有没有做以下措施

在使用LangChain/LangGraph开发智能体时,你是否遇到过设计工具导致幻觉的场景,明明已经约定模型返回值了但还是输出了思考过程,导致提示词越来越复杂难懂(模型层面)。本文将介绍工具设计时的两种方式约定,使智能体的输出在我们预想的范围内。


一、return_direct 的底层机制、场景

1. 核心定义

return_direct 是 LangChain 自定义 Tool 的核心流程控制布尔参数 ,默认值为 False。它的作用是决定工具执行结束后,是否截断整个Agent推理链路

简单来说:控制「工具跑完后,要不要再交给大模型继续思考」。

2. 两种模式完整工作链路

模式1:return_direct = False(默认模式)

完整执行流程

  1. 用户提问 → Agent 解析意图

  2. 判定需要调用工具 → 执行自定义Tool逻辑

  3. 工具返回原始结果(文本/字典/列表)

  4. 结果重新塞入LLM上下文,进入二次推理

  5. LLM结合工具返回结果 + 系统提示词 + 历史对话,整理、润色、扩写、总结

  6. 生成自然语言最终回复返回用户

适用场景 所有工具只负责拿数据、不负责出答案的场景:检索知识库、查询数据库、联网搜索、代码执行、数据统计。

这类场景下,工具返回的是原始、生硬、无排版的数据,必须依靠大模型二次加工才能传递给用户。

优缺点

  • 优点:回答更自然、话术统一、支持多工具多轮联动

  • 缺点:多一轮外层LLM推理、Token消耗更高、耗时更长、存在幻觉风险

模式2:return_direct = True(直返模式)

完整执行流程

  1. 用户提问 → Agent 解析意图

  2. 命中当前工具规则 → 执行Tool

  3. 工具执行完毕后直接返回结果

  4. 不进入LLM二次推理、不刷新prompt、不继续路由

  5. 工具返回内容直接作为本轮对话最终输出

适用场景 业务结果无需润色、规则固定、确定性极强的场景:

  • 纯数值计算、公式推理

  • 固定指令应答、开关类操作

  • 结构化JSON输出、接口透传结果

  • 权限校验、参数校验、拒绝应答

优缺点

  • 优点:零二次推理、极致省Token、耗时最低、杜绝模型篡改工具执行结果

  • 缺点:无法自然润色,仅适合结构化/固定话术输出

3. 使用方式

python 复制代码
class _BaseInput(BaseModel):
    query: str = Field(..., description="...")

class BaseTool(BaseTool):
    name: str = "base_tool"
    description: str = """..."""
    args_schema: type[BaseModel] = _BaseInput
    return_direct: bool = True # BaseTool 原生参数,保证工具输出原封不动返回给父节点

    def _run(self, query: str):
        return self._arun(query)

    async def _arun(self, query: str) -> str:
        try:
            return "成功"
        except Exception as e:
            return f"失败: {str(e)}"

注意:return_direct参数在pydantic~=2.13.3 不兼容新版langchain-core1.3.3,降低pydantic版本

bash 复制代码
pip install pydantic==2.12.3 pydantic-core==2.41.4 --force-reinstall

4. 生产环境缺点

  1. LangGraph 嵌套场景 return_direct 失效

    在 Graph 节点内部通过 create_agent 嵌套子Agent,子Agent工具配置的 return_direct=True 无法穿透外层Graph

    原因:子Agent是独立执行上下文,Graph外层状态流转不感知子工具的直返标记,依旧会继续走图流程,导致直返无效、流程错乱。

  2. 多工具串联时 return_direct 优先级最低

    同一个Agent挂载多个工具时,只要存在后续可执行工具,直返参数工具会被Agent调度逻辑覆盖,无法终止链路。

  3. return_direct 直返不携带记忆润色

    直返结果完全脱离LLM,不会结合历史对话做上下文适配,纯工具原生输出,若工具未做格式化处理,前端极易出现展示错乱。

5. 工程化最佳实践

  • 检索、问答、搜索类工具:统一约定参数为 False,依靠模型润色整合

  • 规则型、计算型、结构化输出工具:统一约定参数为 True,提速降本控幻觉

  • 直返工具建议搭配Pydantic结构化输出,保证工具返回格式稳定可渲染


二、Pydantic 模型约束返回体

1. 为什么必须强制Pydantic约束?

大模型原生输出是自由自然语言,存在三大工程问题:

  1. 字段忽多忽少、随机缺失

  2. 输出格式不统一(时而JSON、时而文本、时而换行)

  3. 特殊字符乱码、嵌套层级错乱、无法对接后端接口

在私有化小模型、低参数量模型、复杂业务prompt场景下,格式幻觉概率会指数级上升 。 Pydantic结构化输出,是LangChain官方唯一推荐的生产级标准化落地方案

2. 工作原理

  1. 开发者基于 Pydantic V2 定义数据模型:字段名、字段类型、必填规则、默认值、字段描述、校验规则

  2. 通过 PydanticOutputParser 绑定模型,自动生成固定格式约束Prompt

  3. 将格式约束注入系统提示词,强制模型必须输出合规JSON

  4. 模型输出后,解析器自动校验:类型校验、空值校验、字段校验

  5. 校验失败自动抛出异常,可配置重试/兜底逻辑,避免服务崩溃

3. 能力详解

(1)强类型强制约束

支持字符串、数字、布尔、枚举、嵌套模型、列表、字典等所有类型,彻底杜绝「类型错乱」。 比如强制分数为float、ID为字符串、状态为枚举值,从根源避免脏数据。

(2)Field语义约束

通过 Field(description="", required=True, default=xxx) 给模型明确业务语义:

  • 告诉模型每个字段代表什么业务含义

  • 强制必填字段不能为空

  • 异常场景自动填充默认值 大幅降低模型字段遗漏、语义混淆的问题。

(3)自动纠错与解析兜底

LangChain解析器具备轻度容错能力:

  • 自动剔除markdown代码块```json标记

  • 自动修复首尾多余字符、换行、空格

  • 配合try-catch可实现解析失败重试、降级兜底输出

(4)适配LangGraph状态流转

Graph的State状态本质是字典结构,Pydantic模型可直接序列化/反序列化,完美适配状态存储、节点传参、上下文回溯

4. 使用方式

python 复制代码
# pydantic 模型
class AnalysisResult(BaseModel):
    param1: bool
    param2: str = Field(default="xxx")
​
agent = create_agent(
        model=model,
        system_prompt=system_prompt,
        name="base-agent",
        # 约定返回结构
        response_format=AnalysisResult,
    )

5. 价值

  1. 彻底消灭输出随机性:无论模型、轮次、输入如何变化,输出结构永远统一

  2. 前后端无缝对接:固定JSON结构,可直接用于前端渲染、数据库存储、第三方接口回调

  3. 降低运维成本:无需人工处理格式错乱,减少线上报错、日志异常

  4. 适配多节点协同:多智能体、多工具、多节点工作流中,统一数据协议,无对接成本


三、LangChain + LangGraph 实践

1. 轻量简单业务(单能力、单工具)

直接使用 LangChain 原生 Agent + 自定义 Tool

  • 确定性结果工具:return_direct=True

  • 检索润色类工具:return_direct=False

  • 全部输出启用 Pydantic 结构化约束

优势:开发快、结构简单、无需Graph编排、运维成本低

2. 复杂业务(多能力、多分支、多路由)

采用 LangGraph 分层架构:

  1. 路由节点:LLM意图识别,分发不同业务技能节点

  2. 技能节点:拆分独立Agent能力,各司其职

  3. 输出节点:统一结构化结果封装、兜底处理

优势:拆分单Agent超大Prompt、降低Token消耗、减少模型幻觉、流程可追溯

3. 流式业务强制规范

  • 所有节点禁止阻塞式嵌套调用

  • 统一使用astream流式消费

  • 所有输出强制Pydantic约束

  • 手动管控Graph终止逻辑,杜绝死循环

4. 通用准则

  1. 永远不要让单Agent承载过多Prompt和工具

  2. 永远不要信任大模型自由文本输出

  3. Graph节点返回必须遵循State结构,禁止随意返回值

  4. 嵌套Agent优先子图方案,禁止黑盒阻塞调用


四、核心总结

  1. return_direct 管控工具推理链路,解决冗余推理、Token浪费、模型二次篡改问题,是工具层的流程开关;

  2. Pydantic结构化输出 从数据层根治模型格式幻觉,是大模型应用从Demo走向工业化的必备约束;

  3. 工业化智能体开发的核心逻辑:分层解耦 + 结构约束 + 流程可控 + 流式保真

关于我:后续会持续分享 Agent 开发的实战经验,欢迎关注。