Danh sách bài viết

Bài 37: Vector Database basic — ChromaDB cho prototype

Bài 36 đã chọn được embedding model — giờ phải có chỗ lưu vector và tìm theo similarity. Vector Database là database chuyên cho việc này: insert vector + metadata, query top-K nearest neighbor trong không gian high-dim, filter theo metadata. Bài này định nghĩa vector DB, đối chiếu với SQL/NoSQL, đi qua core operations và Approximate Nearest Neighbor (HNSW, IVF, ScaNN, PQ, Flat), điểm danh landscape 2024-2026 (ChromaDB, Pinecone, Qdrant, Weaviate, Milvus, pgvector, Redis, Elasticsearch, LanceDB, MongoDB Atlas Vector), rồi tập trung vào ChromaDB cho prototype: in-memory vs PersistentClient vs HttpClient server mode, collection, embedding_function (default all-MiniLM-L6-v2 hoặc OpenAI), pass embeddings explicit, metadata filter (where, where_document), distance metric (l2/cosine/ip). So sánh ngắn với Pinecone, Qdrant, pgvector. Cuối bài là cost, scale rules, backup, multi-tenant, hybrid search và bài tập.

25/05/2026
14 phút đọc
0 lượt xem
1

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.

2

Vector Database là gì

Vector database là database chuyên cho hai việc:

  1. Lưu trữ vector (mỗi vector là array float, thường 384-3072 chiều) cùng metadata kèm theo.
  2. 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.

3

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 q theo 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.

4

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 qK, 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.

5

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.

6

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 nlist cụm (k-means). Query chỉ scan nprobe cụm gần nhất. Ít RAM hơn HNSW, accuracy thấp hơn nếu nprobe nhỏ. 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.

7

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 vector và 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.

8

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 install xong 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ọi all-MiniLM-L6-v2 (sentence-transformers, 384-dim) để embedding documents. Có thể swap sang OpenAI, Cohere, custom function.
  • Persistent localPersistentClient(path=...) ghi xuống disk (SQLite + parquet); restart vẫn còn data.
  • Có server mode — khi muốn deploy, chạy chroma run rồi đổi sang HttpClient mà 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.

9

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
10

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 documentsquery_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 đè.

11

ChromaDB tự embed — embedding_function

Default embedding_functionSentenceTransformerEmbeddingFunction 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.

12

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.

13

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$not_contains (substring matching, không phải full-text search như BM25). Cho hybrid search thật sự, xem Qdrant/Weaviate/Elasticsearch.

14

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.

15

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")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.

16

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.

17

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.

18

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.

19

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.

20

Bảng so sánh nhanh

Nhu cầuĐề xuấtLý do
Prototype, demo, app cá nhânChromaDBEmbedded, không server, API đơn giản
Managed production, không muốn vận hànhPineconeServerless, HA, backup tự lo
Open-source + scale + filtered/hybridQdrant, Milvus, WeaviateSelf-host, feature đầy đủ
Đã có Postgres, dataset < 10MpgvectorJoin + transaction trong cùng DB
Serverless file-based scale lớnLanceDBFormat Lance trên S3, không server
Có Redis/ES sẵnRedis Stack / ElasticsearchTận dụng infra cũ
Trong stack MongoDB AtlasMongoDB Atlas VectorCù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.

21

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.

22

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.

23

Backup và recovery

  • ChromaDB Persistent — copy cả folder ./chroma_db khi 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.

24

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, filter where={"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.

25

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).
  • Weaviatehybrid operator 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ó $contains substring).

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.

26

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).

27

Bài tập

  1. 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, in distance để so sánh.
  2. Thêm metadata {"category": ...} với 3-4 category tự đặt. Lặp lại query nhưng có filter where={"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ả.
  3. Tạo collection mới với OpenAIEmbeddingFunction (model text-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.
  4. Tắt Python, mở lại, gọi chromadb.PersistentClient(path="./chroma_db") rồi get_collection. Verify collection.count() đúng và query vẫn ra kết quả như trước.
  5. (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ùng chromadb.HttpClient(host="localhost", port=8000) để query cùng collection. Confirm cùng kết quả với mode embedded.
  6. (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ằng sentence-transformers), so sánh latency query với ChromaDB trên cùng máy.