kevin commited on
Commit
9cd681c
·
1 Parent(s): 0fd5c22

copilot 优化方案

Browse files
Files changed (1) hide show
  1. app.py +60 -22
app.py CHANGED
@@ -195,39 +195,77 @@ def create_chat_completion_data(
195
  }
196
 
197
  async def handle_stream(response, previous_content):
198
- timestamp = int(datetime.now().timestamp())
199
- last_content = ""
200
 
201
- async def yield_and_flush(data):
202
- yield data
203
- await asyncio.sleep(0.01) # 使用更明确的延迟
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
 
205
  async for chunk in response.aiter_lines():
 
 
 
206
  try:
207
- current_chunk = chunk
208
- if not current_chunk:
209
- continue
210
 
211
- if current_chunk.startswith('data: '):
212
- current_content = ''
213
- data = json.loads(current_chunk[6:])
214
- if data.get('choices') and data['choices'][0].get('delta') and data['choices'][0]['delta'].get('content'):
215
- current_content = data['choices'][0]['delta']['content']
216
 
217
- new_content = (current_content[len(last_content):]
218
- if last_content and current_content.startswith(last_content)
219
- else current_content)
220
 
221
- if new_content:
222
- response_data = f"data: {json.dumps(create_chat_completion_data(new_content, 'qwen', timestamp))}\n\n"
223
- async for item in yield_and_flush(response_data):
224
- yield item
225
- last_content = current_content
 
 
 
 
 
 
 
 
 
 
 
 
226
 
 
 
 
227
  except Exception as e:
228
- logger.error(f"Error processing chunk: {str(e)}")
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