引言

在人工智能飞速发展的今天,大语言模型(LLM)已经不再是单纯的文本生成器。它们正在进化为具备主动行动能力的智能体——能够理解任务、调用外部工具、获取实时信息,并基于这些信息做出更准确的决策。本文将结合一段完整的代码示例,深入剖析如何让LLM通过调用外部API来实现真正的“思考与行动”,从而构建一个能真正解决实际问题的AI系统。


一、背景知识铺垫:为什么需要让LLM“用工具”?

传统的LLM虽然拥有强大的语言理解和生成能力,但它存在一个根本性局限:

它只能基于训练数据中的信息进行推理和回答。

这意味着:

  • 它无法知道最新的新闻事件;
  • 它不知道今天的天气状况;
  • 它不能查询实时股价或航班状态。

因此,为了让LLM具备实时感知世界的能力,我们需要让它能够“使用工具”——比如调用天气API、股票接口等。这正是我们今天要讲解的核心技术:LLM工具调用(Tool Calling)


二、代码详解:一步步构建“会查天气的AI助手”

我们将逐行分析以下Jupyter Notebook中的代码,确保每一个细节都清晰明了。

print("LLM 调用 tools, 让 LLM '身外之物'")

第一步:环境准备 —— 安装依赖包

# npm install
# 先安装 requests
pip install requests
pip install openai

解释:

  • requests 是Python中用于发送HTTP请求的库,用来与外部API通信。
  • openai 是OpenAI官方提供的SDK,支持与ChatGPT等模型交互。
  • 这里虽然使用的是DeepSeek模型,但其接口兼容OpenAI格式,所以可以使用相同的客户端。

第二步:定义工具函数 —— 获取天气信息

import requests

def get_weather(location: str) -> str:
    url = "https://api.seniverse.com/v3/weather/now.json"
    params = {
        "key": "SaVS0t7eYbapka9iv",
        "location": location,
        "language": "zh-Hans"
    }
    try:
        resp = requests.get(url, params=params, timeout=10)
        data = resp.json()
        print(data)
        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}"

详细解析:

  1. 函数签名get_weather(location: str) -> str

    • 接收一个城市名称字符串作为输入;
    • 返回一个描述天气情况的字符串。
  2. API地址https://api.seniverse.com/v3/weather/now.json

    • 使用的是心知天气的免费API。
    • 需要提供API Key(已加密处理)。
  3. 参数说明

    • "key":你的API密钥;
    • "location":目标城市名(如"北京");
    • "language":返回语言设置为简体中文。
  4. 请求逻辑

    • 使用requests.get()发起GET请求;
    • 设置超时时间为10秒,防止卡死;
    • 将响应解析为JSON对象;
    • 提取关键字段:城市名、天气描述、温度;
    • 返回格式化后的结果。
  5. 异常处理

    • 如果网络出错或API无响应,捕获异常并返回错误提示。

测试调用:

print(get_weather("杭州"))

输出示例:

{'results': [{'location': {'id': 'HSFXR95RZD21', 'name': '杭州', 'country': 'CN', 'path': '杭州,杭州,江西,中国', ...}, 'now': {'text': '晴', 'temperature': '12'}, ...}]
杭州当前天气: 晴, 气温 12度

第三步:初始化OpenAI客户端

from openai import OpenAI

client = OpenAI(
    api_key="sk-f258376fcd7662418c578dd236dcbc64",
    base_url="https://api.deepseek.com/v1"
)

详细解析:

  • 使用OpenAI类创建客户端实例;
  • api_key:DeepSeek API的密钥(注意:此为示例密钥,请勿直接使用);
  • base_url:指向DeepSeek的API地址,而非OpenAI官方地址;
  • 这表明我们正在使用兼容OpenAI协议的第三方模型服务,即DeepSeek。

第四步:定义工具(Tools) —— 告诉LLM我能做什么

# OpenAI 接口工具定义
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "获取指定城市的当前天气。",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "城市名称,如 北京"
                    }
                },
                "required": ["location"]
            }
        }
    }
]

详细解析:

  • tools 是一个列表,每个元素是一个工具定义;
  • 每个工具必须包含:
    • "type": "function":表示这是一个可调用的函数;
    • "function":具体函数信息;
      • "name":函数名,必须与实际函数一致;
      • "description":对这个工具功能的自然语言描述;
      • "parameters":参数结构,以JSON Schema形式定义;
        • "properties":参数的具体属性;
          • "location":类型为字符串,描述为“城市名称”;
        • "required":必填参数列表,这里只有location是必需的。

⚠️ 注意:

  • 这个tools配置会被传给LLM,告诉它:“我有一个叫get_weather的功能,你可以用它来查天气。”
  • LLM会根据用户的问题判断是否需要调用该工具。

第五步:发起多轮对话 + 工具调用流程

import json

messages = [{"role": "user", "content": "北京天气怎么样?"}]
response = client.chat.completions.create(
    model="deepseek-reasoner",
    messages=messages,
    tools=tools,
    tool_choice="auto",
    temperature=0.3
)

详细解析:

  • messages:对话历史,初始为用户提问;
  • model="deepseek-reasoner":使用DeepSeek的推理模型(更强的逻辑能力);
  • tools=tools:传递前面定义的工具列表;
  • tool_choice="auto":让模型自动决定是否调用工具;
  • temperature=0.3:控制输出随机性,较低值保证稳定性。

第六步:处理工具调用结果

response_message = response.choices[0].message
# 参考文档
print(response_message)
# tool_calls ChatCompletionMessageFunctionToolCall
messages.append(response_message)

if response_message.tool_calls:
    for tool_call in response_message.tool_calls:
        function_name = tool_call.function.name
        # json 字符串变成json 对象
        function_args = json.loads(tool_call.function.arguments)
        if function_name == "get_weather":
            function_response = get_weather(function_args["location"])
        else:
            function_response = "未知工具"
        messages.append({
            "tool_call_id": tool_call.id,
            "role": "tool",
            "name": function_name,
            "content": function_response
        })
else:
    print(response_message.content)

详细解析:

  1. 获取回复消息

    • response_message = response.choices[0].message
    • 得到LLM返回的消息对象。
  2. 检查是否有工具调用

    • if response_message.tool_calls::如果模型决定调用工具,则进入分支;
    • tool_call.function.name:获取被调用的函数名;
    • tool_call.function.arguments:获取传入的参数(通常是JSON字符串);
    • 使用json.loads()将其转换为字典;
  3. 执行对应函数

    • 判断函数名为get_weather,则调用之前定义的get_weather()函数;
    • 传入参数location
    • 执行后得到真实天气数据;
  4. 构造工具响应消息

    • messages列表追加一条tool角色的消息;
    • 包含:
      • tool_call_id:工具调用ID;
      • role: "tool";
      • name: 函数名;
      • content: 实际执行结果(如“北京当前天气: 晴, 气温 12度”);
  5. 如果没有工具调用

    • 直接打印LLM的纯文本回复。

第七步:最终回复 —— 结合工具结果生成完整答案

final_response = client.chat.completions.create(
    model="deepseek-reasoner",
    messages=messages,
    temperature=0.3
)
print(final_response.choices[0].message.content)

详细解析:

  • 此时messages中已经包含了:
    • 用户提问;
    • 模型要求调用工具;
    • 工具返回的真实天气数据;
  • 再次调用LLM,让它基于完整上下文生成最终回答;
  • 最终输出可能是:
北京当前天气: 晴, 气温 12度
这是一个比较舒适的天气,适合户外活动。不过北京的天气变化较快,建议您:
- 早晚温差可能较大,注意适时增减衣物
- 如果长时间在户外,可以适当防晒
- 关注最新天气预报,了解天气变化

需要我为您查询更详细的天气信息(如未来几天的预报)吗?

三、关键技术点总结

技术点 作用
工具定义(Tools) 告诉LLM你能做什么,以及怎么用
tool_choice="auto" 让模型自主判断是否需要调用工具
tool_calls LLM返回的工具调用指令
function arguments 传给工具的参数,需正确解析
multi-turn conversation 多轮对话机制,先调用工具,再生成最终回复

四、背后的AI原理:LLM如何“学会使用工具”?

现代大模型之所以能调用工具,是因为它经过了专门的训练:

  1. 在训练数据中学习“工具使用模式”

    • 模型看到大量类似“我需要查询天气 → 调用get_weather(北京)”的样本;
    • 学习到“当用户问天气时,应该调用某个函数”。
  2. 通过函数签名理解参数含义

    • 模型能理解location是城市名,必须是字符串;
    • 知道哪些参数是必需的。
  3. 结合上下文推理决策

    • 即使没有明确说“请查天气”,只要语义相关,模型也能触发工具调用。

五、扩展应用方向

一旦掌握了工具调用,就可以构建更多智能场景:

场景 工具示例
智能客服 查询订单状态、退款进度
金融助手 获取股票行情、基金净值
旅游推荐 查景点开放时间、天气、交通
医疗咨询 查询药品说明书、医院挂号信息

只需添加新的工具函数和对应的API,就能不断扩展AI的能力边界。


六、结语:从“被动回答”到“主动行动”

我们今天所展示的代码,只是一个起点。它揭示了一个深刻的趋势:

未来的AI不再只是“会说话”的机器人,而是能“动手做事”的智能代理。

通过将LLM与外部工具结合,我们可以打造真正有用的AI助手——它不仅能理解你的话,还能为你去查天气、订机票、写报告……

正如你看到的,这一切并不复杂。只需要:

  1. 定义好工具;
  2. 给模型提供调用权限;
  3. 让它自己决定何时使用。

剩下的,就交给AI去完成吧!


附录:运行建议

  • 使用自己的API Key替换示例中的密钥;
  • 替换get_weather为其他API(如天气、股票、翻译等);
  • 在本地或云上部署Jupyter Notebook运行;
  • 推荐使用魔搭(ModelScope)平台快速部署和微调模型。

源码链接:python/tools/weather.ipynb · Zou/lesson_zp - Gitee.com

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐