feat(rag): lite-model document summaries — non-markdown docs summarized at import, summary chunk retrieves and resolves to the full source doc
This commit is contained in:
+12
-1
@@ -56,6 +56,7 @@ _LEXICAL_SQL = text(
|
||||
d.content AS doc_content,
|
||||
d.content_hash AS content_hash,
|
||||
d.indexed_at AS indexed_at,
|
||||
c.is_summary AS is_summary,
|
||||
ts_rank(c.tsv, to_tsquery('english', :tsquery)) AS rank
|
||||
FROM chunks c
|
||||
JOIN documents d ON d.id = c.document_id
|
||||
@@ -75,6 +76,11 @@ class RetrievedChunk:
|
||||
* ``cosine`` — vector similarity ``1 − distance`` (the honesty-gate
|
||||
input; ``0.0`` for lexical-only hits that have no vector rank).
|
||||
* ``fts_hit`` — the chunk matched the question's OR-tsquery.
|
||||
* ``is_summary`` — True for the lite-model summary chunk (phase 30,
|
||||
position −1): its parent *is* the source document, so a summary hit
|
||||
resolves to the full source document through the unchanged
|
||||
chunk→document mapping (A7 revised). Default ``False`` keeps every
|
||||
ordinary content chunk valid.
|
||||
"""
|
||||
|
||||
chunk_id: uuid.UUID
|
||||
@@ -84,6 +90,7 @@ class RetrievedChunk:
|
||||
document: Document
|
||||
cosine: float = 0.0
|
||||
fts_hit: bool = False
|
||||
is_summary: bool = False
|
||||
|
||||
|
||||
def lexical_tsquery(question: str) -> str | None:
|
||||
@@ -148,7 +155,9 @@ def _vector_candidates(
|
||||
"""Top-*limit* chunks by pgvector cosine distance (``<=>``).
|
||||
|
||||
``cosine = 1 − distance``. Chunks whose embedding is still NULL
|
||||
(two-phase import in progress) are skipped.
|
||||
(two-phase import in progress) are skipped. Each candidate carries
|
||||
its ``Chunk.is_summary`` flag (phase 30) so a summary hit stays
|
||||
identifiable after fusion.
|
||||
"""
|
||||
distance = Chunk.embedding.cosine_distance(question_embedding)
|
||||
rows = db.execute(
|
||||
@@ -166,6 +175,7 @@ def _vector_candidates(
|
||||
score=0.0, # fused score is filled in by :func:`fuse`
|
||||
document=doc,
|
||||
cosine=round(1.0 - float(dist), 6),
|
||||
is_summary=chunk.is_summary,
|
||||
)
|
||||
for chunk, dist, doc in rows
|
||||
]
|
||||
@@ -205,6 +215,7 @@ def _lexical_candidates(db: Session, question: str, limit: int) -> list[Retrieve
|
||||
document=doc,
|
||||
cosine=0.0, # no vector rank — lexical-only hit
|
||||
fts_hit=True,
|
||||
is_summary=row.is_summary,
|
||||
)
|
||||
)
|
||||
return out
|
||||
|
||||
Reference in New Issue
Block a user