这段代码使用了 OpenAI 兼容的 API 接口(阿里云 DashScope 的 Qwen 模型),结合 函数调用(Function Calling / Tools) 功能,实现了一个简单的“股票收盘价查询”对话系统。下面我将逐部分解析其逻辑和功能。
一、导入依赖
1 2 3
| import json import os from openai import OpenAI
|
json:用于解析模型返回的函数参数(字符串形式的 JSON)。
os:用于读取环境变量中的 API 密钥。
OpenAI:使用官方 OpenAI SDK,但实际调用的是阿里云 DashScope 的兼容接口。
二、初始化 OpenAI 客户端
1 2 3 4
| client = OpenAI( api_key=os.getenv("AliDeep"), base_url="https://dashscope.aliyuncs.com/compatible-mode/v1 " )
|
- 使用环境变量
AliDeep 作为 API Key(需提前设置)。
base_url 指向 阿里云 DashScope 的 OpenAI 兼容模式接口(注意末尾有空格,可能是个笔误,但不影响运行)。
- 这样就可以用 OpenAI SDK 调用阿里云的 Qwen 模型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| tools = [ { "type": "function", "function": { "name": "get_closing_price", "description": "使用该工具获取指定股票的收盘价", "parameters": { "type": "object", "properties": { "name": {"type": "string", "description": "股票名称"} }, "required": ["name"] } } } ]
|
- 定义了一个名为
get_closing_price 的工具(函数)。
- 模型在需要查询股票价格时,会“调用”这个工具,并传入
name 参数(如“青岛啤酒”)。
四、定义实际的工具函数
1 2 3 4 5 6 7
| def get_closing_price(name): if name == "青岛啤酒": return "67.92" elif name == "贵州茅台": return "1488.21" else: return "未搜到该股票"
|
- 这是一个模拟的股票查询函数,仅支持两个股票,其余返回“未搜到”。
五、主流程(__main__)
1. 初始化用户消息
1
| messages = [{"role": "user", "content": "青岛啤酒的收盘价是多少?"}]
|
2. 第一次调用模型
1 2
| response = send_messages(messages) messages.append(response.choices[0].message)
|
- 调用
qwen-max 模型,传入 tools。
- 模型判断需要调用
get_closing_price 工具,不会直接回答,而是返回一个 tool_calls 字段。
- 将模型的回复(包含工具调用信息)追加到
messages 中,用于后续对话上下文。
3. 打印第一次回复
1 2 3 4
| print("回复:") print(response.choices[0].message.content) print("工具选择:") print(response.choices[0].message.tool_calls)
|
- 此时
content 通常为 None,因为模型选择调用工具而非直接回答。
tool_calls 包含函数名和参数(如 {"name": "青岛啤酒"})。
4. 执行工具调用
1 2 3 4 5 6 7 8 9 10
| if response.choices[0].message.tool_calls != None: tool_call = response.choices[0].message.tool_calls[0] if tool_call.function.name == "get_closing_price": arguments_dict = json.loads(tool_call.function.arguments) price = get_closing_price(arguments_dict['name']) messages.append({ "role": "tool", "content": price, "tool_call_id": tool_call.id })
|
- 解析参数(JSON 字符串转字典)。
- 调用本地
get_closing_price 函数获取价格。
- 将工具执行结果作为
role="tool" 的消息加入对话历史(必须包含 tool_call_id 以匹配调用)。
5. 第二次调用模型(传入工具结果)
1 2 3
| response = send_messages(messages) print("回复:") print(response.choices[0].message.content)
|
- 模型收到工具返回的“67.92”后,生成自然语言回答,如:
“青岛啤酒的收盘价是67.92元。”
六、整体流程总结(Function Calling 两步走)
- 第一步:用户提问 → 模型识别需调用工具 → 返回
tool_calls。
- 第二步:程序执行工具 → 将结果返回给模型 → 模型生成最终回答。
这是标准的 LLM Function Calling 工作流,适用于需要外部数据或操作的场景。
七、潜在问题与改进建议
✅ 优点
- 正确实现了工具调用的完整流程。
- 使用 OpenAI SDK 兼容阿里云接口,代码简洁。
⚠️ 注意事项
base_url 末尾空格:
1
| base_url="https://dashscope.aliyuncs.com/compatible-mode/v1 "
|
硬编码股票数据:
- 实际应用中应对接真实股票 API(如 Tushare、新浪财经等)。
错误处理缺失:
- 未处理
json.loads 失败、网络异常、模型无响应等情况。
仅支持单次工具调用:
- 代码假设只有一个
tool_call,若模型返回多个,会出错。可改为循环处理。
八、示例输出(预期)
1 2 3 4 5 6 7 8 9 10 11
| 回复: None 工具选择: [ChatCompletionMessageToolCall(... function=Function(name='get_closing_price', arguments='{"name": "青岛啤酒"}') ...)] messages: [ {'role': 'user', 'content': '青岛啤酒的收盘价是多少?'}, {'role': 'assistant', 'content': None, 'tool_calls': [...]}, {'role': 'tool', 'content': '67.92', 'tool_call_id': '...'} ] 回复: 青岛啤酒的收盘价是67.92元。
|