diff --git a/app.py b/app.py index 4772c92..cf8d2ca 100644 --- a/app.py +++ b/app.py @@ -1,6 +1,6 @@ import os from typing import Optional -from fastapi import FastAPI, HTTPException, Security, Depends +from fastapi import FastAPI, HTTPException, Security, Depends, Request from fastapi.security import APIKeyHeader from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse @@ -27,9 +27,23 @@ import os from PyPDF2 import PdfReader from config import QUIZ_TYPES from config import Config +import logging +import time # Load environment variables load_dotenv() -API_KEY = os.getenv("API_KEY_ACCESS") +from config import Config +API_KEY = Config.API_KEY_ACCESS + +# Configure logging +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' +) +logger = logging.getLogger(__name__) + +# Also configure uvicorn logger +uvicorn_logger = logging.getLogger("uvicorn.access") +uvicorn_logger.setLevel(logging.INFO) base_path = os.path.join("data", "config_files") QUESTIONS_PATH = os.path.join(base_path, "questions.json") @@ -46,6 +60,40 @@ app = FastAPI( version="1.0.0" ) +# Add request logging middleware +@app.middleware("http") +async def log_requests(request: Request, call_next): + start_time = time.time() + + # Log incoming request (using both logger and print for visibility) + log_msg = f"🔥 INCOMING REQUEST: {request.method} {request.url}" + logger.info(log_msg) + print(log_msg) + + + + # Get request body for POST requests + if request.method == "POST": + body = await request.body() + body_msg = f"🔥 Request Body: {body.decode('utf-8') if body else 'Empty'}" + logger.info(body_msg) + print(body_msg) + + # Re-create request with body for downstream processing + async def receive(): + return {"type": "http.request", "body": body} + request._receive = receive + + response = await call_next(request) + + # Log response + process_time = time.time() - start_time + response_msg = f"🔥 RESPONSE: {response.status_code} - Time: {process_time:.4f}s" + logger.info(response_msg) + print(response_msg) + + return response + # Add CORS middleware app.add_middleware( CORSMiddleware, @@ -288,7 +336,7 @@ async def generate_pdf_endpoint( if request.form_id: print(f"Fetching form response for form_id: {request.form_id}") # Debugging print try: - x_api_key = os.getenv("BACKEND_XAPI_KEY") + x_api_key = Config.BACKEND_XAPI_KEY url = f"{backend_base_url}/v3/api/custom/theme-document/answer/{request.form_id}?x-project={x_api_key}" result = requests.get(url) result.raise_for_status() # Ensure we raise an error for bad responses diff --git a/src/llm.py b/src/llm.py index 17834a7..1dcea6e 100644 --- a/src/llm.py +++ b/src/llm.py @@ -62,6 +62,8 @@ def setup_prompt_template(theme: int, resume: str,full_history=None,form_respons ("system", chat_prompt(theme, resume,full_history,form_response,generate_theme)), MessagesPlaceholder(variable_name="messages") ]) + + def fetch_conversation_history(conversation_id: str) -> List[Message]: """ Fetch conversation history from the API using the conversation ID. @@ -74,18 +76,54 @@ def fetch_conversation_history(conversation_id: str) -> List[Message]: response = requests.get(url) response.raise_for_status() # Raise an error for bad responses data = response.json()["data"] # First JSON parse - data = json.loads(json.loads(data)) + + if isinstance(data, str): + print("Data is a string, parsing as JSON...") + data = json.loads(data) + + # Parse the API response into Message objects messages = [] - for item in data: - role = item.get("role", "unknown") - content = item.get("content", "") - timestamp = datetime.now().isoformat() # Use current timestamp if not provided - messages.append(Message(role=role, content=content)) + + # Check if data exists and is a list + if data and isinstance(data, list): + for item in data: + + + # Check if item is a dictionary + if isinstance(item, dict): + role = item.get("role", "unknown") + content = item.get("content", "") + timestamp = datetime.now().isoformat() # Use current timestamp if not provided + messages.append(Message(role=role, content=content)) + elif isinstance(item, str): + # If item is a string, it might be JSON that needs parsing + try: + parsed_item = json.loads(item) + if isinstance(parsed_item, dict): + role = parsed_item.get("role", "unknown") + content = parsed_item.get("content", "") + messages.append(Message(role=role, content=content)) + else: + print(f"Parsed item is not a dict: {parsed_item}") + except json.JSONDecodeError as json_err: + print(f"Failed to parse JSON string: {item}, error: {json_err}") + else: + print(f"Unexpected item type: {type(item)} for item: {item}") + else: + print(f"No data or data is not a list. Data: {data}") + return messages + except requests.RequestException as e: print(f"Error fetching conversation history: {e}") return [] + except KeyError as e: + print(f"Expected key not found in response: {e}") + return [] + except Exception as e: + print(f"Unexpected error: {e}") + return [] def convert_to_langchain_messages(messages: List[Message]) -> List[HumanMessage | AIMessage]: @@ -130,6 +168,8 @@ def ai_chat(query: str, conversation_id: str, theme_id: int, resume: str, full_h # Fetch conversation history from the API history = fetch_conversation_history(conversation_id) + + print(history) config = {"configurable": {"thread_id": conversation_id}} language = "English"