Skip to content

feat(playground): add full-text and hybrid search modes#181

Open
prsasattms wants to merge 2 commits into
mainfrom
feat/playground-fts-hybrid
Open

feat(playground): add full-text and hybrid search modes#181
prsasattms wants to merge 2 commits into
mainfrom
feat/playground-fts-hybrid

Conversation

@prsasattms

Copy link
Copy Markdown
Collaborator

Summary

Adds Full-Text and Hybrid search modes to the Search Playground, which was previously vector-only. The search service already supported FTS (#180) and RRF merge — this exposes them in the playground UI/API and adds rank fusion so hybrid results from the same source are combined rather than duplicated.

Changes

Frontend (web/static/index.html)

  • New Mode selector: Vector / Full-Text / Hybrid.
  • Added an RRF (rank fusion) merge option; Hybrid auto-selects RRF; Full-Text disables the image input.
  • Sends search_mode; result/breakdown rendering tolerates hybrid's suffixed index ids; header renamed to "Search Playground".

Backend API (�pi/api.py)

  • PlaygroundSearchRequest gains search_mode (vector|fts|hybrid) and optional fts_field.
  • _build_index_specs emits vector and/or FTS IndexSpecs per destination. Hybrid produces two specs (ids suffixed ::vec / ::fts) sharing a fusion_group so a document found by both fuses into one result.
  • Forces rrf merge whenever FTS is involved (FTS hits have no comparable native score), rejects FTS without a text query, caps a request at 10 indexes, and resolves friendly per-index names (X (vector) / X (full-text)).
  • pgvector destinations warn/skip for FTS (Cosmos-only in v1).

Search service (search/schemas.py, search/searcher.py)

  • IndexSpec gains an optional fusion_group.
  • _merge fuses indexes sharing a fusion_group under RRF on (fusion_group, doc_id) instead of (index_id, doc_id), so hybrid vector+FTS hits for the same document collapse into one result with a combined RRF score. Behavior is unchanged when fusion_group is unset.

Testing

  • tests/unit/test_search_fts.py: 17 passed.
  • Unit-verified _merge fusion: a doc returned by both ::vec and ::fts fuses to a single result with summed RRF score and ranks first; without fusion groups it appears twice (prior behavior).
  • Deployed all three images to an isolated environment and verified Vector, Full-Text, and Hybrid modes return results via /api/playground/search; hybrid shows a per-index breakdown of (vector) and (full-text).

Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com

prsasatt and others added 2 commits June 8, 2026 22:18
The Search Playground was vector-only. Add a Mode selector (Vector /
Full-Text / Hybrid) so users can exercise the search service's existing
FTS capability and combine vector + FTS via reciprocal rank fusion.

Backend (api/api.py):
- PlaygroundSearchRequest gains search_mode and optional fts_field.
- _build_index_specs emits vector and/or fts IndexSpecs per destination;
  hybrid produces two specs (ids suffixed ::vec / ::fts) sharing a
  fusion_group so the same document fuses into one RRF result.
- Force rrf merge whenever FTS is involved (FTS hits have no comparable
  native score); reject fts without a text query; cap at 10 indexes;
  resolve friendly per-index names (stripping the ::vec/::fts suffix).

Search service:
- IndexSpec gains an optional fusion_group; _merge fuses indexes sharing
  a group under rrf on (fusion_group, doc_id) instead of (index_id, ...).

Frontend (web/static/index.html):
- Mode selector + RRF merge option; hybrid auto-selects rrf; full-text
  disables the image input; sends search_mode; renamed header to
  "Search Playground".

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Simplify the playground controls: remove the Merge strategy dropdown and
always use RRF, the sensible default for vector, multi-index, full-text,
and hybrid searches. The merge value is kept as a hidden input so the
request shape is unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants