向量 top-10 里常常混着「列表推导式」这种高相似、低相关块。生成模型分不清,就会把噪声炼进答案。NodePostprocessor 接在 retrieve 之后、合成之前:过滤、重排、截断到 top_n。索引不用重建;改的是这一次送给 LLM 的名单。
段末注释:交叉编码器(cross-encoder,CE)把
(query, 块)拼成一条输入打相关分,比双塔检索更准、也更贵,所以只对 top-k 短名单用。

1. 一句话定位
| 维度 | 内容 |
|---|---|
| 角色 | 知识层的检索后处理:改名单,不改向量库 |
| 输入 → 输出 | list[NodeWithScore] + query → 更短/重排后的 list[NodeWithScore] |
| 典型调用入口 | postprocess_nodes(nodes, query_str=...);as_query_engine(node_postprocessors=[...]) |
| 与 LangChain / LangGraph | 近邻是 compressor / CohereRerank;LangGraph 节点里调 postprocess_nodes 即可 |
出现背景:双塔 embedding 让 query 与文档分别编码,召回快但排序粗。CE 要成对前向,只能打短名单。LlamaIndex 把这一档收成 Postprocessor,插在 QueryEngine 流水线里。
重排方法的评测口径见 RAG-03;本篇只讲 API 怎么挂。
2. 前置依赖与环境
1 | pip install -U llama-index-core llama-index-llms-ollama llama-index-embeddings-ollama sentence-transformers |
- Python 3.10+;
llama-index-core0.14.x SentenceTransformerRerank首次运行会下载 CE 权重(需联网)postprocess_nodes同步即可;QueryEngine 侧生产用aquery
3. 实现逻辑
1 | 1. retriever.retrieve(q, similarity_top_k=较大) |
字段级变形:
1 | retrieve k=5 |
RRF 融合发生在 Retriever 内;CE 发生在 Postprocessor。先融合再 CE,不要反过来(CE 吃不起全库)。
4. 原理说明
主轴是:Postprocessor 读的是已召回的 NodeWithScore,写回的还是 NodeWithScore;QueryEngine 按列表顺序执行它们。
1 | 1. QueryEngine 拿到 retrieve 结果 |
SimilarityPostprocessor(similarity_cutoff=...) 出现在步骤 3。无 query 也能跑。默认不改相对顺序。
SentenceTransformerRerank(model=..., top_n=...) 出现在步骤 4。必须传 query_str 或 query_bundle。默认模型多为 MiniLM 英文 CE;中英混合方法学可换成 BAAI/bge-reranker-base。
KeywordNodePostprocessor(required_keywords=..., exclude_keywords=...) 出现在步骤 5。英文 token 有效;中文短词容易误杀。
as_query_engine(node_postprocessors=[a, b]) 出现在步骤 2。列表顺序 = 流水线顺序:先滤再 CE,或先 CE 再滤,结果不同。
不要把 CE 当检索器:它对未召回的块无能为力。
5. 最小可运行示例
1 | pip install -U llama-index-core llama-index-llms-ollama llama-index-embeddings-ollama sentence-transformers |
1 | from llama_index.core import Document, Settings, VectorStoreIndex |
6. 重要配置参数
| 参数(API 名) | 类型 / 默认值 | 功能说明 | 作用与影响 | 参考起点 / 常用范围 | 配置指导 |
|---|---|---|---|---|---|
similarity_top_k |
int,引擎/检索器 | CE 之前的召回宽度 | 过小 CE 没候选;过大 CE 延迟线性升 | 10~20 再 rerank | 与 top_n 成对:先宽后窄 |
top_n |
int,CE 默认常 2~3 | 重排后保留条数 | 过小漏第二条证据;过大白做 CE | 3~5 | ≤ 合成窗口能消化的块数 |
model |
str | CE 权重 ID | 英文 MiniLM 对中文方法节偏弱 | BAAI/bge-reranker-base 中英 |
与语料语言对齐 |
similarity_cutoff |
float | 按当前 score 硬截 | 量纲随后端变;过严空上下文 | 先打印 raw.score 再设 | Simple 店建议 0 或关掉 |
required_keywords |
list[str] | 块文本必须命中这些词 | 中文单字易误杀 | 基因名、货号 | 只挡明确噪声 |
exclude_keywords |
list[str] | 命中则丢块 | 过宽会丢掉方法节里的对比句 | 明确跑题词 | 与 CE 叠用时放 CE 后 |
node_postprocessors 顺序 |
list 顺序 | 流水线先后 | 先 CE 再 cutoff 用的是 CE 分 | 滤噪声 → CE → 关键词 | 写进注释,避免调换无感 |
7. 适用 / 不适用
| 维度 | 适用 | 不适用 |
|---|---|---|
| 任务形态 | 召回有了但排序吵、生成被噪声带偏 | 根本没召回到金标准块——先改切分/混合检索 |
| 集成约束 | 可下载 CE;或只用 cutoff/关键词 | 禁止本地模型文件——改云端 rerank API(Cohere 等) |
| 工程阶段 | QueryEngine 已跑通 | 要按用户反馈在线学习排序——不是 Postprocessor 的职责 |
8. 易踩坑
- k=2 再 rerank top_n=2:CE 没有重排空间。
- 比较 CE.score 与向量 score:量纲不同。
- cutoff 抄教程 0.7:Simple 店可能全滤空。
- Keyword 当语义过滤:「小鼠」写在无关块里也会留下。
小结
- Postprocessor 不写索引,只改送给 LLM 的名单。
- 模式:放大 retrieve k → CE top_n → 合成。
source_nodes应是后处理之后的列表。- 救不了漏召回;漏召回回 Retriever。