问题描述
我们发现通过 Accio (Phoenix) 网关 (phoenix-gw.alibaba.com/api/adk/llm/generateContent) 转发 LLM 请求时,所有包含系统提示词 (system prompt) 的请求都会返回空白内容。
由于几乎所有 LLM 客户端(NextChat、AnythingLLM、OpenWebUI 等)在发送对话请求时都会自动附带 role: "system" 的系统提示词,这意味着绝大多数用户和客户端都会遇到空白响应的问题。
根因分析
经过大量排查,我们定位到根本原因:
generateContent 端点不支持 system_instruction 字段。
无论使用什么格式发送 system_instruction,Accio 网关都会返回 400 Invalid request format 错误:
// 格式 1: snake_case + thought 字段 ❌
{
"system_instruction": {
"parts": [{ "text": "You are a helpful assistant.", "thought": false }]
}
}
// 格式 2: 带 role 字段 ❌
{
"system_instruction": {
"role": "user",
"parts": [{ "text": "You are a helpful assistant." }]
}
}
// 格式 3: 不带 role 字段 ❌
{
"system_instruction": {
"parts": [{ "text": "You are a helpful assistant." }]
}
}
所有格式返回的结果相同:
{"turn_complete":true,"error_code":"400","error_message":"Invalid request format"}
这个错误被包装在 SSE 数据流中(HTTP 状态码仍然是 200),因此我们之前的代码没有检测到它,静默地丢弃了所有帧,客户端只收到一个空的 role: "assistant" 帧和 [DONE] 终止符。
我们的排查过程
- 对比参考项目 CLIProxyAPI:发现它使用完全不同的请求结构
request.systemInstruction(camelCase,嵌套在 request 包装器内),而非顶层的 system_instruction
- 直接测试 Accio 网关:验证了三种
system_instruction 格式全部返回 400
- 确认了唯一有效的方式:将系统提示词文本内联到第一条用户消息中
当前临时方案
我们目前采用了系统提示词内联的方式:将所有 role: "system" 和 role: "developer" 的消息内容,前置到第一条用户消息中。
// 不使用 system_instruction 字段
// 将系统提示词拼接到第一条用户消息前面
contents[firstUserIdx] = {
role: "user",
parts: [{ text: `${systemBlock}\n\n${existingText}` }],
};
这个方案能让系统提示词生效,但并不等同于原生的 system_instruction 支持,在以下方面存在差异:
- 模型可能无法像处理原生系统指令一样精确地遵循内联的系统提示
- 多轮对话中系统提示词的持久性可能不同
- Token 计数会略有不同(系统文本被计入用户消息的 token)
请求社区帮助
我们希望社区能提供以下方面的帮助:
- 是否有人知道
generateContent 端点支持系统指令的正确字段名和格式? 是否需要使用 request.systemInstruction(camelCase)并包裹在 request 对象中?
- 是否可以使用 CLIProxyAPI 的
request 包装结构({"project":"","request":{"contents":[],"systemInstruction":{}},"model":"..."})来替代我们当前的扁平结构?
- Accio 网关是否有版本变更或 API 文档可以参考,说明哪些字段被支持?
环境信息
- 网关端点:
https://phoenix-gw.alibaba.com/api/adk/llm/generateContent
- 测试模型:
claude-sonnet-4-6, claude-opus-4-6
- 当前的 workaround commit:
c46d3c0
感谢大家的关注和帮助!如果你也遇到过类似问题或有相关经验,请在下方留言。
问题描述
我们发现通过 Accio (Phoenix) 网关 (
phoenix-gw.alibaba.com/api/adk/llm/generateContent) 转发 LLM 请求时,所有包含系统提示词 (system prompt) 的请求都会返回空白内容。由于几乎所有 LLM 客户端(NextChat、AnythingLLM、OpenWebUI 等)在发送对话请求时都会自动附带
role: "system"的系统提示词,这意味着绝大多数用户和客户端都会遇到空白响应的问题。根因分析
经过大量排查,我们定位到根本原因:
generateContent端点不支持system_instruction字段。无论使用什么格式发送
system_instruction,Accio 网关都会返回400 Invalid request format错误:所有格式返回的结果相同:
{"turn_complete":true,"error_code":"400","error_message":"Invalid request format"}这个错误被包装在 SSE 数据流中(HTTP 状态码仍然是 200),因此我们之前的代码没有检测到它,静默地丢弃了所有帧,客户端只收到一个空的
role: "assistant"帧和[DONE]终止符。我们的排查过程
request.systemInstruction(camelCase,嵌套在request包装器内),而非顶层的system_instructionsystem_instruction格式全部返回 400当前临时方案
我们目前采用了系统提示词内联的方式:将所有
role: "system"和role: "developer"的消息内容,前置到第一条用户消息中。这个方案能让系统提示词生效,但并不等同于原生的
system_instruction支持,在以下方面存在差异:请求社区帮助
我们希望社区能提供以下方面的帮助:
generateContent端点支持系统指令的正确字段名和格式? 是否需要使用request.systemInstruction(camelCase)并包裹在request对象中?request包装结构({"project":"","request":{"contents":[],"systemInstruction":{}},"model":"..."})来替代我们当前的扁平结构?环境信息
https://phoenix-gw.alibaba.com/api/adk/llm/generateContentclaude-sonnet-4-6,claude-opus-4-6c46d3c0感谢大家的关注和帮助!如果你也遇到过类似问题或有相关经验,请在下方留言。