【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,教程通俗易懂,风趣幽默,从深度学习基础原理到各领域实战应用都有讲解。

相关推荐
程序猿炎义2 小时前
【Easy-VectorDB】Faiss核心功能进阶
人工智能·向量数据库
轻造科技2 小时前
包装管理系统+尺寸匹配算法:根据产品规格自动推荐包装方案,材料浪费减少25%
人工智能·mes·mes系统
DS随心转APP2 小时前
deepseek公式复制方法
人工智能·ai·deepseek·ds随心转
打点计时器2 小时前
深度模型量化入门(一)
人工智能·深度学习
BHXDML2 小时前
计算视视觉:实验一车牌检测与识别
人工智能·计算机视觉
迦蓝叶2 小时前
Javaluator 与 Spring AI 深度集成:构建智能表达式计算工具
人工智能·spring·ai·语言模型·tools·spring ai·mcp
爱学习的张大2 小时前
transform基础练习(从细节里面理解)
人工智能·pytorch·深度学习
木土雨成小小测试员2 小时前
Python测试开发之后端一
开发语言·数据库·人工智能·python·django·sqlite
轴测君2 小时前
卷积神经网络的开端:LeNet−5
人工智能·神经网络·cnn