基于工具调用的智能体设计与实现
一、这是什么?(概念解释)
基于工具调用的Agent(Tool Calling Agent) 是利用LLM原生函数调用能力实现的智能体。
与ReACT的区别:
- ReACT:依赖Prompt让LLM按特定格式输出(Thought/Action/Observation)
- 工具调用Agent :利用模型原生的
tool_calls功能,更稳定、更高效
核心优势:
- 原生支持:使用模型内置的函数调用能力
- 结构化输出:自动返回结构化的工具调用指令
- 多轮对话:支持聊天历史,可以实现对话式Agent
- 更简洁:无需复杂的Prompt模板
二、有什么用?(应用场景)
| 场景 | 说明 |
|---|---|
| 对话式助手 | 支持多轮对话的智能助手 |
| 任务自动化 | 自动调用工具完成复杂任务 |
| 信息检索 | 结合搜索工具回答问题 |
| 内容生成 | 调用图片/视频生成工具 |
| 数据分析 | 调用数据分析工具生成报告 |
| API集成 - | 调用外部API服务 |
| 多工具协同 | 自动选择和组合多个工具 |
三、完整示例代码
python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import dotenv
import os
import requests
from datetime import datetime
from langchain_classic.agents import create_tool_calling_agent, AgentExecutor
from langchain_community.tools import GoogleSerperRun
from langchain_community.utilities import GoogleSerperAPIWrapper
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.tools import tool
from pydantic import BaseModel, Field
from langchain_openai import ChatOpenAI
dotenv.load_dotenv()
# ============ 第一步:定义工具 ============
@tool
def generate_image(prompt: str) -> str:
"""
使用通义万相生成图片
Args:
prompt: 图片描述提示词
Returns:
生成图片保存到当前目录
"""
try:
# 调用通义万相API生成图片
response = ImageSynthesis.call(
model='wanx-v1',
prompt=prompt,
n=1,
size='1024*1024'
)
if response.status_code == 200:
image_url = response.output.results[0].url
# 下载图片并保存
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"generated_image_{timestamp}.png"
img_response = requests.get(image_url)
if img_response.status_code == 200:
with open(filename, 'wb') as f:
f.write(img_response.content)
return f"图片生成成功!已保存到: {filename}"
else:
return f"图片下载失败"
else:
return f"图片生成失败"
except Exception as e:
return f"图片生成异常: {str(e)}"
# 定义搜索工具
google_serper = GoogleSerperRun(
name="google_serper",
description="一个低成本的谷歌搜索API。当你需要回答有关时事的问题时,可以调用该工具。",
args_schema=GoogleSerperArgsSchema,
api_wrapper=GoogleSerperAPIWrapper(),
)
tools = [google_serper, generate_image]
# ============ 第二步:定义 Prompt ============
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个智能助手,善于帮助用户解决问题。"),
("placeholder", "{chat_history}"), # 聊天历史
("human", "{input}"), # 用户输入
("placeholder", "{agent_scratchpad}"), # Agent执行历史
])
# ============ 第三步:创建工具调用 Agent ============
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
agent = create_tool_calling_agent(
llm=llm,
prompt=prompt,
tools=tools,
)
# ============ 第四步:创建 Agent 执行器 ============
agent_executor = AgentExecutor(
agent=agent,
tools=tools,
verbose=True, # 打印执行过程
max_iterations=5, # 最大迭代次数
handle_parsing_errors=True,
)
# ============ 第五步:执行 Agent ============
result = agent_executor.invoke({
"input": "帮我绘制一幅鲨鱼在天上游泳的场景"
})
print(result)
四、工具调用Agent vs ReACT Agent
sql
┌─────────────────────────────────────────────────────────────────────────┐
│ 工具调用Agent VS ReACT Agent 对比 │
└─────────────────────────────────────────────────────────────────────────┘
================== ReACT Agent ==================
Prompt 复杂度:高
需要精心设计 Prompt 模板
用户问题 LLM 工具执行
│ │ │
▼ ▼ │
"生成鲨鱼图片" ────────────▶│ Thought: 我需要生成图片 │
│ │ │
│ │ Action: generate_image │
│ │ │
│ │ Action Input: "鲨鱼..." │
│◀──────────────────────│ │
▼ │ │
解析 Action Input │ │
│ │ │
▼ ▼ ▼
调用工具 ─────────────────────────────────────────────▶│
│ 生成图片
│◀───────────────────────────────────────│
▼ ▼ ▼
观察 (Observation) "图片已保存" 返回结果
│ │ │
▼ ▼ │
Thought: 我知道答案了 Final Answer: "图片... │
│ │ │
▼ ▼ ▼
返回结果 完成 完成
================== 工具调用 Agent ==================
Prompt 复杂度:低
只需简单的系统提示
用户问题 LLM 工具执行
│ │ │
▼ ▼ │
"生成鲨鱼图片" ────────────▶│ 自动分析需求 │
│ │ │
│ │ 返回 tool_calls: │
│◀──────────────────────│ [{name: "generate_image",│
│ │ args: {prompt: "..."]}}│
▼ │ │
自动解析 tool_calls │ │
│ │ │
▼ ▼ ▼
自动调用工具 ──────────────────────────────────────────▶│
│ 生成图片
│◀───────────────────────────────────────│
▼ ▼ ▼
自动获取工具结果 "图片已保存" 返回结果
│ │ │
▼ ▼ │
自动生成最终回答 "图片已生成并保存..." │
│ │ │
▼ ▼ ▼
返回结果 完成 完成
┌─────────────────────────────────────────────────────────────────────────┐
│ 核心差异 │
└─────────────────────────────────────────────────────────────────────────┘
特性 ReACT Agent 工具调用 Agent
─────────────────────────────────────────────────────────────────────────
Prompt 复杂度 高(需要严格格式) 低(简单提示)
模型兼容性 广(几乎所有模型) 有限(需要支持函数调用)
解析方式 手动解析文本 自动解析 tool_calls
错误处理 容易出错 更稳定
Token消耗 高 低
多轮对话 需要手动管理 自动支持
五、执行流程示例
假设用户问:"帮我搜索一下深圳今天的天气,然后生成一张天气预报图片"
第1轮迭代:
vbnet
> Entering new AgentExecutor chain...
Invoking: google_serper
with: {'query': '深圳今天天气'}
Observation: 深圳今天晴天,温度25°C,湿度60%
第2轮迭代:
vbnet
Thought: 我需要根据天气信息生成一张天气预报图片
Invoking: generate_image
with: {'prompt': '深圳今天晴天,温度25度,湿度60%,天气预报插图'}
Observation: 图片生成成功!已保存到: generated_image_20260305.png
最终回答:
erlang
> Finished chain.
根据搜索结果,深圳今天晴天,温度25°C,湿度60%。
我已经为您生成了一张天气预报插图,保存为:generated_image_20260305.png
参考资源
- LangChain Tool Calling Agents:python.langchain.com/docs/module...
- OpenAI Function Calling:platform.openai.com/docs/guides...
- AgentExecutor 文档:python.langchain.com/docs/module...
总结一句话:工具调用Agent利用模型原生函数调用能力,比ReACT更简洁、更稳定,是构建现代AI应用的首选方案!