InternLM/lmdeploy 工具调用功能详解
工具调用功能概述
InternLM/lmdeploy 是一个高效的大语言模型推理和部署框架,它支持多种主流大语言模型的工具调用功能。工具调用(Tool Calling)是大语言模型的重要能力之一,它允许模型在对话过程中调用外部工具或函数来完成特定任务,如数学计算、天气查询等。
支持的模型和工具解析器
目前,lmdeploy 支持以下模型的工具调用功能:
- InternLM2 系列模型
- InternLM2.5 系列模型
- Llama3.1 系列模型
- Qwen2.5 系列模型
在使用 api_server 启动服务时,需要通过 --tool-call-parser
参数指定对应的工具解析器:
- internlm:适用于 InternLM2 和 InternLM2.5 模型
- qwen:适用于 Qwen2.5 模型
- llama3:适用于 Llama3.1 模型
单轮工具调用示例
单轮工具调用是最基础的工具使用场景,模型根据用户请求决定是否需要调用工具以及调用哪个工具。下面是一个查询天气的示例:
from openai import OpenAI
# 定义工具集
tools = [
{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "获取指定位置的当前天气",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "城市和州,例如:北京市",
},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
},
"required": ["location"],
},
}
}
]
# 用户消息
messages = [{"role": "user", "content": "今天北京的天气怎么样?"}]
# 创建客户端连接
client = OpenAI(api_key='YOUR_API_KEY', base_url='http://0.0.0.0:23333/v1')
# 获取模型名称
model_name = client.models.list().data[0].id
# 发送请求
response = client.chat.completions.create(
model=model_name,
messages=messages,
temperature=0.8,
top_p=0.8,
stream=False,
tools=tools)
print(response)
在这个例子中,模型会识别出用户询问天气的意图,并返回需要调用 get_current_weather
工具的信息。
多轮工具调用
多轮工具调用更复杂,模型可能需要多次调用工具才能完成用户请求。下面以数学计算为例展示完整流程。
InternLM 多轮工具调用
from openai import OpenAI
# 定义工具函数
def add(a: int, b: int):
return a + b
def mul(a: int, b: int):
return a * b
# 工具集定义
tools = [
{
'type': 'function',
'function': {
'name': 'add',
'description': '计算两个数的和',
'parameters': {
'type': 'object',
'properties': {
'a': {'type': 'int', 'description': '数字'},
'b': {'type': 'int', 'description': '数字'},
},
'required': ['a', 'b'],
},
}
},
{
'type': 'function',
'function': {
'name': 'mul',
'description': '计算两个数的乘积',
'parameters': {
'type': 'object',
'properties': {
'a': {'type': 'int', 'description': '数字'},
'b': {'type': 'int', 'description': '数字'},
},
'required': ['a', 'b'],
},
}
}
]
# 用户请求
messages = [{'role': 'user', 'content': '计算(3+5)*2'}]
# 创建客户端
client = OpenAI(api_key='YOUR_API_KEY', base_url='http://0.0.0.0:23333/v1')
model_name = client.models.list().data[0].id
# 第一轮:识别需要先计算3+5
response = client.chat.completions.create(
model=model_name,
messages=messages,
temperature=0.8,
top_p=0.8,
stream=False,
tools=tools)
# 执行加法工具
add_result = eval(f"add(**{response.choices[0].message.tool_calls[0].function.arguments})")
# 将结果加入对话历史
messages.extend([
response.choices[0].message,
{
'role': 'tool',
'content': f'3+5={add_result}',
'tool_call_id': response.choices[0].message.tool_calls[0].id
}
])
# 第二轮:计算8*2
response = client.chat.completions.create(
model=model_name,
messages=messages,
temperature=0.8,
top_p=0.8,
stream=False,
tools=tools)
# 执行乘法工具
mul_result = eval(f"mul(**{response.choices[0].message.tool_calls[0].function.arguments})")
print(f"最终结果: {mul_result}")
Qwen2.5 多工具并行调用
Qwen2.5 支持在一次请求中同时调用多个工具,这在需要获取多个信息时特别有用:
from openai import OpenAI
import json
# 天气查询工具函数
def get_current_temperature(location: str, unit: str = "celsius"):
"""获取当前位置的当前温度"""
return {
"temperature": 26.1,
"location": location,
"unit": unit,
}
def get_temperature_date(location: str, date: str, unit: str = "celsius"):
"""获取指定位置和日期的温度"""
return {
"temperature": 25.9,
"location": location,
"date": date,
"unit": unit,
}
# 工具集定义
tools = [
{
'type': 'function',
'function': {
'name': 'get_current_temperature',
'description': '获取当前位置的当前温度',
'parameters': {
'type': 'object',
'properties': {
'location': {
'type': 'string',
'description': '位置信息,格式为"城市, 州, 国家"'
},
'unit': {
'type': 'string',
'enum': ['celsius', 'fahrenheit'],
'description': '温度单位,默认为摄氏度'
}
},
'required': ['location']
}
}
},
{
'type': 'function',
'function': {
'name': 'get_temperature_date',
'description': '获取指定位置和日期的温度',
'parameters': {
'type': 'object',
'properties': {
'location': {
'type': 'string',
'description': '位置信息,格式为"城市, 州, 国家"'
},
'date': {
'type': 'string',
'description': '日期,格式为"年-月-日"'
},
'unit': {
'type': 'string',
'enum': ['celsius', 'fahrenheit'],
'description': '温度单位,默认为摄氏度'
}
},
'required': ['location', 'date']
}
}
}
]
# 用户请求
messages = [{'role': 'user', 'content': '今天是2024-11-14,现在旧金山的温度是多少?明天的温度呢?'}]
# 创建客户端
client = OpenAI(api_key='YOUR_API_KEY', base_url='http://0.0.0.0:23333/v1')
model_name = client.models.list().data[0].id
# 发送请求,模型会同时识别需要查询当前温度和明日温度
response = client.chat.completions.create(
model=model_name,
messages=messages,
temperature=0.8,
top_p=0.8,
stream=False,
tools=tools)
# 处理工具调用结果
messages.append(response.choices[0].message)
for tool_call in response.choices[0].message.tool_calls:
args = json.loads(tool_call.function.arguments)
if tool_call.function.name == "get_current_temperature":
result = get_current_temperature(**args)
else:
result = get_temperature_date(**args)
messages.append({
'role': 'tool',
'name': tool_call.function.name,
'content': str(result),
'tool_call_id': tool_call.id
})
# 获取最终回答
final_response = client.chat.completions.create(
model=model_name,
messages=messages,
temperature=0.8,
top_p=0.8,
stream=False,
tools=tools)
print(final_response.choices[0].message.content)
最佳实践建议
-
工具描述清晰:确保工具的描述和参数说明清晰准确,这有助于模型正确理解和使用工具。
-
错误处理:在实际应用中,应该对工具调用可能出现的错误进行处理,如网络问题、参数错误等。
-
安全性:避免直接将用户输入传递给
eval()
等可能执行任意代码的函数,应该进行严格的参数检查和过滤。 -
模型选择:对于复杂的工具调用场景,建议使用更大参数的模型(如70B级别),它们通常能更好地处理多轮工具调用。
-
性能考虑:工具调用会增加交互的延迟,在设计应用时要考虑用户体验。
通过合理使用工具调用功能,可以大大扩展大语言模型的能力边界,使其能够完成更复杂的任务,提供更准确的信息。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考