- #11 VectorIndexProtocol for typed duck-typing of vector_index param - #10 Wrap all sync VectorIndex.query() calls in asyncio.to_thread - #9 Make vector_search async (consistent with to_thread wrapping) - #12 Replace module-level singleton with app.state.query_service - #13 InMemoryGraphDB.close(destroy=False) guard for test safety - #14 Parse dates with datetime.fromisoformat in list_cases sort Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
41 lines
1.2 KiB
Python
41 lines
1.2 KiB
Python
"""FastAPI app factory for the query API."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from contextlib import asynccontextmanager
|
|
|
|
from fastapi import FastAPI
|
|
|
|
from aucourt_ingest.api.errors import register_error_handlers
|
|
from aucourt_ingest.api.routes import router
|
|
from aucourt_ingest.api.service import QueryService
|
|
from aucourt_ingest.storage.graph_db import GraphDB
|
|
|
|
|
|
def create_app(graph_db: GraphDB, vector_index, max_tokens: int = 4000) -> FastAPI:
|
|
"""Create and configure the FastAPI app.
|
|
|
|
Args:
|
|
graph_db: GraphDB instance (InMemoryGraphDB or Neo4jGraphDB)
|
|
vector_index: VectorIndex instance (or duck-typed fake for tests)
|
|
max_tokens: Default token budget for juror context assembly
|
|
"""
|
|
query_service = QueryService(graph_db, vector_index, max_tokens)
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
yield
|
|
await graph_db.close()
|
|
|
|
app = FastAPI(
|
|
title="AuCourtIngest Query API",
|
|
description="Read-only juror RAG query API for Australian legal cases",
|
|
version="0.1.0",
|
|
lifespan=lifespan,
|
|
)
|
|
|
|
app.state.query_service = query_service
|
|
app.include_router(router)
|
|
register_error_handlers(app)
|
|
|
|
return app
|