Spaces:
Sleeping
Sleeping
| """services/copilot/api.py — FastAPI router for the RAG copilot. | |
| Mounted at /api/v1/copilot in app/main.py. Follows the same auth pattern as | |
| the rest of this backend (require_api_key — see app/security.py) since | |
| there's no per-user auth yet. | |
| """ | |
| from __future__ import annotations | |
| import logging | |
| from fastapi import APIRouter, Depends, HTTPException, status | |
| from sqlalchemy.ext.asyncio import AsyncSession | |
| from app.config import Settings, get_settings | |
| from app.database import get_db | |
| from app.security import rate_limit, require_api_key | |
| from app.services.copilot import db as copilot_db | |
| from app.services.copilot.engine import answer_chat | |
| from app.services.copilot.models import ChatRequest, ChatResponse | |
| logger = logging.getLogger(__name__) | |
| router = APIRouter(prefix="/copilot", tags=["Copilot"]) | |
| async def chat( | |
| request: ChatRequest, | |
| session: AsyncSession = Depends(get_db), | |
| settings: Settings = Depends(get_settings), | |
| ) -> ChatResponse: | |
| try: | |
| return await answer_chat(session, request, settings) | |
| except Exception as exc: | |
| # copilot_chunks / pgvector may be entirely unavailable in this | |
| # deployment (see database.py::_create_copilot_table_if_possible) — | |
| # surface a clear 503 rather than a generic 500. | |
| logger.exception("Copilot chat failed: %s", exc) | |
| raise HTTPException( | |
| status_code=status.HTTP_503_SERVICE_UNAVAILABLE, | |
| detail="Copilot is temporarily unavailable. Please try again shortly.", | |
| ) from exc | |
| async def copilot_health(session: AsyncSession = Depends(get_db)) -> dict: | |
| try: | |
| count = await copilot_db.chunk_count(session) | |
| return {"status": "ready" if count > 0 else "empty", "indexed_chunks": count} | |
| except Exception as exc: | |
| return {"status": "unavailable", "detail": str(exc)} | |