“向量搜索擅长根据语义相似度查找项目,但应用程序通常需要的不仅仅是相似度。用户经常需要根据关联元数据限制搜索结果。例如,搜索“机器学习文章”可能需要限制为2022年之后发表的、由特定作者撰写或属于特定类别(如“自然语言处理”)的文章。有效整合这些元数据约束是向量搜索优化中的一个重要难题。”应用元数据过滤有两种主要策略:预过滤和后过滤。它们之间的选择涉及性能、准确性和实施复杂性之间的重要权衡。预过滤:先过滤,后搜索预过滤,也称作先过滤后搜索,在执行近似最近邻(ANN)搜索之前应用元数据约束。其主要思想是将潜在候选的范围缩小到只包含满足过滤条件的向量,然后在这个缩小后的子集中执行向量相似度搜索。工作原理:明确过滤条件: 传入的查询包含查询向量和元数据过滤器(例如,category = 'NLP',year > 2022)。选择匹配向量: 系统首先标识数据库中所有关联元数据与过滤条件匹配的向量。这通常涉及查询单独的元数据索引,或如果向量数据库支持集成元数据存储,则借助其功能。执行ANN搜索: ANN搜索算法(如HNSW或IVF)仅在前一步骤中标识的向量子集上执行。返回结果: 返回来自已过滤子集中的Top-k相似向量。digraph G { rankdir=LR; node [shape=box, style=filled, fillcolor="#e9ecef", fontname="sans-serif"]; edge [fontname="sans-serif"]; subgraph cluster_pre { label = "预过滤"; style=filled; color="#dee2e6"; Query [label="查询\n(向量 + 过滤器)"]; FilterData [label="应用元数据过滤器\n(例如,SQL, Lucene)", fillcolor="#a5d8ff"]; FilteredSet [label="已过滤向量ID\n(子集 N')"]; ANNSearch [label="ANN搜索\n(在 N' 向量上)", fillcolor="#91a7ff"]; Results [label="Top-K 结果"]; Query -> FilterData; FilterData -> FilteredSet; FilteredSet -> ANNSearch; ANNSearch -> Results; } }流程图,图示预过滤过程。首先应用元数据过滤器以标识候选子集,然后在该子集上执行ANN搜索。优点:保证准确性: 预过滤确保所有返回结果严格遵守元数据约束。不会因为在初步近似搜索之后被过滤掉而遗漏相关项目。潜在的更小搜索空间: 如果过滤器具有高度选择性(即它们大幅减少候选数量),随后的ANN搜索将在小得多的向量集上操作,这可以加快搜索时间。缺点:过滤瓶颈: 标识匹配元数据的向量的初始步骤可能成为性能瓶颈,尤其是在过滤器复杂或元数据未有效索引的情况下。此步骤可能比ANN搜索本身耗时更长。索引实施复杂性: 实施高效的预过滤通常需要复杂的索引策略。一些向量数据库提供集成解决方案,但其他数据库可能需要为元数据维护独立的数据库或索引,并管理它们之间的协作。对ANN索引结构的影响: 许多ANN算法(如HNSW)依赖于构建在整个数据集上的图结构。在由过滤器定义的任意子集上执行搜索可能会扰乱图遍历的效率,可能需要对子集进行全扫描或使用效率较低的入口点,与搜索整个图相比会降低性能。专用索引(例如,基于IVF的方法,其中分区有时可以与过滤属性对齐)可能更好地处理这种情况。后过滤:先搜索,后过滤后过滤,或先搜索后过滤,颠倒了顺序。它首先执行ANN搜索,纯粹基于语义相似性查找候选向量,然后根据元数据条件过滤这些候选。工作原理:执行ANN搜索: 系统使用查询向量对整个索引(或相关分区)执行ANN搜索,以检索初始的$K'$个候选集,其中$K'$通常大于最终期望的结果数量$K$(例如,$K' = 10 \times K$)。获取元数据: 对于这$K'$个候选,获取其关联的元数据。应用过滤器: 将元数据过滤器应用于这较小的$K'$个候选集。返回结果: 返回来自满足过滤条件的候选中的Top-$K$结果。digraph G { rankdir=LR; node [shape=box, style=filled, fillcolor="#e9ecef", fontname="sans-serif"]; edge [fontname="sans-serif"]; subgraph cluster_post { label = "后过滤"; style=filled; color="#dee2e6"; Query [label="查询\n(向量 + 过滤器)"]; ANNSearch [label="ANN搜索\n(获取 K' 候选)", fillcolor="#91a7ff"]; InitialSet [label="初始候选\n(Top K' 向量 + 元数据)"]; FilterData [label="应用元数据过滤器\n(在 K' 候选上)", fillcolor="#a5d8ff"]; Results [label="Top-K 结果\n(≤ K 返回)"]; Query -> ANNSearch; ANNSearch -> InitialSet; InitialSet -> FilterData; FilterData -> Results; } }流程图,图示后过滤过程。首先在完整数据集上执行ANN搜索以获取K'个候选,然后根据元数据过滤这些候选。优点:更快的ANN搜索(可能): ANN搜索本身在完整的、可能已优化的索引结构上操作,不受预过滤子集施加的约束。如果ANN搜索是主要成本且过滤器选择性不高,这总体上可能更快。更简单的实施: 通常更易于实施,因为向量搜索和元数据查找可以被视为独立的顺序步骤。标准的ANN库和向量数据库很容易支持获取Top $K'$个邻居。缺点:召回问题: 主要缺点是潜在的不准确性或召回率低。初始ANN搜索可能会检索$K'$个候选,但如果许多满足过滤条件的真正最近邻略远,未能进入初始$K'$集,它们在过滤后将被完全遗漏。增加$K'$可以缓解此问题,但这会增加计算成本并且不提供保证。计算浪费: ANN搜索检索并可能计算$K'$个向量的距离,其中许多向量可能在过滤步骤中被丢弃。这代表着计算资源的浪费。需要获取更多候选: 您需要获取比最终期望数量($K$)多得多的候选($K'$),才能有合理的机会找到$K$个满足过滤条件的项,尤其是在过滤器具有选择性时。选择正确的策略最佳策略很大程度上取决于具体的应用、数据特性和性能要求。在以下情况考虑预过滤:过滤器选择性高: 元数据过滤器大幅减少了搜索空间(例如,将数百万项过滤到数千项)。准确性很重要: 您绝对需要保证所有返回结果都匹配过滤条件,并且不能冒着因后过滤中初始搜索的近似性质而遗漏相关项目的风险。元数据过滤速度快: 您拥有高效的机制(例如,良好索引的数据库)来快速标识匹配过滤条件的向量子集。您的向量索引结构本身支持在子集上进行高效搜索(对于HNSW等基于图的索引,除非专门设计,否则不太常见)。在以下情况考虑后过滤:过滤器选择性低: 过滤器只移除了小部分潜在候选。延迟很重要且ANN搜索成本高: 初始ANN搜索的成本占主导地位,而增加预过滤的开销是令人望而却步的。轻微的召回率下降可接受: 遗漏少量满足过滤器但落在初始$K'$结果之外的潜在相关项是可容忍的。注重实施简便性: 首选简单的顺序处理。混合方法:一些系统采用多阶段过滤或混合方法。例如:粗粒度预过滤 + 细粒度后过滤: 使用宽泛的预过滤(例如,基于易于索引的类别)来适当缩小搜索空间,然后进行ANN搜索,并在后过滤期间应用更复杂的过滤器。索引感知过滤: 一些高级向量数据库实施尝试将元数据过滤直接集成到ANN索引遍历过程中,在纯预过滤和后过滤之间提供一种折衷。例如,在HNSW图遍历期间,元数据不匹配的节点可能会被跳过,但这需要向量索引和元数据存储之间的紧密集成。性能调优:对于预过滤: 优化元数据索引和查询执行。评估过滤对子集中ANN搜索性能的影响。对于后过滤: 试验$K'$的值(最初检索的候选数量)。更大的$K'$能提高召回率,但会增加延迟和计算成本。监控过滤后返回的实际结果数量,以查看$K'$是否足够。{ "layout": { "title": "过滤策略权衡", "xaxis": { "title": "过滤器选择性(从低到高)" }, "yaxis": { "title": "相对性能/成本" }, "legend": { "title": "指标" }, "font": { "family": "sans-serif" } }, "data": [ { "type": "scatter", "mode": "lines", "name": "预过滤:过滤成本", "x": ["Low", "Medium", "High"], "y": [1, 5, 10], "line": { "color": "#f03e3e" } }, { "type": "scatter", "mode": "lines", "name": "预过滤:ANN搜索成本", "x": ["Low", "Medium", "High"], "y": [10, 5, 2], "line": { "color": "#ff6b6b" } }, { "type": "scatter", "mode": "lines", "name": "后过滤:ANN搜索成本 (K')", "x": ["Low", "Medium", "High"], "y": [12, 12, 12], "line": { "color": "#1c7ed6" } }, { "type": "scatter", "mode": "lines", "name": "后过滤:过滤成本", "x": ["Low", "Medium", "High"], "y": [1, 1, 1], "line": { "color": "#4dabf7" } }, { "type": "scatter", "mode": "lines", "name": "后过滤:召回风险", "x": ["Low", "Medium", "High"], "y": [1, 4, 9], "line": { "color": "#74c0fc", "dash": "dot" } } ] }图示预过滤和后过滤的成本与风险如何随过滤器选择性变化。预过滤的ANN搜索成本随选择性增加而降低,但其过滤成本可能会上升。后过滤的ANN成本相对恒定,但召回风险随选择性提高而明显增加。最终,选择和实施有效的过滤策略需要理解这些权衡,并针对您的特定数据集、查询模式和应用要求对不同方法进行基准测试。高效过滤不是事后才考虑的事情;它是为复杂LLM应用构建高性能和相关向量搜索系统的重要组成部分。