from llama_index.core import SimpleKeywordTableIndex
#创建关键词引索
keyword_index = SimpleKeywordTableIndex.from_documents(documents)
#检索器导入 1向量 2关键词 3混合
from llama_index.core.retrievers import (
VectorIndexRetriever,
KeywordTableSimpleRetriever,
QueryFusionRetriever,
)
# 1. 向量召回 10 条
vector_ret = VectorIndexRetriever(
index=vector_index,
similarity_top_k=10,
filters=filtersABC, # 元数据过滤仍可用
)
# 2. 关键词召回 10 条
keyword_ret = KeywordTableSimpleRetriever(
index=keyword_index,
keywords=["author", "childhood"], # 也可放空,让框架自动抽关键词,这里添加可以让后续抽中更多关键词
)
# 3. 融合:去重 + 向量相似度重排(默认 fusion_mode="reciprocal_rerank")
fusion_retriever = QueryFusionRetriever(
[vector_ret, keyword_ret], # 并行跑
similarity_top_k=10, # 融合后最终保留 10 条
)
#后面简写
query_engine = RetrieverQueryEngine(
retriever=fusion_retriever, # 只用换这一行
response_synthesizer=get_response_synthesizer(),
node_postprocessors=[
SimilarityPostprocessor(similarity_cutoff=0.7),
KeywordNodePostprocessor(...), # 仍可再卡关键词
FixedRecencyPostprocessor(top_k=7, date_key="date"),
LLMRerank(top_n=3, choice_batch_size=3),
PrevNextNodePostprocessor(num_prev=1, num_next=1),
],
)
关键词后处理KeywordNodePostprocessor 是后处理阶段的字面关键词硬过滤器——
向量或关键词召回的节点已经拿到手以后,再用字符串包含/排除的方式筛一遍,不走路径、不走模型,纯文本匹配。
不管它是向量检索召回的、关键词检索召回的、还是两者融合后的,KeywordNodePostprocessor 只认节点文本本身:
- 文本里同时包含
required_keywords所有词 → 放行 - 文本里一旦出现
exclude_keywords任意词 → 整段扔掉
它不关心节点最初来自哪个索引、哪个算法,只要最终进了 node_postprocessors 列表,就会被逐个字面扫描一遍。
from llama_index.core.postprocessor import KeywordNodePostprocessor
key_filter = KeywordNodePostprocessor(
required_keywords=["author", "childhood"], # 同时出现才保留
exclude_keywords=["fiction", "novel"] # 出现一个就扔掉
)