xiaoyukkkk commited on
Commit
40a5b01
·
verified ·
1 Parent(s): 7712fa8

Upload main.py

Browse files
Files changed (1) hide show
  1. main.py +73 -39
main.py CHANGED
@@ -781,7 +781,7 @@ async def admin_disable_account(request: Request, account_id: str):
781
  @app.put("/admin/accounts/{account_id}/enable")
782
  @require_login()
783
  async def admin_enable_account(request: Request, account_id: str):
784
- """启用账户"""
785
  global multi_account_mgr
786
  try:
787
  multi_account_mgr = _update_account_disabled_status(
@@ -789,6 +789,15 @@ async def admin_enable_account(request: Request, account_id: str):
789
  ACCOUNT_FAILURE_THRESHOLD, RATE_LIMIT_COOLDOWN_SECONDS,
790
  SESSION_CACHE_TTL_SECONDS, global_stats
791
  )
 
 
 
 
 
 
 
 
 
792
  return {"status": "success", "message": f"账户 {account_id} 已启用", "account_count": len(multi_account_mgr.accounts)}
793
  except Exception as e:
794
  logger.error(f"[CONFIG] 启用账户失败: {str(e)}")
@@ -882,6 +891,8 @@ async def admin_update_settings(request: Request, new_settings: dict = Body(...)
882
  max_connections=200
883
  )
884
  )
 
 
885
 
886
  # 检查是否需要更新账户管理器配置(重试策略变化)
887
  retry_changed = (
@@ -893,7 +904,7 @@ async def admin_update_settings(request: Request, new_settings: dict = Body(...)
893
  if retry_changed:
894
  logger.info(f"[CONFIG] 重试策略已变化,更新账户管理器配置")
895
  # 更新所有账户管理器的配置
896
- multi_account_mgr.session_cache_ttl_seconds = SESSION_CACHE_TTL_SECONDS
897
  for account_id, account_mgr in multi_account_mgr.accounts.items():
898
  account_mgr.account_failure_threshold = ACCOUNT_FAILURE_THRESHOLD
899
  account_mgr.rate_limit_cooldown_seconds = RATE_LIMIT_COOLDOWN_SECONDS
@@ -1501,6 +1512,9 @@ async def stream_chat_generator(session: str, text_content: str, file_ids: List[
1501
  yield f"data: {chunk}\n\n"
1502
 
1503
  # 使用流式请求
 
 
 
1504
  async with http_client.stream(
1505
  "POST",
1506
  "https://biz-discoveryengine.googleapis.com/v1alpha/locations/global/widgetStreamAssist",
@@ -1512,7 +1526,6 @@ async def stream_chat_generator(session: str, text_content: str, file_ids: List[
1512
  raise HTTPException(status_code=r.status_code, detail=f"Upstream Error {error_text.decode()}")
1513
 
1514
  # 使用异步解析器处理 JSON 数组流
1515
- json_objects = [] # 收集所有响应对象用于图片解析
1516
  try:
1517
  async for json_obj in parse_json_array_stream_async(r.aiter_lines()):
1518
  json_objects.append(json_obj) # 收集响应
@@ -1535,45 +1548,13 @@ async def stream_chat_generator(session: str, text_content: str, file_ids: List[
1535
  chunk = create_chunk(chat_id, created_time, model_name, {"content": text}, None)
1536
  yield f"data: {chunk}\n\n"
1537
 
1538
- # 处理图片生成
1539
  if json_objects:
1540
  file_ids, session_name = parse_images_from_response(json_objects)
1541
-
1542
  if file_ids and session_name:
 
1543
  logger.info(f"[IMAGE] [{account_manager.config.account_id}] [req_{request_id}] 检测到{len(file_ids)}张生成图片")
1544
 
1545
- try:
1546
- base_url = get_base_url(request) if request else ""
1547
- file_metadata = await get_session_file_metadata(account_manager, session_name, http_client, USER_AGENT, request_id)
1548
-
1549
- # 并行下载所有图片
1550
- download_tasks = []
1551
- for file_info in file_ids:
1552
- fid = file_info["fileId"]
1553
- mime = file_info["mimeType"]
1554
- meta = file_metadata.get(fid, {})
1555
- correct_session = meta.get("session") or session_name
1556
- task = download_image_with_jwt(account_manager, correct_session, fid, http_client, USER_AGENT, request_id)
1557
- download_tasks.append((fid, mime, task))
1558
-
1559
- results = await asyncio.gather(*[task for _, _, task in download_tasks], return_exceptions=True)
1560
-
1561
- # 处��下载结果
1562
- for idx, ((fid, mime, _), result) in enumerate(zip(download_tasks, results), 1):
1563
- if isinstance(result, Exception):
1564
- logger.error(f"[IMAGE] [{account_manager.config.account_id}] [req_{request_id}] 图片{idx}下载失败: {type(result).__name__}")
1565
- continue
1566
-
1567
- image_url = save_image_to_hf(result, chat_id, fid, mime, base_url, IMAGE_DIR)
1568
- logger.info(f"[IMAGE] [{account_manager.config.account_id}] [req_{request_id}] 图片{idx}已保存: {image_url}")
1569
-
1570
- markdown = f"\n\n![生成的图片]({image_url})\n\n"
1571
- chunk = create_chunk(chat_id, created_time, model_name, {"content": markdown}, None)
1572
- yield f"data: {chunk}\n\n"
1573
-
1574
- except Exception as e:
1575
- logger.error(f"[IMAGE] [{account_manager.config.account_id}] [req_{request_id}] 图片处理失败: {str(e)}")
1576
-
1577
  except ValueError as e:
1578
  logger.error(f"[API] [{account_manager.config.account_id}] [req_{request_id}] JSON解析失败: {str(e)}")
1579
  except Exception as e:
@@ -1581,8 +1562,61 @@ async def stream_chat_generator(session: str, text_content: str, file_ids: List[
1581
  logger.error(f"[API] [{account_manager.config.account_id}] [req_{request_id}] 流处理错误 ({error_type}): {str(e)}")
1582
  raise
1583
 
1584
- total_time = time.time() - start_time
1585
- logger.info(f"[API] [{account_manager.config.account_id}] [req_{request_id}] 响应完成: {total_time:.2f}秒")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1586
 
1587
  if is_stream:
1588
  final_chunk = create_chunk(chat_id, created_time, model_name, {}, "stop")
 
781
  @app.put("/admin/accounts/{account_id}/enable")
782
  @require_login()
783
  async def admin_enable_account(request: Request, account_id: str):
784
+ """启用账户(同时重置错误禁用状态)"""
785
  global multi_account_mgr
786
  try:
787
  multi_account_mgr = _update_account_disabled_status(
 
789
  ACCOUNT_FAILURE_THRESHOLD, RATE_LIMIT_COOLDOWN_SECONDS,
790
  SESSION_CACHE_TTL_SECONDS, global_stats
791
  )
792
+
793
+ # 重置运行时错误状态(允许手动恢复错误禁用的账户)
794
+ if account_id in multi_account_mgr.accounts:
795
+ account_mgr = multi_account_mgr.accounts[account_id]
796
+ account_mgr.is_available = True
797
+ account_mgr.error_count = 0
798
+ account_mgr.last_429_time = 0.0
799
+ logger.info(f"[CONFIG] 账户 {account_id} 错误状态已重置")
800
+
801
  return {"status": "success", "message": f"账户 {account_id} 已启用", "account_count": len(multi_account_mgr.accounts)}
802
  except Exception as e:
803
  logger.error(f"[CONFIG] 启用账户失败: {str(e)}")
 
891
  max_connections=200
892
  )
893
  )
894
+ # 更新所有账户的 http_client 引用
895
+ multi_account_mgr.update_http_client(http_client)
896
 
897
  # 检查是否需要更新账户管理器配置(重试策略变化)
898
  retry_changed = (
 
904
  if retry_changed:
905
  logger.info(f"[CONFIG] 重试策略已变化,更新账户管理器配置")
906
  # 更新所有账户管理器的配置
907
+ multi_account_mgr.cache_ttl = SESSION_CACHE_TTL_SECONDS
908
  for account_id, account_mgr in multi_account_mgr.accounts.items():
909
  account_mgr.account_failure_threshold = ACCOUNT_FAILURE_THRESHOLD
910
  account_mgr.rate_limit_cooldown_seconds = RATE_LIMIT_COOLDOWN_SECONDS
 
1512
  yield f"data: {chunk}\n\n"
1513
 
1514
  # 使用流式请求
1515
+ json_objects = [] # 收集所有响应对象用于图片解析
1516
+ file_ids_info = None # 保存图片信息
1517
+
1518
  async with http_client.stream(
1519
  "POST",
1520
  "https://biz-discoveryengine.googleapis.com/v1alpha/locations/global/widgetStreamAssist",
 
1526
  raise HTTPException(status_code=r.status_code, detail=f"Upstream Error {error_text.decode()}")
1527
 
1528
  # 使用异步解析器处理 JSON 数组流
 
1529
  try:
1530
  async for json_obj in parse_json_array_stream_async(r.aiter_lines()):
1531
  json_objects.append(json_obj) # 收集响应
 
1548
  chunk = create_chunk(chat_id, created_time, model_name, {"content": text}, None)
1549
  yield f"data: {chunk}\n\n"
1550
 
1551
+ # 提取图片信息(在 async with 块内)
1552
  if json_objects:
1553
  file_ids, session_name = parse_images_from_response(json_objects)
 
1554
  if file_ids and session_name:
1555
+ file_ids_info = (file_ids, session_name)
1556
  logger.info(f"[IMAGE] [{account_manager.config.account_id}] [req_{request_id}] 检测到{len(file_ids)}张生成图片")
1557
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1558
  except ValueError as e:
1559
  logger.error(f"[API] [{account_manager.config.account_id}] [req_{request_id}] JSON解析失败: {str(e)}")
1560
  except Exception as e:
 
1562
  logger.error(f"[API] [{account_manager.config.account_id}] [req_{request_id}] 流处理错误 ({error_type}): {str(e)}")
1563
  raise
1564
 
1565
+ # async with 块外处理图片下载(避免占用上游连接)
1566
+ if file_ids_info:
1567
+ file_ids, session_name = file_ids_info
1568
+ try:
1569
+ base_url = get_base_url(request) if request else ""
1570
+ file_metadata = await get_session_file_metadata(account_manager, session_name, http_client, USER_AGENT, request_id)
1571
+
1572
+ # 并行下载所有图片
1573
+ download_tasks = []
1574
+ for file_info in file_ids:
1575
+ fid = file_info["fileId"]
1576
+ mime = file_info["mimeType"]
1577
+ meta = file_metadata.get(fid, {})
1578
+ correct_session = meta.get("session") or session_name
1579
+ task = download_image_with_jwt(account_manager, correct_session, fid, http_client, USER_AGENT, request_id)
1580
+ download_tasks.append((fid, mime, task))
1581
+
1582
+ results = await asyncio.gather(*[task for _, _, task in download_tasks], return_exceptions=True)
1583
+
1584
+ # 处理下载结果
1585
+ success_count = 0
1586
+ for idx, ((fid, mime, _), result) in enumerate(zip(download_tasks, results), 1):
1587
+ if isinstance(result, Exception):
1588
+ logger.error(f"[IMAGE] [{account_manager.config.account_id}] [req_{request_id}] 图片{idx}下载失败: {type(result).__name__}: {str(result)[:100]}")
1589
+ # 降级处理:返回错误提示而不是静默失败
1590
+ error_msg = f"\n\n⚠️ 图片 {idx} 下载失败\n\n"
1591
+ chunk = create_chunk(chat_id, created_time, model_name, {"content": error_msg}, None)
1592
+ yield f"data: {chunk}\n\n"
1593
+ continue
1594
+
1595
+ try:
1596
+ image_url = save_image_to_hf(result, chat_id, fid, mime, base_url, IMAGE_DIR)
1597
+ logger.info(f"[IMAGE] [{account_manager.config.account_id}] [req_{request_id}] 图片{idx}已保存: {image_url}")
1598
+ success_count += 1
1599
+
1600
+ markdown = f"\n\n![生成的图片]({image_url})\n\n"
1601
+ chunk = create_chunk(chat_id, created_time, model_name, {"content": markdown}, None)
1602
+ yield f"data: {chunk}\n\n"
1603
+ except Exception as save_error:
1604
+ logger.error(f"[IMAGE] [{account_manager.config.account_id}] [req_{request_id}] 图片{idx}保存失败: {str(save_error)[:100]}")
1605
+ error_msg = f"\n\n⚠️ 图片 {idx} 保存失败\n\n"
1606
+ chunk = create_chunk(chat_id, created_time, model_name, {"content": error_msg}, None)
1607
+ yield f"data: {chunk}\n\n"
1608
+
1609
+ logger.info(f"[IMAGE] [{account_manager.config.account_id}] [req_{request_id}] 图片处理完成: {success_count}/{len(file_ids)} 成功")
1610
+
1611
+ except Exception as e:
1612
+ logger.error(f"[IMAGE] [{account_manager.config.account_id}] [req_{request_id}] 图片处理失败: {type(e).__name__}: {str(e)[:100]}")
1613
+ # 降级处理:通知用户图片处理失败
1614
+ error_msg = f"\n\n⚠️ 图片处理失败: {type(e).__name__}\n\n"
1615
+ chunk = create_chunk(chat_id, created_time, model_name, {"content": error_msg}, None)
1616
+ yield f"data: {chunk}\n\n"
1617
+
1618
+ total_time = time.time() - start_time
1619
+ logger.info(f"[API] [{account_manager.config.account_id}] [req_{request_id}] 响应完成: {total_time:.2f}秒")
1620
 
1621
  if is_stream:
1622
  final_chunk = create_chunk(chat_id, created_time, model_name, {}, "stop")