← 返回目录
a1.3动手⏱ 约 12 分钟

给小雅装"手":工具调用(含完整可运行代码)

从原理到一份你能直接复制运行的 function calling 代码

🔎 最后验证 2026-06📚 来源:🧰 扣子 Coze、Python、DeepSeek/OpenAI API✅ 49 人学过👁 119 次阅读
为什么学这个

上一节小雅会上网查了。你扔给它一道账:

"机票 800,酒店住 3 晚、每晚 400,一共多花多少?"

它张口就来:"大概 1800 吧。" ——错了(正确 800 + 400×3 = 2000)。大模型天生不擅长精确计算,它是"语感"在估,不是真算。

这一节,我们彻底搞懂"给智能体装手"的原理,然后——给你一份能直接复制、立刻跑起来的 Python 代码,亲手让小雅学会调用工具。学完,你不只是"会配插件",而是真正理解、并能写出工具调用。

一、原理:模型只"点菜",不"做菜"

最关键、也最反直觉的一点:调用工具时,大模型自己并不执行那个工具。 它只做两件事——

  1. 决定:该调用哪个工具、传什么参数;
  2. 读结果:工具被执行后,拿到返回值,再组织成人话。

真正去按计算器、发起搜索的,是模型外面的程序(你的代码 / 平台)。

💡 打个比方

小雅像一个自己不按计算器、但知道"这题得用计算器"的人:他喊一声"帮我算 800+400×3",旁边的助手按下计算器得 2000,递给他,他才说"一共 2000"。模型负责动脑,工具负责动手。

一张图看懂工具调用的来回

用户提问
「一共多花多少?」
模型决定
决定调用 calculator,不亲自执行
程序执行
你的代码运行,得 2000
结果喂回
把 2000 告诉模型
模型作答
「一共 2000 元」

这套"决定 → 执行 → 喂回 → 作答"的来回,就是 function calling(工具调用) 的全部。

二、🔧 上手:一份能直接跑的工具调用代码

下面这段 Python 可以直接复制运行(用 DeepSeek 或任意 OpenAI 兼容接口)。它给小雅装了一个"计算器"工具,完整跑通上面那张图的四步。

准备:pip install openai,把 你的KEY 换成你的 API Key。

# pip install "openai>=1.0"
import json
from openai import OpenAI

client = OpenAI(
    api_key="你的KEY",
    base_url="https://api.deepseek.com",   # 用别家就换成对应地址
)
MODEL = "deepseek-chat"

# ① 真正干活的工具(模型不会执行它,是我们来执行)
def calculator(expression: str) -> str:
    # 注意:真实项目别用 eval,这里仅作教学演示
    try:
        return str(eval(expression))
    except Exception:
        return "算式无效"            # 模型偶尔传来非法算式,兜底别让程序崩

# ② 给模型的"工具说明书":名字 + 用途 + 参数
tools = [{
    "type": "function",
    "function": {
        "name": "calculator",
        "description": "做精确数学运算。输入一个算式字符串,返回数值结果。",
        "parameters": {
            "type": "object",
            "properties": {
                "expression": {"type": "string", "description": "要计算的算式,如 800+400*3"}
            },
            "required": ["expression"],
        },
    },
}]

def ask(user_input: str) -> str:
    messages = [{"role": "user", "content": user_input}]

    # 第一次请求:模型可能决定"要调用工具"
    resp = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
    msg = resp.choices[0].message

    
     msg.tool_calls:
        messages.append(msg)  
         tc  msg.tool_calls:
            args = json.loads(tc.function.arguments)
            result = calculator(**args)          
            ()
            messages.append({
                : ,
                : tc.,
                : result,               
            })
        
        resp = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
        msg = resp.choices[].message

     msg.content

 __name__ == :
    (ask())

运行结果大概长这样:

  [执行] calculator({'expression': '800+400*3'}) = 2000
这趟一共多花 2000 元(机票 800 + 住宿 400×3=1200)。

逐行对应那张图:定义工具(②说明书) → 模型决定调用(①) → calculator(**args) 执行(②返回) → role:"tool" 喂回(③) → 第二次请求得到人话(④)。这 40 行,就是一切"智能体工具调用"的内核——所谓框架,不过是把它包装得更顺手。

❓ 测验
代码里 `calculator(args)` 这一步,是谁在执行计算?

三、案例:再给它加一只"查汇率"的手

工具可以有好几只。把下面这个工具加进 tools 列表、并在执行处加一个分支,小雅就能边算边查汇率了:

# 新增工具:查汇率(演示用固定汇率,真实项目改成调用汇率 API)
RATES = {"USD": 7.2, "EUR": 7.8, "JPY": 0.048}
def exchange_rate(currency: str) -> str:
    return str(RATES.get(currency.upper(), "未知"))

# 加进 tools 列表(写法同 calculator)
tools.append({
    "type": "function",
    "function": {
        "name": "exchange_rate",
        "description": "查询某货币兑人民币的汇率。参数 currency 如 USD/EUR/JPY。",
        "parameters": {
            "type": "object",
            "properties": {"currency": {"type": "string"}},
            "required": ["currency"],
        },
    },
})

# 在执行处按工具名分发(替换原来只有 calculator 的那行):
def run_tool(name, args):
    if name == "calculator":     return calculator(**args)
    if name == "exchange_rate":  return exchange_rate(**args)
    return "未知工具"

现在问它"我在日本花了 30000 日元,折合人民币多少?"——小雅会先查汇率(0.048)、再调计算器(30000×0.048),自己挑对了两只手。这就是"工具箱"的威力。

四、工具的"说明书"决定它会不会用

模型靠你写的 descriptionparameters 来判断"何时用、怎么传"。写好说明,比换更强的模型还管用:

工具说明模型的反应
"description": "处理一些东西"不知道何时用 → 干脆不用
"description": "做精确数学运算,输入算式字符串返回数值""要算数就用它!"
⚠️ 避坑两个真实会踩的坑
  1. 别用 eval 上生产:示例里为省事用了 eval(且未做异常处理),但它能执行任意代码=安全大洞。真实项目要用安全的表达式库,或把工具关进沙箱(第 3 章会讲)。
  2. 工具不是越多越好:塞几十个工具,模型会挑花眼、选错。贵精不贵多,每个说明都写清"什么时候该用我"。

五、🙌 不想写代码?低代码一样能配

代码理解了原理;想快速出活,扣子里点几下就行:

  1. 进小雅编排页 → 插件 / 工具,添加一个计算器类插件(它已有联网搜索)。
  2. 问它"查下北京到上海高铁票价,买 3 张一共多少钱"。
  3. 看它先搜票价、再调计算器——和上面代码做的是同一件事,只是平台替你写好了那 40 行。

📸 低代码界面随版本变化,按"找到对应功能"操作;上线版会配截图。

🤖 让 AI 帮你扩展工具箱
这是我的 function calling 代码(贴上面那段)。请帮我再加一个『查询城市天气』的工具:给出工具的 JSON schema 定义、对应的 Python 函数(先用假数据),以及在分发处怎么接上。
✅ 小结

这一节你不只懂了工具调用的原理,还亲手跑通了一份能用的代码——40 行看穿智能体的"手"是怎么长出来的,再也不觉得它神秘。

但你可能发现:任务一复杂(好几步、还互相依赖),小雅就有点毛躁——想到哪做到哪,漏步骤、也不复查。

下一节,我们教它两手老练功夫:先列计划再动手做完自己检查一遍,并同样给你可运行的实现。小雅要从"能干"迈向"靠谱"了。

下一节 → 先谋后动 + 自我检查:Plan & Reflection
智图软件的赞赏码
都看到这了,打个赏呗!
接下来 · a1.4
先谋后动 + 自我检查:Plan & Reflection
继续读下一节 →