在复杂的知识密集型应用中,可能会面临几百个不同来源于类型的知识文档。如果知识简单地依赖传统的文本分割与top-k检索,就会产生精度不足、知识相互干扰等问题,从而导致效果不佳。
试想下你在一个医学文献数据库中查找关于“糖尿病”的资料,但数据库中也充斥着大量关于其他糖尿病并发症的信息。那么你能查到什么有用的信息?
为此一个重要的优化方法就是在大文档集下“分层”过滤与检索。比如元数据索引
一、 什么是元数据
元数据是对文档的一种属性描述,假设我们使用一个存储了大量科技博客文字的向量数据库。每篇文章都关联了以下标签:
topic:人工智能,区块链,云计算,大数据
author:作者A,作者B,作者C
year:2022,2023,2024
这些标签就是元数据
二、元数据索引思路
- 定义元数据标签,如果文档本身没有,可以利用大模型推理出输入问题的元数据
2。 通过标签先对文档进行过滤 - 结合向量检索进一步定位到最相关的前K个只是快
LangChain中使用SelfQueryRetriever子查询检索器实现
三、示例代码
from langchain_chroma import Chroma
from langchain_classic.chains.query_constructor.schema import AttributeInfo
from langchain_classic.retrievers import SelfQueryRetriever
from Common import get_models
from langchain_core.documents import Document
llm,embeddings_model = get_models()
# 加载文档
docs = [
Document(
page_content="作者A团队开发出基于人工智能的自动驾驶决策系统,在复杂路况下的响应速度提升300%",
metadata={"year": 2024, "rating": 9.2, "genre": "AI", "author": "A"},
),
Document(
page_content="区块链技术成功应用于跨境贸易结算,作者B主导的项目实现交易确认时间从3天缩短至30分钟",
metadata={"year": 2023, "rating": 9.8, "genre": "区块链", "author": "B"},
),
Document(
page_content="云计算平台实现量子计算模拟突破,作者C构建的新型混合云架构支持百万级并发计算",
metadata={"year": 2022, "rating": 8.6, "genre": "云", "author": "C"},
),
Document(
page_content="大数据分析预测2024年全球经济趋势,作者A团队构建的模型准确率超92%",
metadata={"year": 2023, "rating": 8.9, "genre": "大数据", "author": "A"},
),
Document(
page_content="人工智能病理诊断系统在胃癌筛查中达到三甲医院专家水平,作者B获医疗科技创新奖",
metadata={"year": 2024, "rating": 7.1, "genre": "AI", "author": "B"},
),
Document(
page_content="基于区块链的数字身份认证系统落地20省市,作者C设计的新型加密协议通过国家级安全认证",
metadata={"year": 2022, "rating": 8.7, "genre": "区块链", "author": "C"},
),
Document(
page_content="云计算资源调度算法重大突破,作者A研发的智能调度器使数据中心能效提升40%",
metadata={"year": 2023, "rating": 8.5, "genre": "云", "author": "A"},
),
Document(
page_content="大数据驱动城市交通优化系统上线,作者B团队实现早晚高峰通行效率提升25%",
metadata={"year": 2024, "rating": 7.4, "genre": "大数据", "author": "B"},
)
]
vectorsstore = Chroma.from_documents(docs, embeddings_model)
# 元数据字段定义(指导LLM如何解析查询条件)
metadata_field_info = [
AttributeInfo(
name="genre",
description="文章的技术领域,选项:['AI ','区块链','云','大数据']",
type="string",
),
AttributeInfo(
name="year",
description="文章的出版年份",
type="integer",
),
AttributeInfo(
name="author",
description="署名文章的作者姓名",
type="string",
),
AttributeInfo(
name="rating",
description="技术价值评估得分(1-10分)",
type="float"
)
]
# 文档内容描述(指导LLM理解文档内容)
document_content_description = "技术文章简述"
retriever = SelfQueryRetriever.from_llm(
llm,
vectorsstore,
document_content_description,
metadata_field_info,
verbose=True
)
# 检索
print("---------------------评分在9分以上的文章-------------------------------")
#查询条件:查询只约束分数 rating>9
# print(retriever.invoke("我想了解评分在9分以上的文章"))
# print(retriever.invoke("我想了解评分在9分以上的文章,返回1篇文章"))
print("---------------------作者B在2023年发布的文章-------------------------------")
# 第二个查询只约束作者和年份 author="B", year=2023
print(retriever.invoke("作者B在2023年发布的文章"))
# exit()