forked from enderofwings/NexusOS
feat(rag): overlapping chunker, retrieval knobs, sqlite-vec index
- Chunker: char overlap across boundaries + hard-split of oversized paragraphs. - Retrieval knobs: rag_top_k / rag_min_score in settings + Settings UI. - Vector index: sqlite-vec ANN over document embeddings, dual-written and backfilled, with brute-force cosine as the guaranteed fallback. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -57,6 +57,46 @@ def test_search_empty_query_returns_nothing():
|
||||
assert asyncio.run(s.search_documents("", _fake_embed)) == []
|
||||
|
||||
|
||||
def test_chunker_overlap_and_hard_split():
|
||||
s = _store()
|
||||
# a single oversized paragraph (no blank lines, as in PDF text) is split
|
||||
big = "x" * 2000
|
||||
parts = s._chunk_text(big, size=800, overlap=120)
|
||||
# each chunk is one <=size unit, plus at most an overlap tail (+separator)
|
||||
assert len(parts) >= 3 and all(len(p) <= 800 + 120 + 2 for p in parts)
|
||||
# consecutive chunks share an overlap tail
|
||||
two = s._chunk_text("A" * 700 + "\n\n" + "B" * 700, size=800, overlap=120)
|
||||
assert len(two) == 2 and two[1].startswith("A" * 120)
|
||||
|
||||
|
||||
def test_vec_index_used_and_matches_brute_force():
|
||||
# On a host that can load sqlite-vec, the fast path must be exercised (not a
|
||||
# silent fallback) and agree with brute force on the top hit.
|
||||
s = _store()
|
||||
if not s.vec_enabled:
|
||||
import pytest
|
||||
pytest.skip("sqlite-vec not loadable on this host")
|
||||
|
||||
async def run():
|
||||
await s.add_document("Lego", "lego star wars boss fight tips", _fake_embed)
|
||||
await s.add_document("GPU", "gpu vega vram notes", _fake_embed)
|
||||
# vec table populated by the dual-write
|
||||
conn = s._connect()
|
||||
n = conn.execute("SELECT COUNT(*) FROM vec_documents").fetchone()[0]
|
||||
conn.close()
|
||||
assert n == 2
|
||||
|
||||
vec_hits = await s.search_documents("lego star wars", _fake_embed, limit=2, min_score=0.1)
|
||||
assert vec_hits and vec_hits[0]["title"] == "Lego"
|
||||
|
||||
# force the brute-force path and compare the top title
|
||||
s.vec_enabled = False
|
||||
bf_hits = await s.search_documents("lego star wars", _fake_embed, limit=2, min_score=0.1)
|
||||
assert bf_hits[0]["title"] == vec_hits[0]["title"]
|
||||
|
||||
asyncio.run(run())
|
||||
|
||||
|
||||
def test_extract_text_by_type():
|
||||
from synapse.main import _extract_text
|
||||
# plain text / markdown -> UTF-8 decode
|
||||
|
||||
Reference in New Issue
Block a user