Ukweli / app /api /feedback.py
Benard John
feat: implement feedback API endpoint and add new frontend views for status, legal, and documentation pages.
2a72aeb
Raw
History Blame Contribute Delete
2.29 kB
"""
Ukweli — Feedback Endpoint
POST /feedback — Collect user ratings and corrections on RAG responses.
Requires registered or higher tier (per Endpoint Security Matrix).
"""
from __future__ import annotations
import logging
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from app.api.auth import AuthContext, require_auth
from app.db.session import get_db_session
from app.models.database import Feedback, QueryLog
from app.models.enums import AuthTier
from app.models.schemas import FeedbackRequest, FeedbackResponse
logger = logging.getLogger("ukweli.api.feedback")
router = APIRouter(tags=["Feedback"])
@router.post("/feedback", response_model=FeedbackResponse)
async def submit_feedback(
request: FeedbackRequest,
db: AsyncSession = Depends(get_db_session),
auth: AuthContext = Depends(require_auth),
) -> FeedbackResponse:
"""
Submit feedback on a query response.
Validates that the query_id exists before recording.
"""
# Verify tier requirements (Registered or higher)
if auth.tier == AuthTier.PUBLIC.value:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Feedback submission requires a registered account or API key.",
)
# Verify the query exists
result = await db.execute(
select(QueryLog.id).where(QueryLog.id == request.query_id)
)
query_exists = result.scalar_one_or_none()
if query_exists is None:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Query ID {request.query_id} not found.",
)
# Create feedback record
feedback = Feedback(
query_id=request.query_id,
rating=request.rating.value,
correction=request.correction,
suggested_citation=request.suggested_citation,
review_status="pending",
)
db.add(feedback)
await db.flush()
logger.info(
"Feedback recorded: query_id=%s, tier=%s, rating=%d, has_correction=%s",
request.query_id,
auth.tier,
request.rating.value,
request.correction is not None,
)
return FeedbackResponse(status="recorded", review_status="pending")