跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
PythonAI算法

使用 LangChain 构建开源大语言模型智能体实践

如何使用 LangChain 框架结合开源大语言模型构建 ReAct 智能体。文章详细解释了 ReAct 智能体基于推理与行动循环的工作原理,展示了如何通过 ChatHuggingFace 类和 AgentExecutor 实现工具调用。通过基准测试对比发现,Mixtral-8x7B 等开源模型在无需微调的情况下表现优异,甚至超越 GPT-3.5,但也存在工具调用格式不规范等问题。文章最后提供了模型选择、提示词优化及微调增强等最佳实践建议,探讨了开源智能体在降低成本和提升隐私方面的潜力。

NodeJser发布于 2025/2/6更新于 2026/9/262 浏览
使用 LangChain 构建开源大语言模型智能体实践

基于 LangChain 构建开源大语言模型智能体

概要

开源大型语言模型 (LLMs) 现已达到一种性能水平,使它们适合作为推动智能体工作流的推理引擎。例如 Mixtral 等模型在基准测试中甚至超过了 GPT-3.5,并且通过微调,其性能可以轻易得到进一步增强。

引言

针对因果语言建模训练的大型语言模型 (LLMs) 可以处理广泛的任务,但它们经常在逻辑、计算和搜索等基本任务上遇到困难。最糟糕的情况是,它们在某个领域(比如数学)表现不佳,却仍然试图自己处理所有计算。

为了克服这一弱点,除其他方法外,可以将 LLM 整合到一个系统中,在该系统中它可以调用工具:这样的系统称为 LLM 智能体。

在这篇文章中,我们将解释 ReAct 智能体的内部工作原理,然后展示如何使用最近在 LangChain 中集成的 ChatHuggingFace 类来构建它们。最后,我们将几个开源 LLM 与 GPT-3.5 和 GPT-4 进行基准测试对比。

什么是智能体?

LLM 智能体的定义非常宽泛:它们指的是所有将 LLMs 作为核心引擎,并能够根据观察对其环境施加影响的系统。这些系统能够通过多次迭代'感知 ⇒ 思考 ⇒ 行动'的循环来实现既定任务,并常常融入规划或知识管理系统以提升其表现效能。

今天,我们将重点放在 ReAct 智能体 上。ReAct 采用一种基于'推理 (Reasoning)'与'行动 (Acting)'结合的方式来构建智能体。在提示词中,我们阐述了模型能够利用哪些工具,并引导它'逐步'思考(亦称为思维链行为),以规划并实施其后续动作,达成最终的目标。

ReAct 智能体内部工作原理示例

上述图解虽显得有些抽象,但其核心原理其实相当直接。

本质上,LLM 通过一个循环被调用,循环中的提示包含如下内容:

这里是一个问题:'{question}'
你可以使用这些工具:{tools_descriptions}。
首先,你需要进行'思考:{your_thoughts}',接下来你可以:
- 以正确的 JSON 格式发起工具调用,
- 或者,以'最终答案:'为前缀来输出你的答案。

接下来,你需要解析 LLM 的输出:

  1. 如果输出中包含 '最终答案:' 字符串,循环便结束,并输出该答案;
  2. 若不包含,则表示 LLM 进行了工具调用:你需解析此输出以获得工具的名称及其参数,随后根据这些参数执行相应工具的调用。此工具调用的结果将被追加至提示信息中,然后你将带有这些新增信息的提示再次传递给 LLM,直至它获得足够的信息来给出问题的最终答案。

例如,LLM 的输出在回答问题 1:23:45 中有多少秒? 时可能看起来像这样:

{
    "action": "convert_time",
    "action_input": {
        "time": "1:23:45"
    }
}

鉴于此输出未包含 '最终答案:' 字符串,它代表进行了工具调用。因此我们解析该输出,获取工具调用的参数:以参数 {"time": "1:23:45"} 调用 convert_time 工具,执行该工具调用后返回 {'seconds': '5025'}。

于是,我们将这整个信息块追加至提示词中。更新后的提示词现在变为(更为详尽的版本):

这是一个问题:'1:23:45 包含多少秒?'
你可以使用以下工具:
    - convert_time: 将小时、分钟、秒格式的时间转换为秒。

首先,进行'思考:{your_thoughts}',之后你可以:
- 使用正确的 JSON 格式调用工具,
- 或以'最终答案:'为前缀输出你的答案。

思考:我需要把时间字符串转换成秒数。

行动:
{
    "action": "convert_time",
    "action_input": {
        "time": "1:23:45"
    }
}
观测结果:{'seconds': '5025'}

➡️ 我们用这个新的提示再次调用 LLM,鉴于它可以访问工具调用结果中的 观测结果,LLM 现在最有可能输出:

思考:我现在有了回答问题所需的信息。
最终答案:1:23:45 中有 5025 秒。

任务就这样完成了!

智能体系统的挑战

一般来说,运行 LLM 引擎的智能体系统的难点包括:

  1. 从提供的工具中选择一个能够帮助实现目标的工具:例如,当询问 '大于 30,000 的最小质数是什么?' 时,智能体可能会调用 'K2 的高度是多少?' 的 Search 工具,但这并无帮助。这需要模型具备较强的意图识别能力。
  2. 以严格的参数格式调用工具:例如,在尝试计算一辆汽车 10 分钟内行驶 3 公里的速度时,你必须调用 Calculator 工具,通过 distance 除以 time 来计算。即便你的 Calculator 工具接受 JSON 格式的调用 {'tool': 'Calculator', 'args': '3km/10min'},也存在许多陷阱,例如:
    • 工具名称拼写错误:'calculator' 或 'Compute' 是无效的;
    • 提供的是参数名称而非其值:'args': 'distance/time';
    • 格式非标准化:'args": "3km in 10minutes'。
  3. 高效地吸收和利用过去观察到的信息:无论是初始上下文还是使用工具后返回的观察结果,模型需要记住之前的步骤以避免重复工作或产生幻觉。

那么,完整的智能体设置会是怎样的呢?

使用 LangChain 运行智能体

我们在 LangChain 中集成了 ChatHuggingFace 封装器,使你能够基于开源模型创建智能体。

代码实现

创建 ChatModel 并为其配备工具的代码非常简单。以下是完整的 Python 实现示例:

from langchain_community.llms import HuggingFaceHub
from langchain_community.chat_models.huggingface import ChatHuggingFace

# 初始化 HuggingFace Hub LLM
llm = HuggingFaceHub(
    repo_id="HuggingFaceH4/zephyr-7b-beta",
    task="text-generation",
)

# 包装为 ChatModel
chat_model = ChatHuggingFace(llm=llm)

你可以通过为其提供 ReAct 风格的提示词和工具,将 chat_model 转化为一个智能体:

from langchain import hub
from langchain.agents import AgentExecutor, load_tools
from langchain.agents.format_scratchpad import format_log_to_str
from langchain.agents.output_parsers import (
    ReActJsonSingleInputOutputParser,
)
from langchain.tools.render import render_text_description
from langchain_community.utilities import SerpAPIWrapper

# 1. 设置工具
# 加载搜索工具和数学工具
tools = load_tools(["serpapi", "llm-math"], llm=llm)

# 2. 设置 ReAct 风格的提示词
prompt = hub.pull("hwchase17/react-json")
prompt = prompt.partial(
    tools=render_text_description(tools),
    tool_names=", ".join([t.name for t in tools]),
)

# 3. 定义智能体
# 绑定停止符,防止模型继续生成多余内容
chat_model_with_stop = chat_model.bind(stop=["\nObservation"])
agent = (
    {
        "input": lambda x: x["input"],
        "agent_scratchpad": lambda x: format_log_to_str(x["intermediate_steps"]),
    }
    | prompt
    | chat_model_with_stop
    | ReActJsonSingleInputOutputParser()
)

# 4. 实例化 AgentExecutor
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

# 5. 执行任务
result = agent_executor.invoke(
    {
        "input": "Who is the current holder of the speed skating world record on 500 meters? What is her current age raised to the 0.43 power?"
    }
)
print(result["output"])

智能体将处理如下输入并输出中间思考过程:

思考:为了回答这个问题,我需要找出当前速滑世界纪录保持者的年龄。我将使用搜索工具来获取这些信息。
行动:
{
"action": "search",
"action_input": "速滑 500 米世界纪录保持者的年龄"
}
观察:...

智能体对决:开源 LLM 作为通用推理智能体的表现如何?

评估目标

我们旨在评估开源大型语言模型 (LLMs) 作为通用推理智能体的表现。因此,我们选择了需要运用逻辑和使用基本工具(如计算器和互联网搜索访问)的问题。

测试结果分析

鉴于开源模型并没有针对特定的输出格式进行特别的函数调用微调,相较于 OpenAI 智能体,它们处于稍微不利的位置。

尽管存在这样的不利条件,某些模型的表现依然非常优秀!

这是 Mixtral-8x7B 回答'贵阳和塔城哪个城市人口更多?'问题的示例:

思考:为了回答这个问题,我需要找到贵阳和塔城当前的人口数。我将利用搜索工具来查询这些信息。
操作:
{
    "action": "search",
    "action_input": "贵阳当前人口"
}
4.697 百万 (2016 年)
思考:我已获得贵阳的人口数,为 4.697 百万 (截至 2016 年)。现在,我将再次使用搜索工具来确定塔城的人口数。
操作:
{
    "action": "search",
    "action_input": "塔城当前人口"
}
人口:新疆:塔城的数据在 2021 年报告为 1,110,000 人。
...我已确定塔城的人口约为 1.11 百万 (截至 2021 年)。
最终答案:贵阳的人口更多,约为 4.697 百万 (截至 2016 年),而塔城的人口约为 1.11 百万 (截至 2021 年)。

这是各模型在我们的评估数据集上的基准测试结果(原始平均分按 1-5 的评分量表,已转换为 0-100% 的量表以便阅读):

正如所见,一些开源模型在推动智能体工作流程方面表现欠佳:虽然对于小型的 Zephyr-7b 而言这是预期之中的,但令人惊讶的是 Llama2-70b 的表现相当差。然而,Mixtral-8x7B 的表现非常出色:它甚至超越了 GPT-3.5!

这是即开即用的性能:与 GPT-3.5 不同的是,据我们所知,Mixtral 没有针对智能体工作流程进行过微调,这在一定程度上影响了其性能。例如,在 GAIA 上,因为 Mixtral 尝试使用格式不正确的参数调用工具,导致 10% 的问题失败。如果对功能调用和任务规划技能进行适当的微调,Mixtral 的得分可能会更高。

最佳实践建议

基于上述实验结果,在实际生产环境中部署开源智能体时,建议遵循以下原则:

  1. 模型选择:优先选择参数量较大且架构较新的开源模型(如 Mixtral 系列),它们在复杂推理任务上更接近商业闭源模型。
  2. 提示词工程:优化 ReAct 模板,明确工具的描述和调用格式,减少模型产生幻觉的概率。
  3. 微调增强:如果预算允许,使用特定领域的工具调用数据对模型进行 SFT(监督微调),可以显著提升工具调用的准确率和成功率。
  4. 监控与日志:开启 verbose=True 模式记录智能体的每一步思考过程,便于排查错误和优化 Prompt。

总结

本文详细介绍了如何利用 LangChain 框架结合开源大语言模型构建 ReAct 智能体。通过对比测试发现,尽管开源模型在原生支持上略逊一筹,但经过适当优化的 Mixtral-8x7B 已经具备了超越 GPT-3.5 的推理能力。随着开源生态的成熟和微调技术的普及,开源智能体将在更多实际场景中替代或补充商业 API,降低 AI 应用成本并提升数据隐私安全性。

目录

  1. 基于 LangChain 构建开源大语言模型智能体
  2. 概要
  3. 引言
  4. 什么是智能体?
  5. ReAct 智能体内部工作原理示例
  6. 智能体系统的挑战
  7. 使用 LangChain 运行智能体
  8. 代码实现
  9. 初始化 HuggingFace Hub LLM
  10. 包装为 ChatModel
  11. 1. 设置工具
  12. 加载搜索工具和数学工具
  13. 2. 设置 ReAct 风格的提示词
  14. 3. 定义智能体
  15. 绑定停止符,防止模型继续生成多余内容
  16. 4. 实例化 AgentExecutor
  17. 5. 执行任务
  18. 智能体对决:开源 LLM 作为通用推理智能体的表现如何?
  19. 评估目标
  20. 测试结果分析
  21. 最佳实践建议
  22. 总结

更多推荐文章

查看全部
  • CSS 基础:width 与 height 尺寸属性详解
  • Python 3.12 日志核心:深入理解 LogRecord 机制
  • 基于 Rokid CXR-M SDK 的 AR 演讲提词器开发
  • 从零开发 AR 演讲提词器:基于 Rokid CXR-M SDK 的实战指南
  • NVIDIA AI Enterprise 运维指南:医疗行业部署与训练路径
  • 从零构建 gRPC 跨语言通信:C++ 服务端与 C# 客户端
  • 大语言模型发展历程、构建与使用指南
  • 基于 Nexent 平台搭建育儿问答智能体实战
  • DeepSeek-OCR-WEBUI 镜像快速部署与使用指南
  • 基于大模型的智能体开发:从入门到实战的思路与技巧
  • Webmin CVE-2019-15107 漏洞从后门到修复的时间线分析
  • OpenClaw AI Agent 框架核心优势与技术架构解析
  • 从 GAN 到 ChatGPT:AIGC 技术演进与实战应用指南
  • 基于 OpenCode + OpenSpec 的企业级 AI Coding 工程化落地实践
  • OpenStack 架构概念图与核心组件解析
  • 华为 OD 机试真题:挑选宝石 Python & JS 实现
  • Git 远程协作实战指南:从安装到代码提交
  • IDA Pro MCP:用 AI 驱动逆向分析实战
  • Git 本地仓库初始化、提交与分支管理实战
  • Vivado 连接 JTAG 烧录 FPGA 实战指南

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • 随机西班牙地址生成器

    随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online