引言

大型语言模型(LLM)虽然拥有强大的文本生成和理解能力,但它本质上是一个“封闭系统”——无法直接访问互联网、数据库或实时数据。为了让 LLM 真正具备“感知世界”的能力,我们需要为其配备“工具”(Tools),并通过 Function Calling(函数调用) 机制实现与外部世界的交互。

本文将带你从零开始,使用 Python + OpenAI 兼容 API(以 DeepSeek 为例),实现一个能自动查询天气的智能助手。你将学到:

  • 如何定义并注册工具(Tool)
  • 如何解析 LLM 的工具调用请求
  • 如何执行真实函数并将结果返回给模型
  • 如何完成完整的“用户提问 → 模型决策 → 调用工具 → 返回答案”闭环

1. 准备工作

安装依赖

pip install requests openai

导入必要库

import requests
import json
from openai import OpenAI

2. 编写天气查询工具函数

我们使用 心知天气 的免费 API 获取实时天气数据。

def get_weather(location: str) -> str:
    """
    根据城市名称查询当前天气
    :param location: 城市名,如 "北京"
    :return: 天气描述字符串
    """
    url = ""
    params = {
        "key": "---",  # 替换为你自己的 API Key
        "location": location,
        "language": "zh-Hans"
    }
    try:
        resp = requests.get(url, params=params, timeout=10)
        data = resp.json()
        if "results" in data:
            r = data["results"][0]
            city = r["location"]["name"]
            now = r["now"]
            text = now["text"]
            temp = now["temperature"]
            return f"{city}当前天气:{text},气温 {temp}℃"
        else:
            return "查询失败,请检查城市名称"
    except Exception as e:
        return f"请求异常:{e}"

3. 配置 LLM 客户端(以 DeepSeek 为例)

DeepSeek 的 API 兼容 OpenAI 协议,因此我们可以直接使用 openai SDK。

client = OpenAI(
    api_key='---',  # 替换为你的 DeepSeek API Key
    base_url=''
)

4. 定义工具(Tool)Schema

为了让 LLM 知道它可以调用哪些函数,我们需要提供结构化的工具描述:

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "获取指定城市的当前天气",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "城市名称,如‘北京’"
                    }
                },
                "required": ["location"]
            }
        }
    }
]

这个 JSON Schema 告诉模型:

  • 有一个叫 get_weather 的函数可用
  • 它需要一个 location 字符串参数
  • 它的作用是查天气

5. 实现完整的 Function Calling 流程

现在,我们模拟一次完整的对话:

# 用户提问
messages = [{"role": "user", "content": "北京天气怎么样?"}]

# 第一次调用:让模型决定是否需要调用工具
response = client.chat.completions.create(
    model="deepseek-reasoner",
    messages=messages,
    tools=tools,
    tool_choice="auto",
    temperature=0.1
)

# 获取模型返回的消息
response_message = response.choices[0].message
messages.append(response_message)  # 将模型消息加入对话历史

# 检查是否需要调用工具
if response_message.tool_calls:
    for tool_call in response_message.tool_calls:
        function_name = tool_call.function.name
        function_args = json.loads(tool_call.function.arguments)

        # 执行对应函数
        if function_name == "get_weather":
            function_response = get_weather(function_args["location"])
        else:
            function_response = "未知工具"

        # 将函数执行结果作为“tool”角色消息加入对话
        messages.append({
            "tool_call_id": tool_call.id,
            "role": "tool",
            "name": function_name,
            "content": function_response
        })

    # 第二次调用:将工具结果传回,让模型生成最终回答
    final_response = client.chat.completions.create(
        model="deepseek-reasoner",
        messages=messages,
        temperature=0.3
    )
    print(final_response.choices[0].message.content)
else:
    # 不需要工具,直接输出模型回答
    print(response_message.content)

6. 运行效果

当用户输入:

北京天气怎么样?

程序输出:

根据最新天气数据,北京当前天气:多云,气温 5℃。

整个过程如下:

  1. 用户提问
  2. LLM 判断需要调用 get_weather("北京")
  3. 程序执行该函数,获取真实天气
  4. 将结果喂回 LLM
  5. LLM 生成自然语言回答

7. 关键点总结

步骤说明
工具定义使用 JSON Schema 描述函数签名
第一次调用设置 tools 和 tool_choice="auto",让模型决定是否调用
解析 tool_calls从 response_message.tool_calls 中提取函数名和参数
执行真实函数在本地运行 Python 函数(如网络请求)
返回结果以 role="tool" 的消息格式追加到对话历史
第二次调用让模型基于工具结果生成最终回答

8. 扩展思考

  • 可以注册多个工具(如查股票、发邮件、查数据库)
  • 结合 LangChain 或 LlamaIndex 可构建更复杂的 Agent
  • 注意控制上下文长度,避免因消息过长导致 token 超限
  • 敏感操作需加入权限校验和安全过滤

结语

Function Calling 是 LLM 走出“幻觉牢笼”、连接现实世界的关键桥梁。通过本文的实践,你已经掌握了如何让大模型“动手做事”。下一步,不妨尝试接入更多 API,打造属于你自己的 AI 助手!

本站提供的所有下载资源均来自互联网,仅提供学习交流使用,版权归原作者所有。如需商业使用,请联系原作者获得授权。 如您发现有涉嫌侵权的内容,请联系我们 邮箱:[email protected]