本文先以Chroma为例,后续再用Faiss,下面简单说下区别:
Faiss(Facebook AI Similarity Search)和Chroma是两种流行的向量数据库/库,主要用于高效相似性搜索和向量存储,但它们在设计目标、功能特性和适用场景上有显著差异。以下是两者的核心区别:
1. 开发背景与定位
Faiss
由Meta(Facebook)AI团队开发,专注于大规模向量相似性搜索,尤其适合高维稠密向量(如神经网络嵌入)。
核心优势:高性能的近似最近邻(ANN)搜索算法,支持GPU加速,适合工业级大规模数据(如十亿级向量)。
局限性:原生不支持持久化存储或元数据管理,需结合其他工具(如Redis)扩展功能。
Chroma
专为**AI应用(如LLM、RAG)**设计,内置对向量和关联元数据(如文本、标签)的存储与管理。
核心优势:开箱即用的轻量级解决方案,支持动态更新、过滤查询(基于元数据),适合中小规模场景。
局限性:性能优化不如Faiss,大规模向量搜索时可能需额外扩展。
2. 功能对比
特性FaissChroma
搜索算法多种ANN算法(IVF、HNSW、PQ等)基于HNSW或暴力搜索(可配置)
持久化存储需手动保存/加载索引文件内置SQLite或ClickHouse持久化
元数据支持不支持支持向量关联的JSON元数据存储与过滤
动态更新部分索引类型支持增量添加支持实时插入、删除和更新
多模态查询仅向量搜索支持向量+元数据混合查询(如过滤)
部署复杂度需自行搭建服务层(如gRPC/HTTP)内置REST API,快速部署
3. 性能与扩展性
Faiss
优势:在十亿级向量上仍能保持毫秒级响应,支持多GPU并行计算(如IndexShards)。
适用场景:推荐系统、图像检索等需要低延迟、高吞吐的场景。
Chroma
优势:简化了开发流程,适合快速原型开发或中小规模应用(如千万级向量)。
适用场景:聊天机器人(RAG)、文档检索等需要结合语义和结构化过滤的场景。
4. 生态系统与集成
Faiss
需通过Python/C++ API直接调用,或结合Milvus、Weaviate等扩展为完整数据库。
社区提供丰富的预训练索引配置(如faiss-wheels)。
Chroma
原生集成LangChain、LlamaIndex等AI工具链,适合与大模型生态无缝协作。
提供客户端-服务器模式,支持分布式部署(但性能优化有限)。
5. 如何选择?
选Faiss:
需要极致搜索性能或处理超大规模数据。
愿意自行处理元数据管理和服务化封装。
选Chroma:
需要快速构建AI应用(如RAG),且希望内置元数据支持。
数据规模在千万级以下,优先考虑开发效率而非极限性能。
一、安装langchain-chroma
pip install langchain-chroma
二、准备多个Document
documents = [
Document(page_content="狗是人类永恒的守护者,无论风雨晦明,它用摇动的尾巴和炽热的眼神,将忠诚写成跨越千年的契约"),
Document(page_content="猫是人类优雅的伴侣,时而高冷疏离,时而温柔依偎,用灵动的身影点亮生活的静谧。"),
Document(page_content="猪是人类朴实的帮手,憨厚的外表下藏着聪慧,以无私的奉献成为农耕文化的重要符号。"),
Document(page_content="鸡是人类勤劳的闹钟,破晓的啼鸣唤醒沉睡的村庄,用羽翼和蛋壳滋养千家万户。"),
Document(page_content="鱼是人类悠然的诗意,在碧波中舞动生命的韵律,既是餐桌的馈赠,也是文化的象征。")
]
三、向量化,这里用bge-samll-zh-v1.5为例,下载地址:https://modelscope.cn/models/BAAI/bge-small-zh-v1.5/files
pip install sentence-transformers
pip install langchain-huggingface
代码:
# from langchain.embeddings import HuggingFaceEmbeddings #废弃了 下面那个
from langchain_huggingfaceimport HuggingFaceEmbeddings
# 指定本地模型路径(假设模型文件存储在 ./models/bge-small-en-v1.5 下)
embeddings = HuggingFaceEmbeddings(
model_name="./bge-small-zh-v1.5",# 替换为实际路径
model_kwargs={"device":"cpu"}# 可选:指定运行设备(cpu/cuda)
)
# 这个
vector_store = Chroma.from_documents(documents,embedding=embeddings)
print(vector_store.similarity_search_with_score("哈巴狗")) #这个有匹配值,在Chroma中值越小代表匹配度越高
打印结果:
[(Document(id='fb91cbfd-a1ba-4cd2-9c60-f165bba54fe1', metadata={}, page_content='狗是人类永恒的守护者,无论风雨晦明,它用摇动的尾巴和炽热的眼神,将忠诚写成跨越千年的契约'), 1.0324569940567017),
四、创建检索器
retriever = RunnableLambda(vector_store.similarity_search_with_score).bind(k=1) #最相似的 第一个
调用一次:
print(retriever.invoke("加菲猫"))
[(Document(id='f3c2dfd8-4a32-4619-9f6e-865cf4bdb14a', metadata={}, page_content='猫是人类优雅的伴侣,时而高冷疏离,时而温柔依偎,用灵动的身影点亮生活的静谧。'), 0.9588874578475952)]
批量调用:
print(retriever.batch(["加菲猫","汪汪队"]))
[[(Document(id='f3c2dfd8-4a32-4619-9f6e-865cf4bdb14a', metadata={}, page_content='猫是人类优雅的伴侣,时而高冷疏离,时而温柔依偎,用灵动的身影点亮生活的静谧。'), 0.9588874578475952)], [(Document(id='fb91cbfd-a1ba-4cd2-9c60-f165bba54fe1', metadata={}, page_content='狗是人类永恒的守护者,无论风雨晦明,它用摇动的尾巴和炽热的眼神,将忠诚写成跨越千年的契约'), 1.3173881769180298)]]
五、完整代码
from langchain_ollamaimport OllamaLLM
from langchain.schemaimport HumanMessage,SystemMessage
from langchain_core.promptsimport ChatPromptTemplate, MessagesPlaceholder
from langchain_core.output_parsersimport StrOutputParser
from langchain_community.chat_message_historiesimport ChatMessageHistory
from langchain_core.documentsimport Document
from langchain_chromaimport Chroma
# from langchain.embeddings import HuggingFaceEmbeddings #废弃了 下面那个
from langchain_huggingfaceimport HuggingFaceEmbeddings
llm = OllamaLLM(base_url = OLLAMA_HOST,model = MODEL_NAME)
documents = [
Document(page_content="狗是人类永恒的守护者,无论风雨晦明,它用摇动的尾巴和炽热的眼神,将忠诚写成跨越千年的契约"),
Document(page_content="猫是人类优雅的伴侣,时而高冷疏离,时而温柔依偎,用灵动的身影点亮生活的静谧。"),
Document(page_content="猪是人类朴实的帮手,憨厚的外表下藏着聪慧,以无私的奉献成为农耕文化的重要符号。"),
Document(page_content="鸡是人类勤劳的闹钟,破晓的啼鸣唤醒沉睡的村庄,用羽翼和蛋壳滋养千家万户。"),
Document(page_content="鱼是人类悠然的诗意,在碧波中舞动生命的韵律,既是餐桌的馈赠,也是文化的象征。")
]
# 指定本地模型路径(假设模型文件存储在 ./models/bge-small-en-v1.5 下)
embeddings = HuggingFaceEmbeddings(
model_name="./bge-small-zh-v1.5",# 替换为实际路径
model_kwargs={"device":"cpu"}# 可选:指定运行设备(cpu/cuda)
)
# 这个
vector_store = Chroma.from_documents(documents,embedding=embeddings)
print(vector_store.similarity_search_with_score("哈巴狗"))
# 检索器
retriever = RunnableLambda(vector_store.similarity_search_with_score).bind(k=1)
res1 = retriever.invoke("加菲猫")
print(res1)
res2 = retriever.batch(["加菲猫","汪汪队"])
print(res2)