02 Chroma_集合(Collection)与文档(Document)初体验

02 Chroma_集合(Collection)与文档(Document)初体验

💡 一句话核心概念

Collection 是向量数据库的"表",Document 是你要存的"记忆片段"------一个管结构,一个管内容。搞懂这俩,Chroma 的大门就算踹开了。


🧩 关键实操

1. 理解 Collection:不只是"表"

python 复制代码
# 02_collection_basics.py
from chromadb import Client
​
client = Client()
​
# ===== Collection 三大核心参数 =====
# name: 集合名(必填,相当于表名)
# metadata: 集合级别的元数据(比如 hnsw 索引参数)
# embedding_function: 指定嵌入模型(下一章细讲,先不管)
​
# 创建一个"知识库"风格的集合
kb = client.create_collection(
    name="tech_kb",  # 技术知识库
    metadata={
        "description": "存放技术文档的向量知识库",
        "hnsw:space": "cosine",  # 指定距离算法,默认是 l2(欧几里得)
        "created_by": "chroma-tutorial",
    },
)
​
# 看看已经有哪些集合(刚创建的都会列出来)
print("📋 现有集合:", client.list_collections())
arduino 复制代码
uv run python 02_collection_basics.py

2. 添加文档:向量的前世今生

ini 复制代码
# 02_add_docs.py
from chromadb import Client
​
client = Client()
kb = client.get_or_create_collection(name="tech_kb")
# ↑ get_or_create 是懒人福音:有就复用,没有就创建,不会像 create 那样重复创建报错
​
# 添加文档的四种姿势
kb.add(
    documents=[
        "Python 的 GIL 是全局解释器锁,它让多线程变成伪并行。",
        "uv 是一个用 Rust 写的 Python 包管理器,比 pip 快 100 倍。",
        "向量数据库通过 Embedding 模型把文本变成高维向量,实现语义搜索。",
    ],
    metadatas=[
        {"topic": "Python", "difficulty": "进阶", "source": "官方文档"},
        {"topic": "工具链", "difficulty": "入门", "source": "astral.sh"},
        {"topic": "向量数据库", "difficulty": "中级", "source": "chroma docs"},
    ],
    ids=["py_gil", "uv_intro", "vectordb_intro"],
)
​
print(f"✅ 添加了 {kb.count()} 条文档到集合")

ids 不传会怎样? 直接抛异常。Chroma 在这一点上很固执------每条文档必须有唯一 ID,方便后续更新/删除。这跟 MongoDB 的 _id 是一个道理。

3. 查询:语义搜索的"啊哈时刻"

python 复制代码
# 02_query_docs.py
from chromadb import Client
​
client = Client()
kb = client.get_or_create_collection(name="tech_kb")
​
# 用中文搜
results = kb.query(
    query_texts=["怎么管理 Python 依赖包比较好?"],
    n_results=2,
    # include 控制返回字段,不指定默认返回所有
    # include=["documents", "metadatas", "distances"],
)
​
print("🔍 查询结果:")
for i, (doc_id, doc, meta, dist) in enumerate(zip(
    results["ids"][0],
    results["documents"][0],
    results["metadatas"][0],
    results["distances"][0],
)):
    print(f"  #{i+1} | ID: {doc_id} | 距离: {dist:.4f}")
    print(f"      文档: {doc}")
    print(f"      元数据: {meta}")
    print()

运行后你会发现------即使查询词和原文没一个完全匹配的词,Chroma 也能把"uv 是包管理器"这条排到第一位。这就是向量搜索的魔法:搜的是"意思",不是"字面"。


🚧 避坑指南

现象 解法
重复 create_collection ValueError: Collection already exists get_or_create_collection() 代替,或者 create_collection(name, get_or_create=True)
embedding 维度不一致 添加文档时报 dimension mismatch 同一集合必须用同一个 embedding 函数。要么全部用默认(all-MiniLM-L6-v2,384维),要么自定义但保持维度一致。第 3 章会深入讲
每次重启 Client() 数据没了 list_collections() 返回空 Client() 是内存模式,用 PersistentClient("./chroma_data") 代替(第 6 章详讲)

🎤 Chroma 面试题与通关答案

Q1:Chroma 的 Collection 和传统数据库的 Table 有什么区别?

考点拆解: 向量数据库与关系型数据库的核心设计差异。

通关答案:

维度 传统数据库 Table Chroma Collection
主查询方式 精确匹配(WHERE name = 'xxx' 语义相似度(ANN 近似最近邻)
索引核心 B-Tree / Hash HNSW 图索引
"列"的概念 固定 Schema,强类型 弱 Schema:documents + metadatas(JSON),向量自动生成
写入成本 O(log n) O(log n) + Embedding 计算(这是大头!)

底层原理: Collection 内部维护了三套存储:

  1. 向量索引(HNSW 图):负责 ANN 搜索,是 Chroma 的核心竞争力
  2. 元数据存储 (sqlite3):负责 WHERE 过滤和精确查询
  3. 文档存储(sqlite3):原始文本,查询结束后回表拼接

最佳实践: Collection 不适合存高频更新的数据(每次更新要重建向量+更新索引),更适合"写多读多但更新少"的知识库场景。

一句话总结: Table 是 Excel 表格,Collection 是"语义搜索引擎的索引库"------前者精确定位,后者理解含义。


Q2:query() 返回的 distances 字段代表什么?为什么越小越好?

考点拆解: 向量相似度度量,面试官最爱的算法基础题。

通关答案:

distances 是查询向量与结果向量之间的距离值 ,距离越小 = 语义越接近。但具体含义取决于集合的 hnsw:space 设置:

距离算法 范围 最优值 通俗解释
l2(欧几里得,默认) [0, ∞) 0 空间中两点的直线距离
cosine(余弦) [0, 2] 0 只关心方向,不关心长度(归一化后等同于 l2)
ip(内积/点积) (-∞, ∞) 越大越好 向量投影,-ip 转成距离用

避坑点: Chroma 默认是 l2,但 NLP 领域大家习惯用 cosine。如果你没在 metadata={"hnsw:space": "cosine"} 指定,出来的 distances 可能大到离谱(比如 50+),因为 l2 没做归一化。建议一律显式指定 cosine,跟行业对齐。

一句话总结: 距离是你和正确答案之间的"语义差距"------l2 像直线距离,cosine 像夹角,默认用 cosine 就对了。


Q3:get_or_create_collection()create_collection() 有什么区别?什么时候用哪个?

考点拆解: API 设计哲学,幂等性(Idempotency)在数据库操作中的重要性。

通关答案:

  • create_collection(name) :严格创建,集合已存在直接抛 ValueError。适合初始化脚本,语义是"我确定这个集合不该已存在"。
  • get_or_create_collection(name) :幂等操作,集合存在就返回引用,不存在就创建。适合业务代码,语义是"给我一个能用的集合"。

源码视角: get_or_create 内部先调 get_collection,捕获 ValueError 后 fallback 到 create_collection。这个 try-except 设计就是懒加载模式的数据库版

实战最佳实践:

ini 复制代码
# ❌ 不好的写法:脚本跑两次就炸
collection = client.create_collection("my_collection")
​
# ✅ 生产代码的标准写法
collection = client.get_or_create_collection(
    name="my_collection",
    metadata={"hnsw:space": "cosine"},  # ⚠️ 注意:metadata 只在创建时生效!
)

⚠️ 大坑警告: get_or_create 传入的 metadata 只在"create 分支"生效!如果集合已存在,传的 metadata 会被静默忽略 ,不会更新已有集合的配置。要改 metadata 只能用 collection.modify()
一句话总结: create 是"破门而入"(已有人在就炸),get_or_create 是"敲门进"(有人就进,没人就开灯),业务代码永远用后者。

相关推荐
Patrick在香港6 小时前
Claude 计算香港薪俸税实战:从 Prompt 到 API 自动税率对比
ai编程
人月神话-Lee6 小时前
【图像处理】高斯模糊——最优雅的模糊算法
图像处理·人工智能·算法·ios·ai编程·swift
猫头虎6 小时前
【Trea】Trea国内版|国际版|海外版下载|Mac版|Windows版|Linux下载配置教程
linux·人工智能·windows·macos·aigc·ai编程·agi
JAVA面经实录9176 小时前
Java+SpringAI企业级实战项目完整官方文档(生产终版)
java·开发语言·spring·ai编程
kkkliaoo7 小时前
AI编程提示词工程:三层框架让你的Codex输出质量翻倍、Token省75%
ai编程·codex·claudecode
码农阿强7 小时前
Qwen3.7-Max技术特性解析及调用实践
人工智能·ai·aigc·ai编程
DogDaoDao7 小时前
【GitHub】AgentMemory 深度解析:让 AI 编程代理拥有持久化记忆的 16K+ Star 开源方案
人工智能·开源·大模型·github·aigc·ai编程·aiagent
lili00127 小时前
Gemini 3.5发布后的AI格局:谷歌重新定义行业标准
java·人工智能·python·ai编程
名不经传的养虾人7 小时前
从0到1:企业级AI项目迭代日记 Vol.31|可视化、可编辑、可脱敏、可隔离——企业系统接管的四个“可”
人工智能·ai编程·ai工作流·企业ai