ChromaDB is an open-source vector database built for applications that use large language models (LLMs). LLMs like the ones behind OpenAI’s ChatGPT can reason about natural language processing (NLP) problems remarkably well, but on their own, they only know what appeared in their training data.
They can also only read a limited number of text tokens at once. If you asked ChatGPT to summarize confidential company documents, then you’d have to decide which documents to show it first.
A vector database allows you to store encoded unstructured objects, like text, as lists of numbers that you can compare to one another. You can, for example, find the collection of documents relevant to a question that you want an LLM to answer. In this tutorial, you’ll learn the concepts behind embeddings and vector databases, and then you’ll put them to work with ChromaDB in Python.
By the end of this tutorial, you’ll understand that:
- Vectors represent unstructured objects as arrays of numbers, and cosine similarity measures how closely two vectors point in the same direction.
- Embeddings are dense vectors that capture the meaning of words and text, and you can create them in Python with spaCy and SentenceTransformers.
- A vector database stores embeddings and returns the entries most similar to a query instead of exact matches.
- ChromaDB lets you create collections, add documents with metadata, and run semantic queries with metadata filters in a few lines of Python.
- Retrieval-augmented generation (RAG) uses a vector database like ChromaDB to find relevant documents and pass them to an LLM as context.
After reading, you’ll have the foundational knowledge to use ChromaDB in your NLP or LLM applications. Before reading, you should be comfortable with the basics of Python and high school math. This tutorial was written for ChromaDB 1.5 and Python 3.12 or later, and every install command pins the package versions that the code was tested with.
Get Your Code: Click here to download free sample code that shows you how to use ChromaDB to add context to an LLM.
Take the Quiz: Test your knowledge with our interactive “Embeddings and Vector Databases With ChromaDB” quiz. You’ll receive a score upon completion to help you track your learning progress:
Interactive Quiz
Embeddings and Vector Databases With ChromaDBCheck your grasp of ChromaDB, embeddings, and vector search. Practice cosine similarity, querying collections, and using RAG with LLMs in Python.
Represent Data as Vectors
Before diving into embeddings and vector databases, you should understand what vectors are and what they represent. Feel free to skip ahead to the next section if you’re already comfortable with vector concepts. If you’re not or if you could use a refresher, then keep reading!
Vector Basics
You can describe vectors with variable levels of complexity, but one great starting place is to think of a vector as an array of numbers. For example, you could represent vectors using NumPy arrays. To follow along, create a virtual environment, activate it, and install NumPy:
(.venv) $ python -m pip install numpy==2.5.3 With NumPy installed, you can create your first vectors:
>>> import numpy as np >>> vector1 = np.array([1, 0]) >>> vector2 = np.array([0, 1]) >>> vector1 array([1, 0]) >>> vector2 array([0, 1]) In this code block, you import numpy and create two arrays, vector1 and vector2, representing vectors. This is one of the most common and useful ways to work with vectors in Python, and NumPy offers a variety of functionality to manipulate vectors. There are also several other libraries that you can use to work with vector data, such as PyTorch, TensorFlow, JAX, and Polars. You’ll stick with NumPy for this overview.
You’ve created two NumPy arrays that represent vectors. Now what? It turns out you can do a lot of cool things with vectors, but before continuing on, you’ll need to understand some key definitions and properties:
-
Dimension: The dimension of a vector is the number of elements that it contains. In the example above,
vector1andvector2are both two-dimensional since they each have two elements. You can only visualize vectors with three dimensions or less, but generally, vectors can have any number of dimensions. In fact, as you’ll see later, vectors that encode words and text tend to have hundreds or thousands of dimensions. -
Magnitude: The magnitude of a vector is a non-negative number that represents the vector’s size or length. You can also refer to the magnitude of a vector as the norm, and you can denote it with ||v|| or |v|. There are many different definitions of magnitude or norm, but the most common is the Euclidean norm or 2-norm. You’ll learn how to compute this later.
-
Unit vector: A unit vector is a vector with a magnitude of one. In the example above,
vector1andvector2are unit vectors. -
Direction: The direction of a vector specifies the line along which the vector points. You can represent direction using angles, unit vectors, or coordinates in different coordinate systems.
-
Dot product (scalar product): The dot product of two vectors, u and v, is a number given by u ⋅ v = ||u|| ||v|| cos(θ), where θ is the angle between the two vectors. Another way to compute the dot product is to do an element-wise multiplication of u and v and sum the results. The dot product is one of the most important and widely used vector operations because it measures the similarity between two vectors. You’ll see more of this later on.
-
Orthogonal vectors: Vectors are orthogonal if their dot product is zero, meaning that they’re at a 90 degree angle to each other. You can think of orthogonal vectors as being completely unrelated to each other.
-
Dense vector: A vector is considered dense if most of its elements are non-zero. Later on, you’ll see that words and text are most usefully represented with dense vectors because each dimension encodes meaningful information.
While there are many more definitions and properties to learn, these seven are most important for this tutorial. To solidify these ideas with code, check out the following block. Note that for the rest of this tutorial, you’ll use v1, v2, and v3 to name your vectors:
>>> import numpy as np >>> v1 = np.array([1, 0]) >>> v2 = np.array([0, 1]) >>> v3 = np.array([np.sqrt(2), np.sqrt(2)]) >>> # Dimension >>> v1.shape (2,) >>> # Magnitude >>> np.sqrt(np.sum(v1**2)) np.float64(1.0) >>> np.linalg.norm(v1) np.float64(1.0) >>> np.linalg.norm(v3) np.float64(2.0) >>> # Dot product >>> np.sum(v1 * v2) np.int64(0) >>> v1 @ v3 np.float64(1.4142135623730951) You first import numpy and create the arrays v1, v2, and v3. Checking v1.shape shows you that v1 has two elements, which is its dimension as a vector.
You then see two different ways to compute the magnitude of a NumPy array. The first, np.sqrt(np.sum(v1**2)), uses the Euclidean norm that you learned about above. The second computation uses np.linalg.norm(), a NumPy function that computes the Euclidean norm of an array by default but can also compute other matrix and vector norms.
Keep in mind that NumPy 2 displays scalar results wrapped in their type, such as np.float64(2.0). You can treat them like ordinary Python numbers.
Lastly, you see two ways to calculate the dot product between two vectors. Using np.sum(v1 * v2) first computes the element-wise multiplication between v1 and v2 in a vectorized fashion, and you sum the results to produce a single number. A better way to compute the dot product is to use the at-operator (@), as you see with v1 @ v3. This is because @ can perform both vector and matrix multiplications, and the syntax is cleaner.
While all of these vector definitions and properties may seem straightforward to compute, you might still be wondering what they actually mean and why they’re important to understand. One way to better understand vectors is to visualize them in two dimensions. In this context, you can represent vectors as arrows, like in the following plot:
Read the full article at https://realpython.com/chromadb-vector-database/ »
[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]

