added hybrid semantic search with reranking

Implements a three-stage search pipeline:
1. BM25 keyword search via FTS5 with column weights
2. Semantic search via Snowflake arctic-embed-s bi-encoder + HNSW index
3. Optional cross-encoder reranking (on by default, toggleable in settings)

Top 20 results are reranked for precision, next 10 appended from RRF
for coverage, giving 30 total results across 3 pages.

- New embeddings.py with ONNX Runtime inference, text chunking, HNSW
  index management, RRF fusion, and cross-encoder reranking
- Meta description extraction for authentic page snippets with centroid
  extractive fallback
- Stopword filtering in FTS5 queries to avoid overly strict matching
- /reindex page for batch embedding of existing pages
- Semantic embedding of remote pages during subscription sync
- ~125MB dependency footprint (onnxruntime, tokenizers, hnswlib, numpy)
- Models: 34MB bi-encoder + 22MB cross-encoder (downloaded on first use)
This commit is contained in:
lichenblankie 2026-03-27 03:24:41 -07:00
parent 212e9a017d
commit 5ded9f1339
6 changed files with 839 additions and 17 deletions

17
app.py
View file

@ -72,8 +72,25 @@ def ensure_rns_config(config_dir):
print(f"Created Reticulum config at {config_file}")
def _preload_embeddings():
"""Pre-load the embedding model and build the HNSW index in background."""
try:
from embeddings import _get_session, _get_reranker, build_index
_get_session() # downloads model on first run, loads ONNX session
build_index() # builds HNSW index from existing chunks
# Preload cross-encoder unless user has explicitly disabled it
if get_setting("use_reranker", "1") == "1":
_get_reranker()
print("Semantic search ready (with reranker).")
else:
print("Semantic search ready.")
except Exception as e:
print(f"Semantic search unavailable: {e}")
def main():
init_db()
threading.Thread(target=_preload_embeddings, daemon=True).start()
config_dir = os.environ.get("RNS_CONFIG_DIR")
ensure_rns_config(config_dir)
reticulum = RNS.Reticulum(configdir=config_dir)