函數調用

函數調用允许模型為你定義的函數生成結構化參數。模型本身不會直接执行函數,而是輸出 JSON,你可以在程式碼中據此調用该函數。

工作原理

  1. 定義工具 — 在請求中提供函數 schema
  2. 模型決策 — 模型決定是否調用一個或多個工具
  3. 由你执行 — 解析模型的工具調用並運行實際函數
  4. 返回結果 — 將函數輸出回傳給模型
  5. 模型響應 — 模型基於工具結果生成最終回答

定義工具

from openai import OpenAI

client = OpenAI(
    base_url="https://api.linkastra.ai/v1",
    api_key="YOUR_API_KEY"
)

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Get the current weather for a given location",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "City name, e.g., Beijing"
                    },
                    "unit": {
                        "type": "string",
                        "enum": ["celsius", "fahrenheit"],
                        "description": "Temperature unit"
                    }
                },
                "required": ["location"]
            }
        }
    }
]

完整示例

import json

response = client.chat.completions.create(
    model="deepseek/deepseek-v4-pro",
    messages=[{"role": "user", "content": "What's the weather like in Shanghai?"}],
    tools=tools,
    tool_choice="auto"
)

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)

        # Execute the function
        if function_name == "get_weather":
            result = get_weather(**function_args)

        # Send result back to the model
        response = client.chat.completions.create(
            model="deepseek/deepseek-v4-pro",
            messages=[
                {"role": "user", "content": "What's the weather like in Shanghai?"},
                message,
                {
                    "role": "tool",
                    "tool_call_id": tool_call.id,
                    "content": str(result)
                }
            ]
        )

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

工具選擇

說明
auto由模型決定是否調用工具(默认)
none模型不會調用任何工具
required模型必须至少調用一個工具
{"type": "function", "function": {"name": "..."}}強制調用指定函數

多個工具

你可以在單次請求中定義多個工具:

tools = [
    {
        "type": "function",
        "function": {
            "name": "search_products",
            "description": "Search the product catalog",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {"type": "string"},
                    "category": {"type": "string"},
                    "max_price": {"type": "number"}
                },
                "required": ["query"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "place_order",
            "description": "Place an order for a product",
            "parameters": {
                "type": "object",
                "properties": {
                    "product_id": {"type": "string"},
                    "quantity": {"type": "integer"}
                },
                "required": ["product_id", "quantity"]
            }
        }
    }
]

最佳實踐

  • 編寫清晰的描述 — 模型依賴函數和參數的描述来決定何時以及如何調用它們
  • 為受限值使用 enum — 尽可能用 enum 限定參數取值
  • 标注必填字段 — 始終將必要參數标记為 required
  • 優雅地處理錯誤 — 將錯誤資訊作為工具結果返回,便於模型自我纠正
  • 控制工具數量 — 工具過多會讓模型困惑,請保持聚焦

並行工具調用

部分模型支援在單次響應中調用多個工具。可遍歷 message.tool_calls 来處理:

if message.tool_calls:
    tool_results = []
    for tool_call in message.tool_calls:
        result = execute_function(tool_call.function.name, json.loads(tool_call.function.arguments))
        tool_results.append({
            "role": "tool",
            "tool_call_id": tool_call.id,
            "content": str(result)
        })

相關文件