Commit Graph

5 Commits

Author SHA1 Message Date
Vadim Malanov
2e76554188 ci: align backend lint checks
Some checks failed
CI / Backend (lint + tests + compose) (push) Has been cancelled
CI / Frontend (lint + type-check + build) (push) Has been cancelled
2026-06-14 20:14:49 +03:00
Vadim Malanov
01ba710c08 fix(indexing): unblock chunk indexing and gate reranker model load
Three defects surfaced during the first live ingest:

1. OpenSearch index mapping is dynamic:"strict", so the first chunk
   carrying metadata.section_heading was rejected with
   strict_dynamic_mapping_exception and zero chunks were indexed. The
   metadata and quality_flags sub-objects now opt into
   dynamic:true so chunker-specific keys insert without a fixed schema,
   while the top-level mapping stays strict.

2. hybrid_search.run_search called get_reranker() unconditionally, so
   every search - even search_mode=lexical with RERANKER_ENABLED=false
   - triggered a multi-GB FlagReranker download and hung the request.
   The loader is now lazy behind the reranker_enabled flag.

3. docker-compose x-common-env never forwarded RERANKER_ENABLED, so the
   container always defaulted to true regardless of .env. Added
   RERANKER_ENABLED: ${RERANKER_ENABLED:-true} to common-env.

After these fixes POST /search (lexical) returns HTTP 200 in ~50ms with
a ranked hit and citation; OpenSearch _count reports the indexed chunk.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 13:42:10 +03:00
Vadim Malanov
349f4ea838 perf(reranker): add benchmark harness and passage clipping
- scripts/benchmark_reranker.py exercises the configured reranker
  with synthetic queries or live OpenSearch samples and prints
  p50/p95/p99 latency, mean latency, and pairs/sec throughput.
  Supports --warmup, --candidates, --passage-length, --source, and a
  --json-only mode for CI.
- app/indexing/reranker.py clips passages to 2048 characters before
  scoring so a runaway chunk cannot starve the cross-encoder beyond
  bge-reranker-v2-m3's training window.
- RUNBOOK.md gains a Reranker benchmark section with CPU/GPU SLO
  targets and a remediation ladder (lower top-K, raise batch size,
  switch device, disable reranker) when measured p95 exceeds budget.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 17:08:04 +03:00
Vadim Malanov
f42fb978a8 chore: drop dead _qid helper and surface ocr_confidence on SearchHit
- app/indexing/qdrant_client.py: remove the identity-only _qid()
  helper and pass chunk_id straight to PointStruct (Qdrant accepts
  the UUID string directly).
- services/types.ts: SearchHit gets an explicit, optional
  ocr_confidence field so consumers can type the value instead of
  casting through metadata.
- widgets/SearchResultCard.tsx: replaces the
  (hit.metadata as { ocr_confidence? }) cast with the new field. No
  behavior change when the backend omits it.

tsc --noEmit: clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 16:55:32 +03:00
Vadim Malanov
7f72171572 chore: bootstrap repository with governance docs
Initialize git, add Apache-2.0 LICENSE, .gitattributes (LF line
endings), AGENTS.md (entry points, stack, discovery order, baseline
checks), RUNBOOK.md (dev boot, prod deploy with overlay, ingestion,
failures, rollback, scaling notes), .env.prod.example with rotated
credential placeholders, and dev-only warnings on .env.example.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 16:41:50 +03:00