WiiCITMS/ai_tool_guide.md
2025-11-07 14:14:34 +08:00

5.3 KiB
Raw Blame History

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对象字符串 "{}"

错误示例:

tool_call = {
    "type": "function",
    "function": {
        "name": "queryPositions",
        "arguments": None  # 这会导致验证错误
    }
}

正确示例:

tool_call = {
    "type": "function",
    "function": {
        "name": "queryPositions",
        "arguments": "{}"  # 即使没有参数也提供空的JSON对象字符串
    }
}

2. 修改Python客户端代码

如果您使用Python调用OpenAI API可以使用以下模式来确保参数总是有效的JSON字符串

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. 在工具定义中添加必填参数

为避免参数验证问题,可以为每个工具添加至少一个必填参数。这样可以确保调用者必须提供参数。

Tool: mcp.NewTool(
    "queryPositions",
    mcp.WithDescription("查询岗位列表"),
    mcp.WithString("query", mcp.Required(), mcp.Description("搜索关键词,可为空字符串但必须提供")),
    // 其他可选参数...
),

在JavaScript中调用API的正确方式

如果您在前端JavaScript中调用OpenAI API确保遵循以下模式

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示例
result = call_tool("queryPositions", {"query": ""})
// JavaScript示例
callOpenAIWithTool('queryPositions', {query: ''})

如果您遇到同样的问题,对其他工具也采用类似的方法,始终提供至少一个参数,即使是空值。