Course Wiki
Vector Search with sqlitesearch — LLM Zoomcamp Module 2
--- video_url: 'https://www.youtube.com/watch?v=csxKescwJYM&list=PL3MmuxUbc_hLZFNgSad56pDBKK8KO0XIv' --- # Vector Search with sqlitesearch
Related Pages
LLM Zoomcamp › Module 2: Vector Search › Vector Search with sqlitesearch
Notes
video_url: “https://www.youtube.com/watch?v=csxKescwJYM&list=PL3MmuxUbc_hLZFNgSad56pDBKK8KO0XIv”
Vector Search with sqlitesearch
In the previous section we used minsearch for vector search.
It works, but it has three problems:
- It rebuilds the index on every startup
- It keeps everything in memory
- It searches by brute force
With text search we never felt these. Indexing was fast because we didn’t embed anything. With vector search, indexing runs a neural network over every document, so it takes a minute on our dataset. Keeping everything in memory is fine here, but a larger dataset would need too much space.
The third problem is brute-force search. For every query we compare the query vector against every single document. With 1,000 documents this is fine, probably even faster than anything smarter. But as the dataset grows past 10,000 or so, it gets slow, and we’ll want an approximate method instead.
What we’ve done so far is exact nearest neighbor (NN) search. We score every document against query and pick the top ones. It always finds the true top matches, but it pays for that by touching everything.
Approximate nearest neighbor (ANN) search takes a shortcut. Instead of comparing against everything, it first narrows down to a region of likely matches. Then it scores only within that region. It may miss the absolute best match, but the results are still good and it’s much faster.
NN (exact): compare query against ALL documents -> top 5
ANN (approx): narrow down to a region -> compare within region -> top 5
sqlitesearch
sqlitesearch is the persistent sibling of minsearch, and it solves both problems at once.
We already used it in module 1 for persistent text search. It also does
vector search through its VectorSearchIndex class. It stores vectors
in SQLite, a real on-disk database, and uses ANN strategies for
retrieval. Because the data lives on disk, one process can write the
vectors and another can read them back.
If you didn’t install it in the previous module, add it to your project:
uv add sqlitesearch
Creating the index
Initialize it:
from sqlitesearch import VectorSearchIndex
vs_index = VectorSearchIndex(
keyword_fields=["course"],
mode="ivf",
db_path="faq_vectors2.db"
)
sqlitesearch supports three ANN modes:
lsh(default): up to 100K vectors, random hyperplane projectionsivf: 10K-500K vectors, K-means clusteringhnsw: 10K-1M+ vectors, proximity graph (highest recall)
For our small dataset, lsh is fine. All modes use two-phase search:
approximate candidate retrieval, then exact cosine similarity
reranking.
Indexing the data
Fit the index with our vectors and documents:
vs_index.fit(vectors, documents)
The index is saved to faq_vectors2.db. Unlike minsearch, this file
persists on disk. You can search immediately after indexing, or reopen
the index later without re-indexing.
Searching
Search works the same way as with minsearch. We always encode the query into a vector first. This is one thing that makes vector search heavier than text search. With text search we’d throw the raw query straight at the engine.
Encode, then search:
query = "I just discovered the course. Can I still join it?"
query_vector = model.encode(query)
results = vs_index.search(query_vector, num_results=5)
Look at the results:
results
Filtering by course
Filtering works the same way:
results = vs_index.search(
query_vector,
filter_dict={"course": "llm-zoomcamp"},
num_results=5
)
Closing the connection
When you’re done with the index:
vs_index.close()
Reopening the index
In a new Python session, you can reopen the index without re-computing embeddings:
from sentence_transformers import SentenceTransformer
from sqlitesearch import VectorSearchIndex
model = SentenceTransformer("all-MiniLM-L6-v2")
vs_index = VectorSea
## Key concepts
- [OpenAI API](/course-wiki/openai-api/)
- [RAG](/course-wiki/rag/)
- [Reranking](/course-wiki/reranking/)
- [Partitioning and Clustering](/course-wiki/partitioning-and-clustering/)
- [Vector Search](/course-wiki/vector-search/)
- [Classification Metrics](/course-wiki/classification-metrics/)
- [Embeddings](/course-wiki/embeddings/)
- [Kafka](/course-wiki/kafka/)
- [Jupyter Notebooks](/course-wiki/jupyter-notebooks/)
## Related notes
- [llmz-m01-agents](/course-wiki/llmz-m01-agents/)
- [llmz-m01-building-the-prompt](/course-wiki/llmz-m01-building-the-prompt/)
- [llmz-m01-data-ingestion](/course-wiki/llmz-m01-data-ingestion/)
- [llmz-m01-environment](/course-wiki/llmz-m01-environment/)
- [llmz-m01-function-calling](/course-wiki/llmz-m01-function-calling/)
- [llmz-m01-introduction](/course-wiki/llmz-m01-introduction/)
- [llmz-m01-other-frameworks](/course-wiki/llmz-m01-other-frameworks/)
- [llmz-m01-quick-rag-revision-optional](/course-wiki/llmz-m01-quick-rag-revision-optional/)
- [llmz-m01-rag](/course-wiki/llmz-m01-rag/)
- [llmz-m01-rag-helper](/course-wiki/llmz-m01-rag-helper/)
- [llmz-m01-search](/course-wiki/llmz-m01-search/)
- [llmz-m01-the-agentic-loop](/course-wiki/llmz-m01-the-agentic-loop/)
- [llmz-m01-the-course-faq-dataset](/course-wiki/llmz-m01-the-course-faq-dataset/)
- [llmz-m01-the-llm](/course-wiki/llmz-m01-the-llm/)
- [llmz-m01-toyaikit](/course-wiki/llmz-m01-toyaikit/)
- [llmz-m01-wrap-up-of-part-1](/course-wiki/llmz-m01-wrap-up-of-part-1/)
- [llmz-m02-embedding-our-dataset](/course-wiki/llmz-m02-embedding-our-dataset/)
- [llmz-m02-embeddings](/course-wiki/llmz-m02-embeddings/)
- [llmz-m02-next-steps](/course-wiki/llmz-m02-next-steps/)
- [llmz-m02-rag-with-vector-search](/course-wiki/llmz-m02-rag-with-vector-search/)
- [llmz-m02-using-onnx-runtime-instead-of-pytorch](/course-wiki/llmz-m02-using-onnx-runtime-instead-of-pytorch/)
- [llmz-m02-vector-search](/course-wiki/llmz-m02-vector-search/)
- [llmz-m02-vector-search-2](/course-wiki/llmz-m02-vector-search-2/)
- [llmz-m02-vector-search-with-minsearch](/course-wiki/llmz-m02-vector-search-with-minsearch/)
- [llmz-m02-vector-search-with-pgvector](/course-wiki/llmz-m02-vector-search-with-pgvector/)
- [llmz-m03-ai-agents](/course-wiki/llmz-m03-ai-agents/)
- [llmz-m03-ai-copilot](/course-wiki/llmz-m03-ai-copilot/)
- [llmz-m03-ai-orchestration](/course-wiki/llmz-m03-ai-orchestration/)
- [llmz-m03-best-practices](/course-wiki/llmz-m03-best-practices/)
- [llmz-m03-context-engineering](/course-wiki/llmz-m03-context-engineering/)
- [llmz-m03-next-steps](/course-wiki/llmz-m03-next-steps/)
- [llmz-m03-retrieval-augmented-generation](/course-wiki/llmz-m03-retrieval-augmented-generation/)
- [llmz-m03-setting-up-kestra](/course-wiki/llmz-m03-setting-up-kestra/)
- [llmz-m04-agent-evaluation](/course-wiki/llmz-m04-agent-evaluation/)
- [llmz-m04-evaluation](/course-wiki/llmz-m04-evaluation/)
- [llmz-m04-generating-ground-truth-data](/course-wiki/llmz-m04-generating-ground-truth-data/)
- [llmz-m04-generating-ground-truth-for-all-documents](/course-wiki/llmz-m04-generating-ground-truth-for-all-documents/)
- [llmz-m04-generating-rag-answers](/course-wiki/llmz-m04-generating-rag-answers/)
- [llmz-m04-llm-as-a-judge](/course-wiki/llmz-m04-llm-as-a-judge/)
- [llmz-m04-next-steps](/course-wiki/llmz-m04-next-steps/)
- [llmz-m04-rag-and-agent-evaluation](/course-wiki/llmz-m04-rag-and-agent-evaluation/)
- [llmz-m04-search-evaluation](/course-wiki/llmz-m04-search-evaluation/)
- [llmz-m04-search-evaluation-metrics](/course-wiki/llmz-m04-search-evaluation-metrics/)
- [llmz-m04-search-parameter-tuning](/course-wiki/llmz-m04-search-parameter-tuning/)
- [llmz-m05-assistant](/course-wiki/llmz-m05-assistant/)
- [llmz-m05-built-in-judge](/course-wiki/llmz-m05-built-in-judge/)
- [llmz-m05-capturing-metrics](/course-wiki/llmz-m05-capturing-metrics/)
- [llmz-m05-chat-app](/course-wiki/llmz-m05-chat-app/)
- [llmz-m05-docker-compose](/course-wiki/llmz-m05-docker-compose/)
- [llmz-m05-monitoring](/course-wiki/llmz-m05-monitoring/)
- [llmz-m05-next-steps](/course-wiki/llmz-m05-next-steps/)
- [llmz-m05-querying-data](/course-wiki/llmz-m05-querying-data/)
- [llmz-m05-storing-data-in-postgresql](/course-wiki/llmz-m05-storing-data-in-postgresql/)
- [llmz-m05-streamlit-dashboard](/course-wiki/llmz-m05-streamlit-dashboard/)
- [llmz-m05-user-feedback](/course-wiki/llmz-m05-user-feedback/)
- [llmz-m06-best-practices-for-rag](/course-wiki/llmz-m06-best-practices-for-rag/)
- [llmz-m06-document-reranking](/course-wiki/llmz-m06-document-reranking/)
- [llmz-m06-hybrid-search](/course-wiki/llmz-m06-hybrid-search/)
- [llmz-m06-hybrid-search-with-langchain](/course-wiki/llmz-m06-hybrid-search-with-langchain/)
- [llmz-m06-next-steps](/course-wiki/llmz-m06-next-steps/)
- [llmz-m07-chunking-for-longer-texts](/course-wiki/llmz-m07-chunking-for-longer-texts/)
- [llmz-m07-content-processing-cases-and-steps](/course-wiki/llmz-m07-content-processing-cases-and-steps/)
- [llmz-m07-end-to-end-project-example](/course-wiki/llmz-m07-end-to-end-project-example/)
- [llmz-m07-evaluating-rag](/course-wiki/llmz-m07-evaluating-rag/)
- [llmz-m07-evaluating-retrieval](/course-wiki/llmz-m07-evaluating-retrieval/)
- [llmz-m07-interface-and-ingestion-pipeline](/course-wiki/llmz-m07-interface-and-ingestion-pipeline/)
- [llmz-m07-monitoring-and-containerization](/course-wiki/llmz-m07-monitoring-and-containerization/)
- [llmz-m07-summary-and-closing-remarks](/course-wiki/llmz-m07-summary-and-closing-remarks/)
## Sources
- [Video](https://www.youtube.com/watch?v=csxKescwJYM&list=PL3MmuxUbc_hLZFNgSad56pDBKK8KO0XIv)
- [Lesson file](https://github.com/llm-zoomcamp/blob/main/llm-zoomcamp/cohorts/2026/02-vector-search/07-sqlitesearch-vector.md)