一、引言
当大模型能够流畅地撰写文案、解答数学难题、生成代码时,知识固化与幻觉问题始终是一个致命短板制约着大模型的能力发挥。训练完成的大模型如同一个记忆定格的智者,既无法实时吸收新信息,又可能基于碎片化知识生成似是而非的答案。
在这样的背景下,向量数据库应运而生。它并非传统数据库的简单延伸,而是专为非结构化数据打造的语义存储器,通过将文本、图像、音频转化为高维向量,实现毫秒级相似性检索。当向量数据库与大模型强强联合,不仅能破解大模型的失忆难题,更能构建出可扩展、高精度的 AI 应用。今天我们将从技术本质、架构原理、实战案例三个维度,全面拆解向量数据库的核心价值,揭示其如何成为大模型建设的基础设施。
二、向量数据库介绍
1. 核心定义
向量数据库重新定义数据的存储与检索,将传统的关键词匹配进阶为语义相似性检索,传统数据库以结构化数据为核心,依赖“行、列、主键”的逻辑存储,检索时需精准匹配关键词;而向量数据库的核心是高维向量,通过嵌入模型(Embedding Model)将非结构化数据的语义特征转化为一串数值数组,例如一段文本可转化为 768 维向量,一张图片可转化为 512 维向量。
向量数据库的检索逻辑不再是“关键词是否存在”,而是计算向量间的距离,一般常用余弦相似度、欧氏距离来判断,距离越近则语义相似度越高。这种特性使其能够实现 “用户问 A,系统返回语义相关的 B”,例如查询“如何优化大模型推理速度”,无需匹配 “模型量化”关键词,也能精准检索到相关技术文档。
2. 关键术语
术语是理解向量数据库的核心组件,通过几个关键术语加强我们的基础概念理解和作用分析:
- 嵌入模型(Embedding Model):定义是将非结构化数据转化为高维向量的模型,常见的有 Sentence-BERT、CLIP 等;
核心作用是作为数据向量化的核心工具,决定向量的语义表达能力。 - 向量索引:定义是为高维向量构建的特殊数据结构,常见的有 HNSW、IVF-PQ 等;
核心作用是将检索时间复杂度从 O (n) 降至 O (log n),支撑亿级数据检索。 - 相似性计算:定义是衡量向量间语义相似度的算法;
核心作用是余弦相似度适用于文本检索,欧氏距离适用于图像检索。 - 元数据:定义是与向量绑定的辅助信息,比如文本分类、时间戳等;
核心作用是实现 “向量检索 + 属性过滤” 的混合查询。 - RAG(检索增强生成):定义是向量数据库与大模型的协同架构;
核心作用是为大模型提供实时外部知识,消除幻觉。
3. 数据库分类
3.1 专用独立向量数据库
核心特征:专为向量检索设计,支持分布式部署、高并发、动态数据更新,具备完善的索引管理与数据一致性保障。主流产品:
3.1.1 Weaviate
- 定位:开源云原生向量数据库,内置语义搜索引擎。
- 核心优势:支持向量检索与全文检索混合查询,自带 RESTful API,可直接集成 OpenAI、Cohere 等嵌入模型。
3.1.1 Pinecone
- 定位:托管式向量数据库(SaaS)。
- 核心优势:无需关注底层运维,自动扩缩容,适合快速上线的中小型应用;缺点是依赖云服务,数据隐私可控性弱
3.2 嵌入式向量数据库
核心特征:轻量级、无服务端,直接嵌入到应用程序进程中,适合边缘设备、本地应用或低延迟场景。主流产品:
3.2.1 FAISS
- 定位:Facebook 开源的向量检索库,非严格意义上的数据库(无持久化、事务管理功能)。
- 核心优势:支持亿级向量的高效检索,索引算法丰富,适合本地实验、学术研究或对持久化要求低的场景。
3.2.2 Chroma
- 定位:开源嵌入式向量数据库,专为 LLM 应用设计。
- 核心优势:支持数据持久化、元数据过滤,API 简洁易用,可与 LangChain、LlamaIndex 无缝集成,适合本地 RAG 原型开发。
4. 与传统数据库的差异
向量数据库与关系型数据库(MySQL)、非关系型数据库(MongoDB)的核心差异,在于数据的组织方式与检索逻辑,通过以下维度我们进一步了解与传统数据库的差异:
- 核心数据类型维度:
- 向量数据库存储高维向量 + 元数据;
- 关系型数据库存储结构化数据(表、行、列);
- 非关系型数据库存储半结构化数据(文档、键值)。
- 检索逻辑维度:
- 向量数据库采用语义相似性匹配;
- 关系型数据库采用 SQL 条件查询(等值、范围);
- 非关系型数据库采用键值匹配/文档遍历。
- 核心算法维度:
- 向量数据库的核心算法是近似最近邻(ANN)检索;
- 关系型数据库的核心算法是 B + 树索引;
- 非关系型数据库的核心算法是哈希索引/地理空间索引。
- 典型应用维度:
- 向量数据库的典型应用是 RAG、语义搜索、个性化推荐;
- 关系型数据库的典型应用是交易系统、用户管理;
- 非关系型数据库的典型应用是日志存储、内容管理。
- 核心优势维度:
- 向量数据库的核心优势是非结构化数据的语义检索;
- 关系型数据库的核心优势是事务一致性、关联查询;
- 非关系型数据库的核心优势是灵活扩展、海量数据存储。
三、向量数据库的技术原理
1. 向量索引算法
向量索引是向量数据库的性能关键,其本质是通过 “降维” 或 “聚类” 减少相似性计算的次数,主流算法分为以下两类:
1.1 精确检索算法
- 代表:暴力检索(Brute-force)、FLAT 索引。
- 原理:计算目标向量与数据库中所有向量的距离,返回最相似的结果。
- 优缺点:结果精确,但时间复杂度高,仅适合小数据集(万级向量)。
1.2 近似最近邻检索算法(ANN)
- 代表:HNSW(分层导航小世界)、IVF(倒排文件)、PQ(乘积量化)。
- HNSW:目前最主流的 ANN 算法,通过构建多层图结构,实现毫秒级检索亿级向量,支持动态插入与删除,是Weaviate 的默认索引。
- IVF:将向量聚类为多个中心,检索时仅计算目标向量与相近聚类中心的距离,适合高维稀疏向量。
2. 核心功能模块
一个完整的向量数据库通常包含以下模块:
- 数据接入层:支持向量数据的批量导入、增量插入、删除与更新,兼容多种数据源(文件、数据库、API)。
- 索引管理层:负责向量索引的创建、优化、重建,支持索引算法的动态切换。
- 检索引擎层:执行相似性检索、元数据过滤、混合查询(向量 + 全文),返回 Top-N 结果。
- 持久化层:将向量数据与索引持久化到磁盘,保障数据不丢失,支持快照与备份。
- 服务层:提供 SDK、RESTful API、gRPC 接口,支持多语言调用。
四、向量数据库的核心架构
向量数据库的架构遵循 “数据输入 - 向量生成 - 存储索引 - 检索服务 - 应用输出” 的分层逻辑,其通用架构流程图如下,涵盖从原始数据到最终业务应用的全链路:
各分层核心功能详解
- 1. 数据输入层:为向量化做准备该层的核心是数据分块。以长文本为例,若直接将万字文档转化为一个向量,会导致语义信息丢失;而将其拆分为 500 字左右的段落,每个段落生成一个向量,能精准保留局部语义。例如,将一本《Python 编程手册》拆分为 “基础语法”“数据结构”“爬虫实战” 等段落块,每个块对应一个向量。
- 2. 向量生成层:数据的 “语义翻译官”嵌入模型是该层的核心,其本质是将人类可理解的自然语言、图像转化为机器可计算的向量。不同类型的数据需匹配不同的嵌入模型:
- 文本数据:优先选择 Sentence-BERT、BGE(中文场景);
- 图像数据:优先选择 CLIP、ResNet;
- 多模态数据:优先选择 CLIP(支持文本与图像的跨模态匹配)。
- 3. 存储索引层:向量数据库的性能核心这是向量数据库与传统数据库差异最大的一层,分为两个关键模块:
- 向量索引模块:若采用暴力检索(FLAT),亿级向量的检索时间需数秒;而采用 HNSW 索引,可将检索时间压缩至毫秒级。HNSW 的核心原理是构建多层图结构,通过 “上层粗筛、下层精筛” 的方式快速定位相似向量。
- 分布式存储引擎:支持向量数据的分片存储与副本备份,保障系统的高可用性。可通过 K8s 实现水平扩展,应对海量数据的存储需求。
- 4. 检索服务层:面向用户的 “语义查询入口”当用户输入查询语句时,该层会先将查询转化为向量,再通过相似性检索引擎匹配最相似的 Top-N 向量,最后结合元数据过滤(如 “只检索 2025 年的技术文档”)得到最终结果。例如,用户查询 “如何部署 ChromaDB”,系统会检索到包含 “Docker 部署”“Python API 调用” 的向量对应的文档片段。
轻量化架构
对于中小型应用,如我们很多其然文章里面的本地 RAG 原型开发示例,都是基于FAISS的向量数据库,这种无需复杂的分布式架构,通过嵌入式向量数据库(如 Chroma、FAISS)采用“数据 - 索引 - 检索” 一体化的轻量化设计即可达到效果:
- 无需独立部署服务,直接嵌入到应用进程中;
- 支持内存存储(测试场景)或本地文件存储(持久化场景);
- 自动完成 “向量化 - 索引构建 - 检索” 的全流程,降低开发门槛。
五、与大模型的协同
向量数据库并非孤立存在,其最大价值在于为大模型提供外部记忆,二者通过 RAG 架构形成互补。大模型擅长语义理解与内容生成,但存在知识固化、幻觉、上下文窗口有限三大痛点;向量数据库则能精准解决这些问题。
1. 知识固化
向量数据库可以实时更新大模型的知识库,大模型的训练数据是静态快照,无法实时吸收新信息。例如,2025 年发布的新政策,训练于 2024 年的大模型无法知晓。
- 解决方案:将新政策、新文献、新数据实时向量化后存入向量数据库。当用户提问时,先从向量数据库中检索最新相关信息,再将其作为上下文输入大模型。
- 应用示例:金融领域的智能问答系统,每天将最新监管政策存入向量数据库。当用户询问 “2025 年基金备案新规” 时,系统会检索到最新政策文档,辅助大模型生成准确回答。
2. 幻觉问题
为大模型提供权威依据,大模型在生成回答时,可能基于碎片化知识编造不存在的事实,就是我们所说的幻觉。例如,医疗大模型可能推荐不存在的药品。
- 解决方案:通过 RAG 架构,让大模型有据可依。向量数据库中存储权威数据(如医学论文、药品说明书),大模型只能基于检索到的上下文生成回答。
- 应用示例:医疗辅助诊断系统,将百万级病例存入向量数据库。医生输入患者症状后,系统检索相似病例,大模型结合病例生成治疗建议,避免幻觉误诊。
3. 上下文窗口有限
突破大模型的记忆上限,大模型的上下文窗口是有限的,如 GPT-3.5 的 4k 窗口,无法处理超长文本。例如,让大模型直接分析万字的合同文档,会导致信息丢失。
- 解决方案:将万字合同拆分为多个段落向量存入向量数据库。用户查询 “合同中的违约责任条款” 时,系统检索相关段落向量,仅将关键段落作为上下文输入大模型,突破窗口限制。
六、示例解析
1. ChromaDB 基础入门示例
以往的RAG示例我们都采用的是FAISS向量数据库,今天我们换ChromaDB来做示例解析,ChromaDB是轻量级、零依赖的嵌入式向量数据库,无需部署独立服务,一行代码即可启动,适合快速理解向量数据库的核心流程。以下是从环境搭建到完整检索的每一步操作,所有代码可直接复制运行。
1.1 初始化 ChromaDB 客户端
第一步先初始化 Chroma 客户端,Chroma 支持内存模式,数据仅存于内存,关闭程序丢失,同时也支持持久化模式,数据可以保存到本地文件,我们先从最简单的内存模式开始:
# 导入ChromaDB核心库 import chromadb # 1. 初始化内存模式客户端(最简方式) # 特点:数据只在运行时存在,关闭程序后丢失,适合测试 client = chromadb.Client() # (可选)持久化模式:数据保存到本地文件夹,下次运行可读取 # client = chromadb.PersistentClient(path="./my_chroma_data") # 2. 创建/获取集合(Collection,类似数据库的“表”) # 如果集合已存在,会自动获取;不存在则创建 collection = client.create_collection(name="my_first_collection") # 查看集合是否创建成功(输出集合名称) print("集合创建成功:", collection.name)
输出结果:
集合创建成功: my_first_collection
1.2 向集合中插入数据
Chroma 的核心优势是自动生成向量,无需手动调用嵌入模型,只需传入原始文本,底层会用默认模型(all-MiniLM-L6-v2)转为向量。我们插入 3 条简单文本数据:
# 继续在上述代码后添加 # 3. 插入数据:传入ID、文本内容(可选加元数据) # - ids:每条数据的唯一标识(必须) # - documents:原始文本(核心,Chroma会自动转为向量) # - metadatas:可选元数据(如分类、标签,用于过滤检索) collection.add( ids=["id1", "id2", "id3"], # 自定义唯一ID documents=[ "苹果是一种常见的水果,富含维生素C", "香蕉富含钾元素,适合运动后食用", "程序员常用Python语言开发人工智能应用" ], metadatas=[ # 可选:给每条数据加分类标签 {"category": "水果"}, {"category": "水果"}, {"category": "编程"} ] ) # 查看集合中的数据量(输出3) print("插入数据量:", collection.count())
输出结果:
插入数据量: 3
1.3 相似性检索
这是向量数据库的核心功能:输入一个查询文本,Chroma 会先将查询转为向量,再计算与库中所有向量的相似度,返回最相似的结果。
# 继续添加 # 4. 执行相似性检索 # query_texts:查询文本(支持批量,这里只传1条) # n_results:返回最相似的前N条结果 # where:可选过滤条件(如只检索“水果”分类) results = collection.query( query_texts=["哪些水果富含营养?"], # 用户查询 n_results=2, # 返回前2条最相似的结果 # where={"category": "水果"} # 可选:只检索水果分类 ) # 5. 解析并打印结果 print("\n=== 检索结果 ===") # results的结构:包含ids、documents、distances、metadatas等字段 for i in range(len(results["ids"][0])): # 提取每条结果的信息 doc_id = results["ids"][0][i] content = results["documents"][0][i] distance = results["distances"][0][i] # 距离值(越小相似度越高) similarity = 1 - distance # 转换为相似度(0~1,越大越相似) metadata = results["metadatas"][0][i] # 打印结果 print(f"排名{i+1}") print(f"ID:{doc_id}") print(f"内容:{content}") print(f"相似度:{similarity:.4f}") print(f"分类:{metadata['category']}\n")
输出结果:
=== 检索结果 ===
排名1
ID:id1
内容:苹果是一种常见的水果,富含维生素C
相似度:0.5620
分类:水果
排名2
ID:id2
内容:香蕉富含钾元素,适合运动后食用
相似度:0.1341
分类:水果
1.4 删除数据
# 根据ID删除单条数据 collection.delete(ids=["id3"]) print("删除后数据量:", collection.count()) # 输出2
输出结果:
删除后数据量: 2
1.5 更新数据
# 更新id1的内容和元数据 collection.update( ids=["id1"], documents=["苹果是低热量水果,富含膳食纤维和维生素C"], metadatas=[{"category": "水果-低热量"}] ) # 重新检索验证更新 results = collection.query(query_texts=["低热量水果有哪些?"], n_results=1) print("更新后检索结果:", results["documents"][0][0])
输出结果:
更新后检索结果: 苹果是低热量水果,富含膳食纤维和维生素C
1.6 清空集合
# 清空集合所有数据(谨慎使用) ids = collection.get()["ids"] if ids: collection.delete(ids=ids) print("清空后数据量:", collection.count()) # 输出0
输出结果:
清空后数据量: 0
1.7 示例总结
- 核心流程:初始化客户端 → 创建集合 → 插入数据 → 相似性检索,这是所有向量数据库的通用逻辑;
- 向量自动生成:Chroma 默认内置嵌入模型,无需手动转换文本为向量,无需关注向量维度、嵌入模型等复杂概念;
- 相似度解读:Chroma 返回的distance是余弦距离(0~2),转换为相似度的公式是1 - distance(0~1,越接近 1 越相似);
- 元数据过滤:通过where参数可实现 “分类检索 + 语义相似”,比纯关键词搜索更灵活;
- 模式选择:内存模式适合测试,持久化模式(PersistentClient)适合需要保存数据的场景。
2. 本地化存储和元数据过滤检索
和基础示例做个基础进阶,初始化Chroma客户端并持久化存储,数据保存在本地chroma_db目录,使用本地的sentence-transformers的all-MiniLM-L6-v2模型替代Chroma默认模型。
2.1 初始化 Chroma 客户端
import chromadb from chromadb.utils import embedding_functions # 1. 初始化Chroma客户端(持久化存储,数据保存在本地chroma_db目录) client = chromadb.PersistentClient(path="./chroma_db") # 2. 定义嵌入函数(用开源模型生成向量,替代Chroma默认模型) # 使用sentence-transformers的all-MiniLM-L6-v2模型(轻量、效果好) sentence_transformer_ef = embedding_functions.SentenceTransformerEmbeddingFunction( model_name="D:/modelscope/hub/models/sentence-transformers/all-MiniLM-L6-v2" ) # 3. 创建/获取集合(类似数据库的“表”,存储向量+元数据) # 如果集合已存在,直接获取;不存在则创建 collection = client.get_or_create_collection( name="my_first_collection", embedding_function=sentence_transformer_ef, # 绑定嵌入函数 metadata={"hnsw:space": "cosine"} # 相似度计算方式:余弦相似度 )
2.2 向向量库插入数据
准备示例文本数据,转为向量后存入 Chroma:
# 示例数据:6条技术文档片段 documents = [ "Python中列表(list)的append()方法用于在末尾添加元素", "NumPy的ndarray是高性能数值计算的核心数据结构", "Pandas的DataFrame可以方便地处理结构化表格数据", "Chroma是轻量级嵌入式向量数据库,适合LLM原型开发", "向量数据库通过余弦相似度计算文本语义相似性" ] # 每条数据的唯一ID(自定义) ids = [f"doc_{i}" for i in range(len(documents))] # 可选:元数据(用于过滤检索) metadatas = [ {"category": "Python基础"}, {"category": "Python数据科学"}, {"category": "Python数据科学"}, {"category": "向量数据库"}, {"category": "向量数据库"} ] # 插入数据(Chroma自动调用嵌入函数生成向量,无需手动转换) collection.add( documents=documents, ids=ids, metadatas=metadatas ) # 查看集合信息 print("集合数据量:", collection.count())
输出结果:
Insert of existing embedding ID: doc_0
Insert of existing embedding ID: doc_1
Insert of existing embedding ID: doc_2
Insert of existing embedding ID: doc_3
Insert of existing embedding ID: doc_4
Add of existing embedding ID: doc_0
Add of existing embedding ID: doc_1
Add of existing embedding ID: doc_2
Add of existing embedding ID: doc_3
Add of existing embedding ID: doc_4
集合数据量: 5
2.3 相似性检索
输入查询语句,检索语义最相似的文本:
# 目标查询:“Python如何处理表格数据?” query_text = "Python如何处理表格数据?" # 执行检索:返回Top3最相似结果 results = collection.query( query_texts=[query_text], # 查询文本(支持批量) n_results=3, # 返回Top3 # 可选:元数据过滤(仅检索“Python数据科学”分类) # where={"category": "Python数据科学"} ) # 解析结果 print("=== 相似检索结果 ===") for i, (doc, score) in enumerate(zip(results["documents"][0], results["distances"][0])): # Chroma返回的是“距离值”,值越小相似度越高(余弦距离=1-余弦相似度) similarity = 1 - score # 转换为相似度(0~1) print(f"排名{i+1} | 相似度:{similarity:.4f} | 内容:{doc}")
输出结果:
=== 相似检索结果 ===
排名1 | 相似度:0.6185 | 内容:Python中列表(list)的append()方法用于在末尾添加元素
排名2 | 相似度:0.5372 | 内容:NumPy的ndarray是高性能数值计算的核心数据结构
排名3 | 相似度:0.4304 | 内容:Pandas的DataFrame可以方便地处理结构化表格数据
- 向量数据库不是按 “关键词匹配”(如 “表格”),而是按 “语义相似性” 检索 ;
- 即使查询中没有 “DataFrame”,也能精准匹配到相关内容,这是与传统关键词搜索的核心区别。
2.4 元数据过滤检索
实际场景中常需 “按分类检索 + 语义相似”,例如仅检索 “向量数据库” 相关内容:
query_text = "如何快速部署向量数据库?" results = collection.query( query_texts=[query_text], n_results=2, where={"category": "向量数据库"} # 过滤条件 ) print("=== 过滤后检索结果 ===") for doc, score in zip(results["documents"][0], results["distances"][0]): print(f"相似度:{1-score:.4f} | 内容:{doc}")
输出结果:
=== 过滤后检索结果 ===
相似度:0.5319 | 内容:向量数据库通过余弦相似度计算文本语义相似性
七、总结
向量数据库的出现填补了非结构化数据语义检索的空白。当大模型的生成能力遇上向量数据库的记忆能力,二者协同构建的 RAG 架构,正在重塑 AI 应用的底层逻辑。其核心价值在于连接非结构化数据与大模型,通过高效的相似性检索,解决大模型的知识时效性、幻觉、上下文窗口有限等问题,从企业知识库到个性化推荐,从医疗诊断到金融风控,向量数据库的多元化生态,正在满足不同场景的需求。
附录一:基础示例完整代码
# 导入ChromaDB核心库 import chromadb # 1. 初始化内存模式客户端(最简方式) # 特点:数据只在运行时存在,关闭程序后丢失,适合测试 client = chromadb.Client() # (可选)持久化模式:数据保存到本地文件夹,下次运行可读取 # client = chromadb.PersistentClient(path="./my_chroma_data") # 2. 创建/获取集合(Collection,类似数据库的“表”) # 如果集合已存在,会自动获取;不存在则创建 collection = client.create_collection(name="my_first_collection") # 查看集合是否创建成功(输出集合名称) print("集合创建成功:", collection.name)# 继续在上述代码后添加 # 3. 插入数据:传入ID、文本内容(可选加元数据) # - ids:每条数据的唯一标识(必须) # - documents:原始文本(核心,Chroma会自动转为向量) # - metadatas:可选元数据(如分类、标签,用于过滤检索) collection.add( ids=["id1", "id2", "id3"], # 自定义唯一ID documents=[ "苹果是一种常见的水果,富含维生素C", "香蕉富含钾元素,适合运动后食用", "程序员常用Python语言开发人工智能应用" ], metadatas=[ # 可选:给每条数据加分类标签 {"category": "水果"}, {"category": "水果"}, {"category": "编程"} ] ) # 查看集合中的数据量(输出3) print("插入数据量:", collection.count()) # 继续添加 # 4. 执行相似性检索 # query_texts:查询文本(支持批量,这里只传1条) # n_results:返回最相似的前N条结果 # where:可选过滤条件(如只检索“水果”分类) results = collection.query( query_texts=["哪些水果富含营养?"], # 用户查询 n_results=2, # 返回前2条最相似的结果 # where={"category": "水果"} # 可选:只检索水果分类 ) # 5. 解析并打印结果 print("\n=== 检索结果 ===") # results的结构:包含ids、documents、distances、metadatas等字段 for i in range(len(results["ids"][0])): # 提取每条结果的信息 doc_id = results["ids"][0][i] content = results["documents"][0][i] distance = results["distances"][0][i] # 距离值(越小相似度越高) similarity = 1 - distance # 转换为相似度(0~1,越大越相似) metadata = results["metadatas"][0][i] # 打印结果 print(f"排名{i+1}") print(f"ID:{doc_id}") print(f"内容:{content}") print(f"相似度:{similarity:.4f}") print(f"分类:{metadata['category']}\n") # 根据ID删除单条数据 collection.delete(ids=["id3"]) print("删除后数据量:", collection.count()) # 输出2 # 更新id1的内容和元数据 collection.update( ids=["id1"], documents=["苹果是低热量水果,富含膳食纤维和维生素C"], metadatas=[{"category": "水果-低热量"}] ) # 重新检索验证更新 results = collection.query(query_texts=["低热量水果有哪些?"], n_results=1) print("更新后检索结果:", results["documents"][0][0]) # 清空集合所有数据(谨慎使用) ids = collection.get()["ids"] if ids: collection.delete(ids=ids) print("清空后数据量:", collection.count()) # 输出0
附录二:强化检索完整示例代码
import chromadb from chromadb.utils import embedding_functions # 1. 初始化Chroma客户端(持久化存储,数据保存在本地chroma_db目录) client = chromadb.PersistentClient(path="./chroma_db") # 2. 定义嵌入函数(用开源模型生成向量,替代Chroma默认模型) # 使用sentence-transformers的all-MiniLM-L6-v2模型(轻量、效果好) sentence_transformer_ef = embedding_functions.SentenceTransformerEmbeddingFunction( model_name="D:/modelscope/hub/models/sentence-transformers/all-MiniLM-L6-v2" ) # 3. 创建/获取集合(类似数据库的“表”,存储向量+元数据) # 如果集合已存在,直接获取;不存在则创建 collection = client.get_or_create_collection( name="my_first_collection", embedding_function=sentence_transformer_ef, # 绑定嵌入函数 metadata={"hnsw:space": "cosine"} # 相似度计算方式:余弦相似度 ) # 示例数据:6条技术文档片段 documents = [ "Python中列表(list)的append()方法用于在末尾添加元素", "NumPy的ndarray是高性能数值计算的核心数据结构", "Pandas的DataFrame可以方便地处理结构化表格数据", "Chroma是轻量级嵌入式向量数据库,适合LLM原型开发", "向量数据库通过余弦相似度计算文本语义相似性" ] # 每条数据的唯一ID(自定义) ids = [f"doc_{i}" for i in range(len(documents))] # 可选:元数据(用于过滤检索) metadatas = [ {"category": "Python基础"}, {"category": "Python数据科学"}, {"category": "Python数据科学"}, {"category": "向量数据库"}, {"category": "向量数据库"} ] # 插入数据(Chroma自动调用嵌入函数生成向量,无需手动转换) collection.add( documents=documents, ids=ids, metadatas=metadatas ) # 查看集合信息 print("集合数据量:", collection.count()) # 输出:6 # 目标查询:“Python如何处理表格数据?” query_text = "Python如何处理表格数据?" # 执行检索:返回Top3最相似结果 results = collection.query( query_texts=[query_text], # 查询文本(支持批量) n_results=3, # 返回Top3 # 可选:元数据过滤(仅检索“Python数据科学”分类) # where={"category": "Python数据科学"} ) # 解析结果 print("=== 相似检索结果 ===") for i, (doc, score) in enumerate(zip(results["documents"][0], results["distances"][0])): # Chroma返回的是“距离值”,值越小相似度越高(余弦距离=1-余弦相似度) similarity = 1 - score # 转换为相似度(0~1) print(f"排名{i+1} | 相似度:{similarity:.4f} | 内容:{doc}") query_text = "如何快速部署向量数据库?" results = collection.query( query_texts=[query_text], n_results=2, where={"category": "向量数据库"} # 过滤条件 ) print("=== 过滤后检索结果 ===") for doc, score in zip(results["documents"][0], results["distances"][0]): print(f"相似度:{1-score:.4f} | 内容:{doc}")