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

相关推荐
陈广亮22 分钟前
构建具有长期记忆的 AI Agent:从设计模式到生产实践
人工智能
会写代码的柯基犬31 分钟前
DeepSeek vs Kimi vs Qwen —— AI 生成俄罗斯方块代码效果横评
人工智能·llm
Mintopia1 小时前
OpenClaw 是什么?为什么节后热度如此之高?
人工智能
爱可生开源社区1 小时前
DBA 的未来?八位行业先锋的年度圆桌讨论
人工智能·dba
叁两4 小时前
用opencode打造全自动公众号写作流水线,AI 代笔太香了!
前端·人工智能·agent
敏编程4 小时前
一天一个Python库:jsonschema - JSON 数据验证利器
python
前端付豪4 小时前
LangChain记忆:通过Memory记住上次的对话细节
人工智能·python·langchain
strayCat232554 小时前
Clawdbot 源码解读 7: 扩展机制
人工智能·开源
王鑫星4 小时前
SWE-bench 首次突破 80%:Claude Opus 4.5 发布,Anthropic 的野心不止于写代码
人工智能