The pipeline
1. Pick an embedding model
Higher dimensions ≠ always better — they cost more memory in your vector store. With OpenAI v3 models you can request a smaller
dimensions (e.g. 768 or 512) and get most of the quality.
python
2. Chunk the documents
Don’t embed whole documents — embed chunks of ~200–500 tokens with ~50–100 token overlap. Smaller chunks = sharper retrieval; larger = more context per hit.python
3. Embed in batches
The endpoint accepts up to 2 048 strings per call. Batch hard:python
4. Store with metadata
Use a vector store that supports metadata filtering — pgvector, Qdrant, Pinecone, Weaviate, Chroma. Always store:5. Query
Embed the user’s question with the same model, then pull top-k:python
k empirically — usually 4–8. Below 3, you miss relevant chunks; above 10, you push noise into the prompt.
6. Generate the answer
Format retrieved chunks into the prompt with clear separators and source citations:python
Improvements that earn their cost
- Hybrid search — combine vector similarity with BM25 keyword scores. ~10–15% recall lift on technical content.
- Re-ranking — fetch top-30 by vector, re-rank to top-6 with a cross-encoder (coming soon: dedicated reranker endpoint, see changelog).
- Query rewriting — for chat, ask the LLM to rewrite the user’s follow-up into a standalone search query before embedding.
- Multi-query — generate 3–5 paraphrases of the question, search each, dedupe results. Catches lexical mismatches.
Common mistakes
- Mixing embedding models in the same store — vectors don’t compare. Re-embed everything when you switch.
- Embedding raw HTML/PDF bytes — extract clean text first.
- Chunks too large — model only “sees” the centre; edges are wasted.
- No metadata filter — searching all customers’ data for one customer’s question. Always filter by tenant first.
- Forgetting to track
indexed_at— when documents update, you need to know what’s stale.
Cost ballpark
For 100 000 chunks × 400 tokens = 40 M tokens:- Index once with
text-embedding-3-small(≈ 0.80** - Query at 1 query / sec (≈ 50 tokens each) → ~$0.005 / day

