AI RAG 元数据过滤 怎样处理
来源:17golang原创
时间:2026-10-22 07:04:03 223浏览 收藏
AI RAG 元数据过滤 怎样处理
RAG 里遇到“只查某个租户、只看已发布文档、时间不能超过范围”时,不要把这些条件交给 embedding 猜。更稳妥的做法是把它们定义成结构化 metadata,在向量召回时作为硬过滤;语义相似度只负责在合法候选中排序。
官方地址:https://qdrant.tech/
- 租户、权限、状态属于硬边界,必须进入过滤表达式。
- 分类、标签用精确匹配;时间、数值用 range;长文本不要冒充 keyword。
- 空结果先查字段类型、默认值和过滤命中率,再决定是否放宽条件。
先把元数据过滤和语义检索分开
一条文档通常同时拥有向量和 payload。向量回答“语义上像不像”,metadata 回答“业务上能不能看”。例如 tenant_id、visibility、status 是权限或生命周期字段,published_at 是范围字段,tags 可以是多值标签。它们的判断结果应该先限制候选域,再交给向量相似度排序。

工程上建议维护一个字段白名单:查询解析器只能生成允许的字段、操作符和值类型,不能让用户输入直接拼成过滤 JSON。这样既能避免越权,也能让日志记录“过滤了什么”,便于解释召回结果。
把用户条件转换成可审计的过滤表达式
下面用 Qdrant Python 客户端展示一个最小写法。这里的字段名只是示例,关键是把租户条件和文档状态放在 must,把时间范围用 range 表达;如果业务需要排除草稿,再用 must_not。
from qdrant_client import models
def build_filter(tenant_id: str, start_ts: int, end_ts: int) -> models.Filter:
# 只允许服务端定义的字段,租户条件不能由模型自由改写
return models.Filter(
must=[
models.FieldCondition(
key="tenant_id",
match=models.MatchValue(value=tenant_id),
),
models.FieldCondition(
key="status",
match=models.MatchValue(value="published"),
),
models.FieldCondition(
key="published_at",
range=models.Range(gte=start_ts, lt=end_ts),
),
],
must_not=[
models.FieldCondition(
# 排除明确标记为内部资料的文档
key="visibility",
match=models.MatchValue(value="internal"),
)
],
)
如果一个字段是数组,先确认向量库对数组的匹配语义;不要假设“包含任一标签”和“包含全部标签”是一回事。字段缺失也应有明确策略:权限字段缺失通常拒绝,非关键展示字段缺失才允许继续。
过滤字段要和索引类型一致
过滤失败经常不是语法问题,而是写入类型和查询类型不一致。分类、租户 ID、标签值适合精确匹配;数值和时间要统一为数字或规范化时间;需要按词匹配的长文本应使用 text 类型,而不是把整段文本当作一个 keyword。
| 字段场景 | 建议类型 | 常见条件 | 排查重点 |
|---|---|---|---|
| tenant_id、status | keyword | 等于、排除 | 大小写与缺省值 |
| published_at、score | integer/float/datetime | gte、lt、lte | 单位和时区 |
| tags | keyword 数组 | 包含某标签 | 数组是任一匹配还是全部匹配 |
| title、body 摘要 | text | 词或短语匹配 | 分词、停用词和大小写 |

高频过滤字段应建立对应的 payload index,但不要把所有字段都索引。索引会增加内存和维护成本,优先选择真正参与过滤、且能明显缩小候选集合的字段。过滤条件放在向量查询里,才能避免先召回一堆无权访问的文档再在应用层删除。
空结果和过滤过窄怎样排查
先用一条已知存在的文档做基准查询,只保留 tenant_id,确认租户边界能命中;再逐个加入 status、时间和标签条件。每一步记录候选数、过滤命中数和最终 top-k,不要直接把过滤失败归咎于 embedding。
- 命中数为零:检查字段路径、值类型、大小写和时间单位。
- 命中数异常多:检查是否漏了租户条件,或把数组条件写成了宽松的 should。
- 召回相关但答案不完整:确认过滤是否过窄,并提高候选数量,而不是立刻放弃硬约束。
- 权限字段缺失:默认拒绝,修复入库流程后再补数据;不要用“不过滤”作为兜底。
相关问题
元数据过滤能替代向量相似度吗?
不能。过滤只判断候选是否满足业务条件,向量相似度仍负责语义排序;两者解决的是不同问题。
为什么过滤字段有值仍然查不到?
优先检查实际存储类型、字段路径、时区和操作符。字符串数字与真正的数值字段不能混用。
所有 metadata 都要建索引吗?
不需要。为高频过滤字段建立匹配类型正确的索引,并根据过滤选择性和资源成本逐步增加。
可以在应用层过滤召回结果吗?
普通标签可以做补充过滤,但租户、权限、删除状态等硬约束必须在检索层生效,避免越权文档先进入上下文。
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
467 收藏
-
485 收藏
-
429 收藏
-
214 收藏
-
470 收藏
-
科技周边 · 人工智能 | 1小时前 | python · 人工智能 · 结构化输出 · AI Hugging Face 结构化输出 JSON Schema TGI Inference Providers grammar response_format339 收藏
-
219 收藏
-
476 收藏
-
349 收藏
-
科技周边 · 人工智能 | 1小时前 | python · 数据处理 · 人工智能 · AI Hugging Face Datasets select_columns remove_columns DatasetDict 数据集字段373 收藏
-
科技周边 · 人工智能 | 1小时前 | python · 人工智能 · AI 文本分类 pipeline padding Transformers 批量推理 truncation batch_size379 收藏
-
180 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习