pay-equity-for-eu / src /backend /api /endpoints.py
Franskaman110's picture
Cold start once the user answers the first question
9e71f85
Raw
History Blame Contribute Delete
3.59 kB
"""API endpoints registered on the Gradio Server.
Every endpoint uses ``@app.api(...)`` so it runs through Gradio's queue
(concurrency-managed, ZeroGPU-safe) and is reachable from ``gradio_client``
and the frontend JS client.
All endpoints are placeholders: they call the placeholder backend functions
and return canned data. No real parsing/embedding/RAG is wired yet.
"""
from __future__ import annotations
from gradio import Server
from gradio.data_classes import FileData
from ..indexing.store import BACKEND
from ..parsing.directive import parse_directive
from ..parsing.lonstatistik import parse_lonstatistik
from ..rag import answer
from ..schemas import (
ChatMessage,
Chunk,
IndexStatus,
ParseResult,
Profile,
)
def register(app: Server) -> None:
"""Register all backend endpoints on the given Gradio Server."""
@app.api(name="parse_directive")
def parse_directive_endpoint(lang: str = "en") -> list[dict]:
"""Parse Directive 2023/970 into article-level chunks (placeholder)."""
chunks: list[Chunk] = parse_directive(lang=lang)
return [c.model_dump() for c in chunks]
@app.api(name="parse_lonstatistik")
def parse_lonstatistik_endpoint(
file: FileData, source: str = "unknown"
) -> dict:
"""OCR/table-parse an uploaded lønstatistik PDF (placeholder)."""
result: ParseResult = parse_lonstatistik(
file_path=file["path"] if file else None, source=source
)
return result.model_dump()
@app.api(name="index_documents")
def index_documents_endpoint(source: str = "directive") -> dict:
"""Report the loaded vector index status.
The index is built offline (``scripts/build_index.py``); this endpoint
reports how many chunks are loaded, not a live (re)build.
"""
from ..indexing.store import VectorStore
store = VectorStore()
persisted = store.load()
return IndexStatus(
source=source,
indexed_chunks=len(store),
backend=BACKEND,
persisted=persisted,
).model_dump()
@app.api(name="warmup")
def warmup_endpoint() -> dict:
"""Pre-load the chat models (embedder + LLM) on GPU.
Fired by the frontend when onboarding starts, so the model is ready by
the time the user reaches the chat. Best-effort: returns a status dict and
never errors the UI.
"""
from ..rag import warmup
return warmup()
@app.api(name="chat")
def chat_endpoint(messages: list[dict], lang: str = "en", context: str = "") -> dict:
"""Chat with the RAG assistant: retrieve grounded chunks, cite sources.
Returns the full ``{reply, citations, disclaimer}`` in one response.
``context`` is the user's compact salary-dashboard summary, injected so
the answer can be specific to their situation.
"""
msgs = [ChatMessage(**m) for m in messages]
return answer(msgs, lang=lang, context=context or None).model_dump()
@app.api(name="dashboard")
def dashboard_endpoint(profile: dict) -> dict:
"""Build the profile-driven salary dashboard (structured IDA retrieval).
Takes the onboarding answers (a ``Profile``) and returns the fused
``Dashboard`` — per-axis comparison cells, reliability-gated, projected
to 2026, with the user's percentile and gap. CPU-only (no embedding).
"""
from ..fusion import build_dashboard
return build_dashboard(Profile(**profile)).model_dump()