自查询检索器实现动态元数据过滤

0 阅读2分钟

一、SelfQueryRetriever

SelfQueryRetriever(自查询检索器) 是 LangChain 中的一种高级检索器,它能够:

  • 使用 LLM 自动理解用户的自然语言查询
  • 将查询拆分为两部分:语义搜索部分 + 元数据过滤部分
  • 自动构建过滤条件,实现精确的元数据过滤

二、有什么用

1. 解决的问题

普通向量检索只能做语义相似度匹配,无法根据元数据(如年份、评分、导演等)进行精确过滤。

2. 自查询检索器的优势

  • 自动解析查询:用户用自然语言提问,系统自动提取过滤条件
  • 混合检索:同时支持语义搜索 + 元数据过滤
  • 灵活性强:无需手动编写复杂的过滤逻辑

3. 应用场景

  • 电影推荐(按年份、评分、导演筛选)
  • 产品搜索(按价格、品牌、类别筛选)
  • 文档管理(按日期、作者、标签筛选)

三、核心代码示例

1. 准备带元数据的文档

from langchain_core.documents import Document

documents = [
    Document(
        page_content="肖申克的救赎",
        metadata={"year": 1994, "rating": 9.7, "director": "弗兰克·德拉邦特"},
    ),
    Document(
        page_content="霸王别姬",
        metadata={"year": 1993, "rating": 9.6, "director": "陈凯歌"},
    ),
    # ... 更多文档
]

2. 定义元数据字段描述

from langchain_classic.chains.query_constructor.schema import AttributeInfo

metadata_field_info = [
    AttributeInfo(name="year", description="电影的年份", type="integer"),
    AttributeInfo(name="rating", description="电影的评分", type="float"),
    AttributeInfo(name="director", description="电影的导演", type="string"),
]

3. 创建自查询检索器

from langchain_classic.retrievers import SelfQueryRetriever
from langchain_openai import ChatOpenAI
from langchain_pinecone import PineconeVectorStore

self_query_retriever = SelfQueryRetriever.from_llm(
    llm=ChatOpenAI(model="moonshot-v1-8k", temperature=0),
    vectorstore=db,                    # 向量数据库
    document_contents="电影的名字",       # 文档内容描述
    metadata_field_info=metadata_field_info,  # 元数据字段信息
    enable_limit=True,                  # 允许限制返回数量
)

4. 使用检索器

# 自然语言查询,自动提取过滤条件
docs = self_query_retriever.invoke("查找下评分高于9.5分的电影")

# 对比:普通检索器无法理解元数据过滤
base_docs = retriever.invoke("查找下评分高于9.5分的电影")  # 返回所有相关文档

四、工作原理

用户输入:"查找下评分高于9.5分的电影"
              ↓
      LLM 解析查询
              ↓
    ┌─────────┴─────────┐
    ↓                   ↓
语义查询部分        元数据过滤部分
"电影"            rating > 9.5
    ↓                   ↓
    └─────────┬─────────┘
              ↓
      向量数据库查询
    (语义匹配 + 元数据过滤)
              ↓
        返回精确结果