feat: add durable document indexing pipeline

This commit is contained in:
gqt
2026-07-13 11:32:14 +08:00
parent eebcd5d6a7
commit 303116f950
12 changed files with 598 additions and 1 deletions
+56
View File
@@ -0,0 +1,56 @@
import asyncio
from sqlalchemy import select
from sqlalchemy.ext.asyncio import async_sessionmaker
from kbqa.documents.models import Chunk, Document
from kbqa.rag.embeddings import EmbeddingProvider
from kbqa.rag.types import SourceCandidate
from kbqa.rag.vector_store import MilvusVectorStore
class KnowledgeRetriever:
def __init__(
self,
embeddings: EmbeddingProvider,
vector_store: MilvusVectorStore,
session_factory: async_sessionmaker,
) -> None:
self.embeddings = embeddings
self.vector_store = vector_store
self.session_factory = session_factory
async def retrieve(self, query: str, top_k: int) -> list[SourceCandidate]:
vector = await self.embeddings.embed_query(query)
candidate_limit = max(top_k * 3, top_k)
hits = await asyncio.to_thread(self.vector_store.search, vector, candidate_limit)
if not hits:
return []
ids = [hit.chunk_id for hit in hits]
async with self.session_factory() as session:
rows = await session.execute(
select(Chunk, Document)
.join(Document, Document.id == Chunk.document_id)
.where(Chunk.id.in_(ids), Document.status == "indexed")
)
lookup = {chunk.id: (chunk, document) for chunk, document in rows}
sources: list[SourceCandidate] = []
for hit in hits:
record = lookup.get(hit.chunk_id)
if record is None:
continue
chunk, document = record
sources.append(
SourceCandidate(
chunk_id=chunk.id,
document_id=document.id,
filename=document.filename,
order_index=chunk.order_index,
page_number=chunk.page_number,
content=chunk.content,
score=hit.score,
)
)
if len(sources) == top_k:
break
return sources