《DeepSeek原生应用与智能体开发实践》【摘要 书评 试读】- 京东图书
在上一小节中,我们展示了如何在Python中调用函数,但是,我们面临一个更复杂的问题:如何在大模型DeepSeek中调用工具?这个问题看似简单,实则涉及许多深层次的技术与思考。就如同多年前人们询问计算机“今天是晴天还是雨天”一样,我们如今要探讨的是如何让大模型调用工具来解决问题。
先回到日常生活中的一个例子。在决定今天的穿着之前,我们通常会有一个明确的前置任务:了解今天的天气。那么,如何获取天气信息呢?以下是一些可能的方法:
- A:对着衣橱问自己应该穿什么衣服。这显然不是获取天气信息的正确途径。
- B:使用互联网登录天气网站,输入本地名称查询。这是一个有效且常用的方法。
- C:打开一本书并阅读任意一页。这与获取天气信息无关。
- D:打开空调。这同样不能告诉我们今天的天气情况。
对于大多数读者来说,选择B是显而易见的,这是基于我们的常识和日常经验。然而,这种基于目标寻找最合适解决方案的能力并非天生,而是需要我们后天的学习和积累。我们需要知道哪些工具或方法可以帮助我们实现目标,这通常需要一个知识库或他人的指导。有知识库辅助研判的任务流程如图6-2所示。
图6-2 有知识库辅助研判的任务流程
上图所示是一个基于常识的决策过程,同时也是我们在日常生活中做出明智决策并取得良好结果的通用步骤。在每次决策之前,我们依赖的是深厚的知识储备或知识库,它们如同明灯,照亮我们前行的道路,引导我们做出最优决策。
当我们回到DeepSeek调用工具的问题时,面临的挑战是如何让这个大模型也具备这样的决策能力,即根据给定的任务,它能知道应当调用哪些工具。作为深度学习程序设计人员,我们的责任不仅是开发模型,更要引导模型如何使用工具。我们可以提供格式化的API信息,这种方式就像是给大模型提供一本详细的程序文档。在这份文档中,我们详细描述每个工具API的功能、参数以及返回值,告诉大语言模型在何时、何地可以调用这些API,并且当API被调用后,返回相应的API的JSON对象。
这样的方式能够让大模型更加智能化地运用工具,进而提升其解决问题的效率和准确性。想象一下,当大模型遇到问题时,它可以像人类一样查阅“工具书”,找到最合适的工具,然后利用这个工具解决问题。
一个可供DeepSeek进行调用的简单函数如下所示:
# 定义工具函数
def get_weather(function_params):
"""模拟获取天气的工具函数"""
location = function_params[0]
# 这里可以调用真实的天气 API
return f"{location}的天气晴朗"
上述函数对象描述了一个名为get_weather的工具API。通过这个API,大模型可以根据输入的城市名称获取当前的天气情况。这样的描述方式清晰明了,使得大模型能够准确理解并调用这个API。因此,通过对工具API中的描述进行甄别,从而判定使用哪一个最合适的工具,加上合理的引导和训练,可以使大模型更加智能化,从而完成对工具的使用。
作者完成了一个在DeepSeek中使用工具的完整示例,代码如下所示:
from openai import OpenAI
import json
client = OpenAI(
api_key="sk-c646e1c201d74777b54f45c60973f4f3",
base_url="https://api.deepseek.com",
)
def get_weather(function_params):
return "天气晴朗"
def send_messages(messages):
response = client.chat.completions.create(
model="deepseek-chat",
messages=messages
)
return response.choices[0].message
system_prompt = """
你在运行一个“思考”“工具调用”“响应”循环。每次只运行一个阶段
1.“思考”阶段:你要仔细思考用户的问题。
2.“工具调用”阶段:选择可以调用的工具,并且输出对应工具需要的参数。
3.“响应”阶段:根据工具调用返回的影响,回复用户问题。
已有的工具如下:
get_weather:
e.g. get_weather:天津
返回天津的天气情况
Example:
question:天津的天气怎么样?
thought:我应该调用工具查询天津的天气情况
Action:
{
"function_name":"get_weather",
"function_params":["天津"]
}
调用Action的结果:“天气晴朗”
Answer:天津的天气晴朗
"""
question = "Shanghai的天气怎么样"
messages = [{"role": "system", "content": system_prompt},
{"role": "user", "content": question}]
message = send_messages(messages)
response = message.content
action = response.split("Action:")[1]
action = json.loads(action)
print(f"ModelResponse:\n {action}")
# 生成调用代码
function_name = action["function_name"]
function_params = action["function_params"]
code = f"{function_name}({function_params})"
print(code)
# 使用eval对生成的代码进行计算,这里假设get_weather函数已经被定义过
result = eval(code)
print(result)
这段代码实现了一个简单的对话系统,能够根据用户的问题调用相应的工具并生成回答。首先,代码通过OpenAI库初始化了一个客户端,并设置了API密钥和基础URL。接着,定义了一个get_weather函数,用于模拟获取天气的功能,返回固定的“天气晴朗”结果。send_messages函数则负责向模型发送消息并获取模型的响应。系统提示(system_prompt)中详细描述了对话系统的三个阶段:思考、工具调用和响应,并提供了一个示例说明如何调用get_weather工具,以回答与天气相关的问题。
生成结果如下所示:
ModelResponse:
{'function_name': 'get_weather', 'function_params': ['上海']}
get_weather(['上海'])
天气晴朗
具体来看,在代码的执行部分,用户提出了一个关于上海天气的问题。系统通过send_messages函数将问题发送给模型,模型根据系统提示生成一个包含工具调用信息的响应。代码通过解析响应中的Action部分,提取出需要调用的工具名称和参数,并生成相应的调用代码。最后,使用eval函数执行生成的代码,模拟工具调用的过程,并输出结果。整个过程展示了如何通过模型生成工具调用指令,并动态执行这些指令来完成用户请求。