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

相关推荐
kingwebo'sZone几秒前
C#使用Aspose.Words把 word转成图片
前端·c#·word
小Tomkk1 分钟前
数据库 变更和版本控制管理工具 --Bytebase 安装部署(linux 安装篇)
linux·运维·数据库·ci/cd·bytebase
xjt_090119 分钟前
基于 Vue 3 构建企业级 Web Components 组件库
前端·javascript·vue.js
rannn_11122 分钟前
【苍穹外卖|Day4】套餐页面开发(新增套餐、分页查询、删除套餐、修改套餐、起售停售)
java·spring boot·后端·学习
qq_124987075326 分钟前
基于JavaWeb的大学生房屋租赁系统(源码+论文+部署+安装)
java·数据库·人工智能·spring boot·计算机视觉·毕业设计·计算机毕业设计
我是伪码农31 分钟前
Vue 2.3
前端·javascript·vue.js
短剑重铸之日32 分钟前
《设计模式》第十一篇:总结
java·后端·设计模式·总结
若鱼19191 小时前
SpringBoot4.0新特性-Observability让生产环境更易于观测
java·spring
夜郎king1 小时前
HTML5 SVG 实现日出日落动画与实时天气可视化
前端·html5·svg 日出日落
倒流时光三十年1 小时前
SpringBoot 数据库同步 Elasticsearch 性能优化
数据库·spring boot·elasticsearch