跳转到内容

流式行为

当客户端向 ProxAI 请求流式响应时,ProxAI 会保留上游 Server-Sent Events (SSE) 字节流,同时观察协议事件。从使用者视角看,三件事最重要:流最终会结束、错误以可读形态到达、卡住的 tool call 不会让客户端永远等待。

每个 provider 协议都有自己的 terminal event。只有收到预期的 terminal event,ProxAI 才认为这条流完整。这实现了 行为契约 C19

  1. 1
    response.created

    流开始。

  2. 2
    response.output_item.added

    新的 output item 开始(message、reasoning、function_call 等)。

  3. 3
    response.output_text.delta / response.function_call_arguments.delta

    文本或工具调用参数增量 bytes。

  4. 4
    response.output_item.done

    output item 完成。

  5. 5
    response.completed

    terminal event,流完整结束。

  1. 1
    chat.completion.chunk

    content、tool calls 和 finish_reason 的增量 chunk。

  2. 2
    [DONE]

    终止 sentinel;没有它的 EOF 会被视为不完整。

  1. 1
    message_start

    流开始。

  2. 2
    content_block_start / content_block_delta / content_block_stop

    一个 content block(text、thinking、tool_use 等)按增量产生。

  3. 3
    message_delta

    携带 stop_reason、stop_sequence、usage 等 message-level delta。

  4. 4
    message_stop

    terminal event,流完整结束。

如果上游开始流式发送 function/tool arguments 但一直没有完成,ProxAI 可以用协议形态的错误关闭流,而不是让客户端一直挂起。它由以下配置控制:

[tool_calls]
timeout_secs = 120

这是语义超时,不是整条请求的总时长上限。它只在工具调用参数流已经开始后才生效。这实现了 行为契约 C20

工具调用时流卡住
可能原因
  • 上游开始发送 tool arguments,但没有发送匹配的 done event。
  • 原始 HTTP stream 还开着,但 provider 语义层已经 stalled。
下一步检查
  • 调低或调整 `[tool_calls].timeout_secs`。
  • 针对单次请求开启 `upstream_response` capture。
  • 查看诊断中的 recent SSE tail。
流关闭但没有最终答案
可能原因
  • 缺少 `[DONE]`、`response.completed` 或 `message_stop` 等 terminal event。
  • 上游连接在协议状态完成前关闭。
下一步检查
  • 查看 stream outcome 日志。
  • 对照该协议预期的 terminal event。
  • 捕获 upstream response bytes。
Unicode 文本看起来损坏
可能原因
  • 把不完整的 byte chunk 当成完整 UTF-8 文本解释。
  • 某个工具把原始 bytes 当字符串切片。
下一步检查
  • 只在完整 SSE event data 上解码。
  • 保持 byte-oriented scanning。
  • 避免对任意 chunk 做字符串切片。