diff --git a/backend/app/api/routes/chat.py b/backend/app/api/routes/chat.py index 0f76a7a..72aa96a 100644 --- a/backend/app/api/routes/chat.py +++ b/backend/app/api/routes/chat.py @@ -6,8 +6,6 @@ from pydantic import BaseModel, Field from sse_starlette.sse import EventSourceResponse -from app.services.llm import get_english_translation, get_response_stream_async, generate_chat_title_async -from app.services.embedding import embedding_service from app.services.database import get_client from app.core.rate_limit import limiter @@ -38,6 +36,9 @@ async def generate_chat_events(request: Request, query: str, history: List[Histo Generator function that streams SSE events. It yields 'metadata' first, then chunks of 'content'. """ + from app.services.llm import get_english_translation, get_response_stream_async + from app.services.embedding import embedding_service + # 1. Translate Korean query to English // Note: We don't translate history here to save costs and reduce latency try: english_query = await asyncio.wait_for( @@ -153,6 +154,8 @@ async def chat_title_endpoint(request: Request, title_request: TitleRequest): """ Endpoint for generating a short chat room title based on the first user query. """ + from app.services.llm import generate_chat_title_async + query = title_request.query.strip() if not query: return {"title": DEFAULT_CHAT_TITLE} diff --git a/backend/app/main.py b/backend/app/main.py index 9eb9212..4cf370f 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -6,6 +6,7 @@ from app.api.routes import chat from app.core.rate_limit import limiter +import asyncio from contextlib import asynccontextmanager import logging @@ -48,6 +49,8 @@ def _on_preload_done(task: asyncio.Task): await asyncio.wait_for(asyncio.shield(preload_task), timeout=3.0) except asyncio.TimeoutError: logger.warning("Preload task did not finish before shutdown.") + except Exception as e: + logger.exception("Exception occurred while waiting for preload task during shutdown.") app = FastAPI( title="PhiloRAG API", @@ -83,10 +86,13 @@ async def readiness_check(): return JSONResponse({"status": "not_ready"}, status_code=503) if preload_task.cancelled(): + logger.warning("Preload task was cancelled during readiness check") return JSONResponse({"status": "failed"}, status_code=503) try: preload_task.result() # re-raises if failed - return {"status": "ready"} - except Exception: + except Exception as e: + logger.warning("Preload task failed during readiness check: %s", e) return JSONResponse({"status": "failed"}, status_code=503) + else: + return {"status": "ready"} diff --git a/backend/tests/e2e/test_chat_endpoint.py b/backend/tests/e2e/test_chat_endpoint.py index f67d651..6ff131f 100644 --- a/backend/tests/e2e/test_chat_endpoint.py +++ b/backend/tests/e2e/test_chat_endpoint.py @@ -10,10 +10,10 @@ def test_health_check(): assert response.status_code == 200 assert response.json() == {"status": "healthy"} -@patch("app.api.routes.chat.embedding_service.agenerate_embedding") +@patch("app.services.embedding.EmbeddingService.agenerate_embedding") @patch("app.api.routes.chat._search_documents") -@patch("app.api.routes.chat.get_english_translation") -@patch("app.api.routes.chat.get_response_stream_async") +@patch("app.services.llm.get_english_translation") +@patch("app.services.llm.get_response_stream_async") def test_chat_endpoint_success(mock_stream, mock_translate, mock_search, mock_embed): # Setup mocks mock_translate.return_value = "What is life?" diff --git a/backend/tests/integration/test_supabase_match.py b/backend/tests/integration/test_supabase_match.py index df1832f..165a4d4 100644 --- a/backend/tests/integration/test_supabase_match.py +++ b/backend/tests/integration/test_supabase_match.py @@ -9,10 +9,10 @@ @pytest.mark.asyncio async def test_supabase_match_integration(): # 1. We mock the embedding service to return a dummy vector - with patch("app.api.routes.chat.embedding_service.agenerate_embedding") as mock_embed, \ + with patch("app.services.embedding.EmbeddingService.agenerate_embedding") as mock_embed, \ patch("app.api.routes.chat._search_documents") as mock_search, \ - patch("app.api.routes.chat.get_english_translation") as mock_translate, \ - patch("app.api.routes.chat.get_response_stream_async") as mock_stream: + patch("app.services.llm.get_english_translation") as mock_translate, \ + patch("app.services.llm.get_response_stream_async") as mock_stream: mock_translate.return_value = "English Question" mock_embed.return_value = [0.1, 0.2, 0.3]