【大模型应用开发 1.嵌入模型与向量数据库 Chroma】
目录
一、向量表征(Vector Representation)
1.向量表征的本质——万物数字化
Ⅰ、核心思想
Ⅱ、数学意义
2.向量表征的典型应用场景
Ⅰ、自然语言处理(NLP)
Ⅱ、计算机视觉(CV)
Ⅲ、推荐系统
Ⅳ、复杂系统建模
3. 向量表征的技术实现
Ⅰ、经典方法
Ⅱ、前沿方向
二、什么是向量
1.文本向量(Text Embeddings)
2.如何得到文本向量
3.向量间的相似度计算
4.代码示例_distance.py
Ⅰ、百炼API环境配置
Ⅱ、余弦距离
Ⅲ、欧氏距离
Ⅳ、转换为嵌入向量
Ⅴ、完整代码
三、Embedding Models 嵌入模型
1.什么是嵌入(Embedding)
2.嵌入模型概念及原理
Ⅰ、嵌入模型的本质
Ⅱ、核心作用
3.主流嵌入模型分类与选型指南
Ⅰ、通用全能型
Ⅱ、垂直领域特化型
Ⅲ、轻量化部署型
⭐Ⅳ、选型决策树:
4.嵌入模型使用实践
Ⅰ、方式1:使用API调用方式
Ⅱ、方式2:本地私有化部署
四、向量数据库
1.什么是向量数据库
核心功能:
2.如何存储和检索嵌入向量
3.向量数据库与传统数据库对比
Ⅰ、数据类型
Ⅱ、查询方式
Ⅲ、应用场景
Ⅳ、向量数据库选型
4.Chroma向量数据库
Ⅰ、核心优势
Ⅱ、安装
Ⅲ、初始化客户端
① 内存模式(不建议使用)
② 持久化模式
🚀Ⅳ、核心操作流程
① 创建集合
② 查询集合
③ 修改集合名称
④ 删除集合
⑤ 添加数据——方式1:自动生成向量
⑤ 添加数据——方式2:手动生成向量
⑥ 查询数据——方式1:自动向量化查询
⑦ 查询数据——方式2:自定义向量化查询
⑧ 更新集合中的数据
⑨ 删除集合 / 集合中的数据
⑩ 完整代码
Ⅴ、Chroma Client-Server Mode
① Client
② Server
博主在联想研究院AIPC算法研究员实习了两个多月,开始备战大模型应用开发的秋招,从今天开始学习备战大模型应用开发!
—— 25.8.9
一、向量表征(Vector Representation)
在人工智能领域,向量表征(Vector Representation)是核心概念之一。通过将文本、图像、声音、行为甚至复杂关系转化为高维向量(Embedding),AI系统能够以数学方式理解和处理现实世界中的复杂信息。这种表征方式为机器学习模型提供了统一的“语言”。
1.向量表征的本质——万物数字化
Ⅰ、核心思想
① 降维抽象:将复杂对象(如一段文字、一张图片)映射到低维稠密向量空间,保留关键语义或特征。
② 相似性度量:向量空间中的距离(如余弦相似度)反映对象之间的语义关联(如“猫”和“狗”的向量距离小于“猫”和“汽车”)。
Ⅱ、数学意义
① 特征工程自动化:传统机器学习依赖人工设计特征(如文本的TF-IDF),而向量表征通过深度学习自动提取高阶抽象特征。
② 跨模态统一:文本、图像、视频等不同模态数据可映射到同一向量空间,实现跨模态检索(如“用文字搜图片”)。
2.向量表征的典型应用场景
Ⅰ、自然语言处理(NLP)
① 词向量(Word2Vec、GloVe):单词映射为向量,解决“一词多义”问题(如“苹果”在“水果”和“公司”上下文中的不同向量)。
② 句向量(BERT、Sentence-BERT):整句语义编码,用于文本相似度计算、聚类(如客服问答匹配)。
③ 知识图谱嵌入(TransE、RotatE):将实体和关系表示为向量,支持推理(如预测“巴黎-首都-法国”的三元组可信度)。
Ⅱ、计算机视觉(CV)
① 图像特征向量(CNN特征):ResNet、ViT等模型提取图像语义,用于以图搜图、图像分类。
② 跨模态对齐(CLIP):将图像和文本映射到同一空间,实现“描述文字生成图片”或反向搜索。
Ⅲ、推荐系统
用户/物品向量:用户行为序列(点击、购买)编码为用户向量,商品属性编码为物品向量,通过向量内积预测兴趣匹配度(如YouTube推荐算法)。
Ⅳ、复杂系统建模
① 图神经网络(GNN):社交网络中的用户、商品、交互事件均表示为向量,捕捉网络结构信息(如社区发现、欺诈检测)。
② 时间序列向量化:将股票价格、传感器数据编码为向量,预测未来趋势(如LSTM、Transformer编码)。
3. 向量表征的技术实现
Ⅰ、经典方法
① 无监督学习:Word2Vec通过上下文预测(Skip-Gram)或矩阵分解(GloVe)生成词向量。
② 有监督学习:微调预训练模型(如BERT)适应具体任务,提取任务相关向量。
Ⅱ、前沿方向
① 对比学习(Contrastive Learning):通过构造正负样本对(如“同一图片的不同裁剪”为正样本),拉近正样本向量距离,推开负样本(SimCLR、MoCo)。(正减小,负增大)
② 多模态融合:将文本、图像、语音等多模态信息融合为统一向量(如Google的MUM模型)。
③ 动态向量:根据上下文动态调整向量(如Transformer的注意力机制),解决静态词向量无法适应多义性的问题
二、什么是向量
向量是一种有大小和方向的数学对象。它可以表示为从一个点到另一个点的有向线段。例如,二维空间中的向量可以表示为(x,y),表示从原点(0,0)到点(x,y)的有向线段。
以此类推,我可以用一组坐标(x_0, x_1, x_2, …, x_n)表示一个N维空间中的向量,N 叫向量的维度。
1.文本向量(Text Embeddings)
将文本转成一组N维浮点数,即文本向量又叫 Embeddings
向量之间可以计算距离,距离远近对应语义相似度大小
2.如何得到文本向量
① 构建相关(正例)与不相关(负例)的句子对样本
② 训练双塔式模型,让正例间的距离小,负例间的距离大
例如:
3.向量间的相似度计算
余弦相似度是通过计算两个向量夹角的余弦值来衡量相似性,等于两个向量的点积除以两个向量长度的乘积。
度量指标 | 定义 | 公式 | 取值范围 | 说明 |
---|---|---|---|---|
点积 | 向量对应分量乘积之和 | ![]() | 所有实数 | 值越大越相似,正数表同向、负数表反向、0 表垂直 |
余弦相似度 | 衡量两个向量方向的相似程度 | ![]() | [-1, 1] | 仅感知方向差异,与向量长度无关 |
欧几里得距离 | 两个向量在空间中的直线距离 | ![]() | [0, +∞) | 值越小表示向量在空间中越接近 |
4.代码示例_distance.py
Ⅰ、百炼API环境配置
申请阿里百炼平台API,新用户可免费试用:阿里云-计算,为了无法计算的价值
client:通过 OpenAI()
类实例化的客户端实例,用于封装与 API 服务的所有交互逻辑。
api_key:阿里百炼平台的 API 密钥,用于身份验证,需从阿里百炼控制台获取并通过环境变量传入
base_url:阿里百炼 API 的基础地址,不同地区 / 版本可能不同,需从官方文档获取
OpenAI():是用于创建与大模型 API(如阿里百炼、OpenAI)交互的客户端实例
参数名 | 类型 | 是否必填 | 描述 | 默认值 |
---|---|---|---|---|
api_key | str | 是 | API 密钥,用于身份验证(阿里百炼需填写其平台的密钥)。 | 无 |
base_url | str | 否 | API 服务的基础地址(阿里百炼需填写其专属地址,OpenAI 默认无需填写)。 | OpenAI 官方地址 |
timeout | int /float | 否 | 请求超时时间(秒),超过该时间未响应则终止请求。 | 无(取决于系统默认) |
max_retries | int | 否 | 请求失败时的最大重试次数(如网络错误、超时等情况)。 | 2 次 |
organization | str | 否 | 组织 ID(主要用于 OpenAI 团队账号,阿里百炼一般无需填写)。 | 无 |
http_client | 自定义客户端 | 否 | 自定义 HTTP 客户端(如用于代理、自定义请求头等高级配置)。 | 默认 HTTP 客户端 |
os.getenv(): 用于读取操作系统环境变量
参数名 | 类型 | 是否必填 | 描述 | 默认值 |
---|---|---|---|---|
key | str | 是 | 要读取的环境变量名称(如阿里百炼中的 "BAILIAN_API_KEY" )。 | 无 |
default | 任意类型 | 否 | 当环境变量不存在时返回的默认值(未指定时返回 None )。 | None |
# 阿里百炼
client = OpenAI(api_key=os.getenv("BAILIAN_API_KEY"),base_url=os.getenv("BL_BASE_URL")
)
Ⅱ、余弦距离
dot():计算两个 1D 张量的点积(仅支持 1D 张量,多维张量需用 torch.matmul
)
参数名 | 类型 | 是否必填 | 描述 |
---|---|---|---|
input | 张量(Tensor) | 是 | 第一个 1D 张量(维度必须为 1D,否则报错)。 |
other | 张量(Tensor) | 是 | 第二个 1D 张量(长度需与 input 相同)。 |
norm():用于计算向量或矩阵的范数(衡量向量 “长度” 或矩阵 “大小” 的指标),常见的有 L1 范数(绝对值和)、L2 范数(欧氏距离)等。
参数名 | 类型 | 是否必填 | 描述 | 默认值 |
---|---|---|---|---|
x | 数组(array) | 是 | 输入数组(向量或矩阵)。 | 无 |
ord | int/float | 否 | 范数的阶数: - None :默认 L2 范数(向量)或 F - 范数(矩阵)- 1:L1 范数 - 2:L2 范数 - np.inf :无穷范数(最大值) | None |
axis | int/tuple | 否 | 计算范数的轴(用于多维数组): - 向量(1D):无需指定 - 矩阵(2D): axis=0 按列,axis=1 按行 | 无 |
keepdims | bool | 否 | 是否保留输出的维度(True 则输出维度与输入一致,False 则压缩维度)。 | False |
# 余弦距离
def cos_sim(a, b):'''余弦距离 -- 越大越相似'''return dot(a, b) / (norm(a) * norm(b))
Ⅲ、欧氏距离
np.asarray():NumPy 库中用于将输入数据(如列表、元组、其他数组等)转换为 NumPy 数组(ndarray
)的核心函数。
参数名 | 类型 | 是否必填 | 描述 | 默认值 |
---|---|---|---|---|
a | 任意可转换对象 | 是 | 输入数据,可以是列表、元组、列表的列表、NumPy 数组、 Pandas 数据结构等。 | 无 |
dtype | 数据类型(如 np.int32 ) | 否 | 输出数组的数据类型。若未指定,自动从输入数据中推断。 | None (自动推断) |
order | {'C', 'F'} | 否 | 数组在内存中的存储顺序: - 'C' :按行优先(C 语言风格)- 'F' :按列优先(Fortran 风格) | 'C' |
ndmin | int | 否 | 指定输出数组的最小维度。若输入数据维度小于该值,会在前面补维度。 | 0 |
like | 数组对象 | 否 | 参考该数组的属性(如 dtype、shape 等)来创建输出数组(NumPy 1.20+ 支持)。 |
norm():用于计算向量或矩阵的范数(衡量向量 “长度” 或矩阵 “大小” 的指标),常见的有 L1 范数(绝对值和)、L2 范数(欧氏距离)等。
参数名 | 类型 | 是否必填 | 描述 | 默认值 |
---|---|---|---|---|
x | 数组(array) | 是 | 输入数组(向量或矩阵)。 | 无 |
ord | int/float | 否 | 范数的阶数: - None :默认 L2 范数(向量)或 F - 范数(矩阵)- 1:L1 范数 - 2:L2 范数 - np.inf :无穷范数(最大值) | None |
axis | int/tuple | 否 | 计算范数的轴(用于多维数组): - 向量(1D):无需指定 - 矩阵(2D): axis=0 按列,axis=1 按行 | 无 |
keepdims | bool | 否 | 是否保留输出的维度(True 则输出维度与输入一致,False 则压缩维度)。 | False |
# 欧式距离
def l2(a, b):'''欧氏距离 -- 越小越相似'''x = np.asarray(a) - np.asarray(b)return norm(x)
Ⅳ、转换为嵌入向量
texts:函数的输入参数,需转换为嵌入向量的文本集合。每个元素为一个字符串,代表一段文本。
model:函数的输入参数,指定用于生成嵌入向量的模型名称。默认值为 "text-embedding-v1"
(常见的嵌入模型)。
百炼平台通用文本向量模型:
dimensions:函数的输入参数,可选,指定嵌入向量的维度(如 128、256 等)。部分模型支持自定义维度,若模型不支持则需设为 None
(使用默认维度)。
data:嵌入结果列表
client:通过 OpenAI()
类实例化的客户端实例,用于封装与 API 服务的所有交互逻辑。
input:传给 client.embeddings.create()
的参数,即需要转换的文本(与函数的 texts
一致)。
client.embeddings.create():客户端调用嵌入模型 API 的核心方法,用于向模型发送文本,获取对应的嵌入向量。
参数名 | 类型 | 是否必填 | 描述 |
---|---|---|---|
input | 字符串 / 字符串列表 | 是 | 需转换为嵌入向量的文本。可以是单个字符串(如 "hello" )或字符串列表(批量处理,如 ["a", "b"] )。 |
model | 字符串 | 是 | 嵌入模型的名称,需与模型服务支持的名称一致(如 "text-embedding-v1" )。 |
dimensions | 整数 | 否 | 可选,指定嵌入向量的维度。仅部分模型支持(如模型允许自定义维度时),不支持的模型会忽略该参数。 |
encoding_format | 字符串 | 否 | 嵌入向量的编码格式,默认 "float" (返回浮点数列表),部分模型支持 "base64" (Base64 编码)。 |
x.embedding:data
列表中每个元素(嵌入信息对象)的属性,存储具体的嵌入向量值(文本的数值化表示)。
test_query:测试用的查询文本变量,存储了需要转换为向量的具体文本内容。
vec:测试文本test_query
对应的嵌入向量列表。
get_embeddings():封装了 OpenAI 嵌入模型接口的函数,作用是将输入的文本转换为对应的向量(嵌入向量,Embedding)。
len():Python 内置函数,用于返回对象的长度(或元素个数)。
参数名 | 类型要求 | 是否必填 | 作用 | 错误场景示例 |
---|---|---|---|---|
object | 需满足以下任一条件: 1. 内置序列 / 集合类型(如 str 、list 、dict 等);2. 自定义类实现 __len__() 方法。 | 是 | 获取对象的长度 / 元素个数 | len(123) → 抛出 TypeError (整数无长度) |
vec[:4]:取嵌入向量vec
的前 4 个元素,用于简化打印输出。
# 嵌入模型
def get_embeddings(texts, model="text-embedding-v1", dimensions=None):'''封装 OpenAI 的 Embedding 模型接口'''if model == "text-embedding-v1":dimensions = Noneif dimensions:data = client.embeddings.create(input=texts, model=model, dimensions=dimensions).dataelse:data = client.embeddings.create(input=texts, model=model).datareturn [x.embedding for x in data]test_query = "一切都会好的,我一直相信"
vec = get_embeddings([test_query])[0]
print(len(vec))
print(vec[:4])
Ⅴ、完整代码
str.format():Python 字符串的内置方法,用于将指定的值插入字符串中的占位符,生成格式化的新字符串。
参数类型 | 语法形式 | 是否必填 | 作用 |
---|---|---|---|
位置参数 | str.format(val1, val2, ...) | 否(需与占位符数量 / 位置匹配) | 通过顺序对应字符串中的占位符(如 {0} 对应第一个参数)。 |
关键字参数 | str.format(key1=val1, key2=val2, ...) | 否(需与占位符名称匹配) | 通过关键字对应字符串中的命名占位符(如 {name} 对应 name=val 参数)。 |
import os
from openai import OpenAI
import numpy as np
from numpy import dot
from numpy.linalg import norm# 阿里百炼
client = OpenAI(api_key=os.getenv("BAILIAN_API_KEY"),base_url=os.getenv("BL_BASE_URL")
)# 余弦距离
def cos_sim(a, b):'''余弦距离 -- 越大越相似'''return dot(a, b) / (norm(a) * norm(b))# 欧式距离
def l2(a, b):'''欧氏距离 -- 越小越相似'''x = np.asarray(a) - np.asarray(b)return norm(x)# 嵌入模型
def get_embeddings(texts, model="text-embedding-v1", dimensions=None):'''封装 OpenAI 的 Embedding 模型接口'''if model == "text-embedding-v1":dimensions = Noneif dimensions:data = client.embeddings.create(input=texts, model=model, dimensions=dimensions).dataelse:data = client.embeddings.create(input=texts, model=model).datareturn [x.embedding for x in data]test_query = "一切都会好的,我一直相信"
vec = get_embeddings([test_query])[0]
print(len(vec))
print(vec[:4])query = "国际争端"# 且能支持跨语言
# query = "global conflicts"documents = ["联合国就苏丹达尔富尔地区大规模暴力事件发出警告","土耳其、芬兰、瑞典与北约代表将继续就瑞典“入约”问题进行谈判","日本岐阜市陆上自卫队射击场内发生枪击事件 3人受伤","国家游泳中心(水立方):恢复游泳、嬉水乐园等水上项目运营","我国首次在空间站开展舱外辐射生物学暴露实验",
]query_vec = get_embeddings([query])[0]
doc_vecs = get_embeddings(documents)print("Query与自己的余弦距离: {:.2f}".format(cos_sim(query_vec, query_vec)))
print("Query与Documents的余弦距离:")
for vec in doc_vecs:print(cos_sim(query_vec, vec))print()print("Query与自己的欧氏距离: {:.2f}".format(l2(query_vec, query_vec)))
print("Query与Documents的欧氏距离:")
for vec in doc_vecs:print(l2(query_vec, vec))
三、Embedding Models 嵌入模型
1.什么是嵌入(Embedding)
嵌入(Embedding)是指非结构化数据转换为向量的过程,通过神经网络模型或相关大模型,将真实世界的离散数据投影到高维数据空间上,根据数据在空间中的不同距离,反映数据在物理世界的相似度。
2.嵌入模型概念及原理
Ⅰ、嵌入模型的本质
嵌入模型(Embedding Model)是一种将离散数据(如文本、图像)映射到连续向量空间的技术。通过高维向量表示(如 768 维或 3072 维),模型可捕捉数据的语义信息,使得语义相似的文本在向量空间中距离更近。例如,“忘记密码”和“账号锁定”会被编码为相近的向量,从而支持语义检索而非仅关键词匹配。
Ⅱ、核心作用
① 语义编码:将文本、图像等转换为向量,保留上下文信息(如 BERT 的 CLS Token 或均值池化。
② 相似度计算:通过余弦相似度、欧氏距离等度量向量关联性,支撑检索增强生成(RAG)、推荐系统等应用。
③ 信息降维:压缩复杂数据为低维稠密向量,提升存储与计算效率。
3.主流嵌入模型分类与选型指南
Embedding 模型将文本转换为数值向量,捕捉语义信息,使计算机能够理解和比较内容的"意义"。选择 Embedding 模型的考虑因素:
因素 | 说明 |
---|---|
任务性质 | 匹配任务需求(问答、搜索、聚类等) |
领域特性 | 通用vs专业领域(医学、法律等) |
⭐多语言支持 | 需处理多语言内容时考虑 |
⭐维度 | 权衡信息丰富度与计算成本 |
许可条款 | 开源vs专有服务 |
最大Tokens | 适合的上下文窗口大小 |
Ⅰ、通用全能型
① BGE-M3:北京智源研究院开发,支持多语言、混合检索(稠密+稀疏向量),处理 8K 上下文,适合企业级知识库。
② NV-Embed-v2:基于 Mistral-7B,检索精度高(MTEB 得分 62.65),但需较高计算资源。
Ⅱ、垂直领域特化型
① 中文场景: BGE-large-zh-v1.5 (合同/政策文件)、 M3E-base (社交媒体分析)。
② 多模态场景: BGE-VL (图文跨模态检索),联合编码 OCR 文本与图像特征。
Ⅲ、轻量化部署型
① nomic-embed-text:768 维向量,推理速度比 OpenAI 快 3 倍,适合边缘设备。
② gte-qwen2-1.5b-instruct:1.5B 参数,16GB 显存即可运行,适合初创团队原型验。
⭐Ⅳ、选型决策树:
① 中文为主 → BGE 系列 > M3E;
② 多语言需求 → BGE-M3 > multilingual-e5;
③ 预算有限 → 开源模型(如 Nomic Embed)
最好的测试方法:为特定应用测试多个Embedding模型,评估在实际数据上的性能进行选择
4.嵌入模型使用实践
Ⅰ、方式1:使用API调用方式
client:通过 OpenAI()
类实例化的客户端实例,用于封装与 API 服务的所有交互逻辑。
api_key:阿里百炼平台的 API 密钥,用于身份验证,需从阿里百炼控制台获取并通过环境变量传入
base_url:阿里百炼 API 的基础地址,不同地区 / 版本可能不同,需从官方文档获取
OpenAI():是用于创建与大模型 API(如阿里百炼、OpenAI)交互的客户端实例
参数名 | 类型 | 是否必填 | 描述 | 默认值 |
---|---|---|---|---|
api_key | str | 是 | API 密钥,用于身份验证(阿里百炼需填写其平台的密钥)。 | 无 |
base_url | str | 否 | API 服务的基础地址(阿里百炼需填写其专属地址,OpenAI 默认无需填写)。 | OpenAI 官方地址 |
timeout | int /float | 否 | 请求超时时间(秒),超过该时间未响应则终止请求。 | 无(取决于系统默认) |
max_retries | int | 否 | 请求失败时的最大重试次数(如网络错误、超时等情况)。 | 2 次 |
organization | str | 否 | 组织 ID(主要用于 OpenAI 团队账号,阿里百炼一般无需填写)。 | 无 |
http_client | 自定义客户端 | 否 | 自定义 HTTP 客户端(如用于代理、自定义请求头等高级配置)。 | 默认 HTTP 客户端 |
os.getenv(): 用于读取操作系统环境变量
参数名 | 类型 | 是否必填 | 描述 | 默认值 |
---|---|---|---|---|
key | str | 是 | 要读取的环境变量名称(如阿里百炼中的 "BAILIAN_API_KEY" )。 | 无 |
default | 任意类型 | 否 | 当环境变量不存在时返回的默认值(未指定时返回 None )。 | None |
completion:调用client.embeddings.create()
后得到的结果对象,包含生成的嵌入向量及相关元数据。
client.embeddings.create():客户端调用嵌入模型 API 的核心方法,用于向模型发送文本,获取对应的嵌入向量。
参数名 | 类型 | 是否必填 | 描述 |
---|---|---|---|
input | 字符串 / 字符串列表 | 是 | 需转换为嵌入向量的文本。可以是单个字符串(如 "hello" )或字符串列表(批量处理,如 ["a", "b"] )。 |
model | 字符串 | 是 | 嵌入模型的名称,需与模型服务支持的名称一致(如 "text-embedding-v1" )。 |
dimensions | 整数 | 否 | 可选,指定嵌入向量的维度。仅部分模型支持(如模型允许自定义维度时),不支持的模型会忽略该参数。 |
encoding_format | 字符串 | 否 | 嵌入向量的编码格式,默认 "float" (返回浮点数列表),部分模型支持 "base64" (Base64 编码)。 |
completion.model_dump_json():将 completion
对象(即嵌入模型 API 的返回结果)中包含的所有信息(如嵌入向量、模型名称、使用的维度等)序列化为 JSON 字符串,方便查看、存储或传输。
参数名 | 类型 | 是否必填 | 描述 | 默认值 |
---|---|---|---|---|
indent | int | 否 | 格式化 JSON 时的缩进空格数,用于美化输出(如 indent=2 会让 JSON 有缩进,更易读)。 | None |
exclude_unset | bool | 否 | 是否排除未设置的字段(即只保留有实际值的字段)。 | False |
exclude_defaults | bool | 否 | 是否排除值为默认值的字段。 | False |
import os
from openai import OpenAI# 阿里百炼
client = OpenAI(api_key = os.getenv("BAILIAN_API_KEY"),base_url = os.getenv("BL_BASE_URL")
)# 选择embedding模型:
# ① 是否需要多语言支持(BGE-M3)、② 维度大小、
# ③ 中文为主(BGE系列:BGE-large-zh-v1.5)、④ 预算有限,开源为主
completion = client.embeddings.create(model="text-embedding-v3",input='国际争端',dimensions=1024,encoding_format="float"
)print(completion.model_dump_json())
Ⅱ、方式2:本地私有化部署
四、向量数据库
1.什么是向量数据库
向量数据库,是专门为向量检索设计的中间件,高效存储、快速检索和管理高纬度向量数据的系统称为向量数据库
一种专门用于存储和检索高维向量数据的数据库。它将数据(如文本、图像、音频等)通过嵌入模型转换为向量形式,并通过高效的索引和搜索算法实现快速检索。
向量数据库的核心作用是实现相似性搜索,即通过计算向量之间的距离(如欧几里得距离、余弦相似度等)来找到与目标向量最相似的其他向量。它特别适合处理非结构化数据,支持语义搜索、内容推荐等场景。
核心功能:
① 向量存储、② 相似性度量、③ 相似性搜索
2.如何存储和检索嵌入向量
存储:向量数据库将嵌入向量存储为高维空间中的点,并为每个向量分配唯一标识符(ID),同时支持存储元数据。
检索:通过近似最近邻(ANN)算法(如PQ等)对向量进行索引和快速搜索。比如,FAISS和Milvus等数据库通过高效的索引结构加速检索。
3.向量数据库与传统数据库对比
Ⅰ、数据类型
传统数据库:存储结构化数据(如表格、行、列)。
向量数据库:存储高维向量数据,适合非结构化数据。
Ⅱ、查询方式
传统数据库:依赖精确匹配(如=、<、>)。
向量数据库:基于相似度或距离度量(如欧几里得距离、余弦相似度)。
Ⅲ、应用场景
传统数据库:适合事务记录和结构化信息管理。
向量数据库:适合语义搜索、内容推荐等需要相似性计算的场景。
Ⅳ、向量数据库选型
① 企业数据量较大,并发高,需分布式部署:Milvus
② 公司内部知识库:Qdrant、Chroma较轻量化
1.向量数据库的意义是快速的检索
2.向量数据库本身不生成向量,向量是由Embedding模型产生的
3.向量数据库与传统的关系型数据库是互补的,不是替代关系,在实际应用中根据实际需求经常同时使用
4.Chroma向量数据库
Chroma 是一款开源的向量数据库,专为高效存储和检索高维向量数据设计。其核心能力在于语义相似性搜索,支持文本、图像等嵌入向量的快速匹配,广泛应用于大模型上下文增强(RAG)、推荐系统、多模态检索等场景。与传统数据库不同,Chroma 基于向量距离(如余弦相似度、欧氏距离)衡量数据关联性,而非关键词匹配。
Ⅰ、核心优势
① 轻量易用:以 Python/JS 包形式嵌入代码,无需独立部署,适合快速原型开发。
② 灵活集成:支持自定义嵌入模型(如 OpenAI、HuggingFace),兼容 LangChain 等框架。
③ 高性能检索:采用 HNSW 算法优化索引,支持百万级向量毫秒级响应。
④ 多模式存储:内存模式用于开发调试,持久化模式支持生产环境数据落地。
Ⅱ、安装
终端输入:pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple chromadb,使用清华源代理安装
Ⅲ、初始化客户端
① 内存模式(不建议使用)
chromadb.Client():Chroma 向量数据库的核心函数,用于创建一个与 Chroma 数据库的客户端连接实例。通过该实例可以操作数据库中的集合(collections),实现向量数据的存储、查询、更新、删除等功能,是与 Chroma 交互的入口。
参数名 | 是否必填 | 作用 |
---|---|---|
settings | 否 | 客户端配置项(如数据库存储路径、超时时间等),默认使用内存模式。 |
persist_directory | 否 | 指定持久化存储目录(若需本地文件存储而非内存模式),仅适用于本地客户端。 |
import chromadbclient = chromadb.Client()
② 持久化模式
chromadb.PersistentClient():Chroma 向量数据库(一个轻量级开源向量存储库)提供的客户端类,用于创建持久化的客户端连接。
参数名 | 类型 | 是否必填 | 描述 | 默认值 |
---|---|---|---|---|
path | str | 否 | 指定数据持久化存储的磁盘目录路径。若不指定,默认存储在当前工作目录的 ./chroma 文件夹中。 | "./chroma" |
settings | Settings | 否 | 客户端配置对象(chromadb.config.Settings 实例),可自定义数据库行为,如日志级别、超时时间等。 | 默认配置(日志级别、超时等使用系统默认值) |
database | str | 否 | 数据库名称(多数据库场景下用于区分不同数据库),仅在高级版本或特定配置中生效。 | "default" (默认数据库) |
# 初始化客户端,数据保存至本地目录,持久化保存
client = chromadb.PersistentClient(path="数据存储目录")
🚀Ⅳ、核心操作流程
集合(Collection):集合是Chroma中管理数据的基本单元,类似关系数据库的表
① 创建集合
client:通过 OpenAI()
类实例化的客户端实例,用于封装与 API 服务的所有交互逻辑。
default_ef:存储一个 “默认嵌入函数” 的实例,用于将文本(如文档、查询语句)转换为数值化的嵌入向量。在 Chroma 中,当创建集合(Collection)或添加文档时,若未指定自定义嵌入函数,可使用该实例自动完成文本到向量的转换,简化向量生成流程。
collection1:Chroma 向量数据库中对应 “my_collection1” 集合的实例对象,作为操作该集合的入口,封装了集合的配置信息并提供数据管理和向量检索的方法接口。
embedding_functions.DefaultEmbeddingFunction():Chroma 提供的默认嵌入函数类的构造函数,用于创建默认嵌入函数的实例。其核心功能是封装了预训练的文本嵌入模型(基于 Sentence Transformers 库的 all-MiniLM-L6-v2
模型),能直接将文本转换为 384 维的嵌入向量,无需用户手动实现嵌入逻辑,适合快速上手。
参数名 | 类型 | 是否必填 | 描述 | 默认值 |
---|---|---|---|---|
model_name | str | 否 | 指定用于生成嵌入向量的 Sentence Transformers 模型名称。需是 Sentence Transformers 支持的预训练模型(如 all-MiniLM-L6-v2 、all-mpnet-base-v2 等)。 | "all-MiniLM-L6-v2" (384 维向量) |
device | str | 否 | 指定模型运行的设备,"cpu" 表示使用 CPU,"cuda" 表示使用 GPU(需安装 CUDA)。 | 自动推断(优先 GPU,无则用 CPU) |
normalize_embeddings | bool | 否 | 是否对生成的嵌入向量进行归一化(L2 归一化,使向量模长为 1),归一化后更适合计算余弦相似度。 | True (默认归一化) |
client.create_collection():客户端核心方法之一,用于创建一个新的集合(Collection)。
参数名 | 是否必填 | 类型 | 作用 |
---|---|---|---|
name | 是 | str | 集合的唯一名称(不可重复),用于标识集合,后续可通过该名称调用集合(如 client.get_collection(name="xxx") )。 |
metadata | 否 | Optional[dict] | 集合的元数据(键值对字典),用于存储集合级别的额外信息(如创建时间、用途描述等)。 |
embedding_function | 否 | Optional[Callable] | 用于该集合的嵌入函数(将文本转换为向量的函数),若不指定则使用 Chroma 默认嵌入函数(all-MiniLM-L6-v2 )。 |
get_or_create | 否 | bool | 默认为 False ;若设为 True ,当同名集合已存在时不会抛出错误,而是直接返回该已有集合。 |
configuration:集合的高级配置字典,用于指定索引算法、相似度计算方式、嵌入函数等。
子参数名 | 类型 | 描述 | 默认值 |
---|---|---|---|
hnsw | dict | HNSW 索引的配置选项,用于控制向量检索的精度、速度和算法细节。 | 默认包含基础 HNSW 配置(如space="cosine" 等) |
hnsw.space | str | 指定向量相似度的计算方式,可选值: - "cosine" :余弦相似度(常用)- "l2" :欧氏距离- "ip" :内积 | "cosine" (默认余弦相似度) |
hnsw.ef_search | int | 搜索时的 ef 参数,控制搜索精度和速度:值越大,精度越高但速度越慢(推荐 50-200)。 | 100 |
hnsw.ef_construction | int | 构建索引时的 ef 参数,控制索引质量:值越大,索引越精确但构建时间越长(推荐 100-500)。 | 100 |
hnsw.max_neighbors | int | 每个节点在 HNSW 图中的最大邻居数,影响索引结构和检索效率(推荐 16-64)。 | 16 |
hnsw.num_threads | int | 构建索引时使用的线程数,值越大(不超过 CPU 核心数),构建速度越快。 | 4(默认 4 线程) |
embedding_function | 嵌入函数实例(如 DefaultEmbeddingFunction ) | 指定用于将文本转换为向量的嵌入函数,代码中使用了之前创建的 default_ef (基于 MiniLM-L6-v2 模型)。 | Chroma 默认嵌入函数(DefaultEmbeddingFunction ) |
# 创建默认嵌入函数实例
# 默认情况下,Chroma 使用 DefaultEmbeddingFunction,它是基于 Sentence Transformers 的 MiniLM-L6-v2 模型
default_ef = embedding_functions.DefaultEmbeddingFunction()# 类似于MySQL的表结构
collection1 = client.create_collection(name="my_collection1",configuration={# HNSW 索引算法,基于图的近似最近邻搜索算法(Approximate Nearest Neighbor,ANN)"hnsw": {# space:指定相似度计算方式"space": "cosine", # 指定余弦相似度计算"ef_search": 100, # ef参数,用于控制搜索的精度和速度"ef_construction": 100, # ef参数,用于控制构建索引的精度和速度"max_neighbors": 16, # 最大邻居数"num_threads": 4 # 线程数},# 指定向量模型,不指定默认MiniLM-L6-v2模型"embedding_function": default_ef}
)
② 查询集合
collection1:Chroma 向量数据库中对应 “my_collection1” 集合的实例对象,作为操作该集合的入口,封装了集合的配置信息并提供数据管理和向量检索的方法接口。
client:通过 OpenAI()
类实例化的客户端实例,用于封装与 API 服务的所有交互逻辑。
client.get_collection():从 Chroma 客户端中获取已存在的集合(Collection)实例,用于后续操作该集合(如查询、添加数据等)。若集合不存在,会抛出异常(除非指定 get_or_create=True
自动创建)。
参数名 | 类型 | 是否必填 | 描述 | 默认值 |
---|---|---|---|---|
name | str | 是 | 要获取的集合名称(必须是已存在的集合名称)。 | 无 |
get_or_create | bool | 否 | 若为 True ,当集合不存在时自动创建该集合;若为 False ,集合不存在则报错。 | False |
collection1.peek():查看集合中已存储的部分数据(默认前 10 条),包括文档、IDs、元数据和向量(可选),用于快速预览集合内容。
参数名 | 类型 | 是否必填 | 描述 | 默认值 |
---|---|---|---|---|
limit | int | 否 | 指定要返回的数据条数(最多返回集合中实际存在的数量)。 | 10 |
include | list | 否 | 指定要返回的字段,可选值:["documents", "ids", "metadatas", "embeddings"] ,默认返回所有字段。 | 所有字段 |
collection1.count():返回集合中已存储的文档(或向量)的总数量,用于快速了解集合的数据规模。
# 查询集合
collection1 = client.get_collection(name="my_collection1")print(collection1.peek())print(collection1.count())
③ 修改集合名称
collection1.modify():修改已创建集合的配置信息,如名称、元数据、索引参数(如 HNSW 配置)等。
参数名 | 类型 | 是否必填 | 描述 | 默认值 |
---|---|---|---|---|
name | str | 否 | 新的集合名称(修改后原名称失效)。 | 原名称 |
metadata | dict | 否 | 新的集合元数据(键值对形式),用于更新集合的描述信息。 | 原元数据 |
configuration | dict | 否 | 新的集合配置(如 HNSW 索引参数、嵌入函数等),用于更新索引或向量生成规则。 | 原配置 |
# 修改集合名称
print(collection1.modify(name="new_name"))
④ 删除集合
client:通过 OpenAI()
类实例化的客户端实例,用于封装与 API 服务的所有交互逻辑。
client.delete_collection():Chroma 客户端的方法,用于永久删除指定名称的集合(Collection),包括该集合中存储的所有文档、向量、元数据和索引信息。删除后数据无法恢复,适用于清理不再需要的集合。
参数名 | 类型 | 是否必填 | 描述 | 默认值 |
---|---|---|---|---|
name | str | 是 | 要删除的集合的名称(必须是已存在的集合名称,否则会报错)。 | 无 |
# 删除集合
client.delete_collection(name="my_collection1")
⑤ 添加数据——方式1:自动生成向量
collection1:Chroma 向量数据库中对应 “my_collection1” 集合的实例对象,作为操作该集合的入口,封装了集合的配置信息并提供数据管理和向量检索的方法接口。
client:通过 OpenAI()
类实例化的客户端实例,用于封装与 API 服务的所有交互逻辑。
collection1.add(): Chroma 集合(Collection)的核心方法,用于向集合中添加数据,包括文档(文本)、唯一标识(IDs)、元数据(附加信息),以及可选的预生成嵌入向量。若未提供嵌入向量,会自动使用集合配置的嵌入函数(如代码中的 default_ef
)将文档转换为向量,为后续的向量检索(如语义搜索)提供数据基础。
参数名 | 类型 | 是否必填 | 描述 |
---|---|---|---|
documents | list[str] 或 None | 否 | 要添加的文本列表(如 ["文档1内容", "文档2内容"] )。若提供,且未指定 embeddings ,会自动生成向量。与 ids 长度必须一致。 |
ids | list[str] | 是 | 每个文档的唯一标识符列表(如 ["id1", "id2"] ),用于后续定位或删除数据。长度必须与 documents 或 embeddings 一致。 |
metadatas | list[dict] 或 None | 否 | 每个文档的元数据列表(如 [{"category": "news"}, {"category": "tech"}] ),用于附加描述信息(如分类、时间)。长度需与 ids 一致。 |
embeddings | list[list[float]] 或 None | 否 | 预生成的嵌入向量列表(如 [[0.1, 0.2], [0.3, 0.4]] )。若提供,会直接存储,不使用集合的嵌入函数;若不提供,则自动生成。长度需与 ids 一致。 |
images | list 或 None | 否 | 可选,添加图像数据(需配合支持图像的嵌入函数),格式取决于嵌入函数要求。 |
client.get_collection():从 Chroma 客户端中获取已存在的集合(Collection)实例,用于后续操作该集合(如查询、添加数据等)。若集合不存在,会抛出异常(除非指定 get_or_create=True
自动创建)。
参数名 | 类型 | 是否必填 | 描述 | 默认值 |
---|---|---|---|---|
name | str | 是 | 要获取的集合名称(必须是已存在的集合名称)。 | 无 |
get_or_create | bool | 否 | 若为 True ,当集合不存在时自动创建该集合;若为 False ,集合不存在则报错。 | False |
collection1.peek():查看集合中已存储的部分数据(默认前 10 条),包括文档、IDs、元数据和向量(可选),用于快速预览集合内容。
参数名 | 类型 | 是否必填 | 描述 | 默认值 |
---|---|---|---|---|
limit | int | 否 | 指定要返回的数据条数(最多返回集合中实际存在的数量)。 | 10 |
include | list | 否 | 指定要返回的字段,可选值:["documents", "ids", "metadatas", "embeddings"] ,默认返回所有字段。 | 所有字段 |
collection1.count():返回集合中已存储的文档(或向量)的总数量,用于快速了解集合的数据规模。
collection1.add(documents=["大模型应用开发工程师", "提示词工程师", "算法工程师", "公务员"],metadatas=[{"job": "BigModel Engineering"}, {"job": "Prompt Engineering"}, {"job": "AI Engineering"},{"job": "GovernmentOfficer"}],ids=["id1", "id2", "id3", "id4"]
)collection1 = client.get_collection(name="my_collection1")print(collection1.peek())print(collection1.count())
⑤ 添加数据——方式2:手动生成向量
方式1使用了集合创建时指定的嵌入模型自动生成向量,方式2则使用我们之前定义的get_embeddings()函数,手动传入预计算的向量
client.create_collection():客户端核心方法之一,用于创建一个新的集合(Collection)。
参数名 | 类型 | 是否必填 | 描述 | 默认值 |
---|---|---|---|---|
name | str | 是 | 集合的唯一名称(在当前数据库中不可重复),用于标识该集合(类似 MySQL 的表名)。 | 无 |
configuration | dict | 否 | 集合的高级配置字典,用于指定索引算法、相似度计算方式、嵌入函数等。 | 默认为空字典,使用 Chroma 的默认配置(如默认 HNSW 索引、余弦相似度等) |
configuration:集合的高级配置字典,用于指定索引算法、相似度计算方式、嵌入函数等。
子参数名 | 类型 | 描述 | 默认值 |
---|---|---|---|
hnsw | dict | HNSW 索引的配置选项,用于控制向量检索的精度、速度和算法细节。 | 默认包含基础 HNSW 配置(如space="cosine" 等) |
hnsw.space | str | 指定向量相似度的计算方式,可选值: - "cosine" :余弦相似度(常用)- "l2" :欧氏距离- "ip" :内积 | "cosine" (默认余弦相似度) |
hnsw.ef_search | int | 搜索时的 ef 参数,控制搜索精度和速度:值越大,精度越高但速度越慢(推荐 50-200)。 | 100 |
hnsw.ef_construction | int | 构建索引时的 ef 参数,控制索引质量:值越大,索引越精确但构建时间越长(推荐 100-500)。 | 100 |
hnsw.max_neighbors | int | 每个节点在 HNSW 图中的最大邻居数,影响索引结构和检索效率(推荐 16-64)。 | 16 |
hnsw.num_threads | int | 构建索引时使用的线程数,值越大(不超过 CPU 核心数),构建速度越快。 | 4(默认 4 线程) |
embedding_function | 嵌入函数实例(如 DefaultEmbeddingFunction ) | 指定用于将文本转换为向量的嵌入函数,代码中使用了之前创建的 default_ef (基于 MiniLM-L6-v2 模型)。 | Chroma 默认嵌入函数(DefaultEmbeddingFunction ) |
documents:要添加的文本列表(如 ["文档1内容", "文档2内容"]
)。
collection2:Chroma 向量数据库中对应 “my_collection2” 集合的实例对象,作为操作该集合的入口,封装了集合的配置信息并提供数据管理和向量检索的方法接口。
collection2.add(): Chroma 集合(Collection)的核心方法,用于向集合中添加数据,包括文档(文本)、唯一标识(IDs)、元数据(附加信息),以及可选的预生成嵌入向量。若未提供嵌入向量,会自动使用集合配置的嵌入函数(如代码中的 default_ef
)将文档转换为向量,为后续的向量检索(如语义搜索)提供数据基础。
参数名 | 类型 | 是否必填 | 描述 |
---|---|---|---|
documents | list[str] 或 None | 否 | 要添加的文本列表(如 ["文档1内容", "文档2内容"] )。若提供,且未指定 embeddings ,会自动生成向量。与 ids 长度必须一致。 |
ids | list[str] | 是 | 每个文档的唯一标识符列表(如 ["id1", "id2"] ),用于后续定位或删除数据。长度必须与 documents 或 embeddings 一致。 |
metadatas | list[dict] 或 None | 否 | 每个文档的元数据列表(如 [{"category": "news"}, {"category": "tech"}] ),用于附加描述信息(如分类、时间)。长度需与 ids 一致。 |
embeddings | list[list[float]] 或 None | 否 | 预生成的嵌入向量列表(如 [[0.1, 0.2], [0.3, 0.4]] )。若提供,会直接存储,不使用集合的嵌入函数;若不提供,则自动生成。长度需与 ids 一致。 |
images | list 或 None | 否 | 可选,添加图像数据(需配合支持图像的嵌入函数),格式取决于嵌入函数要求。 |
client.get_collection():从 Chroma 客户端中获取已存在的集合(Collection)实例,用于后续操作该集合(如查询、添加数据等)。若集合不存在,会抛出异常(除非指定 get_or_create=True
自动创建)。
参数名 | 类型 | 是否必填 | 描述 | 默认值 |
---|---|---|---|---|
name | str | 是 | 要获取的集合名称(必须是已存在的集合名称)。 | 无 |
get_or_create | bool | 否 | 若为 True ,当集合不存在时自动创建该集合;若为 False ,集合不存在则报错。 | False |
collection2.peek():查看集合中已存储的部分数据(默认前 10 条),包括文档、IDs、元数据和向量(可选),用于快速预览集合内容。
参数名 | 类型 | 是否必填 | 描述 | 默认值 |
---|---|---|---|---|
limit | int | 否 | 指定要返回的数据条数(最多返回集合中实际存在的数量)。 | 10 |
include | list | 否 | 指定要返回的字段,可选值:["documents", "ids", "metadatas", "embeddings"] ,默认返回所有字段。 | 所有字段 |
collection2.count():返回集合中已存储的文档(或向量)的总数量,用于快速了解集合的数据规模。
# 添加数据
# 方式2:手动传入预计算向量collection2 = client.create_collection(name="my_collection2",configuration={# HNSW 索引算法,基于图的近似最近邻搜索算法(Approximate Nearest Neighbor,ANN)"hnsw": {"space": "cosine", # 指定余弦相似度计算"ef_search": 100, # ef参数,用于控制搜索的精度和速度"ef_construction": 100, # ef参数,用于控制构建索引的精度和速度"max_neighbors": 16, # 最大邻居数"num_threads": 4 # 线程数},# 指定向量模型,不指定默认MiniLM-L6-v2模型"embedding_function": default_ef}
)documents = ["大模型应用开发工程师", "提示词工程师", "算法工程师", "公务员"]# embeddings: 向量列表
# documents: 文档列表
# ids: 文档ID列表
collection2.add(embeddings=get_embeddings(documents),documents=documents,metadatas=[{"job": "BigModel Engineering"}, {"job": "Prompt Engineering"}, {"job": "AI Engineering"},{"job": "GovernmentOfficer"}],ids=["id1", "id2", "id3", "id4"]
)collection2 = client.get_collection(name="my_collection2")print(collection2.peek())print(collection2.count())
⑥ 查询数据——方式1:自动向量化查询
result1:字典(或类似结构的对象),包含与查询文本(如 ["RAG是什么?"]
)最相似的文档信息。其核心作用是存储查询结果的详细数据,方便后续对匹配到的内容进行处理(如提取答案、展示给用户等)。
collection1.query():向量数据库中用于基于文本的相似性检索的核心方法
参数名 | 作用说明 | 是否必填 | 示例 |
---|---|---|---|
query_texts | 待查询的文本列表(支持批量查询),函数会自动将其转换为向量。 | 是 | query_texts=["RAG是什么?", "大模型如何结合RAG?"] |
n_results | 指定返回的最相似结果数量(默认通常为 10,可根据需求调整)。 | 否 | n_results=4 (返回前 4 个最相似的文档) |
where | 按元数据过滤文档(仅返回符合元数据条件的文档),支持常见逻辑运算符。 | 否 | where={"source": "ai_tech.pdf", "page": {"$gt": 3}} (来源为指定 PDF 且页码 > 3) |
where_document | 按文档内容过滤(仅返回内容包含指定关键词的文档)。 | 否 | where_document={"$contains": "检索增强"} (内容包含 “检索增强” 的文档) |
include | 指定返回结果中包含的字段(默认包含documents 、metadatas 、distances )。 | 否 | include=["documents", "ids"] (仅返回文档内容和 id) |
namespace | 若集合有命名空间(namespace),指定查询的命名空间(隔离不同数据组)。 | 否 | namespace="tech_docs" (仅查询 “tech_docs” 命名空间下 |
# 查询数据 文本查询(自动向量化)
results1 = collection1.query(query_texts = ["RAG是什么?"],n_results = 4,# where = {"job": "BigModel Engineering"}, # 按元数据过滤# where_document = {"$contains": "工程师"} # 按文档内容过滤
)print("results1:",results1)
⑦ 查询数据——方式2:自定义向量化查询
方式1使用了集合创建时指定的嵌入模型自动生成向量,方式2则使用我们之前定义的get_embeddings()函数,手动传入预计算的向量
result2:字典(或类似结构的对象),包含与查询文本(如 ["RAG是什么?"]
)最相似的文档信息。其核心作用是存储查询结果的详细数据,方便后续对匹配到的内容进行处理(如提取答案、展示给用户等)。
collection2.query():向量数据库中用于基于文本的相似性检索的核心方法
参数名 | 作用说明 | 是否必填 | 示例 |
---|---|---|---|
query_texts | 待查询的文本列表(支持批量查询),函数会自动将其转换为向量。 | 是 | query_texts=["RAG是什么?", "大模型如何结合RAG?"] |
n_results | 指定返回的最相似结果数量(默认通常为 10,可根据需求调整)。 | 否 | n_results=4 (返回前 4 个最相似的文档) |
where | 按元数据过滤文档(仅返回符合元数据条件的文档),支持常见逻辑运算符。 | 否 | where={"source": "ai_tech.pdf", "page": {"$gt": 3}} (来源为指定 PDF 且页码 > 3) |
where_document | 按文档内容过滤(仅返回内容包含指定关键词的文档)。 | 否 | where_document={"$contains": "检索增强"} (内容包含 “检索增强” 的文档) |
include | 指定返回结果中包含的字段(默认包含documents 、metadatas 、distances )。 | 否 | include=["documents", "ids"] (仅返回文档内容和 id) |
namespace | 若集合有命名空间(namespace),指定查询的命名空间(隔离不同数据组)。 | 否 | namespace="tech_docs" (仅查询 “tech_docs” 命名空间下 |
# 查询数据 向量查询(自定义向量化输入)
results2 = collection2.query(query_embeddings = get_embeddings(["正部级干部"]),n_results = 1,
)print("results2:", results2)
⑧ 更新集合中的数据
collection1.update():向量数据库中用于更新集合中已有文档的方法。它允许修改已存储文档的核心信息(如文本内容、元数据、向量值等),适用于当文档内容发生变化、元数据需要更新(如修正标签、来源)或向量需要重新计算时,确保集合中的数据保持准确和最新。
注意:该方法仅用于更新已存在的文档(需通过文档唯一 ID 指定),不用于新增文档(新增通常用 insert()
或 upsert()
)。
参数名 | 作用说明 | 是否必填 | 示例 |
---|---|---|---|
ids | 需更新的文档的唯一标识列表(必须是集合中已存在的 ID),用于指定要更新的文档。 | 是 | ids=["doc_001", "doc_002"] (更新 ID 为这两个的文档) |
documents | 新的文档内容列表,用于替换原有文档的文本内容(若提供,可能会自动重新生成向量,取决于数据库配置)。 | 否 | documents=["新的文档内容1...", "新的文档内容2..."] |
metadatas | 新的元数据列表,用于替换原有文档的元数据(如来源、标签、时间等)。 | 否 | metadatas=[{"source": "updated.pdf", "tag": "AI"}, {"author": "new"}] |
vectors | 新的向量列表,用于直接替换原有文档的向量值(若不提供,且提供了documents ,可能会自动生成)。 | 否 | vectors=[[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]] (新的向量数组) |
namespace | 若集合有命名空间(namespace),指定要更新的文档所在的命名空间(隔离不同数据组)。 | 否 | namespace="tech_docs" (仅更新 “tech_docs” 命名空间下的文档) |
collection1.query():向量数据库中用于基于文本的相似性检索的核心方法
参数名 | 作用说明 | 是否必填 | 示例 |
---|---|---|---|
query_texts | 待查询的文本列表(支持批量查询),函数会自动将其转换为向量。 | 是 | query_texts=["RAG是什么?", "大模型如何结合RAG?"] |
n_results | 指定返回的最相似结果数量(默认通常为 10,可根据需求调整)。 | 否 | n_results=4 (返回前 4 个最相似的文档) |
where | 按元数据过滤文档(仅返回符合元数据条件的文档),支持常见逻辑运算符。 | 否 | where={"source": "ai_tech.pdf", "page": {"$gt": 3}} (来源为指定 PDF 且页码 > 3) |
where_document | 按文档内容过滤(仅返回内容包含指定关键词的文档)。 | 否 | where_document={"$contains": "检索增强"} (内容包含 “检索增强” 的文档) |
include | 指定返回结果中包含的字段(默认包含documents 、metadatas 、distances )。 | 否 | include=["documents", "ids"] (仅返回文档内容和 id) |
namespace | 若集合有命名空间(namespace),指定查询的命名空间(隔离不同数据组)。 | 否 | namespace="tech_docs" (仅查询 “tech_docs” 命名空间下 |
# 更新集合中的数据
collection1.update(ids=["id1"], documents=["事业编"])
results3 = collection1.query(query_texts = ["国家"],n_results = 2,
)print("results3:", results3)
⑨ 删除集合 / 集合中的数据
collection1.delete():删除当前集合(collection1
)中的指定文档,而不是删除集合本身。它支持通过文档 ID 精准删除,或通过条件筛选删除符合要求的文档(如按元数据、文档内容过滤),适用于清理无效数据、移除过期文档等场景。
参数名 | 作用说明 | 是否必填 | 示例 |
---|---|---|---|
ids | 要删除的文档唯一 ID 列表(若提供,将精准删除这些 ID 对应的文档)。 | 否 | ids=["doc_001", "doc_002"] (删除 ID 为这两个的文档) |
where | 按元数据条件删除文档(仅删除符合元数据条件的文档,需与ids 二选一或组合使用)。 | 否 | where={"source": "obsolete.pdf"} (删除来源为 “obsolete.pdf” 的文档) |
where_document | 按文档内容条件删除文档(仅删除内容包含指定关键词的文档)。 | 否 | where_document={"$contains": "错误信息"} (删除内容含 “错误信息” 的文档) |
namespace | 若集合有命名空间(namespace),指定要删除的文档所在的命名空间。 | 否 | namespace="old_docs" (仅删除 “old_docs” 命名空间下的文档) |
client.delete_collection():删除整个集合(包括集合内的所有文档、元数据、向量等全部数据),是集合级别的删除操作。执行后,该集合将从客户端(client
)管理的集合列表中移除,且操作不可逆(需谨慎使用)。
参数名 | 作用说明 | 是否必填 | 示例 |
---|---|---|---|
name | 要删除的集合的名称(必须是已存在的集合名称,用于精准指定目标集合)。 | 是 | name="knowledge_base" (删除名为 “knowledge_base” 的集合) |
timeout | 操作超时时间(单位:秒),超出时间未完成则抛出异常(可选,默认由客户端配置)。 | 否 | timeout=30 (超时时间 30 秒) |
# 删除集合中的数据
collection1.delete(ids=["id2"])# 删除集合
client.delete_collection(name="my_collection1")
client.delete_collection(name="my_collection2")
⑩ 完整代码
import os
import chromadb
from openai import OpenAI
from chromadb.utils import embedding_functions# 初始化客户端,内存存储,一般不推荐使用
'''
import chromadbclient = chromadb.Client()
'''# 初始化客户端,数据保存至本地目录,持久化保存
client = chromadb.PersistentClient(path=r"F:\AI_BigModel\appTest1\ChromaDb\Data")# 创建默认嵌入函数实例
# 默认情况下,Chroma 使用 DefaultEmbeddingFunction,它是基于 Sentence Transformers 的 MiniLM-L6-v2 模型
default_ef = embedding_functions.DefaultEmbeddingFunction()# 使用 OpenAI 的嵌入模型,默认使用 text-embedding-ada-002 模型
# openai_ef = embedding_functions.OpenAIEmbeddingFunction(
# api_key="YOUR_API_KEY",
# model_name="text-embedding-3-small"
# )# 类似于MySQL的表结构
collection1 = client.create_collection(name="my_collection1",configuration={# HNSW 索引算法,基于图的近似最近邻搜索算法(Approximate Nearest Neighbor,ANN)"hnsw": {# space:指定相似度计算方式"space": "cosine", # 指定余弦相似度计算"ef_search": 100, # ef参数,用于控制搜索的精度和速度"ef_construction": 100, # ef参数,用于控制构建索引的精度和速度"max_neighbors": 16, # 最大邻居数"num_threads": 4 # 线程数},# 指定向量模型,不指定默认MiniLM-L6-v2模型"embedding_function": default_ef}
)# 查询集合
collection1 = client.get_collection(name="my_collection1")print(collection1.peek())print(collection1.count())# 修改集合名称
# print(collection1.modify(name="new_name"))# 删除集合
# client.delete_collection(name="my_collection1")print("——————————————————————————————————————————————————————————————————————————")
# 添加数据
# 方式1:自动生成向量(使用集合指定的嵌入模型)
# documents: 文档列表
# metadatas: 元数据列表
# ids: 文档ID列表
collection1.add(documents=["大模型应用开发工程师", "提示词工程师", "算法工程师", "公务员"],metadatas=[{"job": "BigModel Engineering"}, {"job": "Prompt Engineering"}, {"job": "AI Engineering"},{"job": "GovernmentOfficer"}],ids=["id1", "id2", "id3", "id4"]
)collection1 = client.get_collection(name="my_collection1")print(collection1.peek())print(collection1.count())print("——————————————————————————————————————————————————————————————————————————")# 添加数据
# 方式2:手动传入预计算向量# 阿里百炼
client1 = OpenAI(api_key=os.getenv("BAILIAN_API_KEY"),base_url=os.getenv("BL_BASE_URL")
)def get_embeddings(texts, model="text-embedding-v1", dimensions=None):'''封装 OpenAI 的 Embedding 模型接口'''if model == "text-embedding-v1":dimensions = Noneif dimensions:data = client1.embeddings.create(input=texts, model=model, dimensions=dimensions).dataelse:data = client1.embeddings.create(input=texts, model=model).datareturn [x.embedding for x in data]collection2 = client.create_collection(name="my_collection2",configuration={# HNSW 索引算法,基于图的近似最近邻搜索算法(Approximate Nearest Neighbor,ANN)"hnsw": {"space": "cosine", # 指定余弦相似度计算"ef_search": 100, # ef参数,用于控制搜索的精度和速度"ef_construction": 100, # ef参数,用于控制构建索引的精度和速度"max_neighbors": 16, # 最大邻居数"num_threads": 4 # 线程数},# 指定向量模型,不指定默认MiniLM-L6-v2模型"embedding_function": default_ef}
)documents = ["大模型应用开发工程师", "提示词工程师", "算法工程师", "公务员"]# embeddings: 向量列表
# documents: 文档列表
# ids: 文档ID列表
collection2.add(embeddings=get_embeddings(documents),documents=documents,metadatas=[{"job": "BigModel Engineering"}, {"job": "Prompt Engineering"}, {"job": "AI Engineering"},{"job": "GovernmentOfficer"}],ids=["id1", "id2", "id3", "id4"]
)collection2 = client.get_collection(name="my_collection2")print(collection2.peek())print(collection2.count())print("——————————————————————————————————————————————————————————————————————————")# 查询数据 文本查询(自动向量化)
results1 = collection1.query(query_texts = ["RAG是什么?"],n_results = 4,# where = {"job": "BigModel Engineering"}, # 按元数据过滤# where_document = {"$contains": "工程师"} # 按文档内容过滤
)print("results1:",results1)print("——————————————————————————————————————————————————————————————————————————")# 查询数据 向量查询(自定义向量化输入)
results2 = collection2.query(query_embeddings = get_embeddings(["正部级干部"]),n_results = 1,
)print("results2:", results2)print("——————————————————————————————————————————————————————————————————————————")# 更新集合中的数据
collection1.update(ids=["id1"], documents=["事业编"])
results3 = collection1.query(query_texts = ["国家"],n_results = 2,
)print("results3:", results3)# 删除集合中的数据
collection1.delete(ids=["id2"])# 删除集合
client.delete_collection(name="my_collection1")
client.delete_collection(name="my_collection2")# server端
# chroma run --path /db_path
# chroma run --path F:\AI_BigModel\appTest1\ChromaDb\Data# Client端
# import chromadb
#
# chroma_client = chromadb.HttpClient(host='localhost', port=8000)'''
向量数据库,是专门为向量检索设计的中间件!高效存储、快速检索和管理高纬度向量数据的系统称为向量数据库一种专门用于存储和检索高维向量数据的数据库。它将数据(如文本、图像、音频等)通过嵌入模型转换为向量形式,并通过高效的索引和搜索算法实现快速检索。向量数据库的核心作用是实现相似性搜索,即通过计算向量之间的距离(如欧几里得距离、余弦相似度等)来找到与目标向量最相似的其他向量。它特别适合处理非结构化数据,支持语义搜索、内容推荐等场景。核心功能:
① 向量存储
② 相似性度量
③ 相似性搜索存储:向量数据库将嵌入向量存储为高维空间中的点,并为每个向量分配唯一标识符(ID),同时支持存储元数据。
检索:通过近似最近邻(ANN)算法(如PQ等)对向量进行索引和快速搜索。比如,FAISS和Milvus等数据库通过高效的索引结构加速检索。数据类型
传统数据库:存储结构化数据(如表格、行、列)。
向量数据库:存储高维向量数据,适合非结构化数据。
查询方式
传统数据库:依赖精确匹配(如=、<、>)。
向量数据库:基于相似度或距离度量(如欧几里得距离、余弦相似度)。
应用场景
传统数据库:适合事务记录和结构化信息管理。
向量数据库:适合语义搜索、内容推荐等需要相似性计算的场景。向量数据库比较:
① 企业数据量较大,并发高,需分布式部署:Milvus
② 公司内部知识库:Qdrant、Chroma较轻量化
'''
Ⅴ、Chroma Client-Server Mode
① Client
chroma run --path /db_path:启动 Chroma 服务,并将数据库的核心文件(包括元数据、向量索引等)持久化存储到 /db_path
目录中(而非默认的内存或当前目录)。
chroma run --path chroma运行文件(chroma.sqlite3)的存储路径
② Server
chromadb.HttpClient():用于创建一个 连接远程 ChromaDB 服务的 HTTP 客户端实例,通过网络与部署在远程服务器(或本地另一进程)的 ChromaDB 服务进行交互(如创建集合、插入数据、查询等)。适用于 ChromaDB 以客户端 - 服务器模式部署的场景(而非本地文件 / 内存模式),支持跨进程或跨机器操作向量数据。
参数名 | 作用说明 | 是否必填 | 示例值 |
---|---|---|---|
host | 远程 ChromaDB 服务的主机地址(IP 或域名)。 | 否 | "localhost" (默认)、"192.168.1.100" |
port | 远程 ChromaDB 服务的端口号。 | 否 | 8000 (默认,ChromaDB 默认端口) |
ssl | 是否使用 HTTPS 加密连接(True 为 HTTPS,False 为 HTTP)。 | 否 | False (默认,使用 HTTP)、True |
headers | 自定义 HTTP 请求头(如认证信息、用户标识等),以字典形式传入。 | 否 | {"Authorization": "Bearer token123"} |
timeout | 连接超时时间(单位:秒),超出时间未建立连接则抛出异常。 | 否 | 30 (默认值由 ChromaDB 客户端配置) |
persist_directory | (仅特殊场景)指定本地持久化目录(通常用于客户端缓存,远程模式下很少使用)。 | 否 | "./chroma_cache" |
import chromadbchroma_client = chromadb.HttpClient(host='localhost', port=8000)