yym68686 commited on
Commit
a1d3f78
·
1 Parent(s): b269107

Change log display

Browse files
Files changed (4) hide show
  1. log_config.py +6 -0
  2. main.py +3 -22
  3. response.py +11 -22
  4. utils.py +6 -4
log_config.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ import logging
2
+ logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
3
+ logger = logging.getLogger("uni-api")
4
+
5
+ httpx_logger = logging.getLogger("httpx")
6
+ httpx_logger.setLevel(logging.CRITICAL)
main.py CHANGED
@@ -1,5 +1,4 @@
1
- import json
2
- import traceback
3
 
4
  import httpx
5
  import secrets
@@ -58,7 +57,7 @@ async def process_request(request: RequestModel, provider: Dict):
58
 
59
  if provider.get("engine"):
60
  engine = provider["engine"]
61
- print("provider:", provider['provider'], "engine:", engine)
62
 
63
  url, headers, payload = await get_payload(request, engine, provider)
64
 
@@ -71,15 +70,9 @@ async def process_request(request: RequestModel, provider: Dict):
71
 
72
  if request.stream:
73
  model = provider['model'][request.model]
74
- # try:
75
  generator = fetch_response_stream(app.state.client, url, headers, payload, engine, model)
76
  wrapped_generator = await error_handling_wrapper(generator, status_code=500)
77
  return StreamingResponse(wrapped_generator, media_type="text/event-stream")
78
- # except HTTPException as e:
79
- # return JSONResponse(status_code=e.status_code, content={"error": str(e.detail)})
80
- # except Exception as e:
81
- # # 处理其他异常
82
- # return JSONResponse(status_code=500, content={"error": str(e)})
83
  else:
84
  return await fetch_response(app.state.client, url, headers, payload)
85
 
@@ -88,10 +81,6 @@ class ModelRequestHandler:
88
  self.last_provider_index = -1
89
 
90
  def get_matching_providers(self, model_name, token):
91
- # for provider in config:
92
- # print("provider", model_name, list(provider['model'].keys()))
93
- # if model_name in provider['model'].keys():
94
- # print("provider", provider)
95
  api_index = api_list.index(token)
96
  provider_rules = []
97
 
@@ -150,9 +139,7 @@ class ModelRequestHandler:
150
  response = await process_request(request, provider)
151
  return response
152
  except (Exception, HTTPException) as e:
153
- print('\033[31m')
154
- print(f"Error with provider {provider['provider']}: {str(e)}")
155
- print('\033[0m')
156
  if auto_retry:
157
  continue
158
  else:
@@ -164,13 +151,7 @@ model_handler = ModelRequestHandler()
164
 
165
  @app.post("/v1/chat/completions")
166
  async def request_model(request: RequestModel, token: str = Depends(verify_api_key)):
167
- # try:
168
  return await model_handler.request_model(request, token)
169
- # except Exception as e:
170
- # print('\033[31m')
171
- # print(f"request_model Error: {str(e)}")
172
- # traceback.print_exc()
173
- # print('\033[0m')
174
 
175
  @app.options("/v1/chat/completions")
176
  async def options_handler():
 
1
+ from log_config import logger
 
2
 
3
  import httpx
4
  import secrets
 
57
 
58
  if provider.get("engine"):
59
  engine = provider["engine"]
60
+ logger.info(f"provider: {provider['provider']:<10} engine: {engine}")
61
 
62
  url, headers, payload = await get_payload(request, engine, provider)
63
 
 
70
 
71
  if request.stream:
72
  model = provider['model'][request.model]
 
73
  generator = fetch_response_stream(app.state.client, url, headers, payload, engine, model)
74
  wrapped_generator = await error_handling_wrapper(generator, status_code=500)
75
  return StreamingResponse(wrapped_generator, media_type="text/event-stream")
 
 
 
 
 
76
  else:
77
  return await fetch_response(app.state.client, url, headers, payload)
78
 
 
81
  self.last_provider_index = -1
82
 
83
  def get_matching_providers(self, model_name, token):
 
 
 
 
84
  api_index = api_list.index(token)
85
  provider_rules = []
86
 
 
139
  response = await process_request(request, provider)
140
  return response
141
  except (Exception, HTTPException) as e:
142
+ logger.error(f"Error with provider {provider['provider']}: {str(e)}")
 
 
143
  if auto_retry:
144
  continue
145
  else:
 
151
 
152
  @app.post("/v1/chat/completions")
153
  async def request_model(request: RequestModel, token: str = Depends(verify_api_key)):
 
154
  return await model_handler.request_model(request, token)
 
 
 
 
 
155
 
156
  @app.options("/v1/chat/completions")
157
  async def options_handler():
response.py CHANGED
@@ -2,6 +2,8 @@ import json
2
  import httpx
3
  from datetime import datetime
4
 
 
 
5
 
6
  async def generate_sse_response(timestamp, model, content=None, tools_id=None, function_call_name=None, function_call_content=None, role=None, tokens_use=None, total_tokens=None):
7
  sample_data = {
@@ -51,7 +53,7 @@ async def fetch_gemini_response_stream(client, url, headers, payload, model):
51
  sse_string = await generate_sse_response(timestamp, model, content)
52
  yield sse_string
53
  except json.JSONDecodeError:
54
- print(f"无法解析JSON: {line}")
55
 
56
  # # 处理缓冲区中剩余的内容
57
  # if buffer:
@@ -88,13 +90,9 @@ async def fetch_claude_response_stream(client, url, headers, payload, model):
88
  timestamp = datetime.timestamp(datetime.now())
89
  async with client.stream('POST', url, headers=headers, json=payload) as response:
90
  if response.status_code != 200:
91
- print('\033[31m')
92
- # print(f"请求失败,状态码是{response.status_code},错误信息:")
93
  error_message = await response.aread()
94
  error_str = error_message.decode('utf-8', errors='replace')
95
  error_json = json.loads(error_str)
96
- # print(json.dumps(error_json, indent=4, ensure_ascii=False))
97
- print('\033[0m')
98
  yield {"error": f"fetch_claude_response_stream HTTP Error {response.status_code}", "details": error_json}
99
  buffer = ""
100
  async for chunk in response.aiter_text():
@@ -143,19 +141,15 @@ async def fetch_claude_response_stream(client, url, headers, payload, model):
143
  yield sse_string
144
 
145
  async def fetch_response(client, url, headers, payload):
146
- for _ in range(2):
147
- try:
148
- response = await client.post(url, headers=headers, json=payload)
149
- return response.json()
150
- except httpx.ConnectError as e:
151
- print(f"fetch_response 连接错误: {e}")
152
- continue
153
- except httpx.ReadTimeout as e:
154
- print(f"fetch_response 读取响应超时: {e}")
155
- continue
156
 
157
  async def fetch_response_stream(client, url, headers, payload, engine, model):
158
- # for _ in range(2):
159
  try:
160
  if engine == "gemini":
161
  async for chunk in fetch_gemini_response_stream(client, url, headers, payload, model):
@@ -171,12 +165,7 @@ async def fetch_response_stream(client, url, headers, payload, engine, model):
171
  yield chunk
172
  else:
173
  raise ValueError("Unknown response")
174
- # break
175
  except httpx.ConnectError as e:
176
- # print(f"fetch_response_stream 连接错误: {e}")
177
  yield {"error": f"500", "details": "fetch_response_stream Connect Error"}
178
- # continue
179
  except httpx.ReadTimeout as e:
180
- # print(f"fetch_response_stream 读取响应超时 {e}")
181
- yield {"error": f"500", "details": "fetch_response_stream Read Response Timeout"}
182
- # continue
 
2
  import httpx
3
  from datetime import datetime
4
 
5
+ from log_config import logger
6
+
7
 
8
  async def generate_sse_response(timestamp, model, content=None, tools_id=None, function_call_name=None, function_call_content=None, role=None, tokens_use=None, total_tokens=None):
9
  sample_data = {
 
53
  sse_string = await generate_sse_response(timestamp, model, content)
54
  yield sse_string
55
  except json.JSONDecodeError:
56
+ logger.error(f"无法解析JSON: {line}")
57
 
58
  # # 处理缓冲区中剩余的内容
59
  # if buffer:
 
90
  timestamp = datetime.timestamp(datetime.now())
91
  async with client.stream('POST', url, headers=headers, json=payload) as response:
92
  if response.status_code != 200:
 
 
93
  error_message = await response.aread()
94
  error_str = error_message.decode('utf-8', errors='replace')
95
  error_json = json.loads(error_str)
 
 
96
  yield {"error": f"fetch_claude_response_stream HTTP Error {response.status_code}", "details": error_json}
97
  buffer = ""
98
  async for chunk in response.aiter_text():
 
141
  yield sse_string
142
 
143
  async def fetch_response(client, url, headers, payload):
144
+ try:
145
+ response = await client.post(url, headers=headers, json=payload)
146
+ return response.json()
147
+ except httpx.ConnectError as e:
148
+ return {"error": f"500", "details": "fetch_response Connect Error"}
149
+ except httpx.ReadTimeout as e:
150
+ return {"error": f"500", "details": "fetch_response Read Response Timeout"}
 
 
 
151
 
152
  async def fetch_response_stream(client, url, headers, payload, engine, model):
 
153
  try:
154
  if engine == "gemini":
155
  async for chunk in fetch_gemini_response_stream(client, url, headers, payload, model):
 
165
  yield chunk
166
  else:
167
  raise ValueError("Unknown response")
 
168
  except httpx.ConnectError as e:
 
169
  yield {"error": f"500", "details": "fetch_response_stream Connect Error"}
 
170
  except httpx.ReadTimeout as e:
171
+ yield {"error": f"500", "details": "fetch_response_stream Read Response Timeout"}
 
 
utils.py CHANGED
@@ -3,6 +3,8 @@ import json
3
  from fastapi import HTTPException, Depends
4
  from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
5
 
 
 
6
  # 读取YAML配置文件
7
  def load_config():
8
  try:
@@ -20,13 +22,13 @@ def load_config():
20
  conf['providers'][index] = provider
21
  api_keys_db = conf['api_keys']
22
  api_list = [item["api"] for item in api_keys_db]
23
- # print(json.dumps(conf, indent=4, ensure_ascii=False))
24
  return conf, api_keys_db, api_list
25
  except FileNotFoundError:
26
- print("配置文件 'api.yaml' 未找到。请确保文件存在于正确的位置。")
27
  return [], [], []
28
  except yaml.YAMLError:
29
- print("配置文件 'api.yaml' 格式不正确。请检查 YAML 格式。")
30
  return [], [], []
31
 
32
  config, api_keys_db, api_list = load_config()
@@ -59,7 +61,7 @@ async def error_handling_wrapper(generator, status_code=200):
59
  try:
60
  first_item_str = json.loads(first_item_str)
61
  except json.JSONDecodeError:
62
- print("error_handling_wrapper JSONDecodeError!", first_item_str)
63
  pass # 如果不是有效的JSON,保持原样
64
  if isinstance(first_item_str, dict) and 'error' in first_item_str:
65
  # 如果第一个 yield 的项是错误信息,抛出 HTTPException
 
3
  from fastapi import HTTPException, Depends
4
  from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
5
 
6
+ from log_config import logger
7
+
8
  # 读取YAML配置文件
9
  def load_config():
10
  try:
 
22
  conf['providers'][index] = provider
23
  api_keys_db = conf['api_keys']
24
  api_list = [item["api"] for item in api_keys_db]
25
+ # logger.info(json.dumps(conf, indent=4, ensure_ascii=False))
26
  return conf, api_keys_db, api_list
27
  except FileNotFoundError:
28
+ logger.error("配置文件 'api.yaml' 未找到。请确保文件存在于正确的位置。")
29
  return [], [], []
30
  except yaml.YAMLError:
31
+ logger.error("配置文件 'api.yaml' 格式不正确。请检查 YAML 格式。")
32
  return [], [], []
33
 
34
  config, api_keys_db, api_list = load_config()
 
61
  try:
62
  first_item_str = json.loads(first_item_str)
63
  except json.JSONDecodeError:
64
+ logger.error("error_handling_wrapper JSONDecodeError!", first_item_str)
65
  pass # 如果不是有效的JSON,保持原样
66
  if isinstance(first_item_str, dict) and 'error' in first_item_str:
67
  # 如果第一个 yield 的项是错误信息,抛出 HTTPException