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详解,它们有什么区别?

相关推荐
阿昌喜欢吃黄桃几秒前
Dubbo服务重启时注册中心下线不及时问题排查与修复记录
java·rpc·dubbo·问题排查
Hilaku7 分钟前
当 AI 一天写完一周的代码,我们还剩什么优势?
前端·javascript·程序员
尘世中一位迷途小书童11 分钟前
无人机航线里的云台角度怎么调?Cesium 做了个视锥 + 鹰眼联动
前端·javascript·数据可视化
思码梁田15 分钟前
CSS display 属性:从元素类型转换到隐藏元素的实用指南
前端·css·display·inline·block·none·inline-block
confiself16 分钟前
树形思考研究进展
java·大数据·微服务
Csvn16 分钟前
⚡ Vite 依赖预构建(optimizeDeps)的 3 个经典坑:改了源码不生效、新增依赖 404、缓存怎么清都不行
前端
还是鼠鼠19 分钟前
【Spring AI智能体实战 01】Java开发者接入大模型:国内平台、Token与API Key入门
java·大模型·spring ai·deepseek·阿里云百炼
A242073493027 分钟前
Vue3 + TypeScript:后端数据在表格内渲染后进行增删改的完整实现步骤
前端·javascript·typescript
zerozrc030 分钟前
Java Lambda 底层实现
java
他们叫我 悦儿遥遥雨30 分钟前
.NET 8 Web开发入门(六):Blazor 全栈开发——告别 JavaScript 焦虑
前端·javascript·.net