From 2f172ddaf9e6a69ffc3a065639455cd3ce1fbac1 Mon Sep 17 00:00:00 2001 From: Danny Date: Fri, 30 Jan 2026 10:47:03 -0600 Subject: [PATCH] feat: auto-build FAISS index on startup if missing Add lifespan handler that checks for FAISS index at startup and automatically builds it if not found. This ensures the service works on fresh deployments without manual indexing. Co-Authored-By: Claude Opus 4.5 --- app/main.py | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/app/main.py b/app/main.py index c88d992..a2b04ca 100644 --- a/app/main.py +++ b/app/main.py @@ -1,5 +1,6 @@ import logging import uuid +from contextlib import asynccontextmanager from fastapi import FastAPI, HTTPException, BackgroundTasks from fastapi.middleware.cors import CORSMiddleware @@ -7,7 +8,7 @@ from fastapi.responses import StreamingResponse from app.auth import ServiceAuthDependency from app.config import settings, MAX_MESSAGE_LENGTH -from app.embeddings import RetrieverDependency, IndexerDependency, get_retriever, reset_retriever +from app.embeddings import RetrieverDependency, IndexerDependency, get_retriever, reset_retriever, get_indexer from app.embeddings.retriever import RetrievedChunk from app.intent import IntentClassifierDependency from app.llm import AdapterDependency, LLMError, llm_exception_to_http @@ -31,11 +32,35 @@ logging.basicConfig( ) logger = logging.getLogger(__name__) + +@asynccontextmanager +async def lifespan(app: FastAPI): + """Startup and shutdown lifecycle management.""" + # Startup: auto-index if FAISS index is missing + retriever = get_retriever() + if not retriever.is_loaded: + logger.info("FAISS index not found, building index on startup...") + try: + indexer = get_indexer() + result = await indexer.build_index() + reset_retriever() # Reset to load newly built index + logger.info(f"Startup indexing completed: {result.chunks_indexed} chunks from {result.artifacts_processed} artifacts") + except Exception as e: + logger.error(f"Startup indexing failed: {e}") + else: + logger.info(f"FAISS index loaded: {retriever.index_size} vectors") + + yield # App runs here + + # Shutdown: nothing to clean up + + # Create FastAPI app app = FastAPI( title="Tyndale AI Service", description="LLM Chat Service for algorithmic trading support", version="0.1.0", + lifespan=lifespan, ) # Add CORS middleware