15天学会AI应用开发(九)利用Chroma持久化向量数据

在AI应用开发中,向量数据是存储语义信息的关键。无论是构建RAG系统、语义搜索还是推荐引擎,都需要一个高效的向量数据库来持久化和管理嵌入向量。Chroma作为一个轻量级、高性能的向量数据库,完美满足了这一需求。本文将带你从零开始,掌握Chroma的安装、配置、数据持久化和查询操作。## 为什么选择Chroma?Chroma是一个开源向量数据库,专为AI应用设计。它的核心优势在于:- 即插即用:无需复杂配置,几行代码即可开始使用- 内存优先:默认运行在内存中,也可持久化到磁盘- 丰富的API:支持增删改查、相似度搜索、过滤等- 与LangChain无缝集成:是构建RAG应用的首选## 环境准备首先,确保你已安装Python 3.8+。接下来安装Chroma:bashpip install chromadb如果你打算使用嵌入模型生成向量,还需要安装:bashpip install sentence-transformers## 基础操作:创建集合并添加数据Chroma的核心概念是集合(Collection),类似于关系数据库中的表。每个集合存储一组文档及其对应的向量。### 示例1:创建持久化集合,插入和查询数据pythonimport chromadbfrom chromadb.config import Settings# 初始化Chroma客户端,指定持久化路径# 这样数据会保存在本地磁盘,重启后依然存在client = chromadb.Client(Settings( chroma_db_impl="duckdb+parquet", persist_directory="./chroma_data" # 数据保存目录))# 创建一个集合(如果不存在则创建)# 集合名称必须是唯一的collection = client.get_or_create_collection( name="my_documents", metadata={"hnsw:space": "cosine"} # 使用余弦相似度)# 准备数据:ID、文档和对应的元数据documents = [ "人工智能正在改变世界", "深度学习是机器学习的一个分支", "自然语言处理让计算机理解人类语言"]metadata_list = [ {"category": "AI", "source": "book"}, {"category": "ML", "source": "paper"}, {"category": "NLP", "source": "web"}]ids = ["doc1", "doc2", "doc3"]# 添加数据到集合# Chroma会自动调用默认的嵌入函数生成向量# 你也可以手动传入向量collection.add( documents=documents, metadatas=metadata_list, ids=ids)# 持久化数据到磁盘(确保数据保存)client.persist()# 查询示例:搜索与“机器学习”最相似的文档query_text = "机器学习是什么?"results = collection.query( query_texts=[query_text], n_results=2 # 返回最相似的2个结果)# 输出查询结果print("查询结果:")for idx, doc in enumerate(results['documents'][0]): print(f" - 文档: {doc}") print(f" 相似度: {results['distances'][0][idx]:.4f}") print(f" 元数据: {results['metadatas'][0][idx]}") print(f" ID: {results['ids'][0][idx]}")运行结果示例:查询结果: - 文档: 深度学习是机器学习的一个分支 相似度: 0.1234 元数据: {'category': 'ML', 'source': 'paper'} ID: doc2 - 文档: 人工智能正在改变世界 相似度: 0.4567 元数据: {'category': 'AI', 'source': 'book'} ID: doc1## 高级操作:自定义嵌入模型与批量操作在实际生产环境中,你可能需要使用更强大的嵌入模型来生成高质量的向量。Chroma支持自定义嵌入函数。### 示例2:使用SentenceTransformer自定义嵌入并批量处理pythonimport chromadbfrom chromadb.config import Settingsfrom sentence_transformers import SentenceTransformerimport time# 加载预训练的SentenceTransformer模型# 这是一个轻量级且效果不错的中文嵌入模型model = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')# 自定义嵌入函数,将文本转换为向量def custom_embedding_function(texts): """将文本列表转换为向量列表""" if isinstance(texts, str): texts = [texts] embeddings = model.encode(texts, show_progress_bar=False) return embeddings.tolist()# 初始化Chroma客户端(持久化模式)client = chromadb.Client(Settings( chroma_db_impl="duckdb+parquet", persist_directory="./chroma_data_advanced"))# 创建集合,指定自定义嵌入函数collection = client.create_collection( name="advanced_docs", embedding_function=custom_embedding_function # 使用自定义嵌入)# 准备大量数据用于批量插入documents = [ "Python是一种广泛使用的编程语言", "JavaScript主要用于Web开发", "Java在企业级应用中很流行", "C++适合系统编程和游戏开发", "Go语言以并发编程能力著称", "Rust注重内存安全", "Kotlin是Android开发的首选", "Swift用于iOS应用开发", "TypeScript是JavaScript的超集", "PHP在网站开发中仍然有用"]metadata_list = [ {"type": "backend", "popularity": 90}, {"type": "frontend", "popularity": 95}, {"type": "backend", "popularity": 85}, {"type": "system", "popularity": 70}, {"type": "backend", "popularity": 75}, {"type": "system", "popularity": 65}, {"type": "mobile", "popularity": 80}, {"type": "mobile", "popularity": 78}, {"type": "frontend", "popularity": 88}, {"type": "backend", "popularity": 60}]# 生成ID列表ids = [f"doc_{i}" for i in range(len(documents))]# 批量添加数据start_time = time.time()collection.add( documents=documents, metadatas=metadata_list, ids=ids)print(f"批量插入完成,耗时: {time.time() - start_time:.2f}秒")# 持久化数据client.persist()# 复杂查询:带元数据过滤的语义搜索# 查找与“后端开发”相关,且流行度大于80的文档query = "后端开发语言"results = collection.query( query_texts=[query], n_results=3, where={"popularity": {"$gte": 80}}, # 过滤条件:流行度 >= 80 where_document={"$contains": "Python"} # 文档内容包含"Python")print("\n带过滤条件的查询结果:")for idx, doc in enumerate(results['documents'][0]): print(f" - 文档: {doc}") print(f" 相似度: {results['distances'][0][idx]:.4f}") print(f" 元数据: {results['metadatas'][0][idx]}") print(f" ID: {results['ids'][0][idx]}")# 更新文档:修改已有ID的内容collection.update( ids=["doc_0"], documents=["Python现在是最流行的编程语言之一"], metadatas=[{"type": "backend", "popularity": 95}])print("\n文档更新完成")# 删除文档collection.delete(ids=["doc_9"]) # 删除PHP相关文档print("文档删除完成")# 获取集合统计信息count = collection.count()print(f"\n集合中当前文档数量: {count}")运行结果示例:批量插入完成,耗时: 0.45秒带过滤条件的查询结果: - 文档: Python是一种广泛使用的编程语言 相似度: 0.2345 元数据: {'type': 'backend', 'popularity': 90} ID: doc_0文档更新完成文档删除完成集合中当前文档数量: 9## 持久化机制详解Chroma的持久化机制基于DuckDB和Parquet格式:1. 默认存储:数据保存在./chroma_data目录下2. 文件结构: - chroma.sqlite3:元数据数据库 - parquet/:向量数据文件3. 手动持久化:调用client.persist()确保数据写入磁盘4. 自动持久化:可以设置persist_directory实现自动保存## 性能优化技巧1. 批量操作:一次插入100-1000条数据性能最优2. 索引配置:通过hnsw:space参数选择距离度量(cosine/l2/ip)3. 内存管理:设置chroma_db_impl参数控制存储后端4. 查询优化:使用where过滤减少搜索范围## 与LangChain集成Chroma是LangChain的默认向量存储之一,可以无缝集成到RAG应用中:pythonfrom langchain.vectorstores import Chromafrom langchain.embeddings import HuggingFaceEmbeddingsembeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")vector_store = Chroma( collection_name="langchain_docs", embedding_function=embeddings, persist_directory="./chroma_langchain")## 总结本文通过两个完整的实战示例,详细介绍了如何利用Chroma持久化向量数据。从基础的数据插入、查询,到高级的自定义嵌入模型、元数据过滤和批量操作,你已掌握了构建AI应用所需的核心技能。Chroma作为一个轻量级但功能强大的向量数据库,完美平衡了易用性和性能。无论是快速原型开发还是生产环境部署,它都能胜任。记住关键点:- 始终调用persist()确保数据持久化- 合理设计集合名称和元数据结构- 根据场景选择合适的嵌入模型- 善用过滤条件优化查询性能掌握Chroma后,你就可以构建真正的AI应用,如语义搜索系统、智能问答机器人、个性化推荐引擎等。下一章我们将深入探讨如何将Chroma与大型语言模型(LLM)结合,打造完整的RAG应用。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐