多种类型Agent 工具调用机制讲解

概述

工具调用是 Agent 与外部世界交互的核心机制。本教程将详细讲解整个工具调用的完整流程。


一、什么是"工具"?

工具就是普通的 Python 函数 ,预先定义在 tools.py 中。

python 复制代码
# tools/tools.py

def web_search(query: str, search_engine: str = "google", max_results: int = 10) -> str:
    """Search for relevant information on the web"""
    return f"Searched '{query}' on {search_engine}, returned {max_results} results"

def download_file(url: str, save_path: str, file_type: str = "auto") -> str:
    """Download file from URL to local storage"""
    return f"File downloaded from {url} to {save_path}, file type: {file_type}"

def classify_land_cover(image_path: str, classification_scheme: str = "CORINE") -> str:
    """Perform land cover classification on remote sensing imagery"""
    return f"Land cover classification completed, classification scheme: {classification_scheme}"

工具的三要素

要素 说明 示例
函数名 工具的唯一标识符 web_search
文档字符串 工具的功能描述 """Search for relevant information..."""
参数签名 工具的输入参数 query, search_engine, max_results

二、工具注册流程

2.1 add_tool 方法的核心实现

python 复制代码
# agents/base.py

def add_tool(self, func: Callable):
    """Add a tool function to the agent."""
    
    # 1. 提取函数名
    name = func.__name__
    
    # 2. 提取文档字符串作为描述
    description = func.__doc__ or f"Execute {name} function"
    
    # 3. 分析函数签名获取参数信息
    sig = inspect.signature(func)
    parameters = {
        "type": "object",
        "properties": {},
        "required": []
    }
    
    # 4. 遍历参数,分析类型
    for param_name, param in sig.parameters.items():
        if param_name == 'self':
            continue
            
        param_type = "string"  # 默认类型
        if param.annotation != inspect.Parameter.empty:
            if param.annotation == int:
                param_type = "integer"
            elif param.annotation == float:
                param_type = "number"
            elif param.annotation == bool:
                param_type = "boolean"
        
        parameters["properties"][param_name] = {
            "type": param_type,
            "description": f"{param_name} parameter"
        }
        
        # 5. 记录必填参数
        if param.default == inspect.Parameter.empty:
            parameters["required"].append(param_name)
    
    # 6. 存储到字典
    self.tools[name] = {
        "func": func,           # 函数本身
        "description": description,
        "parameters": parameters
    }

2.2 注册示例

python 复制代码
# 创建 Agent
agent = ReActAgent()

# 注册工具
agent.add_tool(web_search)
agent.add_tool(download_file)
agent.add_tool(classify_land_cover)

# 注册后内部结构
self.tools = {
    "web_search": {
        "func": web_search_function,
        "description": "Search for relevant information on the web",
        "parameters": {
            "type": "object",
            "properties": {
                "query": {"type": "string", "description": "query parameter"},
                "search_engine": {"type": "string", "description": "search_engine parameter"},
                "max_results": {"type": "integer", "description": "max_results parameter"}
            },
            "required": ["query"]
        }
    },
    "download_file": {...},
    "classify_land_cover": {...}
}

三、LLM 如何决定调用工具?

3.1 ReAct 模式的提示词设计

python 复制代码
# agents/ReAct.py

def get_action_prompt(self, query: str, thought: str, history: str) -> str:
    """生成行动提示,引导 LLM 选择工具"""
    previous_tool_calls = self.parse_tool_trajectory(history)
    
    return f"""Based on your thinking, decide the next action using function calling.

    User question: {query}
    Your thought: {thought}
    History: {history}
    Your previous_tool_calls: {previous_tool_calls}

    **Decision Rules**:
    1. Check **previous_tool_calls** to avoid repeating same tool call
    2. If sufficient information obtained, do NOT call any function
    3. If must call tools, ensure clear distinction from previous calls
    """

3.2 使用 OpenAI Function Calling API

python 复制代码
# 构建工具 Schema
tools_schema = [
    {
        "type": "function",
        "function": {
            "name": "web_search",
            "description": "Search for relevant information on the web",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {"type": "string", "description": "query parameter"},
                    "max_results": {"type": "integer", "description": "max_results parameter"}
                },
                "required": ["query"]
            }
        }
    }
]

# 调用 LLM
action_response = self.client.chat.completions.create(
    model=self.model,
    messages=[{"role": "user", "content": action_prompt}],
    tools=tools_schema,      # 告诉 LLM 有哪些工具可用
    tool_choice="auto"       # 让 LLM 自动选择
)

# 解析 LLM 的选择
tool_call = action_response.choices[0].message.tool_calls[0]
tool_name = tool_call.function.name      # 例如: "web_search"
args = json.loads(tool_call.function.arguments)  # 例如: {"query": "天气", "max_results": 5}

四、工具的实际执行

4.1 执行流程

python 复制代码
# 从字典中获取函数引用
tool_func = self.tools[tool_name]["func"]

# 使用 LLM 提供的参数调用函数
result = tool_func(**args)

# 示例:实际执行
# tool_func = web_search 函数
# args = {"query": "北京天气", "max_results": 3}
# result = web_search(query="北京天气", max_results=3)

4.2 完整执行流程图

复制代码
┌─────────────────────────────────────────────────────────────────┐
│                        用户提问                                  │
│              "分析这张遥感图像的土地覆盖类型"                     │
└─────────────────────────┬───────────────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────────────┐
│                     LLM 理解问题                                  │
│              确定需要调用 classify_land_cover 工具                │
└─────────────────────────┬───────────────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────────────┐
│               LLM 决定调用参数                                    │
│         tool_name = "classify_land_cover"                       │
│         args = {"image_path": "image.png",                       │
│                  "classification_scheme": "CORINE"}              │
└─────────────────────────┬───────────────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────────────┐
│                    解析并执行工具                                 │
│  result = self.tools["classify_land_cover"]["func"](             │
│      image_path="image.png",                                     │
│      classification_scheme="CORINE"                              │
│  )                                                                │
└─────────────────────────┬───────────────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────────────┐
│                     返回执行结果                                  │
│        "Land cover classification completed..."                 │
└─────────────────────────────────────────────────────────────────┘

五、不同 Agent 的工具调用方式对比

5.1 ReAct Agent(循环式)

python 复制代码
# 特点:每轮循环调用一次工具,实时决定下一步
def run(self, query: str) -> str:
    history = ""
    
    for step in range(self.max_steps):
        # 1. 思考阶段
        thought = self.client.chat.completions.create(...)
        
        # 2. 行动阶段 - 调用 LLM 决定工具
        action_response = self.client.chat.completions.create(
            ...,
            tools=tools_schema,
            tool_choice="auto"
        )
        
        # 3. 实际执行工具
        tool_call = action_response.tool_calls[0]
        result = self.tools[tool_name]["func"](**args)

5.2 Plan & Execute Agent(规划式)

python 复制代码
# 特点:先规划所有工具调用,再批量执行
def run(self, query: str) -> str:
    # 1. 规划阶段 - LLM 生成完整计划
    plan = self.client.chat.completions.create(
        ...,
        response_format=PlanSchema  # JSON 格式
    )
    
    # 2. 执行阶段 - 按计划顺序执行所有工具
    for step in plan.plan:
        result = self.tools[step.tool]["func"](**step.parameters)

5.3 CoT Agent(思维链式)

python 复制代码
# 特点:一次调用生成所有工具调用链,不实际执行
def run(self, query: str) -> str:
    # LLM 在一次调用中生成所有步骤
    result = self.client.chat.completions.create(
        model=self.model,
        messages=[{"role": "user", "content": cot_prompt}],
    )
    
    # 解析轨迹(不执行)
    tool_trajectory = []
    for step in result.split("\n"):
        if step.startswith("step"):
            tool_trajectory.append(step.split(";")[1].strip())

5.4 对比总结

Agent 类型 调用时机 执行方式 实际执行
ReAct 循环中每步调用 实时决定 ✅ 执行
Plan&Execute 规划阶段一次性决定 按计划批量执行 ✅ 执行
CoT 一次生成所有步骤 只解析轨迹 ❌ 不执行
Debate 多轮讨论后决定 最终生成轨迹 ❌ 不执行

六、完整代码示例

python 复制代码
# 完整的工具调用示例
from bench.agents import ReActAgent
from bench.tools import web_search, download_file, classify_land_cover

# 1. 创建 Agent
agent = ReActAgent(model="gpt-4o-mini")

# 2. 注册工具
agent.add_tool(web_search)
agent.add_tool(download_file)
agent.add_tool(classify_land_cover)

# 3. 运行 Agent
user_query = "搜索北京的城市规划信息,然后下载相关文件"
result, history = agent.run(user_query)

# 4. 查看工具调用轨迹
trajectory = agent.run_and_return_tool_trajectory(user_query)
print(trajectory)  # ['web_search', 'download_file']

七、总结

工具调用的核心流程

复制代码
工具定义 → 注册到字典 → LLM 理解问题 → LLM 选择工具 → 解析参数 → 执行函数 → 返回结果

关键理解

  1. 工具 = 普通函数:预先写好的 Python 函数
  2. 注册 = 信息提取:提取函数名、描述、参数类型
  3. LLM 决策:通过提示词告诉 LLM 有哪些工具,LLM 根据问题决定调用哪个
  4. 执行 = 函数调用:找到字典中的函数引用,用参数调用它

整个机制的本质就是 "LLM 决定 + 代码执行" 的协作模式。

相关推荐
Coder_Boy_39 分钟前
技术发展的核心规律是「加法打底,减法优化,重构平衡」
人工智能·spring boot·spring·重构
会飞的老朱3 小时前
医药集团数智化转型,智能综合管理平台激活集团管理新效能
大数据·人工智能·oa协同办公
聆风吟º4 小时前
CANN runtime 实战指南:异构计算场景中运行时组件的部署、调优与扩展技巧
人工智能·神经网络·cann·异构计算
Codebee6 小时前
能力中心 (Agent SkillCenter):开启AI技能管理新时代
人工智能
聆风吟º7 小时前
CANN runtime 全链路拆解:AI 异构计算运行时的任务管理与功能适配技术路径
人工智能·深度学习·神经网络·cann
uesowys7 小时前
Apache Spark算法开发指导-One-vs-Rest classifier
人工智能·算法·spark
AI_56787 小时前
AWS EC2新手入门:6步带你从零启动实例
大数据·数据库·人工智能·机器学习·aws
User_芊芊君子7 小时前
CANN大模型推理加速引擎ascend-transformer-boost深度解析:毫秒级响应的Transformer优化方案
人工智能·深度学习·transformer
智驱力人工智能8 小时前
小区高空抛物AI实时预警方案 筑牢社区头顶安全的实践 高空抛物检测 高空抛物监控安装教程 高空抛物误报率优化方案 高空抛物监控案例分享
人工智能·深度学习·opencv·算法·安全·yolo·边缘计算
qq_160144878 小时前
亲测!2026年零基础学AI的入门干货,新手照做就能上手
人工智能