【Agent从入门到实践】31 工具调用的核心逻辑:Agent如何选择并执行工具

文章目录

    • 前言
    • 一、先搞懂:Agent为什么需要"工具"?
    • 二、工具调用的核心流程(4步走,记牢!)
      • [1. 理解用户意图(Think)](#1. 理解用户意图(Think))
      • [2. 选择合适的工具(Select Tool)](#2. 选择合适的工具(Select Tool))
      • [3. 执行工具(Execute)](#3. 执行工具(Execute))
      • [4. 把结果返回给用户(Feedback)](#4. 把结果返回给用户(Feedback))
    • [三、工具调用的 3 种核心模式(最新主流方案)](#三、工具调用的 3 种核心模式(最新主流方案))
      • [模式1:函数调用(Function Calling)------ 最常用、最稳定](#模式1:函数调用(Function Calling)—— 最常用、最稳定)
      • [模式2:ReAct(Reason + Act)------ 边思考边行动](#模式2:ReAct(Reason + Act)—— 边思考边行动)
      • [模式3:计划执行(Plan & Execute)------ 先规划再干活](#模式3:计划执行(Plan & Execute)—— 先规划再干活)
    • [四、动手实现:极简Agent + 工具调用(Python可运行)](#四、动手实现:极简Agent + 工具调用(Python可运行))
      • [1. 项目结构(超简单)](#1. 项目结构(超简单))
      • [2. 第一步:写工具库(tools.py)------ Agent的"手脚"](#2. 第一步:写工具库(tools.py)—— Agent的“手脚”)
      • [3. 第二步:写Agent核心逻辑(agent.py)------ 指挥系统](#3. 第二步:写Agent核心逻辑(agent.py)—— 指挥系统)
      • [4. 第三步:写启动入口(main.py)------ 一键运行](#4. 第三步:写启动入口(main.py)—— 一键运行)
      • [5. 第四步:配置 .env 文件(和之前一样)](#5. 第四步:配置 .env 文件(和之前一样))
      • [6. 安装依赖(极简,只装必要的)](#6. 安装依赖(极简,只装必要的))
    • 五、运行效果演示(看一遍就懂)
    • 六、核心知识点总结(敲黑板!)

目前国内还是很缺AI人才的,希望更多人能真正加入到AI行业,共同促进行业进步。想要系统学习AI知识的朋友可以看看我的教程http://blog.csdn.net/jiangjunshow,教程通俗易懂,风趣幽默,从深度学习基础原理到各领域实战应用都有讲解。

前言

各位小伙伴,上一篇咱们把代码注释生成Agent从0到1跑通了,能自动解析代码、调用大模型生成注释。但你有没有想过:Agent怎么知道"什么时候该用什么工具"? 比如遇到数学计算、查资料、调接口、写文件这些事,它不是瞎猜,而是有一套完整的"决策+执行+反馈"逻辑。

这篇就用最口语、最接地气的方式,把Agent工具调用的核心逻辑讲透,再用Python写一个可运行的极简示例,让你一看就懂、一跑就会!


一、先搞懂:Agent为什么需要"工具"?

先打个比方:

  • 大模型就像**"大脑",会思考、会说话、会推理,但不会真的"动手"**(比如算 12345×67890、查今天北京天气、写文件到本地);
  • 工具就像**"手和脚"**,计算器、搜索引擎、API、文件读写、代码执行器......专门干"脏活累活"。

Agent = 大脑(大模型) + 手脚(工具) + 指挥系统(工具调用逻辑)

没有工具的Agent,只能"纸上谈兵";有了工具,才能真正落地解决问题!


二、工具调用的核心流程(4步走,记牢!)

不管多复杂的Agent,工具调用都逃不过这 4 步,我叫它**"思考-选工具-执行-反馈"闭环**:

1. 理解用户意图(Think)

Agent先把用户的问题"翻译"成自己能懂的指令:

  • 用户问:"帮我算 12345 × 67890 等于多少,再把结果存到 result.txt 里"
  • Agent理解:需要计算 + 写文件两个动作

2. 选择合适的工具(Select Tool)

Agent根据意图,从"工具库"里挑出能用的工具:

  • 工具库可能有:计算器、文件读写、搜索引擎、代码执行器、API调用器......
  • 上面的问题 → 选:calculator + file_writer

3. 执行工具(Execute)

Agent把参数传给工具,让工具"干活":

  • calculator 传:12345 * 67890
  • file_writer 传:文件名 result.txt,内容是计算结果

4. 把结果返回给用户(Feedback)

工具执行完,把结果返回给Agent,Agent再整理成自然语言回答用户:

  • "计算结果是:838102050,已保存到 result.txt 文件中。"

关键:这 4 步可能循环 N 次!

比如用户问:"帮我查今天北京天气,然后写个天气总结存到文件里"

→ 先调用search查天气 → 拿到结果 → 再调用file_writer写文件 → 最后回答用户。


三、工具调用的 3 种核心模式(最新主流方案)

现在业界主流就 3 种,从简单到复杂,我给你讲人话版:

模式1:函数调用(Function Calling)------ 最常用、最稳定

原理 :大模型直接输出"工具名+参数"的结构化数据(比如JSON),Agent解析后调用对应工具。
代表 :OpenAI Function Calling、通义千问 Function Call、Anthropic Tool Use
优点 :准确率高、速度快、易实现
缺点:依赖大模型支持,工具不能太复杂

模式2:ReAct(Reason + Act)------ 边思考边行动

原理 :大模型先输出"思考过程",再输出"行动(工具+参数)",循环直到问题解决。
代表 :LangChain ReAct、AutoGPT、BabyAGI
优点 :可解释性强,适合复杂多步任务
缺点:速度慢,容易"想太多"或"卡循环"

模式3:计划执行(Plan & Execute)------ 先规划再干活

原理 :Agent先制定完整"执行计划"(比如步骤1、步骤2、步骤3),再按计划依次调用工具。
代表 :Plan-and-Solve、GPT-4 Planner、LangChain PlanExecute
优点 :适合长流程、多工具协作任务
缺点:计划可能出错,需要"重规划"能力

日常开发首选:模式1(Function Calling),简单、稳定、好落地!下面咱们就用它写示例。


四、动手实现:极简Agent + 工具调用(Python可运行)

咱们做一个极简但完整的Agent,支持 3 个工具:

  1. calculator:计算器(加减乘除)
  2. file_writer:写文件到本地
  3. web_search:模拟搜索引擎(这里用假数据,真实场景可接SerpAPI/百度API)

1. 项目结构(超简单)

复制代码
agent_tool_demo/
├── agent.py       # Agent核心逻辑
├── tools.py       # 工具库
└── main.py        # 启动入口

2. 第一步:写工具库(tools.py)------ Agent的"手脚"

所有工具都在这里,每个工具是一个函数,有名称描述参数,方便大模型识别。

python 复制代码
# tools.py
def calculator(expression: str) -> str:
    """
    计算器工具:支持加减乘除四则运算
    :param expression: 数学表达式,比如 "123 + 456"、"789 * 10"
    :return: 计算结果字符串
    """
    try:
        # 安全计算(真实场景建议用 ast.literal_eval 或第三方库)
        result = eval(expression)
        return f"计算结果:{result}"
    except Exception as e:
        return f"计算失败:{str(e)}"

def file_writer(filename: str, content: str) -> str:
    """
    写文件工具:将内容写入指定文件
    :param filename: 文件名,比如 "result.txt"
    :param content: 要写入的内容
    :return: 执行结果字符串
    """
    try:
        with open(filename, "w", encoding="utf-8") as f:
            f.write(content)
        return f"文件写入成功:{filename}"
    except Exception as e:
        return f"写入失败:{str(e)}"

def web_search(query: str) -> str:
    """
    模拟搜索引擎工具:返回假数据(真实场景接SerpAPI/百度/谷歌API)
    :param query: 搜索关键词
    :return: 搜索结果字符串
    """
    # 模拟数据
    mock_results = {
        "北京今天天气": "北京今天晴,15-25℃,微风,适合出行",
        "Python最新版本": "Python最新稳定版是 3.12.0,发布于2023-10-02",
        "AI Agent工具调用": "主流工具调用模式:Function Calling、ReAct、Plan&Execute"
    }
    return mock_results.get(query, f"未找到关于 '{query}' 的信息")

# 工具清单:给大模型看的"工具菜单"(关键!)
TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "calculator",
            "description": "计算器,支持加减乘除四则运算,比如计算 123 * 456",
            "parameters": {
                "type": "object",
                "properties": {
                    "expression": {
                        "type": "string",
                        "description": "数学表达式,如 '123 + 456'、'789 * 10'"
                    }
                },
                "required": ["expression"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "file_writer",
            "description": "将内容写入指定文件,比如把结果存到 result.txt",
            "parameters": {
                "type": "object",
                "properties": {
                    "filename": {
                        "type": "string",
                        "description": "文件名,如 'result.txt'"
                    },
                    "content": {
                        "type": "string",
                        "description": "要写入的文件内容"
                    }
                },
                "required": ["filename", "content"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "web_search",
            "description": "搜索引擎,查询天气、知识、新闻等信息",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {
                        "type": "string",
                        "description": "搜索关键词,如 '北京今天天气'、'Python最新版本'"
                    }
                },
                "required": ["query"]
            }
        }
    }
]

# 工具映射:工具名 → 函数(方便Agent调用)
TOOL_MAP = {
    "calculator": calculator,
    "file_writer": file_writer,
    "web_search": web_search
}

3. 第二步:写Agent核心逻辑(agent.py)------ 指挥系统

核心就是:接收用户问题 → 调用大模型判断是否用工具 → 解析工具调用 → 执行工具 → 返回结果

这里用OpenAI Function Calling(没有OpenAI也可以用通义千问,逻辑几乎一样)。

python 复制代码
# agent.py
import json
from openai import OpenAI
from dotenv import load_dotenv
import os
from tools import TOOLS, TOOL_MAP

# 加载环境变量(OPENAI_API_KEY)
load_dotenv()
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

class ToolCallAgent:
    def __init__(self):
        # 对话历史(保持上下文,多轮工具调用需要)
        self.messages = [
            {"role": "system", "content": "你是一个专业的AI助手,擅长使用工具解决问题。如果需要工具,严格按函数调用格式返回;如果不需要工具,直接回答用户。"}
        ]

    def _call_llm(self, use_tools: bool = True):
        """调用大模型,支持工具调用"""
        kwargs = {
            "model": "gpt-3.5-turbo",
            "messages": self.messages,
            "temperature": 0.3
        }
        if use_tools:
            kwargs["tools"] = TOOLS
            kwargs["tool_choice"] = "auto"  # 自动选择是否用工具
        
        response = client.chat.completions.create(**kwargs)
        return response.choices[0].message

    def run(self, user_query: str) -> str:
        """
        运行Agent,处理用户问题
        :param user_query: 用户问题
        :return: 最终回答
        """
        # 1. 把用户问题加入对话历史
        self.messages.append({"role": "user", "content": user_query})
        print(f"🤖 用户问题:{user_query}")

        # 2. 循环处理工具调用(可能多轮)
        while True:
            # 调用大模型
            response_msg = self._call_llm(use_tools=True)
            # 把大模型回复加入历史
            self.messages.append(response_msg)

            # 3. 判断是否需要调用工具
            tool_calls = response_msg.tool_calls
            if not tool_calls:
                # 没有工具调用,直接返回回答
                return response_msg.content

            # 4. 有工具调用,逐个执行
            print(f"\n🛠️  准备调用工具:{[tc.function.name for tc in tool_calls]}")
            tool_responses = []
            for tc in tool_calls:
                tool_name = tc.function.name
                tool_args = json.loads(tc.function.arguments)
                tool_func = TOOL_MAP.get(tool_name)

                if not tool_func:
                    tool_resp = f"工具 {tool_name} 不存在"
                else:
                    print(f"   执行工具:{tool_name},参数:{tool_args}")
                    # 执行工具
                    tool_resp = tool_func(**tool_args)
                    print(f"   工具结果:{tool_resp}")

                # 把工具执行结果加入对话历史(关键!大模型需要知道结果)
                tool_responses.append({
                    "tool_call_id": tc.id,
                    "role": "tool",
                    "name": tool_name,
                    "content": tool_resp
                })

            # 5. 把工具结果返回给大模型,进入下一轮循环
            self.messages.extend(tool_responses)

# 测试(单独运行 agent.py)
if __name__ == "__main__":
    agent = ToolCallAgent()
    # 测试1:计算 + 写文件
    # resp = agent.run("帮我算 12345 × 67890 等于多少,然后把结果存到 result.txt 里")
    # 测试2:查天气 + 写总结
    resp = agent.run("帮我查北京今天天气,然后写一个天气总结存到 weather.txt 里")
    print(f"\n🎉 最终回答:{resp}")

4. 第三步:写启动入口(main.py)------ 一键运行

python 复制代码
# main.py
from agent import ToolCallAgent

def main():
    print("🚀 工具调用Agent已启动!输入 'exit' 退出")
    agent = ToolCallAgent()
    while True:
        user_input = input("\n请输入你的问题:")
        if user_input.lower() in ["exit", "quit", "q"]:
            print("👋 再见!")
            break
        # 运行Agent
        answer = agent.run(user_input)
        print(f"\n✅ Agent回答:{answer}")

if __name__ == "__main__":
    main()

5. 第四步:配置 .env 文件(和之前一样)

env 复制代码
OPENAI_API_KEY="sk-你的OpenAI密钥"

6. 安装依赖(极简,只装必要的)

bash 复制代码
pip install openai python-dotenv

五、运行效果演示(看一遍就懂)

运行 python main.py,输入问题:

帮我查北京今天天气,然后写一个天气总结存到 weather.txt 里

输出流程

复制代码
🚀 工具调用Agent已启动!输入 'exit' 退出

请输入你的问题:帮我查北京今天天气,然后写一个天气总结存到 weather.txt 里
🤖 用户问题:帮我查北京今天天气,然后写一个天气总结存到 weather.txt 里

🛠️  准备调用工具:['web_search']
   执行工具:web_search,参数:{'query': '北京今天天气'}
   工具结果:北京今天晴,15-25℃,微风,适合出行

🛠️  准备调用工具:['file_writer']
   执行工具:file_writer,参数:{'filename': 'weather.txt', 'content': '北京今天天气总结:晴,15-25℃,微风,适合出行。'}
   工具结果:文件写入成功:weather.txt

✅ Agent回答:已为你查询到北京今天天气:晴,15-25℃,微风,适合出行,并将天气总结写入 weather.txt 文件中。

本地会生成weather.txt,内容就是天气总结。

完美!这就是Agent工具调用的完整闭环


六、核心知识点总结(敲黑板!)

  1. Agent = 大模型(大脑) + 工具(手脚) + 工具调用逻辑(指挥)
  2. 核心流程:理解意图 → 选工具 → 执行 → 反馈(可循环)
  3. 主流模式:Function Calling(首选)、ReAct、Plan&Execute
  4. 关键细节
    • 工具必须有清晰的名称、描述、参数(大模型才能看懂)
    • 工具执行结果必须返回给大模型(上下文很重要)
    • 多轮工具调用需要保留对话历史
  5. 真实场景扩展
    • 工具库可以加:代码执行器、数据库查询、API调用、浏览器操作(Playwright)、邮件发送......
    • 大模型可以换:通义千问、文心一言、Claude、Llama 3(本地大模型也支持Function Calling)
    • 可以加:工具权限控制、工具执行失败重试、工具调用日志、用户确认机制

目前国内还是很缺AI人才的,希望更多人能真正加入到AI行业,共同促进行业进步。想要系统学习AI知识的朋友可以看看我的教程http://blog.csdn.net/jiangjunshow,教程通俗易懂,风趣幽默,从深度学习基础原理到各领域实战应用都有讲解。

相关推荐
火车叼位7 小时前
也许你不需要创建.venv, 此规范使python脚本自备依赖
python
CoderIsArt7 小时前
三大主流智能体框架解析
人工智能
火车叼位7 小时前
脚本伪装:让 Python 与 Node.js 像原生 Shell 命令一样运行
运维·javascript·python
民乐团扒谱机7 小时前
【微实验】机器学习之集成学习 GBDT和XGBoost 附 matlab仿真代码 复制即可运行
人工智能·机器学习·matlab·集成学习·xgboost·gbdt·梯度提升树
Coder_Boy_8 小时前
Deeplearning4j+ Spring Boot 电商用户复购预测案例中相关概念
java·人工智能·spring boot·后端·spring
芷栀夏8 小时前
CANN ops-math:揭秘异构计算架构下数学算子的低延迟高吞吐优化逻辑
人工智能·深度学习·神经网络·cann
L543414468 小时前
告别代码堆砌匠厂架构让你的系统吞吐量翻倍提升
大数据·人工智能·架构·自动化·rpa
孤狼warrior8 小时前
YOLO目标检测 一千字解析yolo最初的摸样 模型下载,数据集构建及模型训练代码
人工智能·python·深度学习·算法·yolo·目标检测·目标跟踪
凯子坚持 c8 小时前
构建企业级 AI 工厂:基于 CANN `cann-mlops-suite` 的端到端 MLOps 实战
人工智能
Elwin Wong8 小时前
浅析OpenClaw:从“贾维斯”梦想看下一代 AI 操作系统的架构演进
人工智能·agent·clawdbot·moltbot·openclaw