debug: 修复流式传输语句重复的问题

This commit is contained in:
肖应宇 2026-03-03 14:37:03 +08:00
parent 485b07c12f
commit a8f631a034
2 changed files with 56 additions and 24 deletions

View File

@ -140,6 +140,8 @@ async def chat_endpoint(request: Request):
temperature=temperature temperature=temperature
) )
full_content = "" # 用于累计完整内容
for idx, response in enumerate(responses): for idx, response in enumerate(responses):
if response.status_code == 200: if response.status_code == 200:
# 检查响应是否包含预期的内容 # 检查响应是否包含预期的内容
@ -156,6 +158,29 @@ async def chat_endpoint(request: Request):
'content' in response.output.choices[0]['message']): 'content' in response.output.choices[0]['message']):
content = response.output.choices[0]['message']['content'] content = response.output.choices[0]['message']['content']
# 只有当内容发生变化时才发送增量
if len(content) > len(full_content):
delta_content = content[len(full_content):]
full_content = content
if delta_content.strip(): # 只有当有非空白新内容时才发送
# 构建 SSE 数据块
data = {
"id": f"chatcmpl-{uuid.uuid4()}",
"object": "chat.completion.chunk",
"created": int(datetime.utcnow().timestamp()),
"model": model,
"choices": [
{
"index": 0,
"delta": {"content": delta_content},
"finish_reason": None
}
]
}
yield f"data: {json.dumps(data, ensure_ascii=False)}\n\n"
# 否则尝试从 output.text 获取内容DashScope特定格式 # 否则尝试从 output.text 获取内容DashScope特定格式
elif (hasattr(response, 'output') and elif (hasattr(response, 'output') and
response.output and response.output and
@ -163,26 +188,28 @@ async def chat_endpoint(request: Request):
content = response.output.get('text') content = response.output.get('text')
if content: # 只有当内容发生变化时才发送增量
# 构建 SSE 数据块 if len(content) > len(full_content):
data = { delta_content = content[len(full_content):]
"id": f"chatcmpl-{uuid.uuid4()}", full_content = content
"object": "chat.completion.chunk",
"created": int(datetime.utcnow().timestamp()),
"model": model,
"choices": [
{
"index": 0,
"delta": {"content": content} if content else {},
"finish_reason": None
}
]
}
yield f"data: {json.dumps(data)}\n\n" if delta_content.strip(): # 只有当有非空白新内容时才发送
else: # 构建 SSE 数据块
# 如果响应中没有内容,跳过 data = {
continue "id": f"chatcmpl-{uuid.uuid4()}",
"object": "chat.completion.chunk",
"created": int(datetime.utcnow().timestamp()),
"model": model,
"choices": [
{
"index": 0,
"delta": {"content": delta_content},
"finish_reason": None
}
]
}
yield f"data: {json.dumps(data, ensure_ascii=False)}\n\n"
else: else:
# 错误处理 # 错误处理
error_data = { error_data = {
@ -193,7 +220,7 @@ async def chat_endpoint(request: Request):
"code": response.code "code": response.code
} }
} }
yield f"data: {json.dumps(error_data)}\n\n" yield f"data: {json.dumps(error_data, ensure_ascii=False)}\n\n"
break break
# 发送结束信号 # 发送结束信号
@ -210,9 +237,8 @@ async def chat_endpoint(request: Request):
} }
] ]
} }
yield f"data: {json.dumps(finish_data)}\n\n" yield f"data: {json.dumps(finish_data, ensure_ascii=False)}\n\n"
yield "data: [DONE]\n\n" yield "data: [DONE]\n\n"
except Exception as e: except Exception as e:
error_data = { error_data = {
"error": { "error": {
@ -220,7 +246,7 @@ async def chat_endpoint(request: Request):
"type": "server_error" "type": "server_error"
} }
} }
yield f"data: {json.dumps(error_data)}\n\n" yield f"data: {json.dumps(error_data, ensure_ascii=False)}\n\n"
return StreamingResponse(event_generator(), media_type="text/event-stream") return StreamingResponse(event_generator(), media_type="text/event-stream")
else: else:
@ -272,7 +298,7 @@ async def chat_endpoint(request: Request):
"totalTokens": response.usage.total_tokens "totalTokens": response.usage.total_tokens
} }
return JSONResponse(content=chat_response) return JSONResponse(content=chat_response, ensure_ascii=False)
else: else:
raise HTTPException( raise HTTPException(
status_code=500, status_code=500,

View File

@ -164,6 +164,12 @@ class ChatApi {
if (match) { if (match) {
try { try {
const data = JSON.parse(match[1]); const data = JSON.parse(match[1]);
// 检查是否有完成原因,如果是完成则跳出
const finishReason = data.choices?.[0]?.finish_reason;
if (finishReason && finishReason !== "null") {
break;
}
const content = data.choices?.[0]?.delta?.content; const content = data.choices?.[0]?.delta?.content;
if (content) { if (content) {
yield content; yield content;