diff --git a/app/__pycache__/main.cpython-312.pyc b/app/__pycache__/main.cpython-312.pyc index 9932cb9..4c7ce62 100644 Binary files a/app/__pycache__/main.cpython-312.pyc and b/app/__pycache__/main.cpython-312.pyc differ diff --git a/app/db/__pycache__/db.cpython-312.pyc b/app/db/__pycache__/db.cpython-312.pyc index f367c0d..3a9580d 100644 Binary files a/app/db/__pycache__/db.cpython-312.pyc and b/app/db/__pycache__/db.cpython-312.pyc differ diff --git a/app/db/db.py b/app/db/db.py index ca7870b..e904339 100644 --- a/app/db/db.py +++ b/app/db/db.py @@ -1,5 +1,4 @@ import os -from pathlib import Path from typing import Annotated from fastapi import Depends diff --git a/app/main.py b/app/main.py index a017939..7a58476 100644 --- a/app/main.py +++ b/app/main.py @@ -1,6 +1,4 @@ import io -import logging -import os import pandas as pd from db.db import Base, db_dependency, engine @@ -44,6 +42,7 @@ class QueryRequest(BaseModel): } } + class CompanyQueryRequest(BaseModel): question: str @@ -54,6 +53,7 @@ class CompanyQueryRequest(BaseModel): } } + @app.get("/") def health(): return {"Hello": "World"} @@ -122,7 +122,7 @@ async def query_investors(request: QueryRequest): - "Healthcare investors in Europe" """ processor = QueryProcessor() - results = processor.process_query(request.question) + results = await processor.process_query(request.question) return results @@ -143,7 +143,7 @@ async def query_companies(request: CompanyQueryRequest): - "European startups founded after 2019" """ processor = CompanyQueryProcessor() - results = processor.process_query(request.question) + results = await processor.process_query(request.question) return results diff --git a/app/services/__pycache__/querying.cpython-312.pyc b/app/services/__pycache__/querying.cpython-312.pyc index 4221e66..056a5e3 100644 Binary files a/app/services/__pycache__/querying.cpython-312.pyc and b/app/services/__pycache__/querying.cpython-312.pyc differ diff --git a/app/services/company_querying.py b/app/services/company_querying.py index e002af3..aabc49c 100644 --- a/app/services/company_querying.py +++ b/app/services/company_querying.py @@ -1,3 +1,4 @@ +import asyncio import hashlib import logging import os @@ -116,11 +117,18 @@ Return ONLY the SQL query, no explanations or markdown.""", """Generate cache key from normalized question.""" return hashlib.md5(question.lower().strip().encode()).hexdigest() - def process_query(self, question: str) -> PaginatedResponse[CompanyData]: - """Process a query by generating and executing SQL directly. + # synchronous helper is provided below as `_process_query_sync` and an + # async wrapper `process_query` runs it in a thread. This keeps the + # FastAPI event loop non-blocking while reusing the existing sync code. + async def process_query(self, question: str) -> PaginatedResponse[CompanyData]: + """Async wrapper for process_query. Runs blocking work in a thread to avoid + blocking the event loop. + """ + return await asyncio.to_thread(self._process_query_sync, question) - Args: - question: The natural language query to process + def _process_query_sync(self, question: str) -> PaginatedResponse[CompanyData]: + """Synchronous implementation of process_query. This is run in a thread by + the async wrapper above. """ cache_key = self._get_cache_key(question) diff --git a/app/services/querying.py b/app/services/querying.py index 2a566eb..2a8bca5 100644 --- a/app/services/querying.py +++ b/app/services/querying.py @@ -1,3 +1,4 @@ +import asyncio import hashlib import logging import os @@ -126,14 +127,19 @@ Return ONLY the SQL query, no explanations or markdown.""", """Generate cache key from normalized question.""" return hashlib.md5(question.lower().strip().encode()).hexdigest() - def process_query( + async def process_query( self, question: str, project_id: Optional[int] = None ) -> PaginatedResponse[InvestmentResponse]: - """Process a query by generating and executing SQL directly. + """Async wrapper for process_query. Runs blocking work in a thread to avoid + blocking the event loop. + """ + return await asyncio.to_thread(self._process_query_sync, question, project_id) - Args: - question: The natural language query to process - project_id: Optional project ID for compatibility scoring + def _process_query_sync( + self, question: str, project_id: Optional[int] = None + ) -> PaginatedResponse[InvestmentResponse]: + """Synchronous implementation of process_query. This is run in a thread by + the async wrapper above. """ cache_key = self._get_cache_key(question)