Mục lục
- Mục tiêu bài học
- Vector Database là gì
- Khác SQL và NoSQL
- Core operations
- Approximate Nearest Neighbor (ANN)
- Index types — HNSW, IVF, Flat, PQ
- Landscape 2024-2026
- Vì sao ChromaDB cho prototype
- Cài đặt ChromaDB
- Basic usage
- ChromaDB tự embed — embedding_function
- Pass vector explicit
- Metadata filter — where và where_document
- Distance metric
- Persistent vs In-memory
- Server mode — HttpClient
- Pinecone — managed alternative
- Qdrant — open-source Rust
- pgvector — Postgres extension
- Bảng so sánh nhanh
- Cost considerations
- Scale rules
- Backup và recovery
- Multi-tenant
- Hybrid search support
- Full code — ChromaDB end-to-end
- Bài tập
Mục tiêu bài học
Sau bài này, bạn cần:
- Giải thích được vector DB khác SQL/NoSQL ở điểm nào (similarity vs exact match).
- Biết bốn core operation: insert, search top-K, update/delete by ID, metadata filter.
- Phân biệt exact NN (Flat) và Approximate NN (HNSW, IVF, ScaNN, PQ) — trade-off giữa speed và accuracy.
- Đọc tên ~10 vector DB phổ biến và biết chọn cái nào cho prototype / managed / open-source / serverless / pgvector.
- Cài và chạy ChromaDB end-to-end: tạo collection, add document, query top-K, metadata filter, switch embedding function, persistent client.
- Biết khi nào nên rời ChromaDB sang Pinecone/Qdrant/Milvus (scale, deployment, hybrid).
Bài này là basic. Chi tiết similarity (cosine/dot/euclidean) và HNSW vs IVF sẽ đào sâu ở Bài 39.
Vector Database là gì
Vector database là database chuyên cho hai việc:
- Lưu trữ vector (mỗi vector là array float, thường 384-3072 chiều) cùng metadata kèm theo.
- Trả lời câu hỏi "K vector nào trong store gần nhất với vector query này?" trong thời gian dưới giây, kể cả khi store có hàng triệu vector.
Ngữ cảnh RAG: mỗi chunk văn bản được embedding ở Bài 36 cho ra 1 vector; vector này được lưu cùng document (text gốc) và metadata (source, page, tenant_id, timestamp). Lúc query, ta embedding câu hỏi rồi tìm top-K chunk gần nhất.
Phân biệt nhanh: vector DB không tự sinh embedding (trừ wrapper tiện ích như ChromaDB). Phần embedding vẫn do model riêng làm; vector DB chỉ lo storage + search.
Khác SQL và NoSQL
Khác biệt cốt lõi nằm ở loại truy vấn:
- SQL / NoSQL truyền thống: exact match hoặc range —
WHERE name = 'Alice',WHERE age > 18. Index B-tree, hash. Câu hỏi "Hàng nào bằng X?". - Vector DB: similarity search trong không gian vector high-dim — "K vector nào gần nhất với
qtheo cosine/L2?". Index HNSW/IVF. Câu hỏi "Hàng nào giống X nhất?".
Hai loại truy vấn có thể cùng tồn tại trên cùng dataset. Vector DB hiện đại đều cho phép kết hợp filter metadata kiểu SQL với similarity search — gọi là filtered vector search hoặc hybrid query.
Ngược lại, vector DB không thay thế SQL: nó không phù hợp cho transaction (ACID, join nhiều bảng, foreign key). Trong system thật, vector DB thường chạy song song với Postgres/Mongo, không thay.
Core operations
Mọi vector DB đều support bốn nhóm operation, tên có thể khác nhưng concept giống:
- Insert / Upsert — add một (hoặc batch) record gồm
id, vector, metadata, và (tuỳ) text gốc. - Search — given vector
qvàK, trả về top-K record có similarity cao nhất, kèm distance/score. - Update / Delete — by
id(đôi khi by filter). Vector DB không có concept "transaction" như RDBMS. - Filter — kết hợp với search: chỉ tìm trong subset thoả metadata (
where source = 'doc1' AND year >= 2024).
Một số DB còn có: count, list ID, get by ID (không qua similarity), peek (xem N record đầu để debug). ChromaDB có cả nhóm này.
Approximate Nearest Neighbor (ANN)
Tìm K vector gần nhất bằng cách quét hết store (brute-force / exact NN) là O(n) cho mỗi query — với 10 triệu vector × 768 chiều, mỗi query mất vài giây và CPU bão hoà. Không scale.
ANN — Approximate Nearest Neighbor đánh đổi một phần accuracy lấy speed: chấp nhận thỉnh thoảng miss 1 trong top-K, nhưng query chạy O(log n) hoặc sub-linear. Trên dataset triệu vector, ANN tốt thường đạt recall@10 ≥ 0.95 trong vài ms.
Các thuật toán ANN phổ biến: HNSW (graph-based, Yury Malkov 2016, arXiv 1603.09320), IVF (Inverted File, Faiss/Jegou), ScaNN (Google Research, 2020), PQ (Product Quantization). Mỗi loại có ưu nhược; chi tiết ở Bài 39.
Bài này chỉ cần nhớ: vector DB production = ANN index. Exact NN chỉ dùng cho dataset rất nhỏ hoặc dùng để baseline đo recall của ANN.
Index types — HNSW, IVF, Flat, PQ
- HNSW (Hierarchical Navigable Small World) — graph-based, mỗi node nối với một số neighbor cùng layer; tìm kiếm đi từ layer trên xuống. Fast và accurate; tốn RAM (giữ graph trong memory). Default của ChromaDB, Qdrant, Weaviate, Milvus.
- IVF (Inverted File) — cluster vector thành
nlistcụm (k-means). Query chỉ scannprobecụm gần nhất. Ít RAM hơn HNSW, accuracy thấp hơn nếunprobenhỏ. Faiss có nhiều biến thể IVF + PQ. - Flat (Brute-force) — không index, scan tất cả. Exact NN, recall = 1.0, nhưng O(n). Dùng cho dataset dưới ~10K vector hoặc làm baseline.
- PQ (Product Quantization) — kỹ thuật nén vector: chia vector thành sub-vector, mỗi sub-vector được mã hoá thành 1 byte (codebook 256 entry). Giảm RAM 4-32×; mất chút accuracy. Thường ghép với IVF (IVF-PQ).
Đa số vector DB cho phép chọn index khi tạo collection và set hyperparameter (HNSW: M, ef_construction, ef_search; IVF: nlist, nprobe). ChromaDB hiện cố định HNSW — đủ cho prototype.
Landscape 2024-2026
10 cái tên hay gặp:
- ChromaDB — open-source, embedded (chạy chung process Python), file storage local. Prototype, demo, app cá nhân.
- Pinecone — managed, không tự host. Có Serverless tier (pay-per-use) và Pod tier (reserved). Khởi tạo nhanh, scale tự lo.
- Qdrant — open-source, viết bằng Rust, HNSW. Self-host hoặc Qdrant Cloud. Filtered search rất mạnh, hybrid (sparse+dense) native.
- Weaviate — open-source, GraphQL API, có module ML built-in (vectorizer, generative). Self-host hoặc Weaviate Cloud.
- Milvus — open-source, distributed (separate compute/storage), nhiều index Faiss. Cho deployment quy mô tỷ vector.
- pgvector — extension cho Postgres, thêm kiểu
vectorvà toán tử<->. Dùng khi đã có Postgres và không muốn thêm DB thứ hai. - Redis (Redis Stack) — vector module, HNSW. Tận dụng Redis có sẵn.
- Elasticsearch / OpenSearch — vector search ghép với BM25; mạnh khi cần hybrid và đã có cluster ES.
- LanceDB — serverless, file format Lance trên S3/local. Embedded như ChromaDB nhưng cho scale lớn hơn.
- MongoDB Atlas Vector Search — vector field trong MongoDB Atlas, query qua aggregation pipeline.
Còn nhiều cái khác (Vespa, Marqo, Vald, Turbopuffer...). Danh sách trên đủ phủ ~90% job description AI Engineer 2025-2026.
Vì sao ChromaDB cho prototype
ChromaDB phù hợp khi học và làm prototype vì:
- Embedded — không cần server riêng, chạy trong cùng Python process.
pip installxong là dùng được. - API gọn — chỉ vài method:
create_collection,add,query,get,delete. Học trong 30 phút. - Tự embed — nếu không truyền
embeddings, ChromaDB tự gọiall-MiniLM-L6-v2(sentence-transformers, 384-dim) để embeddingdocuments. Có thể swap sang OpenAI, Cohere, custom function. - Persistent local —
PersistentClient(path=...)ghi xuống disk (SQLite + parquet); restart vẫn còn data. - Có server mode — khi muốn deploy, chạy
chroma runrồi đổi sangHttpClientmà không phải viết lại app.
Giới hạn: ChromaDB không tối ưu cho dataset rất lớn (> vài triệu vector), không có hybrid sparse+dense native, không phù hợp multi-node distributed. Lúc đó chuyển Qdrant, Milvus, hoặc managed.
Cài đặt ChromaDB
pip install chromadb
Phiên bản tham chiếu khi viết bài: chromadb >= 0.5. Cài kèm sentence-transformers để dùng default embedding function (ChromaDB sẽ tự pull all-MiniLM-L6-v2 lần đầu).
pip install chromadb sentence-transformers
Nếu muốn dùng OpenAI embedding function thì cần thêm openai:
pip install openai
Basic usage
Vòng đời tối thiểu — client, collection, add, query:
import chromadb
client = chromadb.Client() # in-memory, mất khi process kết thúc
collection = client.create_collection("my_docs")
collection.add(
documents=["Python is great", "AI is fun"],
metadatas=[{"source": "doc1"}, {"source": "doc2"}],
ids=["id1", "id2"],
)
results = collection.query(
query_texts=["Tell me about Python"],
n_results=2,
)
print(results)
Vì không truyền embeddings, ChromaDB tự embed documents và query_texts bằng default model. Kết quả results là dict có keys ids, documents, metadatas, distances — mỗi cái là list-of-list (outer list = số query, inner list = top-K).
ids bắt buộc duy nhất trong collection. Lần add tiếp với id trùng sẽ lỗi; dùng upsert nếu muốn ghi đè.
ChromaDB tự embed — embedding_function
Default embedding_function là SentenceTransformerEmbeddingFunction với model all-MiniLM-L6-v2 (384-dim, tiếng Anh là chính). Đủ cho demo, không tốt cho tiếng Việt hoặc multilingual — xem Bài 36 để chọn model phù hợp.
Đổi sang OpenAI:
from chromadb.utils import embedding_functions
ef = embedding_functions.OpenAIEmbeddingFunction(
api_key="sk-...",
model_name="text-embedding-3-small",
)
collection = client.create_collection(
name="my_docs",
embedding_function=ef,
)
Quan trọng: embedding_function phải cố định cho cùng 1 collection. Add bằng model A rồi query bằng model B sẽ ra kết quả vô nghĩa (vector ở hai không gian khác nhau). Khi đổi model, làm collection mới và re-index toàn bộ.
ChromaDB cũng có sẵn function cho Cohere, HuggingFace Inference API, Google Vertex, Jina, Ollama. Tự viết được bằng cách extend EmbeddingFunction.
Pass vector explicit
Khi đã có pipeline embedding riêng (ví dụ batch trên GPU bằng sentence-transformers), truyền thẳng vector:
collection.add(
embeddings=[[0.1, 0.2, 0.3, 0.4], [0.5, 0.6, 0.7, 0.8]],
documents=["doc 1", "doc 2"],
metadatas=[{"page": 1}, {"page": 2}],
ids=["1", "2"],
)
results = collection.query(
query_embeddings=[[0.1, 0.2, 0.3, 0.4]],
n_results=2,
)
Khi pass embeddings + query_embeddings explicit, embedding_function không được gọi. Đây là cách bypass khi muốn kiểm soát hoàn toàn embedding (batch lớn, model on-prem, vector đến từ multi-modal).
Dimension của embeddings phải khớp giữa add và query, và tất cả vector trong cùng collection phải cùng dim.
Metadata filter — where và where_document
ChromaDB cho phép thu hẹp search bằng filter metadata trước/song song với similarity:
results = collection.query(
query_texts=["machine learning"],
n_results=5,
where={"source": "doc1"}, # exact match metadata
where_document={"$contains": "Python"}, # search trong text document
)
Operator metadata: $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin, $and, $or. Ví dụ filter "năm 2024 hoặc 2025":
where={"year": {"$in": [2024, 2025]}}
where_document chỉ có $contains và $not_contains (substring matching, không phải full-text search như BM25). Cho hybrid search thật sự, xem Qdrant/Weaviate/Elasticsearch.
Distance metric
ChromaDB support ba distance metric, set khi tạo collection qua metadata={"hnsw:space": ...}:
l2— Euclidean (mặc định). Khoảng cách Euclidean bình phương.cosine— 1 − cosine similarity. Recommended cho embedding text (embedding thường đã được normalize hoặc gần normalize).ip— Inner Product (negative dot product). Dùng khi vector không normalize và muốn ưu tiên magnitude.
collection = client.create_collection(
name="my_docs",
metadata={"hnsw:space": "cosine"},
)
Distance metric không đổi được sau khi tạo collection. Sai metric chỉ gây xếp hạng kém hơn, không gây crash. Chi tiết so sánh cosine vs dot vs L2 ở Bài 39.
Persistent vs In-memory
import chromadb
# In-memory — data mất khi process kết thúc
client = chromadb.Client()
# Persistent — ghi xuống disk
client = chromadb.PersistentClient(path="./chroma_db")
PersistentClient tạo folder ./chroma_db chứa SQLite metadata + parquet vector. Restart Python, gọi lại chromadb.PersistentClient(path="./chroma_db") và client.get_collection(...) là tiếp tục được.
Đừng dùng cùng một path từ hai process khác nhau — SQLite lock sẽ gây lỗi. Nếu cần share cho nhiều process, chuyển sang server mode.
Server mode — HttpClient
Khi cần share data giữa nhiều service hoặc deploy lên server, chạy ChromaDB ở chế độ standalone:
chroma run --host 0.0.0.0 --port 8000 --path ./chroma_db
Từ app Python, đổi client:
client = chromadb.HttpClient(host="localhost", port=8000)
collection = client.get_or_create_collection("my_docs")
Phần code dùng collection.add, collection.query giữ nguyên — đây là điểm tiện của ChromaDB: cùng API cho embedded và HTTP.
Lưu ý: chroma run ở chế độ default không có auth. Trong môi trường thật, bọc reverse proxy (Nginx/Caddy) + token, hoặc đặt sau VPC.
Pinecone — managed alternative
Pinecone là managed vector DB — không tự host, dùng SDK gọi qua HTTPS. Pinecone tự lo scale, backup, multi-region.
from pinecone import Pinecone, ServerlessSpec
pc = Pinecone(api_key="...")
pc.create_index(
name="my-index",
dimension=1536,
metric="cosine",
spec=ServerlessSpec(cloud="aws", region="us-east-1"),
)
index = pc.Index("my-index")
index.upsert(vectors=[
{"id": "1", "values": [0.1] * 1536, "metadata": {"source": "doc1"}},
])
results = index.query(
vector=[0.1] * 1536,
top_k=5,
include_metadata=True,
)
Pinecone không tự embed — phải truyền vector explicit. Có hai tier: Serverless (pay-per-use, scale tự động), Pod (reserved resource, ổn định latency, đắt hơn).
Trade-off: tiện hơn ChromaDB cho production (HA, backup, scale), nhưng phải trả tiền hàng tháng và vendor lock-in mức độ vừa.
Qdrant — open-source Rust
Qdrant là open-source vector DB viết bằng Rust; performance tốt, filtered search rất mạnh (filter có index riêng, không brute-force qua kết quả ANN), hybrid sparse+dense native.
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct
client = QdrantClient(":memory:") # hoặc url="http://localhost:6333"
client.create_collection(
collection_name="my_docs",
vectors_config=VectorParams(size=384, distance=Distance.COSINE),
)
client.upsert(
collection_name="my_docs",
points=[
PointStruct(id=1, vector=[0.1] * 384, payload={"source": "doc1"}),
],
)
results = client.search(
collection_name="my_docs",
query_vector=[0.1] * 384,
limit=5,
)
Self-host bằng Docker: docker run -p 6333:6333 qdrant/qdrant. Có Qdrant Cloud nếu không muốn vận hành.
Chọn Qdrant khi: cần filtered search nặng, cần hybrid sparse+dense, ngân sách hạn chế (self-host rẻ), muốn open-source nhưng API trưởng thành hơn ChromaDB.
pgvector — Postgres extension
pgvector thêm kiểu vector và toán tử distance vào Postgres:
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE items (
id bigserial PRIMARY KEY,
embedding vector(1536),
source text
);
INSERT INTO items (embedding, source)
VALUES ('[0.1, 0.2, ...]', 'doc1');
-- <-> = L2, <=> = cosine, <#> = inner product
SELECT id, source, embedding <=> '[0.3, 0.1, ...]' AS distance
FROM items
ORDER BY embedding <=> '[0.3, 0.1, ...]'
LIMIT 5;
-- Index HNSW (pgvector 0.5+)
CREATE INDEX ON items USING hnsw (embedding vector_cosine_ops);
Use case chính: đã có Postgres rồi và không muốn vận hành thêm DB riêng. Join với bảng quan hệ trong cùng query, transaction ACID, backup chung với DB. Scale lên ~10M vector vẫn ổn nếu tune index đúng.
Hạn chế: ít tính năng vector-native hơn Qdrant/Pinecone (không sparse+dense hybrid built-in, không multi-tenant tích hợp). Khi cần các thứ này, tách ra DB riêng.
Bảng so sánh nhanh
| Nhu cầu | Đề xuất | Lý do |
|---|---|---|
| Prototype, demo, app cá nhân | ChromaDB | Embedded, không server, API đơn giản |
| Managed production, không muốn vận hành | Pinecone | Serverless, HA, backup tự lo |
| Open-source + scale + filtered/hybrid | Qdrant, Milvus, Weaviate | Self-host, feature đầy đủ |
| Đã có Postgres, dataset < 10M | pgvector | Join + transaction trong cùng DB |
| Serverless file-based scale lớn | LanceDB | Format Lance trên S3, không server |
| Có Redis/ES sẵn | Redis Stack / Elasticsearch | Tận dụng infra cũ |
| Trong stack MongoDB Atlas | MongoDB Atlas Vector | Cùng cluster, query aggregation |
Quy tắc thực tế: bắt đầu với ChromaDB hoặc pgvector cho prototype, đo metric thật, khi đụng giới hạn (latency, scale, feature) mới migrate.
Cost considerations
Ba thành phần chi phí:
- Managed — fee hàng tháng + per-vector / per-query cost. Pinecone Serverless tính theo storage GB-month + read/write unit. Dễ dự đoán khi traffic ổn định, đắt nếu traffic spike.
- Self-host — VM/EC2 + disk + maintenance time. Đỡ tiền nhưng tốn người. Tốt khi đã có team DevOps.
- Storage scale — ước lượng nhanh: 1 vector × 1536 dim × 4 byte (float32) ≈ 6 KB. 1 triệu vector ≈ 6 GB raw. HNSW index thêm ~50-100% RAM. Nếu nén PQ, giảm 4-32×.
Mẹo giảm cost: dùng embedding model dim thấp hơn nếu phù hợp (Bài 36 — Matryoshka, dim 384/768 thay 1536/3072), bật quantization (int8/PQ), tách hot/cold collection.
Scale rules
- < 100K vector — ChromaDB in-memory hoặc Persistent. Latency vài ms trên laptop. Đủ cho hầu hết RAG cá nhân / nội bộ team nhỏ.
- 100K – 10M vector — Qdrant self-host, Pinecone Serverless, Weaviate, pgvector + HNSW. Bắt đầu cần tune
ef_search, đo recall. - > 10M vector — Pinecone Pod / Milvus distributed / Qdrant cluster. Cần sharding, replica, có thể PQ/quantization để fit RAM. Đo cả throughput query/s, không chỉ latency.
Đây là rule of thumb, không phải giới hạn cứng. Cá biệt có team chạy 100K vector trên ChromaDB embedded production thành công, hoặc đẩy pgvector lên 50M với hardware mạnh.
Backup và recovery
- ChromaDB Persistent — copy cả folder
./chroma_dbkhi server đã stop. Snapshot disk volume nếu trên cloud. Restore = bỏ folder back lại. - Managed (Pinecone, Weaviate Cloud, Qdrant Cloud) — built-in snapshot/backup, restore qua UI hoặc API.
- Self-host — backup volume Docker / mount point, hoặc dùng cơ chế snapshot riêng (Qdrant có
POST /collections/{name}/snapshots). - pgvector — backup cùng Postgres (
pg_dump, WAL archive, PITR). Đây là plus lớn nếu team đã quen Postgres backup.
Nên test restore định kỳ — đặc biệt với ChromaDB embedded, dễ bỏ quên cho đến lúc crash.
Multi-tenant
Hai pattern thường dùng khi app phục vụ nhiều khách / nhiều user:
- Collection per tenant — mỗi tenant 1 collection riêng. Isolation tốt, dễ delete/export theo tenant. Tốn metadata overhead nếu nhiều tenant nhỏ (hàng nghìn).
- Metadata filter
tenant_id— chung một collection, filterwhere={"tenant_id": "..."}. Đỡ overhead, nhưng bắt buộc luôn filter đúng — bug ở app code = leak dữ liệu giữa tenant.
Qdrant có concept "tenant_id" + payload index riêng, tối ưu cho pattern thứ hai. ChromaDB không có gì đặc biệt — phải tự kỷ luật trong code.
Khi compliance nghiêm (HIPAA, GDPR strict), thường chọn collection per tenant hoặc thậm chí DB instance riêng.
Hybrid search support
Hybrid search = kết hợp sparse (BM25, SPLADE — match keyword) và dense (vector embedding — match nghĩa). Cải thiện recall trên query có term hiếm (tên riêng, mã sản phẩm, viết tắt).
- Qdrant — sparse + dense native, fusion bằng RRF (Reciprocal Rank Fusion).
- Weaviate —
hybridoperator built-in, alpha parameter. - Pinecone — sparse-dense index từ 2023.
- Elasticsearch / OpenSearch — BM25 đã có sẵn + thêm vector, kết hợp dễ.
- ChromaDB — dense only, không có sparse native (chỉ có
$containssubstring).
Nếu prototype đã thấy cần hybrid (query nhiều keyword hiếm), nên bỏ qua ChromaDB và chuyển thẳng Qdrant/Weaviate.
Full code — ChromaDB end-to-end
import chromadb
from chromadb.utils import embedding_functions
# 1. Persistent client
client = chromadb.PersistentClient(path="./chroma_db")
# 2. Embedding function — default MiniLM cho prototype
ef = embedding_functions.SentenceTransformerEmbeddingFunction(
model_name="all-MiniLM-L6-v2"
)
# 3. Collection — cosine distance
collection = client.get_or_create_collection(
name="notes",
embedding_function=ef,
metadata={"hnsw:space": "cosine"},
)
# 4. Add documents
docs = [
"Python là ngôn ngữ thông dịch, dynamic typing.",
"Rust là ngôn ngữ compile, ownership system.",
"Go là ngôn ngữ compile, garbage collected.",
"JavaScript chạy trên trình duyệt và Node.js.",
]
metas = [
{"source": "wiki", "year": 2024},
{"source": "wiki", "year": 2024},
{"source": "blog", "year": 2025},
{"source": "wiki", "year": 2025},
]
ids = [f"doc_{i}" for i in range(len(docs))]
collection.upsert(documents=docs, metadatas=metas, ids=ids)
# 5. Query với filter
results = collection.query(
query_texts=["ngôn ngữ có garbage collector"],
n_results=3,
where={"year": {"$gte": 2024}},
)
for doc, meta, dist in zip(
results["documents"][0],
results["metadatas"][0],
results["distances"][0],
):
print(f"[{dist:.3f}] {meta} — {doc}")
Chạy file này hai lần: lần đầu add data, lần hai (sau khi comment block add) data vẫn còn nhờ PersistentClient. Đó là điểm khác chính so với chromadb.Client().
Để compare với Pinecone managed: cùng dataset, embed riêng, upsert vào Pinecone index, đo latency, đo cost — đây là bài tập tốt cho lần học sau (xem mục bài tập).
Bài tập
- Lấy 100 đoạn văn bản (5-10 câu mỗi đoạn) — có thể là intro 100 bài blog, 100 mô tả phim, hoặc 100 issue GitHub. Add vào một collection ChromaDB
PersistentClient, dùng default embedding function. Query top-5 với 3 câu hỏi khác nhau, indistanceđể so sánh. - Thêm metadata
{"category": ...}với 3-4 category tự đặt. Lặp lại query nhưng có filterwhere={"category": "..."}. So sánh kết quả với và không filter — nhận xét trường hợp filter cứu hay phá kết quả. - Tạo collection mới với
OpenAIEmbeddingFunction(modeltext-embedding-3-small). Add cùng tập 100 đoạn, query lại 3 câu hỏi cũ, so sánh top-5 với MiniLM. Note ít nhất 2 trường hợp model khác cho ra ranking khác. - Tắt Python, mở lại, gọi
chromadb.PersistentClient(path="./chroma_db")rồiget_collection. Verifycollection.count()đúng và query vẫn ra kết quả như trước. - (Tùy chọn) Chạy
chroma run --host 0.0.0.0 --port 8000 --path ./chroma_dbở một terminal. Ở terminal khác, dùngchromadb.HttpClient(host="localhost", port=8000)để query cùng collection. Confirm cùng kết quả với mode embedded. - (Tùy chọn) Cài Qdrant qua Docker (
docker run -p 6333:6333 qdrant/qdrant), upsert cùng 100 đoạn (embed thủ công bằngsentence-transformers), so sánh latency query với ChromaDB trên cùng máy.
- ChromaDB — Documentation
- ChromaDB — Configure collection (hnsw:space, embedding_function)
- ChromaDB — Metadata filtering ($eq, $in, $and...)
- Pinecone — What is a Vector Database
- Pinecone — Quickstart (Serverless)
- Qdrant — Quickstart
- Qdrant — Hybrid search (sparse + dense, RRF)
- Weaviate — Hybrid search
- Milvus — Overview (distributed vector DB)
- pgvector — Postgres extension
- LanceDB — Documentation
- Malkov, Yashunin — Efficient and robust approximate nearest neighbor search using HNSW (arXiv 1603.09320)
- Faiss — Wiki (IVF, PQ, OPQ)
- Google Research — ScaNN announcement
- sentence-transformers — Pretrained models (all-MiniLM-L6-v2)
