混合搜索的元数据筛选
结合向量相似度和结构化筛选条件(日期、作者、标签),获得精准且符合上下文的检索结果。
混合搜索的元数据筛选 是 CoddyKit 上的免费 AI Agents 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 AI Agents 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 AI Agents 课程共包含 4 节课。
本课时的部分内容尚未翻译,以英文显示。
为什么需要过滤?
纯向量检索会返回最相似的 K 个分块,即使它们属于错误的租户、使用错误的语言或来自错误的文档。
元数据过滤器将检索范围限制在相关子集内,从而同时提升精确率 AND 召回率。
存储元数据
在摄取时,为每个分块附加一个元数据字典:
metadata = {
'tenant_id': 'acme',
'language': 'en',
'source': 'help-docs',
'updated_at': '2024-08-12',
'tags': ['shipping', 'returns']
}
for k, v in metadata.items():
print(f"{k}: {v}")
Filtering in Pinecone
results = index.query(
vector=query_vec,
top_k=5,
filter={
'tenant_id': 'acme',
'language': 'en'
}
)范围过滤器
大多数向量数据库也支持范围过滤器:
filter = {
'updated_at': {'$gte': '2024-01-01'},
'score': {'$gt': 0.5}
}
print(filter)
In and Not-In
filter = {
'tags': {'$in': ['shipping', 'returns']},
'archived': {'$ne': True}
}
print(filter)
在 Qdrant 中进行过滤
Qdrant 具有丰富的过滤语言:
from qdrant_client.models import Filter, FieldCondition, MatchValue
filter = Filter(must=[
FieldCondition(key='tenant_id', match=MatchValue(value='acme')),
FieldCondition(key='language', match=MatchValue(value='en'))
])
results = client.search(
collection_name='docs',
query_vector=query_vec,
query_filter=filter,
limit=5
)预过滤与后过滤
两种策略:
- 预过滤 —— THEN 执行检索(结果正确,但没有元数据索引时可能很慢)
- 后过滤 —— 先检索,再移除不匹配的结果(速度快,但可能返回零个结果)
生产系统会配合适当的元数据索引执行预过滤。
混合向量与关键词检索
将语义检索与经典的 BM25 关键词检索结合起来。两者都执行,然后合并分数(倒数排名融合是标准做法):
def rrf(vec_results, bm25_results, k=60):
scores = defaultdict(float)
for rank, doc in enumerate(vec_results):
scores[doc.id] += 1 / (k + rank)
for rank, doc in enumerate(bm25_results):
scores[doc.id] += 1 / (k + rank)
return sorted(scores.items(), key=lambda x: -x[1])多租户
在 SaaS 中,EVERY 个 query 都必须按租户标识进行过滤。请在检索封装层中将其硬编码,这样就不会忘记:
def search(query, tenant_id, top_k=5):
return index.query(
vector=embed(query),
top_k=top_k,
filter={'tenant_id': tenant_id}
)通过元数据进行访问控制
将用户和角色权限存储在元数据中:
metadata = {
'visibility': 'public', # or 'internal', 'restricted'
'department': 'engineering',
'allowed_roles': ['engineer', 'manager']
}
# At query time:
filter = {'allowed_roles': {'$contains': current_user_role}}新近度提升
若要优先选择较新的文档,请先检索更多候选项,然后根据新近度重新评分:
candidates = index.query(vector=query_vec, top_k=50)
scored = [
(c.score * recency_factor(c.metadata['updated_at']), c)
for c in candidates
]
scored.sort(reverse=True)
final = scored[:5]注意元数据基数
高基数元数据(数百万个唯一值)会使索引变得庞大。在可能的情况下进行预聚合——例如,在按时间过滤时存储年月,而不是完整时间戳。
始终启用的过滤器
每个多租户智能体都应该 ALWAYS 包含什么过滤器?
回顾
元数据过滤器可以限定检索范围。将其与混合检索(向量 + BM25)结合,以获得最佳结果。多租户和访问控制都依赖于此。
常见问题解答
「混合搜索的元数据筛选」课时是免费的吗?
是的 — 「混合搜索的元数据筛选」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 AI Agents 课程的其余内容,请升级到 CoddyKit PRO。 AI Agents 课程共包含 4 节课。
「混合搜索的元数据筛选」这节课中我会学到什么?
结合向量相似度和结构化筛选条件(日期、作者、标签),获得精准且符合上下文的检索结果。 你通过在浏览器中直接运行的动手代码来练习 AI Agents,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 AI Agents 需要有经验吗?
无需任何先前经验。CoddyKit 上的 AI Agents 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「混合搜索的元数据筛选」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 AI Agents 课中编写并运行代码吗?
能。每节 AI Agents 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。