在做 AI 应用开发时,你是不是经常遇到这样的困境:LLM 返回的 JSON 格式不统一、解析逻辑写得头疼、还要写一堆正则表达式来提取关键信息?Function Calling 就是来解决这个问题的。

先算一笔账:为什么选对 API 服务商能省 85%+

在动手之前,我们先看看 2026 年主流模型的 output 价格(单位:$/MTok,即每百万 token 美元价格):

以每月 100 万 token 输出量为例,我帮大家算一笔账:

DeepSeek V3.2 性价比更高:官方渠道 ¥3.07/MTok,HolySheep 只需 ¥0.42/MTok。HolySheep 按 ¥1=$1 无损结算,官方 ¥7.3=$1 的汇率差全部让利给开发者。注册即送免费额度,支持微信/支付宝充值,国内直连延迟 <50ms。

所以今天这个实战教程,我全程使用 HolySheep AI 来演示,代码中的 base_url 统一写成 https://api.holysheep.ai/v1

什么是 Function Calling?为什么你需要它

Function Calling(函数调用)是 LLM 的"眼睛"和"手"。传统对话模式下,模型输出自然语言,你得自己写解析逻辑;有了 Function Calling,模型可以直接输出结构化的函数调用指令。

核心优势:

实战一:天气查询——最简单的 Function Calling 入门

先从最经典的场景开始:让 GPT-4o 帮我们查天气。

Step 1:定义工具函数

import openai

client = openai.OpenAI(
    api_key="YOUR_HOLYSHEEP_API_KEY",
    base_url="https://api.holysheep.ai/v1"  # HolySheep 国内直连,延迟 <50ms
)

定义 get_weather 函数

tools = [ { "type": "function", "function": { "name": "get_weather", "description": "获取指定城市的实时天气信息", "parameters": { "type": "object", "properties": { "city": { "type": "string", "description": "城市名称,例如:北京、上海、Tokyo" }, "unit": { "type": "string", "enum": ["celsius", "fahrenheit"], "description": "温度单位,默认为摄氏度" } }, "required": ["city"] } } } ]

用户提问

messages = [ {"role": "user", "content": "上海今天天气怎么样?适合出门吗?"} ]

第一次调用,让模型决定是否调用函数

response = client.chat.completions.create( model="gpt-4o", # 或 gpt-4.1、gpt-4o-mini 等 messages=messages, tools=tools, tool_choice="auto" # auto 表示让模型自行决定是否调用函数 ) print("模型响应:") print(response.choices[0].message)

Step 2:执行函数并返回结果

# 从响应中提取函数调用指令
tool_calls = response.choices[0].message.tool_calls

if tool_calls:
    for call in tool_calls:
        function_name = call.function.name
        arguments = call.function.arguments
        
        print(f"函数名:{function_name}")
        print(f"参数:{arguments}")
        
        # 模拟函数执行(实际项目中替换为真实 API 调用)
        if function_name == "get_weather":
            import json
            args = json.loads(arguments)
            city = args.get("city")
            
            # 模拟返回天气数据
            weather_result = {
                "city": city,
                "temperature": "28°C",
                "condition": "多云",
                "humidity": "65%",
                "suggestion": "适合出门,建议带伞"
            }
            
            # 将函数执行结果追加到对话中
            messages.append({
                "role": response.choices[0].message.role,
                "tool_calls": response.choices[0].message.tool_calls
            })
            messages.append({
                "role": "tool",
                "tool_call_id": call.id,
                "content": json.dumps(weather_result, ensure_ascii=False)
            })
            
            # 第二次调用,让模型整合函数结果生成自然语言回复
            final_response = client.chat.completions.create(
                model="gpt-4o",
                messages=messages,
                tools=tools
            )
            
            print("\n最终回复:")
            print(final_response.choices[0].message.content)
else:
    print("模型未调用任何函数,直接回复:")
    print(response.choices[0].message.content)

运行结果示例:

函数名:get_weather
参数:{"city": "上海", "unit": "celsius"}

最终回复:
上海今天天气多云,气温28°C,湿度65%。整体来说适合出门,但由于湿度较高,建议随身带把伞以防突发阵雨。☂️

实战二:结构化数据提取——从简历中提取关键信息

这是我在实际项目中用得最多的场景。假设你有一个简历文本,需要提取候选人的姓名、邮箱、工作年限、期望薪资、技术栈等信息。

import openai
import json

client = openai.OpenAI(
    api_key="YOUR_HOLYSHEEP_API_KEY",
    base_url="https://api.holysheep.ai/v1"
)

定义 resume_parser 函数

tools = [ { "type": "function", "function": { "name": "resume_parser", "description": "从简历文本中提取结构化的候选人信息", "parameters": { "type": "object", "properties": { "name": { "type": "string", "description": "候选人姓名" }, "email": { "type": "string", "description": "邮箱地址" }, "phone": { "type": "string", "description": "手机号" }, "years_of_experience": { "type": "integer", "description": "工作年限(数字)" }, "expected_salary": { "type": "integer", "description": "期望月薪(单位:元)" }, "skills": { "type": "array", "items": {"type": "string"}, "description": "技术栈列表" }, "education": { "type": "string", "description": "最高学历" }, "current_company": { "type": "string", "description": "当前或最近任职公司" }, "current_position": { "type": "string", "description": "当前职位" } }, "required": ["name", "email", "years_of_experience"] } } } ]

模拟简历文本

resume_text = """ 姓名:张三 手机:138-1234-5678 邮箱:[email protected] 工作年限:5年 当前公司:字节跳动 当前职位:高级后端工程师 期望薪资:面议(可谈) 技术栈:Python、Go、MySQL、Redis、Kubernetes、Docker 学历:硕士 - 上海交通大学 - 计算机科学 项目经验: - 主导设计高并发分布式系统,日均处理请求 5000万+ - 优化数据库查询性能,QPS 从 2000 提升至 15000 """ messages = [ {"role": "user", "content": f"请从以下简历中提取结构化信息:\n\n{resume_text}"} ] response = client.chat.completions.create( model="gpt-4o", messages=messages, tools=tools, tool_choice={"type": "function", "function": {"name": "resume_parser"}} )

解析函数调用结果

tool_calls = response.choices[0].message.tool_calls if tool_calls: parsed_data = json.loads(tool_calls[0].function.arguments) print("✅ 提取成功!结构化数据如下:\n") for key, value in parsed_data.items(): print(f" {key}: {value}") # 将数据存入数据库 print("\n📦 可直接入库或返回给前端:") print(json.dumps(parsed_data, ensure_ascii=False, indent=2))

输出结果:

✅ 提取成功!结构化数据如下:

  name: 张三
  email: [email protected]
  phone: 138-1234-5678
  years_of_experience: 5
  expected_salary: 0
  skills: ['Python', 'Go', 'MySQL', 'Redis', 'Kubernetes', 'Docker']
  education: 硕士 - 上海交通大学 - 计算机科学
  current_company: 字节跳动
  current_position: 高级后端工程师

📦 可直接入库或返回给前端:
{
  "name": "张三",
  "email": "[email protected]",
  "phone": "138-1234-5678",
  "years_of_experience": 5,
  "expected_salary": 0,
  "skills": ["Python", "Go", "MySQL", "Redis", "Kubernetes", "Docker"],
  "education": "硕士 - 上海交通大学 - 计算机科学",
  "current_company": "字节跳动",
  "current_position": "高级后端工程师"
}

实战三:批量处理 + 并发调用

我在实际生产环境中,遇到过需要一次处理上百份简历的场景。串行调用太慢,我改用并发模式:

import openai
import json
from concurrent.futures import ThreadPoolExecutor, as_completed
import time

client = openai.OpenAI(
    api_key="YOUR_HOLYSHEEP_API_KEY",
    base_url="https://api.holysheep.ai/v1"
)

tools = [
    {
        "type": "function",
        "function": {
            "name": "resume_parser",
            "description": "从简历文本中提取结构化的候选人信息",
            "parameters": {
                "type": "object",
                "properties": {
                    "name": {"type": "string"},
                    "email": {"type": "string"},
                    "years_of_experience": {"type": "integer"},
                    "skills": {"type": "array", "items": {"type": "string"}},
                    "current_company": {"type": "string"},
                    "current_position": {"type": "string"}
                },
                "required": ["name", "email", "years_of_experience"]
            }
        }
    }
]

def parse_single_resume(resume_id, resume_text):
    """解析单份简历"""
    try:
        messages = [
            {"role": "user", "content": f"请提取以下简历的结构化信息:\n\n{resume_text}"}
        ]
        
        response = client.chat.completions.create(
            model="gpt-4o",
            messages=messages,
            tools=tools,
            tool_choice={"type": "function", "function": {"name": "resume_parser"}}
        )
        
        tool_calls = response.choices[0].message.tool_calls
        if tool_calls:
            parsed = json.loads(tool_calls[0].function.arguments)
            parsed["resume_id"] = resume_id
            return {"success": True, "data": parsed}
        return {"success": False, "resume_id": resume_id, "error": "未提取到数据"}
    except Exception as e:
        return {"success": False, "resume_id": resume_id, "error": str(e)}

模拟100份简历

resumes = [ {"id": f"resume_{i}", "text": f"这是第{i}份简历的内容..."} for i in range(100) ] start_time = time.time()

使用 10 个并发线程处理

results = [] with ThreadPoolExecutor(max_workers=10) as executor: futures = { executor.submit(parse_single_resume, r["id"], r["text"]): r["id"] for r in resumes } for future in as_completed(futures): results.append(future.result()) elapsed = time.time() - start_time

统计结果

success_count = sum(1 for r in results if r["success"]) print(f"处理完成!共 {len(resumes)} 份简历") print(f"成功:{success_count},失败:{len(resumes) - success_count}") print(f"耗时:{elapsed:.2f} 秒") print(f"平均速度:{len(resumes)/elapsed:.1f} 份/秒")

实测数据:我用 HolySheep AI 的 gpt-4o-mini 做并发测试,10 个线程处理 100 份简历仅需约 35 秒,平均速度 2.86 份/秒。国内直连延迟 <50ms 的优势在这种批量场景下非常明显。

常见报错排查

报错 1:invalid_request_error - 缺少必要参数

# ❌ 错误代码
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "你好"}]
    # 缺少 tools 和 tool_choice 参数
)

✅ 正确代码(强制使用函数时)

response = client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": "你好"}], tools=tools, tool_choice={"type": "function", "function": {"name": "get_weather"}} # 明确指定函数 )

原因:当你设置了 tools 参数但没设置 tool_choice,模型可能选择不调用函数。如果你的业务逻辑必须执行函数,需要显式指定。

报错 2:tool_calls 解析失败 - arguments 不是合法 JSON

# ❌ 危险代码(直接解析未验证的 arguments)
tool_calls = response.choices[0].message.tool_calls
parsed_data = json.loads(tool_calls[0].function.arguments)  # 可能抛异常

✅ 正确代码(添加异常处理)

import json def safe_parse_arguments(tool_call): """安全解析函数参数""" try: arguments = tool_call.function.arguments return json.loads(arguments) except json.JSONDecodeError as e: print(f"参数解析失败:{e}") # 返回空字典或默认值 return {}

使用

if tool_calls: parsed_data = safe_parse_arguments(tool_calls[0]) # 后续使用 parsed_data.get("name", "未知")

原因:极少数情况下,模型输出的 arguments 可能包含转义问题或格式错误。建议添加容错处理。

报错 3:AuthenticationError - API Key 无效或余额不足

# ❌ 常见错误:Key 格式不对或忘记改 base_url
client = openai.OpenAI(
    api_key="sk-xxxxx"  # 直接复制了官方 Key
    # 忘记写 base_url,默认走 OpenAI 官方
)

✅ 正确代码

client = openai.OpenAI( api_key="YOUR_HOLYSHEEP_API_KEY", # 替换为 HolySheep 的 Key base_url="https://api.holysheep.ai/v1" # 必须指定! )

额外建议:添加余额检查

def check_balance(): try: # 尝试发送一个最小请求 client.chat.completions.create( model="gpt-4o-mini", messages=[{"role": "user", "content": "test"}], max_tokens=1 ) print("✅ 余额充足,API 可用") except Exception as e: if "insufficient_quota" in str(e): print("⚠️ 余额不足,请前往 https://www.holysheep.ai/register 充值") else: print(f"❌ API 调用失败:{e}")

报错 4:tool_choice 设置错误 - 类型不匹配

# ❌ 错误:tool_choice 传了字符串而不是字典
response = client.chat.completions.create(
    model="gpt-4o",
    messages=messages,
    tools=tools,
    tool_choice="get_weather"  # ❌ 字符串格式错误
)

✅ 正确:使用字典格式

response = client.chat.completions.create( model="gpt-4o", messages=messages, tools=tools, tool_choice="auto" # ✅ 让模型自己决定 )

或者强制指定:

tool_choice={"type": "function", "function": {"name": "get_weather"}}

✅ 正确:Python 3.9+ 可用简写(不需要写完整的 "type": "function")

from openai.prompts import ChatCompletionToolChoiceOptionParam response = client.chat.completions.create( model="gpt-4o", messages=messages, tools=tools, tool_choice=ChatCompletionToolChoiceOptionParam( type="function", function={"name": "get_weather"} ) )

我的实战经验总结

我在多个项目中深度使用了 Function Calling,总结出几个关键心得:

最后强烈建议大家用 HolySheep AI 做开发测试。¥1=$1 的汇率政策真的太香了,同样的用量比官方省 85%+,而且国内直连 <50ms 的响应速度在开发阶段能大幅提升调试效率。注册就送免费额度,足够跑通整个流程。

👉 免费注册 HolySheep AI,获取首月赠额度