feat: semantic chunking + pgvector hybrid (BM25+vector) retriever (#2553)

This commit is contained in:
Alex authored and GitHub committed 2026-06-22 17:04:13 +01:00
1 parent c6a33eca32
commit a709b7ccdc
16 files changed
+684 -36

No files matched your search

+55
View File
@@ -131,6 +131,61 @@ class TestPGVectorStoreSearch:
assert len(results) == 2
@pytest.mark.unit
class TestPGVectorStoreKeywordSearch:
def test_keyword_search_returns_documents(self):
store, _, mock_cursor, mock_emb = _make_store(source_id="src1")
mock_cursor.fetchall.return_value = [
("hello world", {"source": "a.txt"}, 0.9),
("foo bar", {"source": "b.txt"}, 0.3),
]
results = store.keyword_search("hello", k=5)
# Keyword search must not embed the query.
mock_emb.embed_query.assert_not_called()
assert len(results) == 2
assert results[0].page_content == "hello world"
assert results[0].metadata == {"source": "a.txt"}
def test_keyword_search_is_parameterized(self):
store, _, mock_cursor, _ = _make_store(source_id="src1")
mock_cursor.fetchall.return_value = []
store.keyword_search("DROP TABLE documents; --", k=7)
sql, params = mock_cursor.execute.call_args[0]
# The raw question must never be interpolated into the SQL text.
assert "DROP TABLE documents" not in sql
assert "websearch_to_tsquery('english', %s)" in sql
# Question is bound twice (rank + WHERE), then source_id and k.
assert params == ("DROP TABLE documents; --", "src1", "DROP TABLE documents; --", 7)
def test_keyword_search_handles_null_metadata(self):
store, _, mock_cursor, _ = _make_store()
mock_cursor.fetchall.return_value = [("text", None, 0.5)]
results = store.keyword_search("query")
assert len(results) == 1
assert results[0].metadata == {}
def test_keyword_search_returns_empty_on_error(self):
store, _, mock_cursor, _ = _make_store()
mock_cursor.execute.side_effect = Exception("fts failed")
assert store.keyword_search("query") == []
def test_ensure_table_exists_creates_fts_index(self):
store, mock_conn, mock_cursor, _ = _make_store()
store._ensure_table_exists()
executed = " ".join(
str(call.args[0]) for call in mock_cursor.execute.call_args_list
)
assert "documents_text_fts_idx" in executed
assert "gin(to_tsvector('english'" in executed
@pytest.mark.unit
class TestPGVectorStoreAddTexts:
def test_add_texts_inserts_and_returns_ids(self):