- Posted on
- • Artificial Intelligence
Vector Databases for Artificial Intelligence
- Author
-
-
- User
- linuxbash
- Posts by this author
- Posts by this author
-
Vector Databases for Artificial Intelligence: A Bash-first Guide on Linux
AI apps don’t just need data—they need memory. When you’re matching a user’s question to the most relevant document, comparing images, or deduplicating content, you’re comparing high‑dimensional vectors (embeddings), not plain text. Grep won’t help you here. Vector databases are purpose-built to store, index, and search embeddings at scale—in milliseconds.
This post shows you why vector databases matter, when to use them, and how to stand up three proven options from your Linux terminal. All commands include apt, dnf, and zypper variants for a smooth start on Debian/Ubuntu, Fedora/RHEL, and openSUSE.
Why vector databases?
Similarity search at scale: Find the “nearest neighbors” to a query vector among millions of embeddings fast (often using approximate nearest neighbor, ANN, indexes like IVF/HNSW).
Tailored distance metrics: Cosine, dot product, L2—choose what matches your model and task.
Metadata filters: Search vectors with structured filters (e.g., by tenant, timestamp, tags).
Production features: Persistence, replication (where supported), schema management, and integrations—beyond what ad hoc FAISS files or in-memory arrays provide.
Common use cases:
RAG (Retrieval Augmented Generation) for docs/code
Semantic search and recommendations
Image/audio similarity
Near-duplicate detection and clustering
Choose the right engine (quick decision points)
PostgreSQL + pgvector: Best when you already live in Postgres; strong relational + vector in one place; great for small-to-mid scale and transactional + semantic blends.
Qdrant: Purpose-built vector DB with a clean HTTP API and filters; fast to run in a single container.
Weaviate: Vector DB with a schema and GraphQL/REST; can ingest with your own vectors or via modules; easy to prototype.
Below: quickstarts for each—pure Bash.
Prerequisites (tools we’ll use)
Install curl and jq:
- apt:
sudo apt update
sudo apt install -y curl jq
- dnf:
sudo dnf install -y curl jq
- zypper:
sudo zypper install -y curl jq
We’ll also use Podman to run containers rootlessly (Docker works too):
- apt:
sudo apt update
sudo apt install -y podman
- dnf:
sudo dnf install -y podman
- zypper:
sudo zypper install -y podman
Option 1: PostgreSQL + pgvector
Postgres gives you vectors where your relational data already lives. Great for hybrid queries (e.g., “top-10 semantically similar docs WHERE tenant_id=123 AND status='active'”).
1) Install PostgreSQL and build tools
- apt (Debian/Ubuntu):
sudo apt update
sudo apt install -y postgresql postgresql-contrib postgresql-server-dev-all build-essential git
sudo systemctl enable --now postgresql
- dnf (Fedora/RHEL/Alma/Rocky):
sudo dnf install -y postgresql-server postgresql-contrib postgresql-server-devel gcc make git
sudo postgresql-setup --initdb
sudo systemctl enable --now postgresql
- zypper (openSUSE/SLES):
sudo zypper install -y postgresql-server postgresql-contrib postgresql-devel gcc make git
sudo systemctl enable --now postgresql
2) Install pgvector from source (works across distros)
git clone https://github.com/pgvector/pgvector.git
cd pgvector
make
sudo make install
3) Enable the extension and create a demo table
sudo -u postgres psql -d postgres -c "CREATE EXTENSION IF NOT EXISTS vector;"
sudo -u postgres psql -d postgres <<'SQL'
DROP TABLE IF EXISTS items;
CREATE TABLE items (
id bigserial PRIMARY KEY,
embedding vector(3),
data text
);
-- Insert some toy 3D vectors
INSERT INTO items (embedding, data) VALUES
('[0.1, 0.2, 0.3]', 'alpha'),
('[0.9, 0.1, 0.2]', 'beta'),
('[0.05, 0.2, 0.1]', 'gamma'),
('[0.2, 0.1, 0.9]', 'delta');
-- Choose a distance; here we’ll build an IVF index for L2
CREATE INDEX ON items USING ivfflat (embedding vector_l2_ops) WITH (lists = 100);
ANALYZE items;
-- Query by vector: smaller distance is better for L2
SELECT id, data, (embedding <-> '[0.1,0.2,0.25]') AS distance
FROM items
ORDER BY embedding <-> '[0.1,0.2,0.25]'
LIMIT 3;
SQL
Notes:
Choose dimension to match your embedding model (e.g., 384, 768, 1024, 1536).
For cosine similarity: store normalized vectors or use
vector_cosine_ops.For approximate search: adjust
lists(index) andivfflat.probes(session) for speed/recall tradeoffs.
Option 2: Qdrant (HTTP-first, fast, simple)
Qdrant is a dedicated vector database with an ergonomic REST API and strong filtering.
1) Run Qdrant via Podman
podman run -d --name qdrant \
-p 6333:6333 \
-v qdrant_storage:/qdrant/storage \
docker.io/qdrant/qdrant:latest
2) Create a collection (3D vectors; cosine distance)
curl -s -X PUT "http://localhost:6333/collections/demo" \
-H "Content-Type: application/json" \
-d '{
"vectors": { "size": 3, "distance": "Cosine" }
}' | jq
3) Upsert points with payloads
curl -s -X PUT "http://localhost:6333/collections/demo/points" \
-H "Content-Type: application/json" \
-d '{
"points": [
{"id": 1, "vector": [0.1,0.2,0.3], "payload": {"doc": "alpha", "tenant": 1}},
{"id": 2, "vector": [0.9,0.1,0.2], "payload": {"doc": "beta", "tenant": 1}},
{"id": 3, "vector": [0.05,0.2,0.1],"payload": {"doc": "gamma", "tenant": 2}},
{"id": 4, "vector": [0.2,0.1,0.9], "payload": {"doc": "delta", "tenant": 2}}
]
}' | jq
4) Search with a filter
curl -s -X POST "http://localhost:6333/collections/demo/points/search" \
-H "Content-Type: application/json" \
-d '{
"vector": [0.1,0.2,0.25],
"limit": 3,
"with_payload": true,
"filter": {"must": [{"key": "tenant", "match": {"value": 1}}]}
}' | jq
Tip: For production, tune HNSW parameters (m, ef_construct, ef) and quantization/compression as needed.
Option 3: Weaviate (schema + GraphQL/REST)
Weaviate adds a flexible schema and GraphQL interface. You can use external vectorizers or push your own vectors.
1) Run Weaviate via Podman
podman run -d --name weaviate \
-p 8080:8080 \
-e QUERY_DEFAULTS_LIMIT=25 \
-e AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED=true \
-e PERSISTENCE_DATA_PATH=/var/lib/weaviate \
-v weaviate_data:/var/lib/weaviate \
docker.io/semitechnologies/weaviate:latest
2) Create a class (no built-in vectorizer; we’ll supply vectors)
curl -s -X POST "http://localhost:8080/v1/schema" \
-H "Content-Type: application/json" \
-d '{
"classes": [{
"class": "Doc",
"vectorizer": "none",
"properties": [{"name": "text", "dataType": ["text"]}]
}]
}' | jq
3) Insert objects with custom vectors
curl -s -X POST "http://localhost:8080/v1/objects" \
-H "Content-Type: application/json" \
-d '{"class":"Doc","properties":{"text":"alpha"},"vector":[0.1,0.2,0.3]}' | jq
curl -s -X POST "http://localhost:8080/v1/objects" \
-H "Content-Type: application/json" \
-d '{"class":"Doc","properties":{"text":"beta"},"vector":[0.9,0.1,0.2]}' | jq
4) GraphQL query by vector
curl -s "http://localhost:8080/v1/graphql" \
-H "Content-Type: application/json" \
-d '{"query":"{ Get { Doc(nearVector:{vector:[0.1,0.2,0.25]}, limit:3) { text _additional { distance } } } }"}' | jq
Tip: If you prefer integrated embeddings, enable and configure a vectorizer module (e.g., text2vec-*), or route embedding generation through your app and pass vectors explicitly as above.
Real-world tips for better results
Pick the right metric:
- Cosine: scale-invariant semantic similarity (common default for text embeddings).
- Dot product: ranking focus when vectors are not normalized.
- L2: useful in many numeric spaces and when models are tuned for Euclidean distance.
Normalize vectors consistently when using cosine:
norm_vec() { # usage: norm_vec "0.1 0.2 0.3"
read -ra a <<<"$1"; s=0; for x in "${a[@]}"; do s=$(awk -v s="$s" -v x="$x" 'BEGIN{print s + x*x}'); done
mag=$(awk -v s="$s" 'BEGIN{print sqrt(s)}')
out=(); for x in "${a[@]}"; do out+=($(awk -v x="$x" -v m="$mag" 'BEGIN{print x/m}')); done
printf '%s\n' "${out[*]}"
}
Index tuning matters:
- pgvector IVF: increase
lists(index build) andivfflat.probes(query) for recall; trade for latency. - Qdrant HNSW: tune
ef(query-time) andef_construct/m(build-time).
- pgvector IVF: increase
Store metadata:
- Keep tenant, timestamps, tags alongside vectors for filtered search.
Batch inserts:
- Use bulk endpoints/transactions to minimize index rebuild overhead.
Conclusion and next steps
Vector databases turn embeddings into a live, searchable memory for your AI systems. Start where you are:
Already on Postgres? Enable pgvector and ship.
Need a lean, HTTP-first engine? Spin up Qdrant.
Prefer schema + GraphQL? Try Weaviate.
Your next step:
Stand up one of the quickstarts above on your distro.
Swap the toy 3D vectors for real embeddings from your model.
Add filters and tune index parameters to hit your latency/recall goals.
Have a favorite workflow or a gotcha worth sharing? Drop it in your team docs or open a gist—your future self (and your users) will thank you.