ayanshuDS
Deploy to HF without binaries
685cc60
Raw
History Blame Contribute Delete
2.94 kB
import os
import sys
import asyncio
from contextlib import asynccontextmanager
from dotenv import load_dotenv
# Psycopg 3 async requires SelectorEventLoop on Windows
if sys.platform == "win32":
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from psycopg_pool import AsyncConnectionPool
from langgraph.checkpoint.postgres.aio import AsyncPostgresSaver
from src.react_agent.agent import get_agent
from src.api.routes import router as chat_router
# Load environment variables (such as DATABASE_URL and GOOGLE_API_KEY)
load_dotenv()
@asynccontextmanager
async def lifespan(app: FastAPI):
database_url = os.getenv("DATABASE_URL")
if not database_url:
raise ValueError("DATABASE_URL environment variable is not set")
# Establish persistent connection pool to Supabase
async with AsyncConnectionPool(
conninfo=database_url,
max_size=10,
kwargs={"autocommit": True}
) as pool:
app.state.pool = pool
checkpointer = AsyncPostgresSaver(pool)
# Create checkpoint tables if they don't exist (migrations)
await checkpointer.setup()
# Create custom chat_sessions table for thread names
async with pool.connection() as conn:
async with conn.cursor() as cur:
await cur.execute("""
CREATE TABLE IF NOT EXISTS chat_sessions (
thread_id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
title TEXT NOT NULL,
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
)
""")
await cur.execute("""
CREATE INDEX IF NOT EXISTS idx_chat_sessions_user_id_updated_at
ON chat_sessions (user_id, updated_at DESC)
""")
# Compile agent with the persistent Postgres checkpointer
app.state.agent = get_agent(checkpointer)
yield
app = FastAPI(
title="Vectorless-RAG API Backend",
description="Local FastAPI backend serving the LangGraph ReAct Legal Assistant",
version="1.0.0",
lifespan=lifespan
)
# Enable CORS for Next.js frontend calls
allowed_origins_env = os.getenv("ALLOWED_ORIGINS", "*")
if allowed_origins_env.strip() == "*":
allowed_origins = ["*"]
else:
allowed_origins = [
o.strip() for o in allowed_origins_env.split(",") if o.strip()
]
app.add_middleware(
CORSMiddleware,
allow_origins=allowed_origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Include the routes
app.include_router(chat_router, prefix="/api")
@app.get("/")
def read_root():
return {
"status": "online",
"message": "Vectorless-RAG Legal Assistant API is fully operational locally."
}