Purpose: Enable semantic similarity search against the pre-computed embeddings using cosine distance. Query embeddings must use RETRIEVAL_QUERY task type (different from RETRIEVAL_DOCUMENT used during indexing) for optimal retrieval accuracy.
Output: src/search/ module with query embedding and top-K search functions for Google, Jina, and MiniLM models.
<execution_context> @./.claude/get-shit-done/workflows/execute-plan.md @./.claude/get-shit-done/templates/summary.md </execution_context>
@src/embeddings/google_embed.py @src/embeddings/jina_embed.py @src/embeddings/minilm_embed.py @src/db.py
In src/search/pgvector_search.py, create query embedding functions:
embed_query_google(query_text: str) -> list[float]:
task_type='RETRIEVAL_QUERY' (not RETRIEVAL_DOCUMENT)embed_query_jina(query_text: str) -> list[float]:
task='retrieval.query' (not retrieval.passage)embed_query_minilm(query_text: str) -> list[float]:
In src/search/init.py, export:
Follow existing module patterns:
from src.search import embed_query_google, embed_query_jina, embed_query_minilm
# Test each returns correct dimension
assert len(embed_query_google("test query")) == 768
assert len(embed_query_jina("test query")) == 1024
assert len(embed_query_minilm("test query")) == 384
search_pgvector(conn, query_embedding: list[float], embedding_column: str, k: int = 5) -> list[dict]:
<=>1 - distance (cosine distance to similarity conversion)WHERE {embedding_column} IS NOT NULL{embedding_column} <=> %s::vectorSet HNSW search parameters for optimal performance:
SET hnsw.ef_search = 40 before search queriesAdd convenience function search_all_models(conn, query_text: str, k: int = 5) -> dict:
IMPORTANT: Use parameterized queries for embedding (pass as %s::vector), but embedding_column must be interpolated directly (f-string) since column names can't be parameterized. Validate column name against allowed values ['embedding_google', 'embedding_jina', 'embedding_minilm'].
Update src/search/init.py exports.
from src.db import get_connection
from src.search import search_pgvector, embed_query_google
conn = get_connection()
emb = embed_query_google("test query")
results = search_pgvector(conn, emb, 'embedding_google', k=3)
# Verify results structure
assert len(results) == 3
assert 'similarity' in results[0]
assert 'supplier_name' in results[0]
assert 'debit_account' in results[0]
assert 0 <= results[0]['similarity'] <= 1
conn.close()
Search returns correct structure:
Module imports work:
from src.search import (
embed_query_google, embed_query_jina, embed_query_minilm,
search_pgvector, search_all_models
)
<success_criteria>