以下是一个简单的 Python 脚本,展示如何用 OpenAI 库调用 Ollama 的 qwen2.5 模型,实现对工具的调用:
import asyncio
from openai import AsyncOpenAI
class LLM:
def __init__(self):
self.model = "qwen2.5"
self.max_tokens = 4096
self.base_url = "http://127.0.0.1:11434/v1"
self.api_key = "key"
self.client = AsyncOpenAI(api_key=self.api_key, base_url=self.base_url)
async def ask_tool(self, prompt, tools=None, temperature=1.0, timeout=None, **kwargs):
"""
向模型发送带有工具调用的提示并获取回复
Args:
prompt (str): 用户输入的提示文本
tools (list, optional): 可用的工具列表
temperature (float, optional): 控制回复的随机性,默认为1.0
timeout (int, optional): 请求超时时间
**kwargs: 其他可选参数
Returns:
str: 模型的回复内容
"""
messages = [{"role": "user", "content": prompt}]
response = await self.client.chat.completions.create(
model=self.model,
messages=messages,
temperature=temperature,
max_tokens=self.max_tokens,
tools=tools,
tool_choice="auto",
timeout=timeout,
**kwargs,
)
print(response)
return response.choices[0].message.content
if __name__ == "__main__":
async def main():
llm = LLM()
# 测试工具调用
tools = [
{
"type": "function",
"function": {
"name": "get_current_time",
"description": "获取当前时间",
"parameters": {
"type": "object",
"properties": {
"timezone": {"type": "string", "description": "时区"}
}
}
}
}
]
results = await llm.ask_tool("当前的北京时间是多少", tools=tools)
print(results)
asyncio.run(main())
安装openai依赖:
uv pip install openai
执行:
% python llm/ollama.tool.py
ChatCompletion(id='chatcmpl-441', choices=[Choice(finish_reason='tool_calls', index=0, logprobs=None, message=ChatCompletionMessage(content='', refusal=None, role='assistant', annotations=None, audio=None, function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_au8ws2w9', function=Function(arguments='{"timezone":"Asia/Shanghai"}', name='get_current_time'), type='function', index=0)]))], created=1745823347, model='qwen2.5', object='chat.completion', service_tier=None, system_fingerprint='fp_ollama', usage=CompletionUsage(completion_tokens=23, prompt_tokens=157, total_tokens=180, completion_tokens_details=None, prompt_tokens_details=None))
返回内容如下(已格式化):
ChatCompletion(
id='chatcmpl-441',
choices=[
Choice(
finish_reason='tool_calls',
index=0,
logprobs=None,
message=ChatCompletionMessage(
content='',
refusal=None,
role='assistant',
annotations=None,
audio=None,
function_call=None,
tool_calls=[
ChatCompletionMessageToolCall(
id='call_au8ws2w9',
function=Function(
arguments='{"timezone":"Asia/Shanghai"}',
name='get_current_time'
),
type='function',
index=0
)
]
)
)
],
created=1745823347,
model='qwen2.5',
object='chat.completion',
service_tier=None,
system_fingerprint='fp_ollama',
usage=CompletionUsage(
completion_tokens=23,
prompt_tokens=157,
total_tokens=180,
completion_tokens_details=None,
prompt_tokens_details=None
)
)
解释
choices
:模型的回复列表,这里只有一个回复。finish_reason='tool_calls'
:表示模型决定调用工具(function call),而不是直接回复文本。message.content=''
:回复内容为空,因为模型选择了工具调用。tool_calls
:工具调用的详细信息。id='call_au8ws2w9'
:本次工具调用的唯一ID。function
:要调用的函数信息。name='get_current_time'
:要调用的函数名。arguments='{"timezone":"Asia/Shanghai"}'
:传递给函数的参数(这里是时区)。
type='function'
:调用类型为函数。
- 其他字段如
created
、model
、usage
等为元数据。
总结
你的模型没有直接返回“北京时间”,而是决定调用你定义的 get_current_time
工具,并传递了参数 {"timezone":"Asia/Shanghai"}
。
这说明你的工具调用机制是正常的,下一步你需要实现 get_current_time
这个函数,并让系统能够根据工具调用结果返回最终答案。
完整的例子实现
import asyncio
import json
from datetime import datetime
import pytz
from openai import AsyncOpenAI
class LLM:
def __init__(self):
self.model = "qwen2.5"
self.max_tokens = 4096
self.base_url = "http://10.1.60.15:31434/v1"
self.api_key = "key"
self.client = AsyncOpenAI(api_key=self.api_key, base_url=self.base_url)
async def ask_tool(self, prompt, tools=None, temperature=1.0, timeout=None, **kwargs):
"""
向模型发送带有工具调用的提示并获取回复
Args:
prompt (str): 用户输入的提示文本
tools (list, optional): 可用的工具列表
temperature (float, optional): 控制回复的随机性,默认为1.0
timeout (int, optional): 请求超时时间
**kwargs: 其他可选参数
Returns:
str: 模型的回复内容
"""
messages = [{"role": "user", "content": prompt}]
response = await self.client.chat.completions.create(
model=self.model,
messages=messages,
temperature=temperature,
max_tokens=self.max_tokens,
tools=tools,
tool_choice="auto",
timeout=timeout,
**kwargs,
)
print(f"模型初次回复: {response}")
tool_calls = response.choices[0].message.tool_calls
if tool_calls:
tool_call = tool_calls[0]
print(f"检测到工具调用: {tool_call.function.name}, 参数: {tool_call.function.arguments}")
tool_result = self.handle_tool_call(tool_call)
print(f"本地工具返回: {tool_result}")
messages.append({
"role": "assistant",
"content": "",
"tool_calls": [tool_call]
})
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"name": tool_call.function.name,
"content": tool_result
})
response = await self.client.chat.completions.create(
model=self.model,
messages=messages,
temperature=temperature,
max_tokens=self.max_tokens,
timeout=timeout,
**kwargs,
)
print(f"最终模型回复: {response.choices[0].message.content}")
return response.choices[0].message.content
else:
print(f"最终模型回复: {response.choices[0].message.content}")
return response.choices[0].message.content
def handle_tool_call(self, tool_call):
"""
根据 tool_call 调用本地工具函数
"""
function_name = tool_call.function.name
arguments = json.loads(tool_call.function.arguments)
if function_name == "get_current_time":
return get_current_time(**arguments)
else:
return f"未实现的工具: {function_name}"
def get_current_time(timezone):
tz = pytz.timezone(timezone)
return datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S")
if __name__ == "__main__":
async def main():
llm = LLM()
# 测试工具调用
tools = [
{
"type": "function",
"function": {
"name": "get_current_time",
"description": "获取当前时间",
"parameters": {
"type": "object",
"properties": {
"timezone": {"type": "string", "description": "时区"}
}
}
}
}
]
results = await llm.ask_tool("当前的北京时间是多少", tools=tools)
print(results)
asyncio.run(main())
安装依赖
uv pip install pytz
执行
% python llm/ollama.tool.py
模型初次回复: ChatCompletion(id='chatcmpl-633', choices=[Choice(finish_reason='tool_calls', index=0, logprobs=None, message=ChatCompletionMessage(content='', refusal=None, role='assistant', annotations=None, audio=None, function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_higvk9pm', function=Function(arguments='{"timezone":"Asia/Shanghai"}', name='get_current_time'), type='function', index=0)]))], created=1745824286, model='qwen2.5', object='chat.completion', service_tier=None, system_fingerprint='fp_ollama', usage=CompletionUsage(completion_tokens=23, prompt_tokens=157, total_tokens=180, completion_tokens_details=None, prompt_tokens_details=None))
检测到工具调用: get_current_time, 参数: {"timezone":"Asia/Shanghai"}
本地工具返回: 2025-04-28 15:11:26
最终模型回复: 当前的北京时间是2025年4月28日 15点11分26秒。请注意,这个时间是基于提供的工具响应。实际情况可能会有所不同,请以最新的时钟为准。
当前的北京时间是2025年4月28日 15点11分26秒。请注意,这个时间是基于提供的工具响应。实际情况可能会有所不同,请以最新的时钟为准。