Build semantic search
Find documents by meaning rather than keywords, using embeddings, then optionally answer with citations.
Index
- Split documents into passages of 200 to 500 words at natural boundaries (headings, paragraphs). Keep the title and section heading with each passage.
- Embed passages with
syntic-embed-1andinput_type: "document". - Store vectors with the passage text and source in a vector database or a vector column in your existing database.
Query
- Embed the user’s query with
input_type: "query". - Retrieve the top 20 passages by cosine similarity.
- Optionally re-rank with a cheap model call that scores relevance 0 to 3 and keep the top 5.
Answer
Send the top passages as search result blocks with citations on, and ask the model to answer only from them. The response’s citations link each sentence back to a passage you can show.
Hybrid search
Embeddings miss exact identifiers such as error codes and SKUs. Combine vector search with keyword search and merge the results; this beats either alone on most real data.
Keep it fresh
Re-embed passages when documents change, and delete vectors for removed documents. Store the embedding model id with each vector so a future model change can be rolled out by re-indexing, not by mixing vectors from different models.
Evaluate
Collect 50 real queries with the passages that should be found, and measure recall at 5 and 20. Improve chunking before trying a bigger model.