feat(evidence): use server-side Qdrant BM25 retrieval
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
import re
|
||||
|
||||
from tht.evidence.corpus.store import CorpusStore
|
||||
from tht.ports.vector import VectorStoreError
|
||||
|
||||
|
||||
class CorpusWorkspaceMismatchError(RuntimeError):
|
||||
@@ -12,12 +13,27 @@ class CorpusWorkspaceMismatchError(RuntimeError):
|
||||
class ActiveEvidenceSearcher:
|
||||
"""Searcher facade that enforces ACTIVE generation predicates before LIMIT."""
|
||||
|
||||
def __init__(self, corpus: CorpusStore, delegate, expected_workspace_id: str | None = None):
|
||||
def __init__(
|
||||
self,
|
||||
corpus: CorpusStore,
|
||||
delegate,
|
||||
expected_workspace_id: str | None = None,
|
||||
evidence_language: str = "italian",
|
||||
):
|
||||
self.corpus = corpus
|
||||
self.delegate = delegate
|
||||
self.expected_workspace_id = expected_workspace_id
|
||||
self.evidence_language = evidence_language
|
||||
|
||||
def search(self, embedding, top_n=10, kinds=None, metadata_filter=None):
|
||||
def search(
|
||||
self,
|
||||
embedding,
|
||||
top_n=10,
|
||||
kinds=None,
|
||||
metadata_filter=None,
|
||||
query_text=None,
|
||||
query_language=None,
|
||||
):
|
||||
requested = set(kinds) if kinds is not None else {
|
||||
"schema_table", "schema_column", "evidence", "memory", "solved_question",
|
||||
}
|
||||
@@ -59,9 +75,13 @@ class ActiveEvidenceSearcher:
|
||||
generation = mapping.get(document.document_id, manifest.vector_generation)
|
||||
if generation:
|
||||
by_generation.setdefault(generation, []).append(document.document_id)
|
||||
if by_generation and (not isinstance(query_text, str) or query_text.strip() == ""):
|
||||
raise VectorStoreError("Evidence hybrid query text is required")
|
||||
for generation, document_ids in sorted(by_generation.items()):
|
||||
hits.extend(self.delegate.search(
|
||||
embedding, top_n=top_n, kinds=["evidence"],
|
||||
query_text=query_text,
|
||||
query_language=query_language or self.evidence_language,
|
||||
metadata_filter={
|
||||
"vector_generation": generation,
|
||||
"document_ids": sorted(document_ids),
|
||||
@@ -73,7 +93,11 @@ class ActiveEvidenceSearcher:
|
||||
|
||||
def active_searcher(cfg, delegate, *, workspace_id: str | None = None):
|
||||
corpus_root = cfg.paths.artifacts.parent / "corpus"
|
||||
return ActiveEvidenceSearcher(CorpusStore(corpus_root), delegate, workspace_id)
|
||||
languages = {"en": "english", "it": "italian"}
|
||||
language = languages.get(getattr(cfg, "language", "en"))
|
||||
if language is None:
|
||||
raise VectorStoreError("workspace language is unsupported for Qdrant BM25")
|
||||
return ActiveEvidenceSearcher(CorpusStore(corpus_root), delegate, workspace_id, language)
|
||||
|
||||
|
||||
def validate_corpus_workspace(cfg, workspace_id: str) -> None:
|
||||
|
||||
Reference in New Issue
Block a user