向量 (vector)数据库是为高维向量嵌入 (embedding)优化的专用数据存储,是检索增强生成(RAG)等系统的支柱。有效地管理这些数据库会带来不同于传统关系型或NoSQL数据库的特别操作挑战。它们的性能和可靠性直接影响信息获取的质量和速度,信息获取是为大型语言模型提供支持的。
核心操作与管理要点
操作向量 (vector)数据库不只是存储向量那么简单;它需要认真管理索引、数据摄入、查询、扩展和维护,以确保在LLMOps工作流程中实现最佳性能和成本效益。
模式设计与索引
在摄入数据之前,定义结构和索引策略是基本工作。具体包含:
向量维度: 根据所用嵌入 (embedding)模型选择向量维度(例如768、1024、1536)。维度越高,包含信息越多,但存储和计算成本会增加。
距离度量: 选择合适的度量方式来衡量向量间的相似度。常见选项包括:
余弦相似度: 衡量两个向量之间夹角的余弦值。常用于文本嵌入,在此情况下,方向比大小更重要。计算方法是 余弦相似度 = A ⋅ B ∥ A ∥ ∥ B ∥ 余弦相似度 = \frac{A \cdot B}{\|A\| \|B\|} 余弦相似度 = ∥ A ∥∥ B ∥ A ⋅ B 。
欧氏距离 (L 2 L_2 L 2 ): 衡量向量空间中两点之间的直线距离。计算方法是 L 2 = ∑ i = 1 n ( A i − B i ) 2 L_2 = \sqrt{\sum_{i=1}^{n}(A_i - B_i)^2} L 2 = ∑ i = 1 n ( A i − B i ) 2 。
点积: 如果向量已归一化 (normalization),这种方法可能很高效。
选择取决于您的模型生成的嵌入的特性。
索引算法: 向量数据库使用近似最近邻(ANN)算法来寻找相似向量,而无需详尽比较每个向量,这在大规模情况下计算上不可行。常用算法包括:
HNSW (分层可导航小世界图): 一种基于图的方法,在各种数据集上表现良好。ef_construction(构建时质量/速度权衡)和ef_search(查询时准确性/速度权衡)等可调参数 (parameter)会影响性能。
IVF (倒排文件索引): 将向量空间划分为簇(使用nlist),并在查询时只搜索其中一个子集(nprobe)。常与量化 (quantization)(IVF-PQ)结合使用,以提高内存效率。
其他: Flat(暴力搜索,精确但慢),DiskANN(为SSD优化)。
选择时需要平衡查询延迟、召回率(准确性)、索引构建时间以及内存/存储占用。
元数据存储: 将相关元数据与向量一起存储(例如文档ID、文本块、时间戳)对于查询筛选和为获取的结果提供上下文 (context)非常重要。定义元数据将如何索引以实现高效筛选。
数据摄入
摄入向量(“upserting”——更新或插入)需要高效且可靠,尤其是在处理数百万甚至数十亿向量时。
批处理: 以批次而非单个方式处理数据,以提高吞吐量 (throughput)和减少开销。
嵌入生成: 通常,原始数据(文本、图像)在摄入前需要通过嵌入模型处理。这个嵌入步骤可能是摄入管道的一部分。
幂等性: 确保用相同数据重新运行摄入过程不会产生重复项或错误。
错误处理: 为摄入过程中的暂时性故障实施错误处理和重试机制。
查询
高效查询是主要目标。
ANN搜索: 使用所选索引和距离度量执行相似度搜索,以找到查询向量的top-k最近邻。
元数据筛选: 根据元数据在ANN搜索之前 (预筛选)或之后 (后筛选)筛选候选数据。如果索引结构支持良好,预筛选通常更高效,因为它能减少搜索空间。
混合搜索: 将向量相似度搜索与传统关键词搜索(例如BM25)结合,以提高相关性,尤其是在需要精确关键词匹配时。
性能调优: 通过调整索引参数(如ef_search或nprobe)、扩展资源和优化查询批处理来优化查询延迟和吞吐量。
扩展
随着数据增长和查询负载增加,扩展变得必要。
纵向扩展: 增加现有数据库节点的资源(CPU、内存)。受硬件限制。
横向扩展(分片): 将索引和数据分布到多个节点或副本上。分片可以根据ID范围或元数据属性创建。这使得处理更大的数据集和更高的查询量成为可能。
复制: 创建分片或整个数据库的副本,以提高读取吞吐量并提供高可用性。
一种向量数据库的横向扩展模式,它使用分片和复制来处理大型数据集和高查询负载。路由器将查询分发给适当的副本。
更新与删除向量
在ANN结构中修改索引数据可能比较复杂。
逻辑删除: 许多系统最初会将向量标记 (token)为待删除,但不会立即将它们从索引结构中移除。查询可能仍会暂时考虑这些向量,但稍后会将它们筛选掉。
物理删除/压缩: 通常需要后台进程或定期重建索引,以物理删除已删除的向量并回收空间,这可能会在操作期间影响性能。
更新: 通常实现为删除操作,然后插入新向量。
监控
持续监控对于维护性能和可靠性非常重要。重要指标包括:
查询性能: 延迟(平均值、p95、p99)、吞吐量(每秒查询数 - QPS)。
摄入性能: 摄入速率、批处理时间、错误率。
索引健康状况: 索引大小、新鲜度(自上次更新以来的时间)、构建/压缩时间。
资源使用情况: CPU、内存(对于HNSW等内存索引尤其重要)、磁盘I/O、网络带宽。
准确性/召回率: 如果存在真实数据(在生产环境中通常难以获得),则定期监控ANN查询与精确最近邻的召回率。
成本: 跟踪与数据库相关的计算、存储和数据传输成本。
备份与恢复
考虑到向量索引的潜在庞大体积以及重新生成嵌入和重建索引的成本,需要有力的备份策略。
索引快照: 定期备份索引文件。
数据备份: 单独备份原始数据和元数据。
恢复计划: 定义并测试从备份恢复数据库或在必要时从源数据重建索引的程序。
选择解决方案:托管型与自建型
实施向量 (vector)搜索功能有几种方案:
托管型向量数据库: 云原生服务(例如Pinecone、Weaviate云服务、Zilliz Cloud、Google Vertex AI Matching Engine、支持向量的Azure AI Search、带有k-NN的AWS OpenSearch)处理基础设施管理、扩展和部分操作任务。它们提供更快的设置,但可能控制较少,成本较高。
自建型向量数据库: 开源数据库(例如Milvus、Weaviate、Qdrant)提供灵活性和控制权,但需要自行管理底层基础设施、扩展、更新和操作。
库: Faiss (Facebook AI Similarity Search) 或 ScaNN (Scalable Nearest Neighbors) 等库提供核心索引和搜索算法,但需要构建周围的数据库基础设施和API层。
选择取决于您团队的专业能力、预算、扩展需求、期望的控制水平以及现有基础设施。
索引管理生命周期
向量 (vector)索引并非总是静态的。特别是对于HNSW或IVF等算法,随着大量插入和删除操作,性能可能会随时间下降。通常需要定期维护:
重新索引: 使用当前数据集从头重建索引可以优化其结构并提高性能。这可能需要大量资源,并需要仔细规划以最大程度地减少停机时间(例如,并行构建新索引并进行切换)。
压缩: 对于使用逻辑删除的系统,运行压缩过程可以回收空间并提高查询效率。
参数 (parameter)调优: 随着数据分布或查询模式的变化,可能需要重新评估和调整索引参数(ef_construction、ef_search、nlist、nprobe等)。
集成到LLMOps管道中
向量 (vector)数据库操作应集成到自动化MLOps/LLMOps管道中。示例包括:
数据摄入的CI/CD: 由新数据可用性触发的管道,它会预处理数据,使用指定模型生成嵌入 (embedding),并将向量/元数据更新或插入到数据库中。
自动化索引管理: 用于索引优化、压缩或重建的计划任务。
监控触发的行动: 基于查询性能下降或高错误率的警报会触发自动化扩展行动或通知以进行人工干预。
RAG系统更新: 协调向量数据库更新与RAG系统中使用的LLM或提示模板的更新。
有效管理向量数据库的操作生命周期是构建和维护先进LLM系统(特别是那些依赖RAG的系统)中一个专业但重要的部分。这需要数据库管理技能、对ANN算法的了解以及与更广泛的自动化工作流程的整合。