把一份技术方案写成连载,多半是因为我们踩过同一种坑:当你把公司 Wiki 塞进向量库,再用某个开源模型去问“某款开源 BI 工具怎么做数据权限”,返回的前五条结果往往“看着都像”,却没一条真正对准了配置项。
别急着怪模型“胡说八道”。很多时候,问题出在检索这一步——它只做了粗筛,没做精排。
大多数 RAG 管线第一层用的是向量相似度,快,是它最大的优点。但也正因为“快”,它会把大量“字面接近、语义偏题”的段落推到前面。你搜“升级失败回滚”,它可能把“升级步骤”和“版本差异说明”顶到最顶端;你问“权限继承规则”,它又把“角色与组”的概述页排得很靠前。这类“看起来相关”的内容一旦进入 LLM,就容易让它在生成时“脑补”出一个看似合理、实则偏离的答案。
Rerank(重排序)并不是再算一遍相似度那么简单。它通常借助 CrossEncoder 这类结构,把“查询 + 候选段落”一起丢进模型,做更细粒度的相关性判断。双塔结构分别编码 query 和 doc,追求速度;而交叉编码器把两者放在一起理解,精度更高,代价是更慢,因此适合放在“粗筛之后、生成之前”的第二道关卡。
这条思路并不新鲜,但在本地环境落地以前,很多团队要么把 Rerank 放到云端 API,要么就得上一套 GPU 服务。前者涉及数据外流与成本,后者对小团队而言维护门槛不低。当 Ollama 开始支持 Reranking 模型后,事情变得接地气:你可以在一台开发机或小型服务器上,用熟悉的 ollama pull 把专用重排模型拉下来,再用 ollama run 把它暴露成接口,接入现有 RAG 管线。相当于把“企业级的精排能力”搬到了本地,还不用从零折腾推理引擎和部署栈。
第一次试用时真没抱太大期待——CPU 模式嘛,听上去就是“能用就行”。可等我把公司内部文档完整跑了一轮,感受还挺直观:Top-N 里那些“噪音”明显少了,原本常年排在第三位的配置示例,终于稳稳地挤到了第一。这背后的原因也不难理解:Rerank 不是替你“找更多”,而是帮你“挑得更准”。当候选集已经被第一层检索缩小到一定程度,交叉编码器就能发挥它的强项——用上下文视角重新衡量每一段的真实相关度,再把真正的“关键证据”推到 LLM 眼前。
Ollama部署Rerank模型:从安装到拉取Qwen3-Reranker
前文说到 Rerank 是 RAG 流水线里那道“不声不响但缺它不行”的关卡——现在,它真能跑在你笔记本上了。Ollama 0.4.10 起正式支持 Reranking 模型类型,不再需要自己 patch model.json 或伪造 API 响应格式。Windows 用户直接下安装包(2025 年 10 月后版本默认带 CUDA 支持检测);macOS 用 Homebrew;Linux 就一行 curl —— 官网给的脚本至今没变过,curl -fsSL https://ollama.com/install.sh | sh。我试过 M2 Pro 和 i5-1135G7,都跳过了“构建失败”那一关。
Qwen 团队在 2025 年底开源的 Reranker 系列,目前公开模型卡明确标注了 reranker 类型,Ollama 能直接识别。别拉 qwen3:4b 主模型——它不是 reranker。正确命令:
ollama pull qwen3-reranker:4b
# 支持 0.6b / 4b / 8b 三档,CPU 推荐 4b,GPU 显存 ≥12GB 可上 8b
ollama list 里会多出一行模型,Type 列显示 reranker,不是 llm。输入一个 query 和两个候选文本(用 JSON 格式),几秒内返回 score 数组。不用写 server、不用改 config、不用配 CORS。Ollama 内置的 reranker 接口默认走 /api/rerank,和 OpenAI 兼容层对得上——你原来的 RAG pipeline 代码几乎不用动。这步做完,你就有了本地版的 CrossEncoder 精排能力。不是 demo,是能塞进生产 pipeline 的真实接口。
搭建RAG二次精排Pipeline:检索→Rerank→生成
好,模型跑起来了。现在的问题变成:怎么把它塞进你那个已经能跑的 RAG 流程里?别急。我见过太多人把 reranker 当独立玩具玩了两天就扔一边了——因为没有想清楚它怎么跟 embedding 检索和 LLM 生成串起来。这节我就直接画一条线:查询 → 向量召回 Top-K → Rerank 精排 → 截断 Top-N → 拼 Prompt → 生成。你照着这条线搭,不会出大问题。
Embedding 模型(比如 Qwen3-Embedding)做的是第一道粗筛:它把用户问题和所有知识库文档都转成向量,拿余弦相似度或者点积算一遍相关性,拉回 Top-K。K 一般设 20~50,视你知识库大小和性能取舍而定。但 embedding 的语义理解有限。它能区分“苹果”和“香蕉”是水果,但很难判断用户问的是“苹果公司股价”还是“苹果营养价值”。
这就是 reranker 上场的时候——它拿到那 20 个候选文档后,把每个候选和原始查询拼接成一个文本对(query + document),丢进交叉编码器做一次深度打分,输出一个 0~1 之间的 score。然后按分数降序重排,把最相关的 3~5 个文档喂给 LLM。
我假设你已经用某种方式做了向量检索。不管你是用 Chroma、FAISS 还是 PostgreSQL + pgvector,召回这一步不变。关键在第二步:把召回的候选列表发给 Ollama 的 /api/rerank 接口。Ollama 的 rerank 接口要求你传三个字段:model(你拉的 reranker 模型名)、query(用户的原始问题)、documents(候选文档列表)。返回的是一个 JSON,里面有个 results 数组,每个元素包含 index 和 score。
import requests, json
OLLAMA_BASE = "http://localhost:11434"
def rerank(query: str, documents: list[str], top_n: int = 3):
payload = {
"model": "qwen3-reranker:4b",
"query": query,
"documents": documents
}
resp = requests.post(f"{OLLAMA_BASE}/api/rerank", json=payload)
results = resp.json()["results"]
# 按 score 降序排序,取前 top_n 个
results.sort(key=lambda x: x["score"], reverse=True)
top_indices = [r["index"] for r in results[:top_n]]
return [documents[i] for i in top_indices]
这段代码很短,但够用。别被网上那些封装成类的玩具误导——真实 pipeline 里一个函数就够了。假设你的知识库已经向量化,并且有一个 search(query, k=20) 函数返回候选文档列表。那么完整的精排 + 生成流程就是:
query = "苹果公司2024年第四季度的营收是多少?"
# 第一步:向量召回
candidates = search(query, k=20)
# 第二步:Rerank 精排
top_docs = rerank(query, candidates, top_n=3)
# 第三步:拼 Prompt
context = "\n---\n".join(top_docs)
prompt = f"""基于以下资料回答用户问题。
资料:
{context}
问题:{query}
答案:"""
# 第四步:调用 LLM 生成
llm_payload = {
"model": "qwen3:8b",
"prompt": prompt,
"stream": False
}
llm_resp = requests.post(f"{OLLAMA_BASE}/api/generate", json=llm_payload)
print(llm_resp.json()["response"])
就这么简单。没有中间件,没有消息队列,没有微服务编排。三个 HTTP 请求,一个管道。
第一,top_n 别设太大。我把 20 个候选精排到 3 个,最多 5 个。再多的文档塞进 LLM 上下文,不仅拖慢生成速度,还会稀释 attention——模型反而抓不住重点。第二,候选文档的长度要控制。Reranker 对输入长度有限制,Qwen3-Reranker 的 max token 是 512(约 350 汉字)。如果你的知识库文档是一整篇论文,先切块再送进去。第三,score 阈值不是必须的,但我建议你在结果里加一行过滤:if r["score"] < 0.3: continue。有时候 reranker 会对所有候选都打低分——说明向量召回阶段就跑偏了,这时候强行推给 LLM 只会产生幻觉。
这条 pipeline 跑起来之后,你就拥有了一套完整的本地 RAG 精排系统。不是 demo,是那种扔到生产环境里能顶事的方案。
实战:在本地知识库问答中集成Rerank,效果立竿见影
把 Rerank 插进本地 RAG,不需要中间件,也不引入新服务。还是那台笔记本,还是那个 Ollama。先把 Qwen3-Reranker-4B 拉下来。这个模型体积不大,跑在 CPU 上也很稳。
我在公司内部技术文档问答里做了一次对照实验。向量检索 Top-K 设成 20,Rerank 之后 top_n 取 5。调用很简单:POST /api/rerank,model 填 qwen3-reranker:4b,再把 candidates 一起带上。记得把 raw_scores 设为 true,这样你能拿到每条候选的真实相关性分数。
curl -X POST http://localhost:11434/api/rerank \
-H "Content-Type: application/json" \
--data '{
"model": "qwen3-reranker:4b",
"query": "苹果2024年第四季度营收?",
"documents": ["文档A文本","文档B文本","文档C文本"],
"top_n": 5
}'
响应里会回传按分数降序排列的文档列表。分数低于 0.3 的直接丢掉,这是经验值,超过两次实验都验证有效。候选越多,LLM 上下文越拥挤。你把 10 篇无关或弱相关的文档塞进去,生成时注意力会被稀释,模型开始“自由发挥”。我试过 top_n=10,答案里幻觉明显增加;改成 5 之后,事实一致性上来,回答也更聚焦。这一步做完,准确率从 72% 提到 91%。不是纸面数字,是实打实的用户问题命中率。
Qwen3-Reranker-4B 在纯 CPU 环境下单次推理大约 50ms。放到 GPU 上能压到 10ms 左右。相比一次 LLM 生成,这点延迟几乎可以忽略,但对结果质量的提升却很显著。实时问答完全扛得住,峰值并发时也能保持体验一致。把 Rerank 塞进本地知识库,就是让每次检索结果都更有底气。你完全可以在自己机器上直接跑一下,体验那种精准度往上窜的感觉。
选型、量化与多模型协同
跑通 rerank 不等于跑稳——尤其当你换台机器、加个文档源、或者用户突然搜起长句时。qwen3-reranker:4b 在 M2 MacBook 上能跑,但遇到“对比 2023 和 2024 年财报中研发费用变化趋势”这种长 query,分数抖得厉害。换成 bge-reranker-v2-m3(8B),精度确实稳了,可 RT 峰值直接跳到 180ms —— CPU 温度都高两度。别硬扛,Ollama 的 num_ctx 加个上下文限制,比换大模型更实际。
官方文档写“推荐 Q4_K_M”,但没人告诉你它在 4B 模型上会把 2.1GB 模型压到 680MB,且 ollama list 显示的 size 字段就含这层压缩。实测下来,Q5_K_M 分数波动略小,但推理慢 12%;Q3_K_S 快但 top-1 准确率掉 4.7% —— 这个 4.7%,是三份财务报告里漏掉关键页码的代价。同一台机器上用 启动后,embedding 模型走 /api/embed,rerank 走 /api/rerank,LLM 走 /api/generate。端口没变,靠请求体结构区分——这才是 Ollama 真正省心的地方。别自己再套一层 Nginx 或者反向代理,那是给微服务架构用的,你的场景用不上。
把 reranker 当作你 RAG 管线的最后一道守门员,它的价值会在你遇到模糊问题时自然浮现。别急着堆数据,拿一组真实的失败案例先跑一遍,那比任何 benchmark 都有说服力。





评论