170 lines
5.3 KiB
Markdown
170 lines
5.3 KiB
Markdown
# AI工具调用指南
|
||
|
||
本文档提供了解决OpenAI API工具调用验证错误的方法和建议。
|
||
|
||
## 常见错误
|
||
|
||
您遇到的错误是一个标准的OpenAI API参数验证错误:
|
||
|
||
```
|
||
BadRequestError: Error code: 400 - {'error': {'message': "3 validation errors for ValidatorIterator\n0.ChatCompletionMessageFunctionToolCallParam.function.arguments\n Input should be a valid string [type=string_type, input_value=None, input_type=NoneType]\n For further information visit https://errors.pydantic.dev/2.11/v/string_type\n0.ChatCompletionMessageCustomToolCallParam.custom\n Field required [type=missing, input_value={'type': 'function', 'id'...ns', 'arguments': None}}, input_type=dict]\n For further information visit https://errors.pydantic.dev/2.11/v/missing\n0.ChatCompletionMessageCustomToolCallParam.type\n Input should be 'custom' [type=literal_error, input_value='function', input_type=str]\n For further information visit https://errors.pydantic.dev/2.11/v/literal_error None", 'type': 'BadRequestError', 'param': None, 'code': 400}}
|
||
```
|
||
|
||
这个错误表明您在调用OpenAI API时,工具调用参数验证失败。
|
||
|
||
## 解决方案
|
||
|
||
### 1. 确保每个工具调用都有有效的参数JSON字符串
|
||
|
||
在OpenAI API调用中,即使工具不需要任何参数,也必须提供一个空的JSON对象字符串 `"{}"`。
|
||
|
||
**错误示例:**
|
||
```python
|
||
tool_call = {
|
||
"type": "function",
|
||
"function": {
|
||
"name": "queryPositions",
|
||
"arguments": None # 这会导致验证错误
|
||
}
|
||
}
|
||
```
|
||
|
||
**正确示例:**
|
||
```python
|
||
tool_call = {
|
||
"type": "function",
|
||
"function": {
|
||
"name": "queryPositions",
|
||
"arguments": "{}" # 即使没有参数,也提供空的JSON对象字符串
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2. 修改Python客户端代码
|
||
|
||
如果您使用Python调用OpenAI API,可以使用以下模式来确保参数总是有效的JSON字符串:
|
||
|
||
```python
|
||
import json
|
||
from openai import OpenAI
|
||
|
||
client = OpenAI(api_key="your-api-key")
|
||
|
||
def call_tool(tool_name, params=None):
|
||
# 确保参数是有效的JSON字符串
|
||
if params is None:
|
||
params_str = "{}"
|
||
elif isinstance(params, str):
|
||
# 如果已经是字符串,确保是有效的JSON
|
||
try:
|
||
json.loads(params) # 验证JSON有效性
|
||
params_str = params
|
||
except json.JSONDecodeError:
|
||
params_str = "{}" # 如果无效,使用空对象
|
||
else:
|
||
# 将对象转换为JSON字符串
|
||
params_str = json.dumps(params)
|
||
|
||
# 调用OpenAI API
|
||
response = client.chat.completions.create(
|
||
model="gpt-4-turbo",
|
||
messages=[{"role": "user", "content": "使用工具执行任务"}],
|
||
tools=[{
|
||
"type": "function",
|
||
"function": {
|
||
"name": tool_name,
|
||
"description": "工具描述",
|
||
"parameters": {
|
||
"type": "object",
|
||
"properties": {},
|
||
"required": []
|
||
}
|
||
}
|
||
}],
|
||
tool_choice={"type": "function", "function": {"name": tool_name}}
|
||
)
|
||
|
||
# 处理工具调用结果
|
||
tool_calls = response.choices[0].message.tool_calls
|
||
if tool_calls:
|
||
tool_call = tool_calls[0]
|
||
# 执行实际工具调用...
|
||
return tool_call.function.arguments
|
||
|
||
return None
|
||
|
||
# 使用示例
|
||
result = call_tool("queryPositions", {"query": "经理"})
|
||
# 或者不带参数
|
||
result = call_tool("queryPositions")
|
||
```
|
||
|
||
### 3. 在工具定义中添加必填参数
|
||
|
||
为避免参数验证问题,可以为每个工具添加至少一个必填参数。这样可以确保调用者必须提供参数。
|
||
|
||
```go
|
||
Tool: mcp.NewTool(
|
||
"queryPositions",
|
||
mcp.WithDescription("查询岗位列表"),
|
||
mcp.WithString("query", mcp.Required(), mcp.Description("搜索关键词,可为空字符串但必须提供")),
|
||
// 其他可选参数...
|
||
),
|
||
```
|
||
|
||
## 在JavaScript中调用API的正确方式
|
||
|
||
如果您在前端JavaScript中调用OpenAI API,确保遵循以下模式:
|
||
|
||
```javascript
|
||
async function callOpenAIWithTool(toolName, params = {}) {
|
||
const response = await fetch('https://api.openai.com/v1/chat/completions', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'Authorization': `Bearer ${OPENAI_API_KEY}`
|
||
},
|
||
body: JSON.stringify({
|
||
model: 'gpt-4-turbo',
|
||
messages: [{ role: 'user', content: '使用工具执行任务' }],
|
||
tools: [{
|
||
type: 'function',
|
||
function: {
|
||
name: toolName,
|
||
description: '工具描述',
|
||
parameters: {
|
||
type: 'object',
|
||
properties: {}
|
||
}
|
||
}
|
||
}],
|
||
tool_choice: { type: 'function', function: { name: toolName } }
|
||
})
|
||
});
|
||
|
||
const data = await response.json();
|
||
return data;
|
||
}
|
||
|
||
// 调用示例
|
||
callOpenAIWithTool('queryPositions', {query: ''}) // 提供空字符串也可以
|
||
.then(result => console.log(result))
|
||
.catch(error => console.error(error));
|
||
```
|
||
|
||
## 针对您的工具的特定解决方案
|
||
|
||
对于`queryPositions`工具,我建议始终提供一个空的查询参数:
|
||
|
||
```python
|
||
# Python示例
|
||
result = call_tool("queryPositions", {"query": ""})
|
||
```
|
||
|
||
```javascript
|
||
// JavaScript示例
|
||
callOpenAIWithTool('queryPositions', {query: ''})
|
||
```
|
||
|
||
如果您遇到同样的问题,对其他工具也采用类似的方法,始终提供至少一个参数,即使是空值。
|