Skip to content

fix(api): 兼容 Chat 纯文本 assistant 尾轮续写 - #49

Merged
Mag1cFall merged 2 commits into
Mag1cFall:mainfrom
anon0v0:fix/chat-assistant-tail
Oct 7, 2026
Merged

Mag1cFall merged 2 commits into
Mag1cFall:mainfrom
anon0v0:fix/chat-assistant-tail

Conversation

@anon0v0

@anon0v0 anon0v0 commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

问题

OpenAI Chat 请求可能以纯文本 assistant 结尾;即使原始数组最后一项是 system / developer,提取系统提示后也可能变成这种形状。Google 上游会拒绝此类请求:

Requests ending with a model turn are not supported

最小合成示例(不含真实对话内容):

{
  "model": "gemini-3.8-flash",
  "messages": [
    {"role": "user", "content": "Start a story."},
    {"role": "assistant", "content": "Once upon a time,"},
    {"role": "system", "content": "Continue the story."}
  ]
}

改动

基于当前 main / v0.2.6(e2dd10f),只修改 OpenAI Chat 请求转换、回归测试和协议文档。

  • 在提取系统提示、过滤空消息之后检查连续的末尾 assistant 轮。
  • 仅当这些轮次全部为纯文本,且最后一轮包含非空白文本时,保留原文与角色并追加一条独立 user 续写指令。
  • 保留系统提示与原文空白;克隆切片后追加,不覆盖调用方共享的底层数组;重复处理不会重复追加。
  • user/tool 结尾、未完成的末尾工具调用、媒体、推理/签名、代码执行及语音元数据均不改写,不伪造工具结果。
  • 不改 OpenAI Responses、Anthropic 或 Gemini 原生入口,不增加配置或依赖。

这是提示驱动的近似续写,不是原生 token 级 prefill。 不保证逐字衔接或绝不重复;响应端不拼接、裁剪前缀。流式与非流式请求共用同一转换。

验证

  • 上游原有 go test -mod=readonly ./internal/api 通过。
  • 先加入转换层复现测试:未应用修复时失败,确认请求仍以 assistant 结尾;应用后通过。
  • 回归覆盖 system/developer 尾部、空 user 过滤、连续 assistant、空白/空末轮、工具调用保护、全部非文本字段排除、幂等与并发共享历史。
  • 编码层断言确认修复后的 Playground 请求以 user 结尾。
  • npm ci --no-audit --no-fund、npm run lint、npm run build 通过(仅有前端 chunk 体积提示)。
  • go test -mod=readonly ./cmd/... ./internal/... 通过。
  • go vet ./... 通过。
  • go test -mod=readonly -race ./internal/api ./internal/aistudio 通过。
  • Windows amd64 和 Linux amd64 构建通过。
  • gofmt、git diff --check 和三文件范围检查通过。

@Mag1cFall

Copy link
Copy Markdown
Owner

我觉得可以做成Anthropic协议一样的造system而不是user,我先去sillytavern试一下效果;以及 这个commit有点过度防御性了,我一起修一下

- 续写:上游适配层统一处理末尾连续 assistant 轮,正文与代码执行内容作为系统指令中的续写前缀,响应只返回续写部分,末尾未回传结果的函数调用由模型重新生成;各生成入口与计数接口共用,删除 Anthropic 入口的单独实现与 Chat 入口追加 user 指令的实现
- 请求内容:没有对话内容时以系统提示作为 user 轮;Chat、Responses、Anthropic、Gemini 与 Interactions 入口只要求模型,Anthropic max_tokens 可省略;既无系统提示也无对话内容时在选择账户前返回 400
- 流式:五个协议入口在写出响应头前等待首个事件,首个事件为错误时按非流式返回 HTTP 状态与错误对象,10 秒内没有事件时照常推流
- 测试:删除针对 Chat 单独实现的测试
- 文档:protocol.md 写明续写方式、必需字段与流式错误的返回时机
@Mag1cFall
Mag1cFall merged commit 9641c63 into Mag1cFall:main Oct 7, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants