Spaces:
Sleeping
Sleeping
kevin
commited on
Commit
·
9cd681c
1
Parent(s):
0fd5c22
copilot 优化方案
Browse files
app.py
CHANGED
|
@@ -195,39 +195,77 @@ def create_chat_completion_data(
|
|
| 195 |
}
|
| 196 |
|
| 197 |
async def handle_stream(response, previous_content):
|
| 198 |
-
|
| 199 |
-
|
| 200 |
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 204 |
|
| 205 |
async for chunk in response.aiter_lines():
|
|
|
|
|
|
|
|
|
|
| 206 |
try:
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
continue
|
| 210 |
|
| 211 |
-
|
| 212 |
-
|
| 213 |
-
|
| 214 |
-
|
| 215 |
-
|
| 216 |
|
| 217 |
-
|
| 218 |
-
if last_content and current_content.startswith(last_content)
|
| 219 |
-
else current_content)
|
| 220 |
|
| 221 |
-
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
|
| 225 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 226 |
|
|
|
|
|
|
|
|
|
|
| 227 |
except Exception as e:
|
| 228 |
-
logger.error(f"
|
| 229 |
yield f"data: {{\"error\":true,\"message\":\"{str(e)}\"}}\n\n"
|
| 230 |
|
|
|
|
| 231 |
yield "data: [DONE]\n\n"
|
| 232 |
|
| 233 |
|
|
|
|
| 195 |
}
|
| 196 |
|
| 197 |
async def handle_stream(response, previous_content):
|
| 198 |
+
"""
|
| 199 |
+
优化后的流式响应处理函数
|
| 200 |
|
| 201 |
+
主要改进:
|
| 202 |
+
1. 使用简单的字符串切片而不是startswith比较
|
| 203 |
+
2. 增加内容缓存来减少重复处理
|
| 204 |
+
3. 优化内存使用
|
| 205 |
+
"""
|
| 206 |
+
timestamp = int(datetime.now().timestamp())
|
| 207 |
+
content_cache = "" # 用于缓存已处理的内容
|
| 208 |
+
|
| 209 |
+
async def send_chunk(content: str):
|
| 210 |
+
"""内部函数:格式化并发送数据块"""
|
| 211 |
+
chunk_data = {
|
| 212 |
+
"id": f"chatcmpl-{uuid.uuid4()}",
|
| 213 |
+
"object": "chat.completion.chunk",
|
| 214 |
+
"created": timestamp,
|
| 215 |
+
"model": "qwen",
|
| 216 |
+
"choices": [{
|
| 217 |
+
"index": 0,
|
| 218 |
+
"delta": {
|
| 219 |
+
"content": content,
|
| 220 |
+
"role": "assistant"
|
| 221 |
+
},
|
| 222 |
+
"finish_reason": None
|
| 223 |
+
}]
|
| 224 |
+
}
|
| 225 |
+
return f"data: {json.dumps(chunk_data)}\n\n"
|
| 226 |
|
| 227 |
async for chunk in response.aiter_lines():
|
| 228 |
+
if not chunk or not chunk.startswith('data: '):
|
| 229 |
+
continue
|
| 230 |
+
|
| 231 |
try:
|
| 232 |
+
# 解析数据
|
| 233 |
+
data = json.loads(chunk[6:]) # 去掉 'data: ' 前缀
|
|
|
|
| 234 |
|
| 235 |
+
# 提取新内容
|
| 236 |
+
if not (data.get('choices') and
|
| 237 |
+
data['choices'][0].get('delta') and
|
| 238 |
+
data['choices'][0]['delta'].get('content')):
|
| 239 |
+
continue
|
| 240 |
|
| 241 |
+
current_content = data['choices'][0]['delta']['content']
|
|
|
|
|
|
|
| 242 |
|
| 243 |
+
# 智能差异检测
|
| 244 |
+
if content_cache:
|
| 245 |
+
# 找到新内容的起始位置
|
| 246 |
+
for i in range(min(len(current_content), len(content_cache))):
|
| 247 |
+
if current_content[i] != content_cache[i]:
|
| 248 |
+
new_content = current_content[i:]
|
| 249 |
+
break
|
| 250 |
+
else:
|
| 251 |
+
# 如果前面的内容都相同,新内容就是超出的部分
|
| 252 |
+
new_content = current_content[len(content_cache):]
|
| 253 |
+
else:
|
| 254 |
+
new_content = current_content
|
| 255 |
+
|
| 256 |
+
# 只有真正有新内容时才发送
|
| 257 |
+
if new_content:
|
| 258 |
+
yield await send_chunk(new_content)
|
| 259 |
+
content_cache = current_content # 更新缓存
|
| 260 |
|
| 261 |
+
except json.JSONDecodeError as e:
|
| 262 |
+
logger.error(f"JSON解析错误: {str(e)}")
|
| 263 |
+
continue
|
| 264 |
except Exception as e:
|
| 265 |
+
logger.error(f"处理数据流时发生错误: {str(e)}")
|
| 266 |
yield f"data: {{\"error\":true,\"message\":\"{str(e)}\"}}\n\n"
|
| 267 |
|
| 268 |
+
# 发送结束标记
|
| 269 |
yield "data: [DONE]\n\n"
|
| 270 |
|
| 271 |
|