当前位置: 首页 > news >正文

LangChain-Chatchat 开发与应用(六) Agent能力揭秘-让大模型不仅能聊天还能干活

Agent 能力揭秘:让大模型不仅能"聊天",还能"干活"

标签:Agent | Function Call | 工具调用 | 自主决策 | ReAct


一、从一个"不够用"的场景说起

前面几篇,咱们搭的知识库问答系统已经能回答很多问题了。但很快你会发现:

用户问:“今天北京天气怎么样?”

系统答:“抱歉,知识库中没有关于天气的信息。”

用户:“…”

知识库只能回答"已知的、静态的"信息,但用户的问题可能是实时的、动态的——天气、股价、新闻…

这时候就需要Agent出场了。


二、Agent 是什么?和普通对话有什么区别?

2.1 一句话定义

Agent = LLM + 工具(Tools)+ 自主决策能力

普通对话:LLM 只用自己的"脑子"(训练数据)回答问题。

Agent 对话:LLM 可以"动手"——调用外部工具获取实时信息,然后再回答。

2.2 对比图

普通 LLM 对话: 用户提问 ──→ LLM ──→ 回答 ↑ └─ 只用训练数据 Agent 对话: 用户提问 ──→ LLM ──→ 需要实时数据?──→ 调用工具 ──→ 获取结果 ↑ ↓ └─ 结合训练数据 + 工具结果 ←────┘

2.3 Chatchat 的 Agent 能力

Chatchat 0.3.x 对 Agent 做了大幅增强,支持:

能力说明
工具调用让模型自动选择并调用工具
多轮决策复杂任务可以分多步执行
内置工具搜索引擎、数据库、ARXIV、Wolfram 等
自定义工具开发自己的工具接入系统
Function Call结构化工具调用,更可靠

三、Agent 的核心机制:ReAct

3.1 什么是 ReAct?

ReAct =Reasoning(推理)+Acting(行动)

核心思想:LLM 不直接回答,而是先思考、再行动、再观察、再思考…循环直到解决问题。

3.2 ReAct 的循环过程

用户提问:"今天北京气温多少?适合穿什么衣服?" ↓ [思考 1] 用户问的是北京今天的天气和穿衣建议。 我需要先获取北京的实时天气数据。 ↓ [行动 1] 调用工具:search_weather(city="北京") ↓ [观察 1] 工具返回:北京今天晴,气温 15-25°C,微风 ↓ [思考 2] 现在有了天气数据。气温 15-25°C,比较舒适。 可以建议穿薄外套或长袖。 ↓ [行动 2] 不需要再调用工具了,直接生成回答 ↓ [最终回答] 北京今天天气晴,气温 15-25°C,建议穿薄外套...

3.3 ReAct 的 Prompt 模板

你可以使用以下工具: {tools_description} 请按以下格式回答: 问题:用户的问题 思考:分析当前情况,决定下一步行动 行动:选择要调用的工具,格式为 {"tool": "工具名", "input": "参数"} 观察:工具返回的结果 ...(思考、行动、观察可以循环多次) 最终回答:基于所有观察结果,给出最终答案 开始! 问题:{user_question}

四、Function Call:更靠谱的工具调用

4.1 传统 ReAct 的问题

传统 ReAct 是让模型自由生成工具调用指令,格式不固定,容易出错:

模型输出:"我需要查一下天气,让我调用 search_weather 工具,参数是北京" ↑ 这种自然语言描述,解析起来很费劲

4.2 Function Call 的改进

Function Call 让模型输出结构化的 JSON,更可靠:

{"tool":"search_weather","input":{"city":"北京"}}

支持 Function Call 的模型:

  • GPT-4 / GPT-3.5-turbo
  • Qwen2(通义千问)
  • ChatGLM4
  • Claude 3

4.3 Chatchat 中的 Function Call

Chatchat 的chat/completions接口兼容 OpenAI 的 Function Call 格式:

importopenai client=openai.OpenAI(api_key="EMPTY",base_url="http://localhost:7861/v1")# 定义可用工具tools=[{"type":"function","function":{"name":"search_weather","description":"查询指定城市的天气","parameters":{"type":"object","properties":{"city":{"type":"string","description":"城市名称"}},"required":["city"]}}}]# 发送请求response=client.chat.completions.create(model="qwen2-instruct",messages=[{"role":"user","content":"北京今天天气怎么样?"}],tools=tools,tool_choice="auto"# 让模型自动决定是否调用工具)# 模型可能返回工具调用请求ifresponse.choices[0].message.tool_calls:tool_call=response.choices[0].message.tool_calls[0]print(f"模型要调用工具:{tool_call.function.name}")print(f"参数:{tool_call.function.arguments}")

五、Chatchat 内置工具详解

5.1 工具一览

Chatchat 内置了多种实用工具:

工具功能配置要求
search_internet搜索引擎(Bing/Google)需要 API Key
search_arxivARXIV 学术论文搜索免费
search_wolframWolfram Alpha 计算需要 App ID
database_chat数据库自然语言查询配置数据库连接
text2image文生图需要文生图模型
calculator计算器无需配置

5.2 配置搜索引擎工具

# tool_settings.yamlsearch_internet:search_engine:bing# 或 googlebing_search_url:"https://api.bing.microsoft.com/v7.0/search"bing_subscription_key:"your-bing-api-key"top_k:3

5.3 在 WebUI 中使用 Agent

  1. 打开对话页面
  2. 勾选“启用 Agent”
  3. 选择要使用的工具(可多选)
  4. 输入问题,模型会自动判断是否需要调用工具

三种使用模式:

模式操作效果
全自动启用 Agent + 选多个工具模型自己决定调哪个
半自动启用 Agent + 选单个工具模型只填参数,不调选择
手动不启用 Agent + 选单个工具直接调用,不走 LLM

六、自定义工具开发实战

6.1 工具的结构

一个工具需要包含:

# 伪代码:工具的标准结构classMyTool:name="my_tool"# 工具名称description="这个工具能做什么..."# 工具描述(给 LLM 看的)# 参数定义(JSON Schema 格式)args_schema={"type":"object","properties":{"param1":{"type":"string","description":"参数说明"}},"required":["param1"]}definvoke(self,params):"""执行工具逻辑"""result=do_something(params)returnresult

6.2 实战:开发一个"查询公司库存"工具

# custom_tools/inventory_tool.pyfromtypingimportDict,AnyclassInventoryQueryTool:"""查询公司产品库存"""name="query_inventory"description="查询指定产品的库存数量。当用户询问某个产品是否有货、库存多少时,使用此工具。"args_schema={"type":"object","properties":{"product_name":{"type":"string","description":"产品名称,如'iPhone 15'、'MacBook Pro'"},"warehouse":{"type":"string","description":"仓库名称,可选。如'北京仓'、'上海仓'。不指定则查询所有仓库。"}},"required":["product_name"]}def__init__(self):# 实际项目中这里连接数据库或调用库存系统 APIself.mock_db={"iPhone 15":{"北京仓":100,"上海仓":50},"MacBook Pro":{"北京仓":20,"上海仓":30},}definvoke(self,params:Dict[str,Any])->str:product=params["product_name"]warehouse=params.get("warehouse")ifproductnotinself.mock_db:returnf"抱歉,未找到产品 '{product}' 的库存信息。"inventory=self.mock_db[product]ifwarehouse:count=inventory.get(warehouse,0)returnf"{product}{warehouse}的库存为:{count}件"else:total=sum(inventory.values())details=", ".join([f"{k}:{v}件"fork,vininventory.items()])returnf"{product}总库存:{total}件({details})"# 注册工具fromchatchat.server.utilsimportregister_tool register_tool(InventoryQueryTool())

6.3 工具注册到 Chatchat

# 在 server/tool/custom_tools.py 中注册from.inventory_toolimportInventoryQueryTool# 启动时自动加载defload_custom_tools():register_tool(InventoryQueryTool())

6.4 测试自定义工具

importopenai client=openai.OpenAI(api_key="EMPTY",base_url="http://localhost:7861/v1")response=client.chat.completions.create(model="qwen2-instruct",messages=[{"role":"user","content":"iPhone 15 还有货吗?"}],tools=[{"type":"function","function":{"name":"query_inventory","description":"查询指定产品的库存数量","parameters":{"type":"object","properties":{"product_name":{"type":"string"}},"required":["product_name"]}}}],tool_choice="auto")print(response.choices[0].message.content)

七、Agent 的局限与注意事项

7.1 当前局限

局限说明
模型依赖需要支持 Function Call 的模型,老模型不行
延迟较高多轮工具调用会增加响应时间
错误传播工具返回错误信息,模型可能"将错就错"
成本问题多轮调用消耗更多 Token

7.2 最佳实践

  1. 工具描述要清晰:LLM 靠描述决定调不调用,描述不清会误调或漏调
  2. 参数要简单:复杂的嵌套参数模型容易填错
  3. 做好错误处理:工具内部要捕获异常,返回友好的错误信息
  4. 设置超时:防止工具卡死导致整个请求挂掉
  5. 记录调用日志:便于排查问题和优化

八、小结

这篇咱们把 Agent 的方方面面过了一遍:

✅ Agent 的定义:LLM + 工具 + 自主决策
✅ ReAct 机制:思考 → 行动 → 观察的循环
✅ Function Call:结构化的可靠工具调用
✅ Chatchat 内置工具:搜索、ARXIV、Wolfram、数据库等
✅ 自定义工具开发:从结构到实现的完整示例
✅ Agent 的局限和最佳实践

Agent 让 RAG 系统从"静态知识库"进化成了"动态智能助手",能处理更复杂的用户请求。

但记住:Agent 不是万能的。简单问答不需要 Agent,直接走知识库更快。Agent 适合需要实时数据、多步推理的复杂场景。



你在使用 Agent 时遇到过什么有趣或抓狂的情况?模型有没有"自作聪明"调错工具的时候?欢迎分享!

http://www.zskr.cn/news/1326150.html

相关文章:

  • VCSA底层网络配置实战:从IP修改到SSH登录的运维指南
  • Cinemachine - Unity相机进阶:从基础到实战的镜头艺术
  • 基于安信可VC-02与Wi-Fi 6模组打造毫秒级本地智能家居语音控制方案
  • 从DOCK 6.11新特性到实战:RDKit集成与描述符驱动的药物设计
  • STM32F103 ADC多通道采样,用DMA搬运数据到底有多省心?一个数组搞定所有
  • 惠州三岛新材料一站式密封胶解决方案!耐高温密封胶、导热硅胶、玻璃胶、导热垫片、环氧AB胶、平面密封胶生产厂家甄选 - 栗子测评
  • 中小团队如何利用Taotoken用量看板实现API成本精细化管理
  • 为开源Agent工具OpenClaw配置Taotoken作为后端模型的详细教程
  • Unity3d 2020 WebGL部署IIS实战:从SyntaxError到wasm加载失败的完整排错指南
  • 别再死记硬背了!用一张图+三个故事彻底搞懂PCIe TLP帧结构
  • Jetson Nano项目实战:用udev规则永久绑定USB雷达/传感器,告别串口号漂移烦恼
  • 数据分析篇---U型关系与与阈值效应
  • HarmonyOS实战解析:ServiceExtensionAbility的启动、连接与生命周期管理
  • 2026年质量好的长春钢模板/长春钢模板出租/钢模板买卖/钢模板出租品牌厂家推荐 - 品牌宣传支持者
  • CVUSA:跨视角地理定位的基石数据集详解(含论文与资源)
  • Perplexity旅游信息可信度危机:权威信源交叉验证协议(ISO/IEC 25010合规版)首次公开
  • University-1652:首个基于无人机的跨视角地理定位数据集
  • 09. 极速:多级缓存策略与 LRU 算法实战
  • 双人成行2026最新官方正版免费下载 520情侣必玩 一键转存 永久更新 (看到速转存 资源随时走丢)
  • 别再折腾解码器了!用DXVA Checker和GPU-Z一键排查Chrome播不了H265视频的根源
  • 为什么Google Sans Code是程序员的终极选择?5大核心优势详解
  • STM32F407标准库USB Host驱动广和通MC665模块:从官方例程到实战移植的保姆级避坑指南
  • 一文读懂机箱机柜供应商:惠州市凌泰实业,深耕工控/钣金/铝型材/轨道交通/车载信号/仪器仪表/便携式机箱定制配件专业生产 - 栗子测评
  • 避坑指南:RK3568多屏配置中那些让你uboot启动失败的GPIO和PWM复用陷阱
  • 不用Remix在线版!在VSCode里用Hardhat写合约,搭配Ganache和MetaMask本地测试全流程
  • 告别文献混乱!用Zotero+OneDrive打造你的跨设备论文库(附ZotFile插件配置)
  • 2026年评价高的烟台装修公司/烟台全包装修公司/烟台毛坯房装修公司/烟台二手房翻新装修公司哪家经验丰富 - 行业平台推荐
  • VS2019编译OpenCASCADE 7.6.0避坑实录:从custom.bat修改到Demo测试,一次搞定
  • 告别‘天书’!手把手教你用vdex2dex、odex2smali等工具,把Android应用的vdex/odex/cdex转成可读的dex文件
  • Unity Timeline实战:除了过场动画,你的Signal Track和Control Track用对了吗?