Function Calling 是什么?

你 Day 11 做的聊天程序,大模型只能"聊天"——回答问题全靠它自己的知识。

但如果你问它"今天北京天气怎么样",它只能瞎编,因为它没有真实数据。

Function Calling 的作用:让大模型能调用你写的 Python 函数,拿到真实数据再回答。

整体流程

用户:"北京天气怎么样"
    ↓
你的代码把"可用工具"列表发给大模型
    ↓
大模型判断:需要调用 get_weather 函数,参数是 "北京"
    ↓
你的代码执行 get_weather("北京"),拿到结果
    ↓
把结果发回给大模型
    ↓
大模型用自然语言总结结果,返回给用户

关键点

角色 做什么
大模型 决定调哪个函数、传什么参数
你的代码 执行函数、把结果发回给大模型
函数 你预先写好的 Python 函数(查天气、做计算等)

大模型不会直接执行函数——它只是"说"要调用,你来执行


第 1 步:定义你的函数

def calculate(expression: str) -> str:
    """计算数学表达式,返回结果"""
    try:
        result = eval(expression)    # eval 把字符串当代码执行
        return str(result)
    except:
        return "计算错误"

这就是一个普通的 Python 函数,和大模型无关。

eval() 是 Python 内置函数,它能把字符串当代码执行:

  • eval("123 * 456") → 计算 123×456 → 返回 56088
  • eval("100 + 200 - 50") → 计算 100+200-50 → 返回 250

第 2 步:告诉大模型"你有哪些工具"

tools = [
    {
        "type": "function",
        "function": {
            "name": "calculate",
            "description": "计算数学表达式,如 123*456 或 100+200",
            "parameters": {
                "type": "object",
                "properties": {
                    "expression": {
                        "type": "string",
                        "description": "要计算的数学表达式"
                    }
                },
                "required": ["expression"]
            }
        }
    }
]

每个字段是给谁看的?

字段 给谁看的 看了之后做什么
type: "function" 大模型 知道这是一个函数工具
name: "calculate" 大模型 + 你的代码 大模型:知道调哪个函数 你的代码:用它判断执行哪个函数
description 大模型 根据这个描述决定什么时候调用这个工具
parameters 大模型 知道要传什么参数
properties.expression 大模型 知道参数名叫 expression,类型是字符串
required 大模型 知道哪些参数必须传

properties 是什么?

properties = 这个函数需要哪些参数,每个参数长什么样。

"parameters": {
    "type": "object",
    "properties": {
        "expression": {           # 参数名叫 expression
            "type": "string",     # 类型是字符串
            "description": "要计算的数学表达式"
        }
    },
    "required": ["expression"]    # expression 是必填的
}

类比函数签名:def calculate(expression: str) -> str:

如果函数有多个参数:

"properties": {
    "city": {
        "type": "string",
        "description": "城市名称"
    },
    "date": {
        "type": "string",
        "description": "日期,格式为 YYYY-MM-DD"
    }
},
"required": ["city"]    # city 必填,date 选填

第 3 步:第一次调用 API

messages = [
    {"role": "user", "content": "123乘以456等于多少?"}
]

response = client.chat.completions.create(
    model="mimo-v2.5-pro",
    messages=messages,
    tools=tools        # 把工具列表发给大模型
)

参数怎么传的:

messages=[{"role": "user", "content": "123乘以456等于多少?"}]
    ↓
发给大模型:用户问了"123乘以456等于多少?"

tools=[...]
    ↓
同时发给大模型:你有这些工具可以用(calculate 能算数学)

大模型收到后:

  1. 看到用户问"123乘以456"
  2. 看到 tools 里有 calculate 能算数学
  3. 决定:调用 calculate,参数是 “123 * 456”
  4. 返回:response.choices[0].message.tool_calls

第 4 步:执行函数,把结果发回给大模型

# 检查大模型是否要调用工具
if response.choices[0].message.tool_calls:

    # 取出大模型的调用指令
    tool_call = response.choices[0].message.tool_calls[0]

    # 读取函数名和参数(和第 2 步的字段对应)
    function_name = tool_call.function.name       # "calculate"
    arguments = eval(tool_call.function.arguments) # {"expression": "123 * 456"}

    # 根据函数名,调用对应的 Python 函数
    if function_name == "calculate":
        result = calculate(arguments["expression"])
        # calculate("123 * 456") → "56088"

    # 把结果发回给大模型
    messages.append(response.choices[0].message.model_dump())   # 大模型说"我要调函数"
    messages.append({                                           # 函数执行结果
        "role": "tool",
        "tool_call_id": tool_call.id,
        "content": result
    })

    # 再次调用 API,大模型基于函数结果生成自然语言回答
    final_response = client.chat.completions.create(
        model="mimo-v2.5-pro",
        messages=messages
    )

    print(final_response.choices[0].message.content)

完整数据流图

用户输入:"123×456等于多少?"
    ↓
第 3 步:messages=[用户问题] + tools=[工具列表] → 发给大模型
    ↓
大模型返回:tool_calls=[{name: "calculate", arguments: '{"expression":"123*456"}'}]
    ↓
第 4 步:你取出 name="calculate",arguments='{"expression":"123*456"}'
    ↓
你执行:calculate("123*456") → 得到 "56088"
    ↓
你把结果放回 messages:[{用户问题}, {调用指令}, {role:"tool", content:"56088"}]
    ↓
再次发给大模型
    ↓
大模型看到所有内容,回答:"123×456=56088"

三步之间的字段对应关系

第 2 步你定义了什么 第 3 步大模型收到什么 第 4 步你读取什么
name: "calculate" 看到工具名 tool_call.function.name"calculate"
properties.expression 知道需要参数 tool_call.function.arguments'{"expression":"123*456"}'

完整代码

"""
Day 12:Function Calling 完整示例
让大模型调用 calculate 函数进行数学计算
"""

# 第 1 步:定义函数
def calculate(expression: str) -> str:
    """计算数学表达式,返回结果"""
    try:
        result = eval(expression)
        return str(result)
    except:
        return "计算错误"

# 第 2 步:定义工具(告诉大模型有哪些函数可以调用)
tools = [
    {
        "type": "function",
        "function": {
            "name": "calculate",
            "description": "计算数学表达式,如 123*456 或 100+200",
            "parameters": {
                "type": "object",
                "properties": {
                    "expression": {
                        "type": "string",
                        "description": "要计算的数学表达式"
                    }
                },
                "required": ["expression"]
            }
        }
    }
]

# 第 3 步:调用 LLM API
from openai import OpenAI
import os
from dotenv import load_dotenv

load_dotenv()
client = OpenAI(
    api_key=os.getenv("LLM_API_KEY"),
    base_url=os.getenv("LLM_BASE_URL")
)

messages = [
    {"role": "user", "content": "123乘以456等于多少?"}
]

response = client.chat.completions.create(
    model="mimo-v2.5-pro",
    messages=messages,
    tools=tools
)

# 第 4 步:执行函数,把结果发回给大模型
if response.choices[0].message.tool_calls:
    tool_call = response.choices[0].message.tool_calls[0]
    function_name = tool_call.function.name
    arguments = eval(tool_call.function.arguments)

    if function_name == "calculate":
        result = calculate(arguments["expression"])

    messages.append(response.choices[0].message.model_dump())
    messages.append({
        "role": "tool",
        "tool_call_id": tool_call.id,
        "content": result
    })

    final_response = client.chat.completions.create(
        model="mimo-v2.5-pro",
        messages=messages
    )

    print(final_response.choices[0].message.content)

你踩过的坑

坑 1:tools JSON 结构写错

# ❌ required 放在了 function 里面
"function": {
    "name": "calculate",
    ...
    "required": ["expression"]    # 错!required 不在这里
}

# ✅ required 应该在 parameters 里面
"parameters": {
    "type": "object",
    "properties": {...},
    "required": ["expression"]    # 对!required 在这里
}

坑 2:函数名拼写错误

def calulate(...):    # ❌ 拼错了
def calculate(...):   # ✅ 正确

tools 里的 name 必须和函数名完全一致。

坑 3:eval 把字符串当字典

arguments = eval(tool_call.function.arguments)
# tool_call.function.arguments 是 JSON 字符串:'{"expression": "123*456"}'
# eval 把它转成 Python 字典:{"expression": "123*456"}

概念速查表

概念 一句话理解
Function Calling 让大模型能调用你写的 Python 函数
tools 告诉大模型有哪些工具、每个工具需要什么参数
name 工具名,必须和 Python 函数名一致
description 工具的描述,大模型根据这个决定什么时候调用
properties 工具需要哪些参数,每个参数是什么类型
tool_calls 大模型返回的调用指令(调哪个函数、传什么参数)
role: “tool” 把函数执行结果发回给大模型的格式

一句话总结

Function Calling = 你告诉大模型有哪些工具,大模型决定用哪个,你来执行,把结果发回去。

大模型是"决策者"(决定调哪个工具),你的代码是"执行者"(真的去执行函数)。

Day 1-11 的知识全都用上了:循环判断、API 调用、类型提示、LLM API——Function Calling 是所有技能的汇聚点。


本文是 Python 熟练度特训 Day 12 的笔记。Phase 2(AI 核心技能)进入核心——Function Calling 是 AI Agent 的基础。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐