Niansuh commited on
Commit
dd3e05b
·
verified ·
1 Parent(s): 71498b7

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +15 -34
main.py CHANGED
@@ -20,9 +20,7 @@ from pydantic import BaseModel
20
  logging.basicConfig(
21
  level=logging.INFO,
22
  format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
23
- handlers=[
24
- logging.StreamHandler()
25
- ]
26
  )
27
  logger = logging.getLogger(__name__)
28
 
@@ -38,10 +36,6 @@ if not API_KEYS or API_KEYS == ['']:
38
  rate_limit_store = defaultdict(lambda: {"count": 0, "timestamp": time.time()})
39
 
40
  async def get_api_key(authorization: str = Header(...)) -> str:
41
- """
42
- Dependency to extract and validate the API key from the Authorization header.
43
- Expects the header in the format: Authorization: Bearer <API_KEY>
44
- """
45
  if not authorization.startswith('Bearer '):
46
  logger.warning("Invalid authorization header format.")
47
  raise HTTPException(status_code=401, detail='Invalid authorization header format')
@@ -52,14 +46,9 @@ async def get_api_key(authorization: str = Header(...)) -> str:
52
  return api_key
53
 
54
  async def rate_limiter(api_key: str = Depends(get_api_key)):
55
- """
56
- Dependency to enforce rate limiting per API key.
57
- Raises HTTP 429 if the rate limit is exceeded.
58
- """
59
  current_time = time.time()
60
  window_start = rate_limit_store[api_key]["timestamp"]
61
  if current_time - window_start > 60:
62
- # Reset the count and timestamp after the time window
63
  rate_limit_store[api_key] = {"count": 1, "timestamp": current_time}
64
  else:
65
  if rate_limit_store[api_key]["count"] >= RATE_LIMIT:
@@ -244,6 +233,10 @@ class Blackbox:
244
  random_id = ''.join(random.choices(string.ascii_letters + string.digits, k=7))
245
  messages[-1]['id'] = random_id
246
  messages[-1]['role'] = 'user'
 
 
 
 
247
  if image is not None:
248
  messages[-1]['data'] = {
249
  'fileText': '',
@@ -283,7 +276,7 @@ class Blackbox:
283
  data["trendingAgentMode"] = cls.trendingAgentMode[model]
284
  elif model in cls.userSelectedModel:
285
  data["userSelectedModel"] = cls.userSelectedModel[model]
286
- logger.info(f"Sending request to {cls.api_endpoint} with data: {data}")
287
 
288
  timeout = ClientTimeout(total=60) # Set an appropriate timeout
289
  retry_attempts = 10 # Set the number of retry attempts
@@ -299,7 +292,7 @@ class Blackbox:
299
  url_match = re.search(r'https://storage\.googleapis\.com/[^\s\)]+', response_text)
300
  if url_match:
301
  image_url = url_match.group(0)
302
- logger.info(f"Image URL found: {image_url}")
303
  yield ImageResponse(image_url, alt=messages[-1]['content'])
304
  else:
305
  logger.error("Image URL not found in the response.")
@@ -366,7 +359,7 @@ def create_response(content: str, model: str, finish_reason: Optional[str] = Non
366
  return {
367
  "id": f"chatcmpl-{uuid.uuid4()}",
368
  "object": "chat.completion.chunk",
369
- "created": int(datetime.now().timestamp()), # datetime is now correctly imported
370
  "model": model,
371
  "choices": [
372
  {
@@ -380,22 +373,18 @@ def create_response(content: str, model: str, finish_reason: Optional[str] = Non
380
 
381
  @app.post("/niansuhai/v1/chat/completions", dependencies=[Depends(rate_limiter)])
382
  async def chat_completions(request: ChatRequest, req: Request, api_key: str = Depends(get_api_key)):
383
- """
384
- Endpoint to handle chat completions.
385
- Protected by API key and rate limiter.
386
- """
387
- logger.info(f"Received chat completions request from API key: {api_key} | Request: {request}")
388
  try:
389
  # Validate that the requested model is available
390
  if request.model not in Blackbox.models and request.model not in Blackbox.model_aliases:
391
  logger.warning(f"Attempt to use unavailable model: {request.model}")
392
  raise HTTPException(status_code=400, detail="Requested model is not available.")
393
 
394
- messages = [{"role": msg.role, "content": msg.content} for msg in request.messages]
395
-
396
  async_generator = Blackbox.create_async_generator(
397
  model=request.model,
398
- messages=messages,
399
  image=None,
400
  image_name=None,
401
  webSearchMode=request.webSearchMode
@@ -411,10 +400,8 @@ async def chat_completions(request: ChatRequest, req: Request, api_key: str = De
411
  else:
412
  response_chunk = create_response(chunk, request.model)
413
 
414
- # Yield each chunk in SSE format
415
  yield f"data: {json.dumps(response_chunk)}\n\n"
416
 
417
- # Signal the end of the stream
418
  yield "data: [DONE]\n\n"
419
  except HTTPException as he:
420
  error_response = {"error": he.detail}
@@ -437,7 +424,7 @@ async def chat_completions(request: ChatRequest, req: Request, api_key: str = De
437
  return {
438
  "id": f"chatcmpl-{uuid.uuid4()}",
439
  "object": "chat.completion",
440
- "created": int(datetime.now().timestamp()), # datetime is now correctly imported
441
  "model": request.model,
442
  "choices": [
443
  {
@@ -450,9 +437,9 @@ async def chat_completions(request: ChatRequest, req: Request, api_key: str = De
450
  }
451
  ],
452
  "usage": {
453
- "prompt_tokens": sum(len(msg['content'].split()) for msg in messages),
454
  "completion_tokens": len(response_content.split()),
455
- "total_tokens": sum(len(msg['content'].split()) for msg in messages) + len(response_content.split())
456
  },
457
  }
458
  except ModelNotWorkingException as e:
@@ -467,23 +454,17 @@ async def chat_completions(request: ChatRequest, req: Request, api_key: str = De
467
 
468
  @app.get("/niansuhai/v1/models", dependencies=[Depends(rate_limiter)])
469
  async def get_models(api_key: str = Depends(get_api_key)):
470
- """
471
- Endpoint to fetch available models.
472
- Protected by API key and rate limiter.
473
- """
474
  logger.info(f"Fetching available models for API key: {api_key}")
475
  return {"data": [{"id": model} for model in Blackbox.models]}
476
 
477
  # Additional endpoints for better functionality
478
  @app.get("/niansuhai/v1/health", dependencies=[Depends(rate_limiter)])
479
  async def health_check(api_key: str = Depends(get_api_key)):
480
- """Health check endpoint to verify the service is running."""
481
  logger.info(f"Health check requested by API key: {api_key}")
482
  return {"status": "ok"}
483
 
484
  @app.get("/niansuhai/v1/models/{model}/status", dependencies=[Depends(rate_limiter)])
485
  async def model_status(model: str, api_key: str = Depends(get_api_key)):
486
- """Check if a specific model is available."""
487
  logger.info(f"Model status requested for '{model}' by API key: {api_key}")
488
  if model in Blackbox.models:
489
  return {"model": model, "status": "available"}
 
20
  logging.basicConfig(
21
  level=logging.INFO,
22
  format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
23
+ handlers=[logging.StreamHandler()]
 
 
24
  )
25
  logger = logging.getLogger(__name__)
26
 
 
36
  rate_limit_store = defaultdict(lambda: {"count": 0, "timestamp": time.time()})
37
 
38
  async def get_api_key(authorization: str = Header(...)) -> str:
 
 
 
 
39
  if not authorization.startswith('Bearer '):
40
  logger.warning("Invalid authorization header format.")
41
  raise HTTPException(status_code=401, detail='Invalid authorization header format')
 
46
  return api_key
47
 
48
  async def rate_limiter(api_key: str = Depends(get_api_key)):
 
 
 
 
49
  current_time = time.time()
50
  window_start = rate_limit_store[api_key]["timestamp"]
51
  if current_time - window_start > 60:
 
52
  rate_limit_store[api_key] = {"count": 1, "timestamp": current_time}
53
  else:
54
  if rate_limit_store[api_key]["count"] >= RATE_LIMIT:
 
233
  random_id = ''.join(random.choices(string.ascii_letters + string.digits, k=7))
234
  messages[-1]['id'] = random_id
235
  messages[-1]['role'] = 'user'
236
+
237
+ # Don't log the full message content for privacy
238
+ logger.debug(f"Generated message ID: {random_id} for model: {model}")
239
+
240
  if image is not None:
241
  messages[-1]['data'] = {
242
  'fileText': '',
 
276
  data["trendingAgentMode"] = cls.trendingAgentMode[model]
277
  elif model in cls.userSelectedModel:
278
  data["userSelectedModel"] = cls.userSelectedModel[model]
279
+ logger.info(f"Sending request to {cls.api_endpoint} with data (excluding messages).")
280
 
281
  timeout = ClientTimeout(total=60) # Set an appropriate timeout
282
  retry_attempts = 10 # Set the number of retry attempts
 
292
  url_match = re.search(r'https://storage\.googleapis\.com/[^\s\)]+', response_text)
293
  if url_match:
294
  image_url = url_match.group(0)
295
+ logger.info(f"Image URL found.")
296
  yield ImageResponse(image_url, alt=messages[-1]['content'])
297
  else:
298
  logger.error("Image URL not found in the response.")
 
359
  return {
360
  "id": f"chatcmpl-{uuid.uuid4()}",
361
  "object": "chat.completion.chunk",
362
+ "created": int(datetime.now().timestamp()),
363
  "model": model,
364
  "choices": [
365
  {
 
373
 
374
  @app.post("/niansuhai/v1/chat/completions", dependencies=[Depends(rate_limiter)])
375
  async def chat_completions(request: ChatRequest, req: Request, api_key: str = Depends(get_api_key)):
376
+ logger.info(f"Received chat completions request from API key: {api_key} | Model: {request.model}")
377
+
 
 
 
378
  try:
379
  # Validate that the requested model is available
380
  if request.model not in Blackbox.models and request.model not in Blackbox.model_aliases:
381
  logger.warning(f"Attempt to use unavailable model: {request.model}")
382
  raise HTTPException(status_code=400, detail="Requested model is not available.")
383
 
384
+ # Process the request but do not log sensitive content
 
385
  async_generator = Blackbox.create_async_generator(
386
  model=request.model,
387
+ messages=[{"role": msg.role, "content": "[redacted]"} for msg in request.messages], # Redact user messages in logs
388
  image=None,
389
  image_name=None,
390
  webSearchMode=request.webSearchMode
 
400
  else:
401
  response_chunk = create_response(chunk, request.model)
402
 
 
403
  yield f"data: {json.dumps(response_chunk)}\n\n"
404
 
 
405
  yield "data: [DONE]\n\n"
406
  except HTTPException as he:
407
  error_response = {"error": he.detail}
 
424
  return {
425
  "id": f"chatcmpl-{uuid.uuid4()}",
426
  "object": "chat.completion",
427
+ "created": int(datetime.now().timestamp()),
428
  "model": request.model,
429
  "choices": [
430
  {
 
437
  }
438
  ],
439
  "usage": {
440
+ "prompt_tokens": sum(len(msg['content'].split()) for msg in request.messages),
441
  "completion_tokens": len(response_content.split()),
442
+ "total_tokens": sum(len(msg['content'].split()) for msg in request.messages) + len(response_content.split())
443
  },
444
  }
445
  except ModelNotWorkingException as e:
 
454
 
455
  @app.get("/niansuhai/v1/models", dependencies=[Depends(rate_limiter)])
456
  async def get_models(api_key: str = Depends(get_api_key)):
 
 
 
 
457
  logger.info(f"Fetching available models for API key: {api_key}")
458
  return {"data": [{"id": model} for model in Blackbox.models]}
459
 
460
  # Additional endpoints for better functionality
461
  @app.get("/niansuhai/v1/health", dependencies=[Depends(rate_limiter)])
462
  async def health_check(api_key: str = Depends(get_api_key)):
 
463
  logger.info(f"Health check requested by API key: {api_key}")
464
  return {"status": "ok"}
465
 
466
  @app.get("/niansuhai/v1/models/{model}/status", dependencies=[Depends(rate_limiter)])
467
  async def model_status(model: str, api_key: str = Depends(get_api_key)):
 
468
  logger.info(f"Model status requested for '{model}' by API key: {api_key}")
469
  if model in Blackbox.models:
470
  return {"model": model, "status": "available"}