如何在MongoDB中结合日期筛选实现Python版RAG?
RAG中实现日期范围筛选的可行方案(基于Langchain)
以下是几种在Langchain框架内实现RAG日期范围筛选的实用方案,覆盖不同场景需求:
1. 向量数据库原生元数据过滤(推荐)
绝大多数主流向量数据库(Chroma、Pinecone、Weaviate等)都支持基于元数据的筛选,这是最直接高效的方案。核心思路是存储文档时将日期作为元数据字段,检索时传入日期范围过滤条件。
示例(Chroma为例)
from langchain.vectorstores import Chroma from langchain.embeddings import OpenAIEmbeddings # 初始化向量库(假设已存入带date元数据的文档) embeddings = OpenAIEmbeddings() db = Chroma(persist_directory="./chroma_db", embedding_function=embeddings) # 定义日期范围过滤规则(Chroma使用MongoDB风格的查询语法) date_filter = { "$and": [ {"date": {"$gte": "2024-01-01"}}, {"date": {"$lte": "2024-06-01"}} ] } # 创建带过滤条件的检索器 retriever = db.as_retriever(search_kwargs={"filter": date_filter}) # 执行检索 relevant_docs = retriever.get_relevant_documents("你的查询内容")
注意:不同向量库的过滤语法有差异,比如Pinecone使用>=/<=,Weaviate使用GraphQL风格的过滤,需对应库的文档调整语法。
2. 自定义Retriever实现筛选逻辑
如果向量库原生过滤不满足需求,可以自定义Retriever实现前置/后置筛选:
- 后置筛选:先执行向量搜索,再在结果中过滤日期;
- 前置筛选:先从数据源(如数据库)筛选出符合日期范围的文档ID,再针对这些ID做向量检索。
示例(后置筛选)
from langchain.schema import Document from langchain.retrievers import BaseRetriever from typing import List class DateFilteredRetriever(BaseRetriever): base_retriever: BaseRetriever start_date: str end_date: str def _get_relevant_documents(self, query: str) -> List[Document]: # 先获取基础向量检索结果 raw_docs = self.base_retriever.get_relevant_documents(query) # 过滤符合日期范围的文档(假设date为ISO格式字符串) filtered_docs = [ doc for doc in raw_docs if self.start_date <= doc.metadata["date"] <= self.end_date ] return filtered_docs # 使用方式 base_retriever = db.as_retriever() date_retriever = DateFilteredRetriever( base_retriever=base_retriever, start_date="2024-01-01", end_date="2024-06-01" ) relevant_docs = date_retriever.get_relevant_documents("你的查询内容")
3. 基于SelfQueryRetriever的自然语言日期筛选
如果需要支持用户用自然语言描述日期范围(如“2024年上半年的技术文档”),可以用Langchain的SelfQueryRetriever,它能将自然语言查询转换为元数据过滤条件+向量检索。
示例
from langchain.retrievers.self_query.base import SelfQueryRetriever from langchain.chains.query_constructor.base import AttributeInfo from langchain.llms import OpenAI # 定义元数据字段描述 metadata_fields = [ AttributeInfo( name="date", description="文档的发布日期,格式为YYYY-MM-DD", type="string" ) ] doc_content_desc = "技术文档的正文内容" # 创建SelfQueryRetriever retriever = SelfQueryRetriever.from_llm( llm=OpenAI(temperature=0), vectorstore=db, document_contents=doc_content_desc, metadata_field_info=metadata_fields, verbose=True ) # 自然语言查询 relevant_docs = retriever.get_relevant_documents("2024年1月到6月之间的AI技术文档")
4. 结合SQL的前置筛选(适用于带SQL能力的向量库)
如果使用Postgres+pgvector、MySQL+向量插件这类支持SQL的向量存储,可以先通过SQL筛选出符合日期范围的文档,再进行向量检索。
示例(PGVector为例)
from langchain.vectorstores.pgvector import PGVector from langchain.embeddings import OpenAIEmbeddings CONNECTION_STRING = "postgresql+psycopg2://user:pass@localhost:5432/dbname" embeddings = OpenAIEmbeddings() # 先执行SQL筛选日期范围的文档ID date_filter_sql = """ SELECT id FROM document_table WHERE date >= '2024-01-01' AND date <= '2024-06-01' """ # 针对筛选出的ID执行向量检索 db = PGVector( connection_string=CONNECTION_STRING, embedding_function=embeddings, table_name="document_table", query_vector_name="embedding" ) relevant_docs = db.similarity_search( "你的查询内容", k=5, filter_ids=[row[0] for row in db._conn.execute(date_filter_sql)] )
常见失败原因排查
- 元数据日期格式不统一:确保存储时用标准ISO格式(如
YYYY-MM-DD),避免混用datetime对象、时间戳或不同格式的字符串; - 过滤语法错误:不同向量库的过滤规则差异大,务必对照官方文档调整;
- 自定义Retriever实现问题:需正确继承
BaseRetriever,并实现_get_relevant_documents方法; - SelfQueryRetriever解析失败:可调整Prompt模板,或使用更擅长实体提取的LLM(如GPT-4)提升解析准确率。
内容的提问来源于stack exchange,提问作者Mahimai Raja J
相关产品推荐
相关产品推荐

