OpenAI 函数调用 #

什么是函数调用? #

函数调用(Function Calling)是 OpenAI 提供的一项强大功能,它允许 GPT 模型在对话过程中"调用"预定义的函数,从而获取实时数据、执行操作或与外部系统交互。

text
┌─────────────────────────────────────────────────────────────┐
│                    函数调用工作流程                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   用户:"北京今天天气怎么样?"                               │
│                                                             │
│   ┌─────────────────────────────────────────────────────┐   │
│   │  1. GPT 分析意图,决定调用 get_weather 函数          │   │
│   │     参数: {"city": "北京"}                           │   │
│   └─────────────────────────────────────────────────────┘   │
│                           │                                 │
│                           ▼                                 │
│   ┌─────────────────────────────────────────────────────┐   │
│   │  2. 应用执行函数,获取天气数据                        │   │
│   │     返回: {"temp": 25, "condition": "晴"}           │   │
│   └─────────────────────────────────────────────────────┘   │
│                           │                                 │
│                           ▼                                 │
│   ┌─────────────────────────────────────────────────────┐   │
│   │  3. GPT 根据数据生成自然语言回复                      │   │
│   │     "北京今天天气晴朗,气温 25 度。"                  │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

函数调用的优势 #

text
┌─────────────────────────────────────────────────────────────┐
│                    函数调用优势                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ✅ 获取实时数据                                            │
│     - 天气、股价、新闻等实时信息                            │
│     - 数据库查询                                            │
│                                                             │
│  ✅ 执行操作                                                │
│     - 发送邮件                                              │
│     - 创建订单                                              │
│     - 调用外部 API                                          │
│                                                             │
│  ✅ 结构化输出                                              │
│     - 提取特定格式的数据                                    │
│     - 参数验证                                              │
│                                                             │
│  ✅ 扩展能力                                                │
│     - 突破模型知识截止日期限制                              │
│     - 访问私有数据                                          │
│                                                             │
└─────────────────────────────────────────────────────────────┘

基本用法 #

定义函数 #

python
from openai import OpenAI
import json

client = OpenAI()

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "获取指定城市的当前天气",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "城市名称,如:北京、上海"
                    },
                    "unit": {
                        "type": "string",
                        "enum": ["celsius", "fahrenheit"],
                        "description": "温度单位"
                    }
                },
                "required": ["city"]
            }
        }
    }
]

发送请求 #

python
response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {"role": "user", "content": "北京今天天气怎么样?"}
    ],
    tools=tools
)

print(response.choices[0].message)

处理函数调用 #

python
message = response.choices[0].message

if message.tool_calls:
    for tool_call in message.tool_calls:
        function_name = tool_call.function.name
        function_args = json.loads(tool_call.function.arguments)
        
        print(f"函数名: {function_name}")
        print(f"参数: {function_args}")
        
        if function_name == "get_weather":
            result = get_weather(
                city=function_args["city"],
                unit=function_args.get("unit", "celsius")
            )
            print(f"结果: {result}")

完整示例 #

python
from openai import OpenAI
import json

client = OpenAI()

def get_weather(city: str, unit: str = "celsius") -> dict:
    """模拟天气 API"""
    weather_data = {
        "北京": {"temp": 25, "condition": "晴"},
        "上海": {"temp": 28, "condition": "多云"},
        "广州": {"temp": 32, "condition": "雨"}
    }
    
    data = weather_data.get(city, {"temp": 20, "condition": "未知"})
    
    if unit == "fahrenheit":
        data["temp"] = data["temp"] * 9/5 + 32
    
    return data

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "获取指定城市的当前天气",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "城市名称"
                    },
                    "unit": {
                        "type": "string",
                        "enum": ["celsius", "fahrenheit"]
                    }
                },
                "required": ["city"]
            }
        }
    }
]

def run_conversation(user_input: str) -> str:
    messages = [{"role": "user", "content": user_input}]
    
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=messages,
        tools=tools
    )
    
    message = response.choices[0].message
    messages.append(message)
    
    if message.tool_calls:
        for tool_call in message.tool_calls:
            function_name = tool_call.function.name
            function_args = json.loads(tool_call.function.arguments)
            
            if function_name == "get_weather":
                result = get_weather(**function_args)
            
            messages.append({
                "role": "tool",
                "tool_call_id": tool_call.id,
                "content": json.dumps(result, ensure_ascii=False)
            })
        
        response = client.chat.completions.create(
            model="gpt-4o-mini",
            messages=messages,
            tools=tools
        )
        
        return response.choices[0].message.content
    
    return message.content

print(run_conversation("北京今天天气怎么样?"))

函数定义详解 #

函数结构 #

text
┌─────────────────────────────────────────────────────────────┐
│                    函数定义结构                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  {                                                          │
│    "type": "function",                                      │
│    "function": {                                            │
│      "name": "函数名称",          // 必填                   │
│      "description": "函数描述",   // 推荐                   │
│      "parameters": {              // JSON Schema            │
│        "type": "object",                                    │
│        "properties": {                                      │
│          "参数名": {                                        │
│            "type": "类型",                                  │
│            "description": "参数描述"                        │
│          }                                                  │
│        },                                                   │
│        "required": ["必需参数列表"]                         │
│      }                                                      │
│    }                                                        │
│  }                                                          │
│                                                             │
└─────────────────────────────────────────────────────────────┘

参数类型 #

python
tools = [
    {
        "type": "function",
        "function": {
            "name": "search_products",
            "description": "搜索商品",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {
                        "type": "string",
                        "description": "搜索关键词"
                    },
                    "category": {
                        "type": "string",
                        "enum": ["electronics", "clothing", "books", "food"],
                        "description": "商品类别"
                    },
                    "price_range": {
                        "type": "object",
                        "properties": {
                            "min": {"type": "number"},
                            "max": {"type": "number"}
                        }
                    },
                    "in_stock": {
                        "type": "boolean",
                        "description": "是否只显示有库存"
                    },
                    "limit": {
                        "type": "integer",
                        "description": "返回结果数量限制",
                        "default": 10
                    },
                    "tags": {
                        "type": "array",
                        "items": {"type": "string"},
                        "description": "标签列表"
                    }
                },
                "required": ["query"]
            }
        }
    }
]

多函数定义 #

python
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "获取天气信息",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {"type": "string"}
                },
                "required": ["city"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "get_stock_price",
            "description": "获取股票价格",
            "parameters": {
                "type": "object",
                "properties": {
                    "symbol": {"type": "string", "description": "股票代码"}
                },
                "required": ["symbol"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "send_email",
            "description": "发送邮件",
            "parameters": {
                "type": "object",
                "properties": {
                    "to": {"type": "string", "description": "收件人邮箱"},
                    "subject": {"type": "string", "description": "邮件主题"},
                    "body": {"type": "string", "description": "邮件内容"}
                },
                "required": ["to", "subject", "body"]
            }
        }
    }
]

高级用法 #

并行函数调用 #

python
response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {"role": "user", "content": "北京和上海的天气怎么样?"}
    ],
    tools=tools
)

message = response.choices[0].message

if message.tool_calls:
    print(f"需要调用 {len(message.tool_calls)} 个函数")
    
    for tool_call in message.tool_calls:
        print(f"函数: {tool_call.function.name}")
        print(f"参数: {tool_call.function.arguments}")

函数调用流程封装 #

python
from openai import OpenAI
import json
from typing import Callable, Dict, Any, List

client = OpenAI()

class FunctionCaller:
    def __init__(self):
        self.functions: Dict[str, Callable] = {}
        self.tools: List[Dict] = []
    
    def register(self, func: Callable, description: str, parameters: dict):
        """注册函数"""
        self.functions[func.__name__] = func
        self.tools.append({
            "type": "function",
            "function": {
                "name": func.__name__,
                "description": description,
                "parameters": parameters
            }
        })
    
    def execute(self, name: str, arguments: dict) -> Any:
        """执行函数"""
        if name not in self.functions:
            raise ValueError(f"Unknown function: {name}")
        return self.functions[name](**arguments)
    
    def chat(self, user_input: str, max_iterations: int = 5) -> str:
        """执行对话"""
        messages = [{"role": "user", "content": user_input}]
        
        for _ in range(max_iterations):
            response = client.chat.completions.create(
                model="gpt-4o-mini",
                messages=messages,
                tools=self.tools
            )
            
            message = response.choices[0].message
            messages.append(message)
            
            if not message.tool_calls:
                return message.content
            
            for tool_call in message.tool_calls:
                function_name = tool_call.function.name
                function_args = json.loads(tool_call.function.arguments)
                
                try:
                    result = self.execute(function_name, function_args)
                    result_str = json.dumps(result, ensure_ascii=False)
                except Exception as e:
                    result_str = json.dumps({"error": str(e)})
                
                messages.append({
                    "role": "tool",
                    "tool_call_id": tool_call.id,
                    "content": result_str
                })
        
        return "达到最大迭代次数"

caller = FunctionCaller()

def get_weather(city: str) -> dict:
    return {"city": city, "temp": 25, "condition": "晴"}

caller.register(
    get_weather,
    "获取城市天气",
    {
        "type": "object",
        "properties": {
            "city": {"type": "string", "description": "城市名称"}
        },
        "required": ["city"]
    }
)

print(caller.chat("北京天气怎么样?"))

流式函数调用 #

python
from openai import OpenAI
import json

client = OpenAI()

def stream_with_tools(user_input: str):
    messages = [{"role": "user", "content": user_input}]
    
    stream = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=messages,
        tools=tools,
        stream=True
    )
    
    tool_calls = []
    current_content = ""
    
    for chunk in stream:
        delta = chunk.choices[0].delta
        
        if delta.content:
            print(delta.content, end="", flush=True)
            current_content += delta.content
        
        if delta.tool_calls:
            for tool_call_delta in delta.tool_calls:
                idx = tool_call_delta.index
                
                while len(tool_calls) <= idx:
                    tool_calls.append({"id": "", "name": "", "arguments": ""})
                
                if tool_call_delta.id:
                    tool_calls[idx]["id"] = tool_call_delta.id
                if tool_call_delta.function.name:
                    tool_calls[idx]["name"] = tool_call_delta.function.name
                if tool_call_delta.function.arguments:
                    tool_calls[idx]["arguments"] += tool_call_delta.function.arguments
    
    return tool_calls

tool_calls = stream_with_tools("北京天气怎么样?")
print("\n\n函数调用:")
for tc in tool_calls:
    print(f"  {tc['name']}: {tc['arguments']}")

实际应用示例 #

数据库查询 #

python
import sqlite3
from openai import OpenAI
import json

client = OpenAI()

def query_database(query: str) -> list:
    """执行 SQL 查询"""
    conn = sqlite3.connect("example.db")
    cursor = conn.cursor()
    cursor.execute(query)
    results = cursor.fetchall()
    conn.close()
    return results

tools = [
    {
        "type": "function",
        "function": {
            "name": "query_database",
            "description": "执行 SQL 查询获取数据",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {
                        "type": "string",
                        "description": "SQL 查询语句"
                    }
                },
                "required": ["query"]
            }
        }
    }
]

def chat_with_db(user_input: str) -> str:
    messages = [
        {
            "role": "system",
            "content": "你是一个数据分析助手,可以查询数据库。"
        },
        {"role": "user", "content": user_input}
    ]
    
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=messages,
        tools=tools
    )
    
    message = response.choices[0].message
    messages.append(message)
    
    if message.tool_calls:
        for tool_call in message.tool_calls:
            args = json.loads(tool_call.function.arguments)
            result = query_database(args["query"])
            
            messages.append({
                "role": "tool",
                "tool_call_id": tool_call.id,
                "content": json.dumps(result)
            })
        
        response = client.chat.completions.create(
            model="gpt-4o-mini",
            messages=messages,
            tools=tools
        )
        return response.choices[0].message.content
    
    return message.content

API 调用 #

python
import requests
from openai import OpenAI
import json

client = OpenAI()

def call_external_api(endpoint: str, method: str = "GET", data: dict = None) -> dict:
    """调用外部 API"""
    base_url = "https://api.example.com"
    
    if method == "GET":
        response = requests.get(f"{base_url}/{endpoint}")
    else:
        response = requests.post(f"{base_url}/{endpoint}", json=data)
    
    return response.json()

tools = [
    {
        "type": "function",
        "function": {
            "name": "call_external_api",
            "description": "调用外部 API",
            "parameters": {
                "type": "object",
                "properties": {
                    "endpoint": {
                        "type": "string",
                        "description": "API 端点"
                    },
                    "method": {
                        "type": "string",
                        "enum": ["GET", "POST"]
                    },
                    "data": {
                        "type": "object",
                        "description": "POST 数据"
                    }
                },
                "required": ["endpoint"]
            }
        }
    }
]

结构化数据提取 #

python
from openai import OpenAI
import json

client = OpenAI()

tools = [
    {
        "type": "function",
        "function": {
            "name": "extract_person_info",
            "description": "提取人物信息",
            "parameters": {
                "type": "object",
                "properties": {
                    "name": {"type": "string"},
                    "age": {"type": "integer"},
                    "email": {"type": "string"},
                    "phone": {"type": "string"},
                    "address": {"type": "string"}
                },
                "required": ["name"]
            }
        }
    }
]

def extract_info(text: str) -> dict:
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {
                "role": "system",
                "content": "从文本中提取人物信息,使用函数返回结构化数据。"
            },
            {"role": "user", "content": text}
        ],
        tools=tools,
        tool_choice={"type": "function", "function": {"name": "extract_person_info"}}
    )
    
    tool_call = response.choices[0].message.tool_calls[0]
    return json.loads(tool_call.function.arguments)

text = "张三今年28岁,邮箱是zhangsan@example.com,住在北京朝阳区"
info = extract_info(text)
print(json.dumps(info, indent=2, ensure_ascii=False))

工具选择控制 #

tool_choice 参数 #

text
┌─────────────────────────────────────────────────────────────┐
│                    tool_choice 选项                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  "auto"(默认)                                              │
│  ─────────────────────────────────────────────────────────  │
│  模型自动决定是否调用函数                                   │
│                                                             │
│  "none"                                                     │
│  ─────────────────────────────────────────────────────────  │
│  不调用任何函数,只生成文本                                 │
│                                                             │
│  "required"                                                 │
│  ─────────────────────────────────────────────────────────  │
│  必须调用至少一个函数                                       │
│                                                             │
│  {"type": "function", "function": {"name": "函数名"}}       │
│  ─────────────────────────────────────────────────────────  │
│  强制调用指定函数                                           │
│                                                             │
└─────────────────────────────────────────────────────────────┘

强制调用特定函数 #

python
response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {"role": "user", "content": "用户输入"}
    ],
    tools=tools,
    tool_choice={
        "type": "function",
        "function": {"name": "get_weather"}
    }
)

禁止调用函数 #

python
response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {"role": "user", "content": "用户输入"}
    ],
    tools=tools,
    tool_choice="none"
)

最佳实践 #

1. 函数描述要清晰 #

python
tools = [
    {
        "type": "function",
        "function": {
            "name": "search_products",
            "description": "在商品数据库中搜索商品。支持按名称、类别和价格范围筛选。",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {
                        "type": "string",
                        "description": "搜索关键词,如商品名称或描述"
                    },
                    "category": {
                        "type": "string",
                        "enum": ["electronics", "clothing", "books"],
                        "description": "商品类别,可选"
                    }
                },
                "required": ["query"]
            }
        }
    }
]

2. 错误处理 #

python
def safe_execute_function(name: str, arguments: dict) -> dict:
    try:
        result = execute_function(name, arguments)
        return {"success": True, "data": result}
    except Exception as e:
        return {"success": False, "error": str(e)}

3. 验证参数 #

python
import jsonschema

def validate_arguments(schema: dict, arguments: dict) -> bool:
    try:
        jsonschema.validate(arguments, schema)
        return True
    except jsonschema.ValidationError:
        return False

下一步 #

现在你已经掌握了函数调用的使用方法,接下来学习 图像生成,了解如何使用 DALL·E 生成图像!

最后更新:2026-03-29