diff --git a/app/main.py b/app/main.py index cac379f..156c43c 100644 --- a/app/main.py +++ b/app/main.py @@ -2,6 +2,7 @@ import os import sys import logging import time +import json from dotenv import load_dotenv from fastapi import FastAPI, HTTPException, Depends, Request from starlette.responses import StreamingResponse @@ -58,31 +59,42 @@ async def startup_event(): @app.post("/v1/chat/completions") async def chat_completions( - request: IncomingRequest, + request: Request, settings: Settings = Depends(get_settings) ): """ This endpoint mimics the OpenAI Chat Completions API and supports both streaming and non-streaming responses, with detailed logging. """ - log_id = log_request(client_request=request.model_dump()) + # Read raw request body + raw_body = await request.body() + body_str = raw_body.decode('utf-8') + + # Log the raw client request + client_request = json.loads(body_str) + log_id = log_request(client_request=client_request) logger.info(f"Request body logged with ID: {log_id}") + # Parse into IncomingRequest model for validation and type safety + try: + request_obj = IncomingRequest(**client_request) + except Exception as e: + logger.error(f"Failed to parse request: {e}") + raise HTTPException(status_code=400, detail=f"Invalid request format: {str(e)}") + if not settings.REAL_LLM_API_KEY or not settings.REAL_LLM_API_URL: logger.error("REAL_LLM_API_KEY or REAL_LLM_API_URL is not configured.") raise HTTPException(status_code=500, detail="LLM API Key or URL is not configured.") - messages_to_llm = request.messages - if request.tools: - messages_to_llm = inject_tools_into_prompt(request.messages, request.tools) + messages_to_llm = request_obj.messages + if request_obj.tools: + messages_to_llm = inject_tools_into_prompt(request_obj.messages, request_obj.tools) # Handle streaming request - if request.stream: + if request_obj.stream: logger.info(f"Initiating streaming request for log ID: {log_id}") async def stream_and_log(): - import json - stream_content_buffer = [] raw_chunks = [] diff --git a/app/models.py b/app/models.py index 8f705b3..ffd6cf0 100644 --- a/app/models.py +++ b/app/models.py @@ -5,7 +5,9 @@ from typing import List, Dict, Any, Optional class ChatMessage(BaseModel): """Represents a single message in the chat history.""" role: str - content: str + content: Optional[str] = None + name: Optional[str] = None # For function role messages + tool_calls: Optional[List[Dict[str, Any]]] = None # For assistant messages with tool calls class Function(BaseModel): """Represents the function definition within a tool."""