RandomZ / app /api /canonical_rollout.py
StormShadow308's picture
Added canonical rollout functionality, including new API endpoints and request/response models for upgrading indexed content. Updated main application to include the canonical rollout router. Introduced a new document loading function for raw documents in the ingestion pipeline. This enhances content management and semantic upgrades across the application.
569bceb
Raw
History Blame Contribute Delete
2.73 kB
"""Canonical paragraph rollout: scan indexed chunks, optionally apply replacement to .docx."""
import logging
from fastapi import APIRouter, Depends, HTTPException, Request
from sqlalchemy.ext.asyncio import AsyncSession
from app.api.rate_limit import check_generate, check_read
from app.db.database import get_db
from app.models.schemas import (
CanonicalApplyRequest,
CanonicalApplyResponse,
CanonicalRolloutRequest,
CanonicalRolloutResponse,
)
from app.services.canonical_rollout import (
apply_canonical_replacement,
scan_canonical_rollout,
)
logger = logging.getLogger(__name__)
router = APIRouter()
@router.post(
"/content/canonical-scan",
response_model=CanonicalRolloutResponse,
summary="Find chunks semantically similar to a canonical paragraph",
)
async def canonical_scan(
request: Request,
body: CanonicalRolloutRequest,
db: AsyncSession = Depends(get_db),
_: None = Depends(check_read),
) -> CanonicalRolloutResponse:
"""Discover candidate chunks for upgrading to an improved standard paragraph.
Uses the same embedding search as the rest of the RAG stack, plus token Jaccard
versus the canonical text to reduce false positives. Proposed text is either
the canonical paragraph or an LLM merge (``adapt_with_llm``) when an API key is set.
Review ``compatibility`` (high / review / low) before any automatic apply policy.
"""
tenant_id: str = request.state.tenant_id
try:
return await scan_canonical_rollout(db, tenant_id, body)
except Exception as exc: # noqa: BLE001
logger.exception("canonical-scan failed: %s", exc)
raise HTTPException(status_code=500, detail="Canonical scan failed") from exc
@router.post(
"/content/canonical-apply",
response_model=CanonicalApplyResponse,
summary="Replace one chunk in a .docx and re-index (destructive layout)",
)
async def canonical_apply(
request: Request,
body: CanonicalApplyRequest,
db: AsyncSession = Depends(get_db),
_: None = Depends(check_generate),
) -> CanonicalApplyResponse:
"""Apply a replacement string for one indexed chunk.
Rebuilds the Word file as plain paragraphs (tables/complex layout are not preserved),
deletes old vector rows for the document, and re-runs ingestion.
**Requires** ``confirm_destructive_docx: true``.
"""
tenant_id: str = request.state.tenant_id
try:
return await apply_canonical_replacement(db, tenant_id, body)
except HTTPException:
raise
except Exception as exc: # noqa: BLE001
logger.exception("canonical-apply failed: %s", exc)
raise HTTPException(status_code=500, detail="Canonical apply failed") from exc