Vector retrieval in Haystack only works when query text is embedded with the same vector assumptions used during indexing. A Sentence Transformers text embedder keeps that query step local, so a search or RAG pipeline can turn a user question into a vector without calling a hosted embeddings API.
The maintained integration package is sentence-transformers-haystack. It exposes SentenceTransformersTextEmbedder through the haystack_integrations import path for query strings, while document embedding uses the matching document embedder during indexing.
Set the model name, normalization behavior, prefix, and progress output before wiring the component into retrieval. Calling warm_up() loads the model before the first request, and a small retriever smoke test catches missing integration packages, wrong vector dimensions, and normalization mismatches before the component reaches a larger pipeline.
$ . .venv/bin/activate
Related: How to install Haystack with pip
$ python -m pip install --upgrade sentence-transformers-haystack Collecting sentence-transformers-haystack ##### snipped ##### Successfully installed sentence-transformers-haystack-0.1.0 sentence-transformers-5.6.0
The package installs the Sentence Transformers integration and its model runtime dependencies. Use the same environment that will run the Haystack pipeline.
from haystack import Document from haystack.components.retrievers.in_memory import InMemoryEmbeddingRetriever from haystack.document_stores.in_memory import InMemoryDocumentStore from haystack_integrations.components.embedders.sentence_transformers import SentenceTransformersTextEmbedder embedder = SentenceTransformersTextEmbedder( model="sentence-transformers/all-MiniLM-L6-v2", normalize_embeddings=True, progress_bar=False, ) embedder.warm_up() query_result = embedder.run(text="password reset approval policy") query_embedding = query_result["embedding"] document_store = InMemoryDocumentStore(embedding_similarity_function="cosine") document_store.write_documents( [ Document( content="Password reset requests require help desk approval.", meta={"name": "password-reset-policy"}, embedding=query_embedding, ) ] ) retriever = InMemoryEmbeddingRetriever(document_store=document_store, top_k=1) match = retriever.run(query_embedding=query_embedding)["documents"][0] print(f"embedding_dimensions={len(query_embedding)}") print( f"first_values={query_embedding[0]:.4f}," f"{query_embedding[1]:.4f}," f"{query_embedding[2]:.4f}" ) print(f"normalized_l2={sum(value * value for value in query_embedding):.6f}") print(f"retriever_top_document={match.meta['name']}")
normalize_embeddings=True returns vectors with L2 norm near 1.0, which fits cosine-similarity retrieval. Add a prefix only for models whose model documentation requires a query instruction, and use the same model and normalization settings when embedding documents for the retriever.
$ python haystack-sentence-embedder.py embedding_dimensions=384 first_values=-0.0675,-0.0224,0.0136 normalized_l2=1.000000 retriever_top_document=password-reset-policy
The first values can differ by package version and model runtime. embedding_dimensions=384 matches sentence-transformers/all-MiniLM-L6-v2, normalized_l2=1.000000 confirms unit-length output, and retriever_top_document=password-reset-policy confirms the query vector can drive an embedding retriever.
$ rm haystack-sentence-embedder.py