bobocup commited on
Commit
78862b8
·
verified ·
1 Parent(s): 0ca70be

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +67 -45
app.py CHANGED
@@ -62,7 +62,6 @@ class KeyInfo:
62
  keys_info: Dict[str, KeyInfo] = {}
63
  chat_keys = []
64
  first_key = None
65
-
66
  # 初始化keys
67
  def init_keys():
68
  global keys_info, chat_keys, first_key
@@ -132,6 +131,64 @@ async def access_control(request: Request, call_next):
132
  raise HTTPException(status_code=403, detail="IP not allowed")
133
 
134
  return await call_next(request)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  # 添加静态文件支持
136
  app.mount("/static", StaticFiles(directory="static"), name="static")
137
 
@@ -243,48 +300,6 @@ async def add_key(request: Request):
243
  raise
244
  except Exception as e:
245
  raise HTTPException(status_code=400, detail=str(e))
246
-
247
- # 处理API请求
248
- async def handle_api_request(url: str, headers: dict, method: str = "GET", body: dict = None, for_chat: bool = False):
249
- max_retries = 3
250
- current_try = 0
251
-
252
- while current_try < max_retries:
253
- try:
254
- # 获取key
255
- if for_chat:
256
- key = get_chat_key()
257
- else:
258
- key = first_key
259
-
260
- if not key:
261
- raise HTTPException(status_code=500, detail="No API keys available")
262
-
263
- headers["Authorization"] = f"Bearer {key}"
264
-
265
- async with httpx.AsyncClient(timeout=60.0) as client:
266
- response = await client.request(
267
- method=method,
268
- url=url,
269
- headers=headers,
270
- json=body
271
- )
272
-
273
- # 检查配额不足
274
- if response.status_code == 429 or "insufficient_quota" in response.text.lower():
275
- print(f"Key {key} quota exceeded, trying next key...")
276
- set_key_cooling(key)
277
- current_try += 1
278
- continue
279
-
280
- return response
281
-
282
- except Exception as e:
283
- print(f"Request error: {str(e)}")
284
- current_try += 1
285
- if current_try == max_retries:
286
- raise HTTPException(status_code=500, detail=f"API request failed after {max_retries} retries")
287
-
288
  # 聊天完成路由
289
  @app.post("/api/v1/chat/completions")
290
  async def chat_completions(request: Request):
@@ -313,6 +328,7 @@ async def chat_completions(request: Request):
313
 
314
  print(f"Chat completion response status: {response.status_code}")
315
 
 
316
  if body_json.get("stream"):
317
  return StreamingResponse(
318
  stream_generator(response),
@@ -320,10 +336,12 @@ async def chat_completions(request: Request):
320
  headers={
321
  "Cache-Control": "no-cache",
322
  "Connection": "keep-alive",
323
- "Content-Type": "text/event-stream"
 
324
  }
325
  )
326
 
 
327
  return Response(
328
  content=response.text,
329
  media_type="application/json",
@@ -332,7 +350,10 @@ async def chat_completions(request: Request):
332
 
333
  except Exception as e:
334
  print(f"Chat completion error: {str(e)}")
335
- raise HTTPException(status_code=500, detail=str(e))
 
 
 
336
 
337
  # 代理其他请求
338
  @app.api_route("/api/v1/{path:path}", methods=["GET", "POST", "PUT", "DELETE"])
@@ -360,6 +381,7 @@ async def proxy(path: str, request: Request):
360
  )
361
 
362
  except Exception as e:
 
363
  raise HTTPException(status_code=500, detail=str(e))
364
 
365
  # 健康检查路由
 
62
  keys_info: Dict[str, KeyInfo] = {}
63
  chat_keys = []
64
  first_key = None
 
65
  # 初始化keys
66
  def init_keys():
67
  global keys_info, chat_keys, first_key
 
131
  raise HTTPException(status_code=403, detail="IP not allowed")
132
 
133
  return await call_next(request)
134
+
135
+ # 流式响应生成器
136
+ async def stream_generator(response):
137
+ async for chunk in response.aiter_bytes():
138
+ try:
139
+ # 解码字节为文本
140
+ chunk_str = chunk.decode('utf-8')
141
+ # 处理多行数据
142
+ for line in chunk_str.split('\n'):
143
+ if line.strip(): # 忽略空行
144
+ if line.startswith('data: '):
145
+ yield f"{line}\n\n"
146
+ else:
147
+ yield f"data: {line}\n\n"
148
+ except Exception as e:
149
+ print(f"Stream error: {str(e)}")
150
+ continue
151
+
152
+ # 处理API请求
153
+ async def handle_api_request(url: str, headers: dict, method: str = "GET", body: dict = None, for_chat: bool = False):
154
+ max_retries = 3
155
+ current_try = 0
156
+
157
+ while current_try < max_retries:
158
+ try:
159
+ # 获取key
160
+ if for_chat:
161
+ key = get_chat_key()
162
+ else:
163
+ key = first_key
164
+
165
+ if not key:
166
+ raise HTTPException(status_code=500, detail="No API keys available")
167
+
168
+ headers["Authorization"] = f"Bearer {key}"
169
+
170
+ async with httpx.AsyncClient(timeout=60.0) as client:
171
+ response = await client.request(
172
+ method=method,
173
+ url=url,
174
+ headers=headers,
175
+ json=body
176
+ )
177
+
178
+ # 检查配额不足
179
+ if response.status_code == 429 or "insufficient_quota" in response.text.lower():
180
+ print(f"Key {key} quota exceeded, trying next key...")
181
+ set_key_cooling(key)
182
+ current_try += 1
183
+ continue
184
+
185
+ return response
186
+
187
+ except Exception as e:
188
+ print(f"Request error: {str(e)}")
189
+ current_try += 1
190
+ if current_try == max_retries:
191
+ raise HTTPException(status_code=500, detail=f"API request failed after {max_retries} retries")
192
  # 添加静态文件支持
193
  app.mount("/static", StaticFiles(directory="static"), name="static")
194
 
 
300
  raise
301
  except Exception as e:
302
  raise HTTPException(status_code=400, detail=str(e))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
303
  # 聊天完成路由
304
  @app.post("/api/v1/chat/completions")
305
  async def chat_completions(request: Request):
 
328
 
329
  print(f"Chat completion response status: {response.status_code}")
330
 
331
+ # 处理流式响应
332
  if body_json.get("stream"):
333
  return StreamingResponse(
334
  stream_generator(response),
 
336
  headers={
337
  "Cache-Control": "no-cache",
338
  "Connection": "keep-alive",
339
+ "Content-Type": "text/event-stream",
340
+ "X-Accel-Buffering": "no" # 禁用 Nginx 缓冲
341
  }
342
  )
343
 
344
+ # 处理普通响应
345
  return Response(
346
  content=response.text,
347
  media_type="application/json",
 
350
 
351
  except Exception as e:
352
  print(f"Chat completion error: {str(e)}")
353
+ error_detail = str(e)
354
+ if len(error_detail) > 200: # 如果错误信息太长,只保留前200个字符
355
+ error_detail = error_detail[:200] + "..."
356
+ raise HTTPException(status_code=500, detail=error_detail)
357
 
358
  # 代理其他请求
359
  @app.api_route("/api/v1/{path:path}", methods=["GET", "POST", "PUT", "DELETE"])
 
381
  )
382
 
383
  except Exception as e:
384
+ print(f"Proxy error: {str(e)}")
385
  raise HTTPException(status_code=500, detail=str(e))
386
 
387
  # 健康检查路由