From d0ed9e213f67fc77f3f365e2ddabb26c882aaf71 Mon Sep 17 00:00:00 2001 From: Yiorgis Gozadinos Date: Thu, 23 Apr 2026 17:23:40 +0300 Subject: [PATCH] Pin FTS search column to content_fts --- .../haiku/rag/store/repositories/chunk.py | 6 ++- ...fts_search_targets_content_fts_column.yaml | 42 +++++++++++++++++++ tests/test_search.py | 35 ++++++++++++++++ 3 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 tests/cassettes/test_search/test_fts_search_targets_content_fts_column.yaml diff --git a/haiku_rag_slim/haiku/rag/store/repositories/chunk.py b/haiku_rag_slim/haiku/rag/store/repositories/chunk.py index d0be740a..5fde340d 100644 --- a/haiku_rag_slim/haiku/rag/store/repositories/chunk.py +++ b/haiku_rag_slim/haiku/rag/store/repositories/chunk.py @@ -264,7 +264,9 @@ class ChunkRepository: ) elif search_type == "fts": - results = self.store.chunks_table.query().nearest_to_text(query) + results = self.store.chunks_table.query().nearest_to_text( + query, columns="content_fts" + ) else: # hybrid (default) query_embedding = await self.embedder.embed_query(query) @@ -275,7 +277,7 @@ class ChunkRepository: self.store.chunks_table.query() .nearest_to(query_embedding) .column("vector") - .nearest_to_text(query) + .nearest_to_text(query, columns="content_fts") .refine_factor(self.store._config.search.vector_refine_factor) .rerank(reranker) ) diff --git a/tests/cassettes/test_search/test_fts_search_targets_content_fts_column.yaml b/tests/cassettes/test_search/test_fts_search_targets_content_fts_column.yaml new file mode 100644 index 00000000..45a29ad6 --- /dev/null +++ b/tests/cassettes/test_search/test_fts_search_targets_content_fts_column.yaml @@ -0,0 +1,42 @@ +interactions: +- request: + headers: + accept: + - application/json + accept-encoding: + - gzip, deflate, zstd + connection: + - keep-alive + content-length: + - '74' + content-type: + - application/json + host: + - localhost:11434 + method: POST + parsed_body: + encoding_format: base64 + input: + - seed + model: qwen3-embedding:4b + uri: http://localhost:11434/v1/embeddings + response: + headers: + content-type: + - application/json + transfer-encoding: + - chunked + parsed_body: + data: + - embedding: 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 + index: 0 + object: embedding + model: qwen3-embedding:4b + object: list + usage: + prompt_tokens: 2 + total_tokens: 2 + status: + code: 200 + message: OK +version: 1 diff --git a/tests/test_search.py b/tests/test_search.py index 7eca9c93..d235bfb1 100644 --- a/tests/test_search.py +++ b/tests/test_search.py @@ -241,6 +241,41 @@ async def test_search_result_format_includes_metadata(temp_db_path): assert "machine learning" in formatted.lower() +@pytest.mark.vcr() +async def test_fts_search_targets_content_fts_column(temp_db_path): + """FTS search must target the content_fts column (where the FTS index + lives and where contextualized heading prefixes end up) — not the raw + content column. Regression guard against upstream default-column changes + in LanceDB's nearest_to_text(). + """ + from haiku.rag.store.models.chunk import Chunk + + async with HaikuRAG(temp_db_path, create=True) as client: + doc = await client.create_document(content="seed", uri="test://doc") + assert doc.id is not None + + # Heading-only term — contextualization will prepend headings to the + # body when populating content_fts, so this word ends up ONLY in + # content_fts, not in the content column. + heading_only_term = "zxqvjfoowizardry" + chunk = Chunk( + content="unrelated body text", + document_id=doc.id, + metadata={"headings": [heading_only_term]}, + embedding=[0.0] * client.store.embedder._vector_dim, + ) + await client.chunk_repository.create(chunk) + + # FTS on the heading-only word must match via content_fts. + results = await client.chunk_repository.search( + heading_only_term, limit=5, search_type="fts" + ) + assert any(c.content == "unrelated body text" for c, _ in results), ( + "FTS did not match a heading-only term — nearest_to_text is not " + "targeting the content_fts column" + ) + + def test_search_result_primary_label_prioritizes_structural_types(): """Test _get_primary_label prioritizes structural labels correctly.""" # Table should be prioritized