Repository navigation
usage 代理是不是把流式输出「憋」成了非流式? #2
|
问题:启动实例后全部模型流量都被强制改道到本地 usage 代理(commands/process.rs:129 把 DEEPSEEK_BASE_URL 证据(都在 apps/desktop/src-tauri/src/usage_proxy.rs): ┌─────────┬──────────────────────────────────────────┬────────────────────────────────────────────────────────────┐ ensure_stream_usage 为了保证能记到 usage,要求上游以 SSE 发 怎么验:起一个实例,问一个会产生长回答的问题(比如让它写 500 |
Replies: 1 comment
|
是的,确认了 —— 这个代理把 SSE 整个憋完才吐出去。 usage_proxy.rs:146 的 resp.bytes().await? 会一直等到上游 EOF 才返回,然后 149-157 拼一个带 content-length 不过 ensure_stream_usage 那段算不上「语义打架」,它只是往请求里塞 stream_options.include_usage,好让最后一帧 SSE 带上 想验证的话有个比掐表更快的办法:直接看响应头。真流式是 transfer-encoding: chunked,被缓冲的必然是 content-length。 改法就是把 146 换成 resp.bytes_stream() 边收边以 chunked 转发,同时复制一份字节攒着,流结束后再交给 maybe_record_usage |
是的,确认了 —— 这个代理把 SSE 整个憋完才吐出去。
usage_proxy.rs:146 的 resp.bytes().await? 会一直等到上游 EOF 才返回,然后 149-157 拼一个带 content-length
的头一次性写下去。整个文件没有任何 chunked / bytes_stream 分支。只要代理起来了(process.rs 里是 best-effort,只有
start 失败才跳过),逐 token 输出就是关着的 —— 用户看到的就是转圈等全文。
不过 ensure_stream_usage 那段算不上「语义打架」,它只是往请求里塞 stream_options.include_usage,好让最后一帧 SSE 带上
usage。响应整体缓冲对它没影响,record_sse_usage 照样能拿整段 SSE 解析出数字。真正的问题只有缓冲这一件事。
想验证的话有个比掐表更快的办法:直接看响应头。真流式是 transfer-encoding: chunked,被缓冲的必然是 content-length。
改法就是把 146 换成 resp.bytes_stream() 边收边以 chunked 转发,同时复制一份字节攒着,流结束后再交给 maybe_record_usage
—— usage 逻辑不用动,它本来就只看最后一帧。