Spaces:
Sleeping
Sleeping
| import httpx | |
| import asyncio | |
| from starlette.responses import Response | |
| from api_key_sb import get_api_key_info, update_api_key_ran_at, supabase as sb_client # 移除 get_supabase_client | |
| # from supabase import Client | |
| from dotenv import load_dotenv | |
| import os | |
| from datetime import timezone, timedelta, datetime | |
| from fastapi import FastAPI, Request, HTTPException, Depends, status | |
| import httpx | |
| import asyncio | |
| from starlette.responses import Response | |
| from api_key_sb import get_api_key_info, update_api_key_ran_at, supabase as sb_client | |
| from dotenv import load_dotenv | |
| import os | |
| from datetime import timezone, timedelta, datetime | |
| from fastapi import FastAPI, Request, HTTPException, status | |
| import logging | |
| import json | |
| load_dotenv() | |
| logger = logging.getLogger(__name__) | |
| def _create_error_response(status_code: int, detail: str, error_type: str = "ProxyError"): | |
| """Creates a standardized error response.""" | |
| return Response( | |
| content=json.dumps({"detail": detail, "error_type": error_type}), | |
| status_code=status_code, | |
| media_type="application/json" | |
| ) | |
| async def do_proxy(url: str, method: str, headers: dict, content: str, max_retries: int = 3): | |
| logger.info(f"Proxy service started for URL: {url}") | |
| client = None | |
| try: | |
| async with httpx.AsyncClient() as client: | |
| for attempt in range(max_retries): | |
| model_name = None | |
| try: | |
| content_json = json.loads(content) | |
| model_name = content_json.get('model') | |
| if model_name: | |
| logger.info(f"从内容中提取的模型名称: {model_name}") | |
| else: | |
| logger.warning("内容中未找到 'model' 键。") | |
| except json.JSONDecodeError: | |
| logger.warning("内容不是有效的 JSON 格式,无法提取 'model' 键。") | |
| except Exception as e: | |
| logger.error(f"提取模型名称时发生错误: {str(e)}") | |
| # api_key_info = await get_api_key_info('chat', model_name) | |
| api_key_info = await get_api_key_info(model_name) | |
| if not api_key_info: | |
| return _create_error_response(status.HTTP_500_INTERNAL_SERVER_ERROR, "无法获取API密钥信息", "APIKeyError") | |
| api_key = api_key_info.get('api_key') | |
| api_key_id = api_key_info.get('api_key_id') | |
| if not api_key: | |
| return _create_error_response(status.HTTP_500_INTERNAL_SERVER_ERROR, "API密钥为空", "APIKeyError") | |
| api_key_show = api_key[:5]+'*****'+api_key[-5:] | |
| logger.info(f"使用API密钥:{api_key_show}") | |
| headers["Authorization"] = f"Bearer {api_key}" | |
| response = await client.request( | |
| method=method, | |
| url=url, | |
| headers=headers, | |
| content=content, | |
| timeout=30 | |
| ) | |
| if response.status_code == 429: | |
| retry_after = response.headers.get("Retry-After", "5") | |
| wait_time = int(retry_after) + attempt * 2 | |
| logger.warning(f"⚠️ 429错误!{wait_time}秒后重试 (尝试:{attempt+1})") | |
| await asyncio.sleep(wait_time) | |
| try: | |
| beijing_tz = timezone(timedelta(hours=8)) | |
| now_beijing = datetime.now(beijing_tz) | |
| future_time = now_beijing + timedelta(days=1) | |
| future_timestamp = future_time.isoformat() | |
| logger.info(f'future_timestamp: {future_timestamp}') | |
| await update_api_key_ran_at(api_key_id, future_time) | |
| logger.info('API密钥运行时间更新成功') | |
| except HTTPException as e: | |
| logger.error(f"更新API密钥运行时间失败!错误信息:{e.detail}") | |
| return _create_error_response(e.status_code, e.detail, "APIKeyUpdateError") | |
| except Exception as e: | |
| logger.error(f"更新API密钥运行时间失败!错误信息:{str(e)}") | |
| return _create_error_response(status.HTTP_500_INTERNAL_SERVER_ERROR, f"更新API密钥运行时间失败!错误信息:{str(e)}", "APIKeyUpdateError") | |
| continue | |
| response.raise_for_status() | |
| return Response( | |
| content=response.content, | |
| status_code=response.status_code, | |
| headers=dict(response.headers) | |
| ) | |
| except httpx.HTTPStatusError as e: | |
| logger.error(f"🚨 服务器错误 {e.response.status_code}: {e.request.url}") | |
| return _create_error_response(e.response.status_code, str(e), "HTTPStatusError") | |
| except HTTPException as e: | |
| logger.error(f"🔥 HTTPException: {e.detail}") | |
| return _create_error_response(e.status_code, e.detail, "HTTPException") | |
| except Exception as e: | |
| print('请检查当前是否运行在本机开发环境') | |
| logger.error(f"🔥 致命错误: {type(e).__name__}: {str(e)}") | |
| return _create_error_response(status.HTTP_500_INTERNAL_SERVER_ERROR, f"内部服务器错误: {str(e)}", "InternalServerError") | |