Function calling实践

Function calling案例

bash 复制代码
from openai import OpenAI
import json

# ========================
# 配置部分
# ========================
API_KEY = "sk-......"
API_BASE =  "https://api.deepseek.com/v1"
# 初始化 v2 Client
client = OpenAI(api_key=API_KEY, base_url=API_BASE)

# 1. 定义工具 (使用最新的 tools 格式)
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"]
            }
        }
    }
]

# 2. 构建初始对话
messages = [
    {"role": "system", "content": "你是一个智能助手。请调用天气工具回答问题。"},
    {"role": "user", "content": "请告诉我北京的天气"}
]

try:
    # 第一次调用:模型判断是否需要调用工具
    response = client.chat.completions.create(
        model="deepseek-chat", # 注意:R1 (reasoner) 目前不支持 tools
        messages=messages,
        tools=tools,
        tool_choice="auto"
    )

    message = response.choices[0].message
    
    # 检查是否有工具调用请求
    if message.tool_calls:
        # 必须:先将模型的 tool_calls 消息加入对话历史
        messages.append(message)
        
        for tool_call in message.tool_calls:
            func_name = tool_call.function.name
            func_args = json.loads(tool_call.function.arguments)
            
            # 模拟本地函数执行
            if func_name == "get_weather":
                city = func_args.get("city")
                result = f"{city} 的天气是 25°C,晴天。" # 实际应对接天气API
                
                print(f"本地执行函数: {func_name} | 参数: {func_args}")
                
                # 必须:将函数结果回传,角色为 'tool',并带上 tool_call_id
                messages.append({
                    "role": "tool",
                    "tool_call_id": tool_call.id,
                    "content": result
                })

        # 第二次调用:模型根据函数结果生成自然语言回答
        final_response = client.chat.completions.create(
            model="deepseek-chat",
            messages=messages
        )
        print("-" * 30)
        print("最终回答:", final_response.choices[0].message.content)
        
    else:
        print("模型没有发起工具调用,回复内容为:", message.content)

except Exception as e:
    print("发生错误:", e)

思考:

  1. Function calling要解决的问题:
    • 模型无法与外部数据源交互
    • 模型没有执行的能力,不能帮助用户执行实际任务,比如运行程序,发邮件,上传文件等。
  2. Function calling=后端+LLM。
    • 后端调用本地封装的方法。用户的提问不是直接给大模型的。
    • 后端能够执行任务,但是不够"聪明"。大模型虽然"聪明",但是没有执行能力。
  3. Function calling会不会超出token的限制?
    • Function Calling 的输入(messages + 函数 schema + 历史上下文)都算 token。
    • 如果函数 schema 很复杂,或者多轮历史消息很多,可能超出模型的上下文上限。
  4. 模型覆盖有限,开发生态不统一
    • 并不是所有模型都原生支持 Function Calling(如 DeepSeek R1 系列就不支持)。
    • 不同模型对 schema、参数类型、返回格式的支持不统一。

参考资料:
一期视频带你彻底了解:Function calling与MCP详解,它们有什么区别?

相关推荐
掘金安东尼5 小时前
纯 CSS 实现弹性文字效果
前端·css
牛奶5 小时前
Vue 基础理论 & API 使用
前端·vue.js·面试
牛奶6 小时前
Vue 底层原理 & 新特性
前端·vue.js·面试
anOnion6 小时前
构建无障碍组件之Radio group pattern
前端·html·交互设计
pe7er6 小时前
状态提升:前端开发中的状态管理的设计思想
前端·vue.js·react.js
SoaringHeart7 小时前
Flutter调试组件:打印任意组件尺寸位置信息 NRenderBox
前端·flutter
晚风予星8 小时前
Ant Design Token Lens 迎来了全面升级!支持在 .tsx 或 .ts 文件中直接使用 Design Token
前端·react.js·visual studio code
sunny_8 小时前
⚡️ vite-plugin-oxc:从 Babel 到 Oxc,我为 Vite 写了一个高性能编译插件
前端·webpack·架构
GIS之路8 小时前
ArcPy 开发环境搭建
前端
林小帅9 小时前
【笔记】OpenClaw 架构浅析
前端·agent