打破 LLM 知识边界:Python + DeepSeek 打造能“联网”的 AI Agent

0 阅读5分钟

摘要:大模型(LLM)基于预训练数据,天生存在“知识截止”的硬伤。本文将基于 ModelScope 环境,使用 Python 和 DeepSeek API,通过 Function Calling 机制实现一个最小可行性 Agent(MVP),让模型拥有获取实时天气的能力。

0. 前言:从 Chatbot 到 Agent

大模型很强,但它不仅是一个只知道过去的“书呆子”,还常常一本正经地胡说八道。
如果你问 DeepSeek:“现在抚州气温多少度?”
它只能依靠预训练数据中的概率预测,无法给出事实。因为文本模式匹配实时感知

要打破这个限制,我们需要引入 Function Calling(工具调用) 。简单来说,就是教 LLM 在遇到无法回答的问题时,不要瞎编,而是生成一个“调用指令”,由 Python 去执行这个指令,并将结果返还给 LLM。

Python 是粘合剂,LLM 是大脑。本文将带你手写一个具备联网感知能力的 AI Agent。

0.5 环境准备:工欲善其事

在开始编写代码之前,我们需要安装两个核心库。如果你熟悉前端开发,Python 的 pip 就相当于 Node.js 的 npm。

在 Jupyter Notebook 或 ModelScope 的交互式环境中,我们需要使用 ! 前缀来运行 Shell 命令:

Python

# ! 代表在 Notebook 单元格中运行系统 Shell 命令
!pip install requests openai

依赖解析:

  • requests:Python 界的 HTTP 标配库。我们的 get_weather 工具需要用它向气象接口发起网络请求(相当于 JS 中的 axios 或 fetch)。
  • openai:官方 SDK。为什么调 DeepSeek 要装 OpenAI?  因为 DeepSeek 采用了与 OpenAI 完全一致的 API 规范。这意味着你无需学习新的 SDK,只需更改 base_url,就能用这套最成熟的工具链顺滑接入。

1. The Hand:定义“工具” (Python Side)

Agent 的第一步,是给它一双手。
我们定义一个 get_weather 函数,通过调用第三方 API(这里使用心知天气)获取数据。

核心代码实现:

Python

import requests

# Type Hinting 在这里至关重要,它不仅仅是给开发者看的
# 更是后续生成 JSON Schema 给 LLM 理解的关键依据
def get_weather(location: str) -> str:
    # 实际开发中,Key 应存放在环境变量中
    url = 'https://api.seniverse.com/v3/weather/now.json'
    params = {
        'key': 'Sq7ZF2yrZ_zczwqg-', # 示例 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']
            # 将结构化 JSON 转化为自然语言描述,降低 LLM 理解成本
            return f"{city}当前天气:{now['text']},气温:{now['temperature']}度"
        else:
            return "查询失败:未找到该城市"
    except Exception as e:
        return f"接口异常: {e}"

# 本地测试
# print(get_weather("抚州")) 
# Output: 抚州当前天气:阴,气温:8度

技术点

  • 鲁棒性:网络请求必须包含 try-except,Agent 的工具报错不应导致整个对话崩溃,返回错误信息本身也是一种有效的反馈。
  • Pythonic:利用 Python 强大的字符串处理能力,清洗 API 返回的冗余 JSON,只喂给 LLM 最核心的信息。

2. The Brain:配置模型 (DeepSeek)

DeepSeek 完美兼容 OpenAI SDK 标准,这意味着我们不需要学习新的库,直接替换 base_url 和 api_key 即可。

codePython

from openai import OpenAI

client = OpenAI(
    api_key='sk-xxxx',  # 你的 DeepSeek API Key
    base_url='https://api.deepseek.com/v1'
)

3. The Protocol:确立通信协议 (JSON Schema)

这是最关键的一步。LLM 运行在云端,它跑不了本地 Python 代码。我们需要用 JSON Schema 告诉它:“我有这个工具,参数格式如下”。

Python

tools = [
    {
        'type': 'function',
        'function': {
            'name': 'get_weather',
            'description': '获取指定城市的当前天气信息', # Prompt Engineering 的一部分,越清晰模型决策越准
            'parameters': {
                'type': 'object',
                'properties': {
                    'location': {
                        'type': 'string',
                        'description': '城市名称,例如 "北京", "Shanghai"'
                    }
                },
                'required': ['location']
            }
        }
    }
]

4. The Loop:构建闭环 (Agent Logic)

真正的 Agent 是一个闭环系统。我们需要手动处理模型和工具之间的“握手”。

流程解析:

  1. Ask: 用户提问。
  2. Reason: 模型思考,发现自己不知道,但工具列表里有能用的,于是返回 tool_calls。
  3. Act: Python 捕获 tool_calls,解析参数,执行 get_weather。
  4. Observe: 将执行结果封装为 role: tool 的消息,追加回历史记录。
  5. Response: 模型结合“用户问题”+“工具结果”,生成最终答案。

完整代码逻辑:

Python

import json

# 1. 初始对话上下文
messages = [{"role": "user", "content": "北京天气怎么样"}]

# 2. 第一轮交互:模型决策
response = client.chat.completions.create(
    model='deepseek-reasoner',
    messages=messages,
    tools=tools,
    tool_choice="auto", # 让模型自己决定是否用工具
    temperature=0.3
)

response_message = response.choices[0].message
# 必须将模型的“思考结果”加入历史,否则上下文不连续
messages.append(response_message)

# 3. 检查模型是否发起了工具调用请求
if response_message.tool_calls:
    print(f"Triggered Tool Calls: {len(response_message.tool_calls)}")
    
    for tool_call in response_message.tool_calls:
        function_name = tool_call.function.name
        # 解析 LLM 生成的 JSON 参数字符串
        function_args = json.loads(tool_call.function.arguments)
        
        # 路由分发
        if function_name == "get_weather":
            print(f"Executing: {function_name} with {function_args}")
            tool_result = get_weather(location=function_args.get("location"))
        else:
            tool_result = "未知工具"
            
        # 4. 关键:构造 tool 类型的消息回传给模型
        # tool_call_id 是连接请求与结果的唯一标识
        messages.append({
            "tool_call_id": tool_call.id,
            "role": "tool",
            "name": function_name,
            "content": tool_result
        })

    # 5. 第二轮交互:模型根据工具结果生成最终回答
    final_response = client.chat.completions.create(
        model="deepseek-reasoner",
        messages=messages
    )
    
    print("-" * 20)
    print("Final Answer:", final_response.choices[0].message.content)
else:
    print("Model did not call any tools.")

5. 总结

通过以上 50 行左右的代码,我们实现了一个 Agent 的雏形。

  • DeepSeek 负责理解意图(Intent Recognition)和参数提取(Slot Filling)。
  • Python 负责与物理世界(API)交互。
  • Context (Messages)  是两者同步状态的内存。

这就将 LLM 从一个“聊天机器”升级为了一个能干活的“智能体”。下一步,你可以尝试加入 Google Search 工具,或者让 Agent 操作本地文件,玩转更广阔的自动化场景。