feat: persist isolated vector snapshots and exact retrieval

This commit is contained in:
2026-10-16 09:52:02 +08:00
parent 1c07d9ed16
commit 5e5cba2698
24 changed files with 1729 additions and 20 deletions
+9 -2
View File
@@ -8,6 +8,7 @@ from app.db.session import get_db
from app.models import RetrievalRun
from app.schemas.catalog import Page
from app.schemas.retrieval import RetrievalRequest, RetrievalResponse
from app.schemas.vectors import VectorRetrievalResponse
from app.services.auth import require_admin
from app.services.retrieval import retrieve
@@ -20,7 +21,11 @@ def keyword_retrieval(payload: RetrievalRequest, db: Session = Depends(get_db)):
return retrieve(db, payload)
@router.get("/runs", response_model=Page[RetrievalResponse], dependencies=[Depends(require_admin)])
@router.get(
"/runs",
response_model=Page[RetrievalResponse | VectorRetrievalResponse],
dependencies=[Depends(require_admin)],
)
def list_runs(
page: int = Query(1, ge=1),
page_size: int = Query(20, ge=1, le=100),
@@ -41,7 +46,9 @@ def list_runs(
@router.get(
"/runs/{run_id}", response_model=RetrievalResponse, dependencies=[Depends(require_admin)]
"/runs/{run_id}",
response_model=RetrievalResponse | VectorRetrievalResponse,
dependencies=[Depends(require_admin)],
)
def read_run(run_id: UUID, db: Session = Depends(get_db)):
row = db.get(RetrievalRun, str(run_id))
+106
View File
@@ -0,0 +1,106 @@
from uuid import UUID
from fastapi import APIRouter, Depends, Query
from sqlalchemy import select
from sqlalchemy.orm import Session
from app.db.session import get_db
from app.models.vectors import EmbeddingSpace, VectorPublication, VectorVersion
from app.schemas.catalog import Page
from app.schemas.indexing import PublicationRead, PublishIndex
from app.schemas.vectors import (
ActiveVectors,
BuildVectors,
SpaceRead,
VectorRead,
VectorRequest,
VectorRetrievalResponse,
)
from app.services.auth import CurrentSession, require_admin
from app.services.catalog import page_result
from app.services.embedding_runtime import get_embedding_provider
from app.services.vectors import (
active_vectors,
build_vectors,
publish_vectors,
retrieve_vectors,
vector_or_404,
)
router = APIRouter(
prefix="/vector-indexes", tags=["vector-indexes"], dependencies=[Depends(require_admin)]
)
retrieval_router = APIRouter(tags=["retrieval"])
@router.post("", response_model=VectorRead, status_code=201)
def build(
payload: BuildVectors,
current: CurrentSession = Depends(require_admin),
db: Session = Depends(get_db),
provider=Depends(get_embedding_provider),
):
return build_vectors(db, payload.text_index_version_id, current.user.id, provider)
@router.get("", response_model=Page[VectorRead])
def versions(
page: int = Query(1, ge=1),
page_size: int = Query(20, ge=1, le=100),
db: Session = Depends(get_db),
):
return page_result(
db,
select(VectorVersion).order_by(VectorVersion.created_at.desc(), VectorVersion.id),
page,
page_size,
)
@router.get("/active", response_model=ActiveVectors)
def active(db: Session = Depends(get_db)):
return active_vectors(db)
@router.get("/spaces", response_model=Page[SpaceRead])
def spaces(
page: int = Query(1, ge=1),
page_size: int = Query(20, ge=1, le=100),
db: Session = Depends(get_db),
):
return page_result(db, select(EmbeddingSpace).order_by(EmbeddingSpace.id), page, page_size)
@router.get("/publications", response_model=Page[PublicationRead])
def publications(
page: int = Query(1, ge=1),
page_size: int = Query(20, ge=1, le=100),
db: Session = Depends(get_db),
):
return page_result(
db, select(VectorPublication).order_by(VectorPublication.generation.desc()), page, page_size
)
@router.get("/{version_id}", response_model=VectorRead)
def read_version(version_id: UUID, db: Session = Depends(get_db)):
return vector_or_404(db, str(version_id))
@router.post("/{version_id}/publish", response_model=ActiveVectors)
def publish(
version_id: UUID,
payload: PublishIndex,
current: CurrentSession = Depends(require_admin),
db: Session = Depends(get_db),
):
return publish_vectors(db, version_id, payload.expected_generation, current.user.id)
@retrieval_router.post("/retrieval/vector", response_model=VectorRetrievalResponse)
def search(
payload: VectorRequest,
db: Session = Depends(get_db),
provider=Depends(get_embedding_provider),
):
return retrieve_vectors(db, payload, provider)