转换器: 修复 Responses 流式 response.completed 缺 usage
- 上游 chat 流 finish_reason 块先于 usage 块, 原实现在 finish 时即发 response.completed 导致 usage 为空; 改为等 usage 块到达(或 [DONE] 兜底)再发, completed 携带 input/output tokens Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -412,9 +412,10 @@ func (t *responsesToChat) line(line []byte) []byte {
|
||||
|
||||
type chatToResponses struct {
|
||||
sseState
|
||||
model string
|
||||
usage any
|
||||
done bool
|
||||
model string
|
||||
usage any
|
||||
finishSeen bool
|
||||
done bool
|
||||
}
|
||||
|
||||
func newChatToResponses() *chatToResponses { return &chatToResponses{} }
|
||||
@@ -425,6 +426,7 @@ func (t *chatToResponses) line(line []byte) []byte {
|
||||
return nil
|
||||
}
|
||||
if done {
|
||||
// 流结束兜底:finish 后 usage 未随块到达时在此补发 completed
|
||||
if !t.done {
|
||||
t.done = true
|
||||
return eventLine("response.completed", map[string]any{
|
||||
@@ -453,6 +455,9 @@ func (t *chatToResponses) line(line []byte) []byte {
|
||||
finish, _ = c0["finish_reason"].(string)
|
||||
}
|
||||
}
|
||||
if finish != "" {
|
||||
t.finishSeen = true
|
||||
}
|
||||
var out [][]byte
|
||||
if role, _ := delta["role"].(string); role == "assistant" {
|
||||
out = append(out, eventLine("response.created", map[string]any{
|
||||
@@ -465,7 +470,8 @@ func (t *chatToResponses) line(line []byte) []byte {
|
||||
"type": "response.output_text.delta", "delta": content, "item_id": "msg_1", "output_index": 0, "content_index": 0,
|
||||
}))
|
||||
}
|
||||
if finish != "" && !t.done {
|
||||
// 上游 usage 块(choices 为空)通常晚于 finish_reason:此时再发 completed,携带 usage
|
||||
if _, hasUsage := m["usage"]; hasUsage && t.finishSeen && !t.done {
|
||||
t.done = true
|
||||
out = append(out, eventLine("response.completed", map[string]any{
|
||||
"type": "response.completed",
|
||||
|
||||
Reference in New Issue
Block a user