Skip to content

[Bug] 使用 ps.air-outer.com 调用 deepseek-v4-flash 时出现协议兼容错误 #864

Description

@9Rebels

What happened? / 问题描述

在 PI-Desktop 中配置以下 AI 服务后,调用模型会返回 PROVIDER_ERROR:

Provider:3cd5ede2-eff6-41c1-9c9c-00968b6dd143
Model:deepseek-v4-flash
API 地址:https://ps.air-outer.com/
当前错误看起来与 PI-Desktop 发出的 thinking 消息格式和工具 JSON Schema 有关。

Steps to reproduce / 复现步骤

复现步骤
打开 PI-Desktop;

新建或选择一个自定义 API Provider;

配置 API 地址:

https://ps.air-outer.com/
选择模型:

deepseek-v4-flash
启用工具调用或执行需要多轮对话的任务;

发送消息;

观察返回 PROVIDER_ERROR。

相关 Trace ID
e320891a15fed3ccc44d9ac1868f8859
9dc88a447eac00afa406ae41c32ca01a

错误一:thinking 内容未被完整回传
400: {
"message": "The content[].thinking in the thinking mode must be passed back to the API. [trace_id=e320891a15fed3ccc44d9ac1868f8859]",
"type": "invalid_request_error",
"param": "",
"code": null
}
服务端要求在 thinking 模式下,后续请求必须完整保留并回传上一轮 assistant 消息中的:

{
"type": "thinking",
"thinking": "..."
}
推测 PI-Desktop 在以下某个环节丢失了 content[].thinking:

多轮对话历史重新组装;
工具调用后的 assistant 消息重新序列化;
自动重试;
上下文压缩;
从响应中只保留可见文本,删除 thinking block。
希望 PI-Desktop 检查模型原始响应和下一次请求的 messages,确保 thinking 内容在 thinking 模式下被原样保留和回传。

错误二:Read 工具的 JSON Schema 无效
400: {
"message": "Invalid schema for function 'Read': null is not of type "array" [trace_id=9dc88a447eac00afa406ae41c32ca01a]",
"type": "invalid_request_error",
"param": "",
"code": null
}
服务端指出 PI-Desktop 发出的 Read 工具定义中,有一个应为数组的 Schema 字段被传成了 null。

最可能涉及:

"required": null
也可能是其他数组类型字段被序列化为 null。标准 JSON Schema 中,这些字段至少应当是数组,例如:

"required": []
或:

"required": ["path"]
建议 PI-Desktop 在发送请求前对内置工具 Schema 做校验,确保:

parameters 不为 null;
properties 不为 null;
required 不为 null,没有必填参数时使用 [];
所有工具的 JSON Schema 符合 OpenAI 兼容接口格式;
工具定义经过序列化和 provider 转换后仍保持合法。

Expected behavior / 预期行为

期望行为
PI-Desktop 应该能够在 OpenAI 兼容 API 或 DeepSeek 兼容 API 下:

正确保留 thinking 模式产生的完整 assistant content;
在后续请求中原样回传 content[].thinking;
发送前验证内置工具的 JSON Schema;
将 null 数组字段规范化为空数组;
对 provider 返回的协议错误给出更明确的诊断信息;
支持无法兼容 thinking 模式的 provider 关闭 thinking,或提供 provider 级兼容选项。
建议增加的兼容处理
请求发送前,可以执行类似以下规范化:

function normalizeTool(tool) {
const parameters = tool?.function?.parameters;

if (!parameters || typeof parameters !== "object") {
return {
...tool,
function: {
...tool.function,
parameters: {
type: "object",
properties: {},
required: [],
additionalProperties: false
}
}
};
}

return {
...tool,
function: {
...tool.function,
parameters: {
...parameters,
type: parameters.type || "object",
properties: parameters.properties || {},
required: Array.isArray(parameters.required)
? parameters.required
: [],
additionalProperties: parameters.additionalProperties ?? false
}
}
};
}
thinking 消息则不应只保存最终文本。应保留完整结构:

{
"role": "assistant",
"content": [
{
"type": "thinking",
"thinking": "完整 thinking 内容"
},
{
"type": "text",
"text": "最终回答"
}
]
}
如果某个 provider 不支持该格式,建议提供“关闭 thinking”或“provider 兼容模式”选项,而不是直接发送不完整的消息历史。

Actual behavior / 实际行为

初步判断
这不是普通的 API Key、余额或网络连接问题。服务端已经收到请求,并在校验以下内容时拒绝:

thinking 模式下的 assistant 消息历史;
PI-Desktop 发送的 Read 工具 JSON Schema。
建议官方通过 debug 日志或请求抓包确认:

PI-Desktop 实际发送的完整 request body;
messages 中是否保留 content[].thinking;
Read.function.parameters 中哪个字段被序列化为 null;
是否可以为不兼容 provider 增加 thinking 禁用选项和工具 Schema 兼容层。

App version / 应用版本

0.15.3

Operating system / 操作系统

Windows

Extra environment / 其他环境信息

PI-Desktop 0.15.3 · win32 x64 · protocol 11 · host 0.15.3

Logs / 日志

Screenshots / 截图

No response

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions