feat(gateway): stadio rerank con catena di fallback resiliente (frigate→brain)
- gateway/rerank.py: catena da RERANK_CHAIN (JSON, per-nodo key+timeout),
cooldown 60s sui nodi falliti, score sigmoide [0,1], degrada con grazia
all'ordine di fusione se tutti i nodi sono giù
- routes: /v1/memories:search applica il rerank post-fusione (fetch esteso a
RERANK_CANDIDATES), risposta con rerank{used,backend,took_ms}, flag
per-query rerank=false; /v1/version espone lo stato rerank
- store: search() accetta limit esteso; models: SearchIn.rerank
- metrics: qmem_rerank_calls_total + durata per backend
- test: 10 nuovi (fallback, cooldown, degradazione, integrazione) — 46 pass
This commit is contained in:
+8
-6
@@ -2,7 +2,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
from typing import Any
|
||||
from typing import Any, Optional
|
||||
|
||||
from qdrant_client.http import models as qm
|
||||
|
||||
@@ -27,25 +27,27 @@ def search_filter(body: SearchIn) -> qm.Filter | None:
|
||||
return None
|
||||
|
||||
|
||||
def search(qdrant: Any, collection: str, body: SearchIn, vector: list[float], sparse: Any) -> list[Any]:
|
||||
def search(qdrant: Any, collection: str, body: SearchIn, vector: list[float], sparse: Any, limit: Optional[int] = None) -> list[Any]:
|
||||
"""Ricerca ibrida o densa. Con reranking attivo limit > top_k per dare candidati extra allo stadio di rerank."""
|
||||
eff_limit = limit if limit is not None else body.top_k
|
||||
qfilter = search_filter(body)
|
||||
if body.hybrid and sparse is not None:
|
||||
return qdrant.query_points(
|
||||
collection_name=collection,
|
||||
prefetch=[
|
||||
qm.Prefetch(query=vector, using="", limit=body.top_k * 4, score_threshold=body.min_score),
|
||||
qm.Prefetch(query=sparse, using=SPARSE_VECTOR_NAME, limit=body.top_k * 4),
|
||||
qm.Prefetch(query=vector, using="", limit=max(body.top_k * 4, eff_limit), score_threshold=body.min_score),
|
||||
qm.Prefetch(query=sparse, using=SPARSE_VECTOR_NAME, limit=max(body.top_k * 4, eff_limit)),
|
||||
],
|
||||
query=qm.FusionQuery(fusion=qm.Fusion.RRF),
|
||||
query_filter=qfilter,
|
||||
limit=body.top_k,
|
||||
limit=eff_limit,
|
||||
with_payload=True,
|
||||
).points
|
||||
return qdrant.query_points(
|
||||
collection_name=collection,
|
||||
query=vector,
|
||||
query_filter=qfilter,
|
||||
limit=body.top_k,
|
||||
limit=eff_limit,
|
||||
score_threshold=body.min_score,
|
||||
with_payload=True,
|
||||
).points
|
||||
|
||||
Reference in New Issue
Block a user