Embedding

image-20241016102402609

Vector Store

概述

  1. 在 AI 时代,文字图像语音视频多模态数据的复杂性显著增加
  2. 多模态数据具有非结构化多维特征
    • 向量表示能够有效表示语义和捕捉潜在的语义关系
    • 促使向量数据库成为存储、检索和分析高维向量的关键工具

Qdrant / Milvus

image-20241016105046214

优势

image-20241016105836730

SQL vs NoSQL

  1. 传统数据库通常分为关系型(SQL)数据库和非关系型(NoSQL)数据库
  2. 存储复杂非结构化半结构化信息的需求,主要依赖于 NoSQL 的能力
Store Desc Note
Key-Value 用于简单的数据存储,通过 Key 来快速访问数据 精准定位信息
Document 用于存储文档结构的数据,如 JSON 格式 复杂的结构化信息
Graph 用于表示和存储复杂的关系数据,常用于社交网络推荐等场景 复杂的关系数据
Vector 用于存储和检索基于向量表示的数据,用于 AI 模型的高维度和复杂的嵌入向量 语义最相关的数据
  1. 向量数据库的核心在于能够基于向量之间的相似性,能够快速精确定位检索数据
  2. 向量数据库不仅为嵌入向量提供了优化的存储查询性能
    • 同时也继承了传统数据库的诸多优势 - 性能可扩展性灵活性 - 充分利用大规模数据
  3. 传统的基于标量的数据库
    • 无法应对数据复杂性规模化处理的挑战,难以有效提取洞察并实现实时分析

主要优势

  1. 数据管理
    • 向量数据库提供易于使用的数据存储功能 - 插入 + 删除 + 更新
    • Faiss 是独立的向量索引工具,需要额外的工作才能与存储解决方案集成
  2. 元数据存储和筛选
    • 向量数据库能够存储与每个向量条目关联的元数据
    • 基于元数据,可以进行更细粒度的查询,从而提升查询的精确度灵活性
  3. 可扩展性
    • 向量数据库支持分布式并行处理
    • 并通过无服务器架构优化大规模场景下成本
  4. 实时更新
    • 向量数据库支持实时数据更新
    • 允许动态修改数据以确保检索结果的时效性准确性
  5. 备份与恢复
    • 向量数据库具备完善的备份机制,确保数据的安全性持久性
  6. 生态系统集成
    • 向量数据库能够与数据处理生态系统中的其它组件轻松集成 - Spark
    • 还能无缝集成 AI 相关工具 - LangChain / LlamaIndex / Cohere
  7. 数据安全与访问控制
    • 向量数据库提供内置的数据安全功能访问控制机制,以保护敏感信息
    • 通过命名空间实现多租户管理,允许对索引进行完全分区

应用场景

  1. 向量数据库广泛应用于 LLM RAG 系统、推荐系统等多种 AI 产品中
  2. 向量数据库是一类专门为生产场景下的嵌入向量管理而构建的数据库
    • 与传统基于标量的数据库以及独立的向量索引工具相比
    • 向量数据库在性能可扩展性安全性生态系统集成等方面展现了显著的优势

原理

  1. 向量数据库是一种专门用于存储和检索多维向量的数据库类型
    • 与传统的基于行列结构的数据库不同,向量数据库主要处理高维空间中的数据点
    • 传统数据库通常处理字符串数字标量,并通过精确匹配来查询数据
    • 向量数据库的操作逻辑是基于相似性搜索
      • 在查询时,应用特定的相似性度量(余弦相似度、欧几里得距离等)来查找与查询向量相似的向量
  2. 向量数据库的核心在于其高效的索引搜索机制
    • 为了优化查询性能,采用哈希(LSH)、量化(PQ)和基于图形(HNSW)的多种算法
    • 构建层次化可导航小世界(HNSW)、产品量化(PQ)和位置敏感哈希(LSH)等索引结构,提升查询性能
    • 搜索过程并非追求绝对精确
      • 通过近似最近邻算法(ANN)在速度准确性之间进行权衡
      • ANN 算法允许一定程度的误差 - 显著提升搜索速度 + 找到与查询相似度较高的向量

向量数据库的索引结构相当于一种预处理步骤

Index structure Desc
HNSW 通过在多层结构中将相似向量连接在一起,快速缩小搜索范围
PQ 通过压缩高维向量,减少内存占用加速检索
LSH 通过哈希函数相似向量聚集在一起,便于快速定位

流程

image-20241016170031508

  1. 数据处理 + 向量化
    • 原始数据首先被处理并转化为嵌入向量
    • 通过嵌入模型实现,利用深度学习算法提取数据的语义特征,生成适合后续处理的高维向量表示
  2. 向量存储
    • 将转化后的嵌入向量存储到向量数据库
    • 数据高效检索 + 以优化的方式管理和维护存储资源(适应不同规模复杂度的应用需求)
  3. 向量索引
    • 存储的嵌入向量经过索引处理,便于在后续查询快速定位相关数据
    • 索引过程通过构建特定结构,使得数据库能够在大规模数据集上实现高效的查询响应
  4. 向量搜索
    • 在收到查询向量后,向量数据库通过已建立的索引结构执行相似性搜索 - 与查询向量最接近数据点
    • 平衡搜索速度准确性 - 在大数据环境下提供快速相关的查询结果
    • 相似度度量
      • 余弦相似度 - 用于文件处理信息检索 - 关注向量之间的角度,捕捉语义相似性
      • 欧几里得距离 - 测量向量之间的实际距离 - 适用于密集特征集聚类分类
      • 曼哈顿距离 - 计算笛卡尔坐标中绝对差值之和,适用于稀疏数据的处理
      • 点积
  5. 数据检索
    • 向量数据库从匹配的向量中检索出对应原始数据,并按需处理
    • 确保最终结果能够准确反映用户的查询意图,并提供有意义的输出

RAG

image-20241016175937752

  1. 在 RAG 系统中,向量数据库的主要功能在于索引过程中,建立高效的向量索引结构
  2. 查询阶段,系统将输入的提示转化为向量表示形式
    • 从向量数据库中检索出与之最相关向量及其对应的分块数据
  3. 通过索引和检索,检索到的向量为 LLM 提供了必要的上下文信息
    • LLM 能够依据当前的语义上下文生成更加精确和相关的响应

选型

image-20241016181814194

场景 选型
快速开发 + 轻量化部署 Chroma / Qdrant
高性能 + 可扩展性 Milvus / Zilliz
极致性能 + 无需持久化 + 无需数据管理 FAISS
多模态数据 Weaviate / LanceDB
集成现有数据库 PGVector / Elasticsearch / Redis
全托管 Pinecone

Chroma

  1. Chroma 是一种简单且易于持久化的向量数据库,以轻量级开箱即用的特性著称
  2. Chroma 支持内存中操作和磁盘持久化,能够高效地管理查询向量数据,非常适合快速集成和开发

Client + Collection

1
2
3
4
# 创建ChromaDB本地存储实例和collection
client = chromadb.PersistentClient(chroma_db_path)
collection = client.get_or_create_collection(name="documents")
embedding_model = load_embedding_model()

Indexing

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
def indexing_process(folder_path, embedding_model, collection):
all_chunks = []
all_ids = []

for filename in os.listdir(folder_path):
file_path = os.path.join(folder_path, filename)

if os.path.isfile(file_path):
document_text = load_document(file_path)
if document_text:
print(f"文档 {filename} 的总字符数: {len(document_text)}")

text_splitter = RecursiveCharacterTextSplitter(chunk_size=512, chunk_overlap=128)
chunks = text_splitter.split_text(document_text)
print(f"文档 {filename} 分割的文本Chunk数量: {len(chunks)}")

all_chunks.extend(chunks)
# 生成每个文本块对应的唯一ID
all_ids.extend([str(uuid.uuid4()) for _ in range(len(chunks))])

embeddings = [embedding_model.encode(chunk, normalize_embeddings=True).tolist() for chunk in all_chunks]

# 将文本块的ID、嵌入向量和原始文本块内容添加到ChromaDB的collection中
collection.add(ids=all_ids, embeddings=embeddings, documents=all_chunks)
print("嵌入生成完成,向量数据库存储完成.")
print("索引过程完成.")
print("********************************************************")

Retrieval

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def retrieval_process(query, collection, embedding_model=None, top_k=6):
query_embedding = embedding_model.encode(query, normalize_embeddings=True).tolist()

# 使用向量数据库检索与query最相似的top_k个文本块
results = collection.query(query_embeddings=[query_embedding], n_results=top_k)

print(f"查询语句: {query}")
print(f"最相似的前{top_k}个文本块:")

retrieved_chunks = []
# 打印检索到的文本块ID、相似度和文本块信息
for doc_id, doc, score in zip(results['ids'][0], results['documents'][0], results['distances'][0]):
print(f"文本块ID: {doc_id}")
print(f"相似度: {score}")
print(f"文本块信息:\n{doc}\n")
retrieved_chunks.append(doc)

print("检索过程完成.")
print("********************************************************")
return retrieved_chunks

Persistence

image-20241016223236449