Improve search quality: RERANK_LIMIT 10→60, search_text for dense, variants+hyde multi-vector

- RERANK_LIMIT 10→60: rerank more candidates → better NDCG ordering
- Dense query uses search_text if available (semantically richer than text)
- Sparse query always appends keywords on top of base text
- Multi-vector: use variants[:2] + hyde[:2] as extra dense queries
  (previously only hyde[:2])
- Index UVICORN_WORKERS 8→4: matches 4-core constraint, saves ~1GB RAM

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
q 2026-04-18 19:04:23 +03:00
parent 84eec2321e
commit 4822bbb24b
2 changed files with 17 additions and 10 deletions

View file

@ -11,7 +11,7 @@ from pydantic import BaseModel
HOST = os.getenv("HOST", "0.0.0.0")
PORT = int(os.getenv("PORT", "8000"))
UVICORN_WORKERS = 8
UVICORN_WORKERS = 4
logging.basicConfig(level=os.getenv("LOG_LEVEL", "INFO"))
logger = logging.getLogger("index-service")

View file

@ -165,7 +165,7 @@ app = FastAPI(title="Search Service", version="0.1.0", lifespan=lifespan)
DENSE_PREFETCH_K = 80
SPARSE_PREFETCH_K = 200
RETRIEVE_K = 150
RERANK_LIMIT = 10
RERANK_LIMIT = 60
async def embed_dense(client: httpx.AsyncClient, text: str) -> list[float]:
@ -211,15 +211,16 @@ def embed_sparse_sync(text: str) -> SparseVector:
def build_dense_query(question: Question) -> str:
if question.search_text:
return question.search_text.strip()
return question.text.strip()
def build_sparse_query(question: Question) -> str:
parts = [question.text.strip()]
base = question.search_text.strip() if question.search_text else question.text.strip()
parts = [base]
if question.keywords:
parts.extend(question.keywords)
if question.search_text:
parts = [question.search_text]
return " ".join(parts)
@ -358,13 +359,19 @@ async def search(payload: SearchAPIRequest) -> SearchAPIResponse:
dense_vector, sparse_vector = await asyncio.gather(dense_task, sparse_task)
dense_vectors = [dense_vector]
if question.hyde and len(question.hyde) > 0:
extra_texts: list[str] = []
for v in (question.variants or [])[:2]:
if v.strip():
extra_texts.append(v.strip())
for h in (question.hyde or [])[:2]:
if h.strip():
extra_texts.append(h.strip())
if extra_texts:
try:
hyde_texts = question.hyde[:2]
hyde_vectors = await embed_dense_batch(client, hyde_texts)
dense_vectors.extend(hyde_vectors)
extra_vectors = await embed_dense_batch(client, extra_texts)
dense_vectors.extend(extra_vectors)
except Exception as e:
logger.warning(f"HyDE embedding failed: {e}")
logger.warning(f"Extra dense embedding failed: {e}")
all_points = await qdrant_search(qdrant, dense_vectors, sparse_vector)