今天聊一聊我们如何做高质量rerank。
一个常识是,无论企业知识库、电商、新闻,还是RAG、agent场景,只依靠语义相似度对检索结果进行排名,无疑都是粗暴且低效的。
一方面,元数据往往包含了语义、时间、标签、地理位置等多元信息,语义并不总是最重要的那一项;
另一方面,用户检索时,往往还需要对数据按照距离远近、好评分数、复购数量等信息进行综合排序。
比如:
在很多数据库的向量插件,或者早期版本的向量数据库产品中,向量检索结果排序主要依赖向量相似度本身(距离越近/相似度越高越靠前),或者通过模型类 Reranker(如 BGE, Voyage, Cohere)进行更智能的重排。但很显然,这两种方案中的任意一种,都无法解决实际场景中复杂的rerank需求。
针对这一困境,Milvus推出了Boost Ranker 功能:在 Milvus 内部,我们可以对候选结果应用一组基于元数据的“加权规则”,做到不改索引、不改向量模型,就能按照需求更新排序逻辑。
那么这个功能是如何实现的,要如何在实战中使用,本文将重点解读。
Boost Ranker 是 Milvus 2.6.2 引入的一种 rerank 策略,通过 Function API 配置:
random_score,在 0~1 范围内生成一个随机因子,做轻量的“打散”。相比模型类 Reranker(调用外部 LLM / rerank 模型),Boost Ranker 完全基于已有的标量字段 + 简单规则,不需要外部服务,代价低,实时性强。
第一步,向量检索阶段:每个 segment 独立返回一批候选结果(包含 id、原始 score、相关元数据);
第二步,应用 Boost Ranker:
filter 表达式(可选)在候选中筛出“需要加权”的实体;weight、random_score 做缩放;第三步,再聚合所有 segment 的候选,按新的分数排序得到最终 TopK。
需要注意的是 Boost Ranker 对候选集合生效,而不是在全量数据上跑一次新查询,因此性能开销非常小。
典型场景:
publish_time 字段);doctype == 'policy' 或 is_canonical == true 的权威文档。这些都可以通过简单的 filter + weight 实现,无需触碰向量模型、索引。
另一类是温柔的隐藏而不是直接过滤:
stock < 10 适当降权;year < 2020 适当往后排。优势是:用户仍能在某些场景看到这些结果,但它们会自然地出现在靠后位置。
Boost Ranker 支持 random_score 字段:
"random_score": {
"seed": 126,
"field": "id"
}
seed:随机数种子,控制全局一致性;field:作为随机数生成的输入(通常用主键),保证同一条数据多次搜索随机结果一致。可以用它来:
Function(FunctionType.RERANK, params.reranker='boost') 创建的 rerank 函数;AnnSearchRequest 的 ranker 使用。Boost Ranker 是通过 Function 和FunctionScore (可选)配置的。
Python 里一般这么创建(后面实战会给完整代码):
name:这个 Function 的名字;input_field_names:Boost Ranker 必须是空列表 [];function_type:固定使用 FunctionType.RERANK;params.reranker:固定字符串 "boost",告诉 Milvus 使用 Boost Ranker。(1)params.weight(必填)
如果“分数越小越好”(典型是距离类度量),要 提升 某类结果,就用 < 1 的权重; 如果“分数越大越好”,要提升就用 > 1 的权重。
(2)params.filter(可选)
一条基础的标量过滤表达式,例如
(3)params.random_score(可选)
search(..., ranker=ranker) 里传入即可。boost_mode:单个函数内部如何组合原始分数与其权重(乘法/加法);function_mode:多个 Boost Ranker 之间如何合并(乘法/加法)。Function,然后通过 FunctionScore 组合,配置:假设我们有一个集合 milvus_collection,字段如下:
id: INT64 主键;embedding: FLOAT_VECTOR,content字段的embeddding数据;content: VARCHAR,文档内容;source: VARCHAR,取值如 "official", "community", "ticket" 等。is_official: BOOL, 官方文档(即source是official)为True,否则是False。from pymilvus import (
MilvusClient,
DataType,
Function,
FunctionType,
)
# 1. 连接 Milvus
client = MilvusClient(uri="http://localhost:19530")
collection_name = "milvus_collection"
# 如果已存在就先删除,方便反复调试
if collection_name in client.list_collections():
client.drop_collection(collection_name)
# 2. 定义 schema
schema = MilvusClient.create_schema(
auto_id=False,
enable_dynamic_field=False,
)
schema.add_field(
field_name="id",
datatype=DataType.INT64,
is_primary=True,
)
schema.add_field(
field_name="content",
datatype=DataType.VARCHAR,
max_length=512,
)
schema.add_field(
field_name="source",
datatype=DataType.VARCHAR,
max_length=32,
)
schema.add_field(
field_name="is_official",
datatype=DataType.BOOL,
)
schema.add_field(
field_name="embedding",
datatype=DataType.FLOAT_VECTOR,
dim=3072,
)
text_embedding_function = Function(
name="openai_embedding",
function_type=FunctionType.TEXTEMBEDDING,
input_field_names=["content"],
output_field_names=["embedding"],
params={
"provider": "openai",
"model_name": "text-embedding-3-large"
}
)
schema.add_function(text_embedding_function)
# 3. 创建 Collection
client.create_collection(
collection_name=collection_name,
schema=schema,
)
# 4. 创建索引
index_params = client.prepare_index_params()
index_params.add_index(
field_name="embedding",
index_type="IVF_FLAT",
metric_type="COSINE",
params={"nlist": 16},
)
client.create_index(
collection_name=collection_name,
index_params=index_params,
)
# 5. 加载 Collection 到内存
client.load_collection(collection_name=collection_name)
docs = [
{
"id": 1,
"content": "如何在 Kubernetes 上部署 Milvus(官方手册)",
"source": "official",
"is_official": True
},
{
"id": 2,
"content": "Milvus 在 Docker Compose 下的快速部署(官方教程)",
"source": "official",
"is_official": True
},
{
"id": 3,
"content": "社区经验:Milvus部署经验之谈",
"source": "community",
"is_official": False
},
{
"id": 4,
"content": "工单记录:Milvus 部署问题",
"source": "ticket",
"is_official": False
},
]
client.insert(
collection_name=collection_name,
data=docs,
)
我们希望:在语义相关性相近的情况下,Milvus官方文档优先出现。
# 6. 基线搜索(不加 Boost Ranker)
query_vector = "如何部署milvus"
search_params = {
"metric_type": "COSINE",
"params": {"nprobe": 2},
}
results = client.search(
collection_name=collection_name,
data=[query_vector],
anns_field="embedding",
search_params=search_params,
limit=4,
output_fields=["content", "source", "is_official"],
)
print("=== Baseline search (no Boost Ranker) ===")
for hit in results[0]:
entity = hit["entity"]
print(
f"id={hit['id']}, "
f"score={hit['distance']:.4f}, "
f"source={entity['source']}, "
f"is_official={entity['is_official']}"
)
# 7. 定义 Boost Ranker:给 is_official == true 的文档加权
boost_official_ranker = Function(
name="boost_official",
input_field_names=[], # Boost Ranker 要求必须为空列表
function_type=FunctionType.RERANK,
params={
"reranker": "boost", # 指定使用 Boost Ranker
"filter": "is_official==true",
# 对于 COSINE / IP(分数越大越好),使用 >1 的权重进行提升
"weight": 1.2
},
)
boosted_results = client.search(
collection_name=collection_name,
data=[query_vector],
anns_field="embedding",
search_params=search_params,
limit=4,
output_fields=["content", "source", "is_official"],
ranker=boost_official_ranker,
)
print("\n=== Search with Boost Ranker (official boosted) ===")
for hit in boosted_results[0]:
entity = hit["entity"]
print(
f"id={hit['id']}, "
f"score={hit['distance']:.4f}, "
f"source={entity['source']}, "
f"is_official={entity['is_official']}"
)
查询结果
=== Baseline search (no Boost Ranker) ===
id=1, score=0.7351, source=official, is_official=True
id=4, score=0.7017, source=ticket, is_official=False
id=3, score=0.6706, source=community, is_official=False
id=2, score=0.6435, source=official, is_official=True
=== Search with Boost Ranker (official boosted) ===
id=1, score=0.8821, source=official, is_official=True
id=2, score=0.7722, source=official, is_official=True
id=4, score=0.7017, source=ticket, is_official=False
id=3, score=0.6706, source=community, is_official=False
Boost Ranker作为Milvus 2.6的新功能,极大地扩展了向量数据库的灵活性,让搜索不再局限于纯向量相似度,而是能融入业务逻辑,实现更精准的排名。
通过本文的介绍和更真实的实践案例,读者可以快速理解并应用这一功能。在未来,随着AI应用的深化,Boost Ranker将在RAG、推荐和检索系统中发挥更大作用。
作者介绍

Zilliz 黄金写手:臧伟
文章来自于“Zilliz”,作者 “臧伟”。
【开源免费】字节工作流产品扣子两大核心业务:Coze Studio(扣子开发平台)和 Coze Loop(扣子罗盘)全面开源,而且采用的是 Apache 2.0 许可证,支持商用!
项目地址:https://github.com/coze-dev/coze-studio
【开源免费】n8n是一个可以自定义工作流的AI项目,它提供了200个工作节点来帮助用户实现工作流的编排。
项目地址:https://github.com/n8n-io/n8n
在线使用:https://n8n.io/(付费)
【开源免费】DB-GPT是一个AI原生数据应用开发框架,它提供开发多模型管理(SMMF)、Text2SQL效果优化、RAG框架以及优化、Multi-Agents框架协作、AWEL(智能体工作流编排)等多种技术能力,让围绕数据库构建大模型应用更简单、更方便。
项目地址:https://github.com/eosphoros-ai/DB-GPT?tab=readme-ov-file
【开源免费】VectorVein是一个不需要任何编程基础,任何人都能用的AI工作流编辑工具。你可以将复杂的工作分解成多个步骤,并通过VectorVein固定并让AI依次完成。VectorVein是字节coze的平替产品。
项目地址:https://github.com/AndersonBY/vector-vein?tab=readme-ov-file
在线使用:https://vectorvein.ai/(付费)
【开源免费】AutoGPT是一个允许用户创建和运行智能体的(AI Agents)项目。用户创建的智能体能够自动执行各种任务,从而让AI有步骤的去解决实际问题。
项目地址:https://github.com/Significant-Gravitas/AutoGPT
【开源免费】MetaGPT是一个“软件开发公司”的智能体项目,只需要输入一句话的老板需求,MetaGPT即可输出用户故事 / 竞品分析 / 需求 / 数据结构 / APIs / 文件等软件开发的相关内容。MetaGPT内置了各种AI角色,包括产品经理 / 架构师 / 项目经理 / 工程师,MetaGPT提供了一个精心调配的软件公司研发全过程的SOP。
项目地址:https://github.com/geekan/MetaGPT/blob/main/docs/README_CN.md
【开源免费】FASTGPT是基于LLM的知识库开源项目,提供开箱即用的数据处理、模型调用等能力。整体功能和“Dify”“RAGFlow”项目类似。很多接入微信,飞书的AI项目都基于该项目二次开发。
项目地址:https://github.com/labring/FastGPT
【开源免费】graphrag是微软推出的RAG项目,与传统的通过 RAG 方法使用向量相似性作为搜索技术不同,GraphRAG是使用知识图谱在推理复杂信息时大幅提高问答性能。
项目地址:https://github.com/microsoft/graphrag
【开源免费】Dify是最早一批实现RAG,Agent,模型管理等一站式AI开发的工具平台,并且项目方一直持续维护。其中在任务编排方面相对领先对手,可以帮助研发实现像字节扣子那样的功能。
项目地址:https://github.com/langgenius/dify
【开源免费】RAGFlow是和Dify类似的开源项目,该项目在大文件解析方面做的更出色,拓展编排方面相对弱一些。
项目地址:https://github.com/infiniflow/ragflow/tree/main
【开源免费】phidata是一个可以实现将数据转化成向量存储,并通过AI实现RAG功能的项目
项目地址:https://github.com/phidatahq/phidata
【开源免费】TaskingAI 是一个提供RAG,Agent,大模型管理等AI项目开发的工具平台,比LangChain更强大的中间件AI平台工具。
项目地址:https://github.com/TaskingAI/TaskingAI
【开源免费】XTuner 是一个高效、灵活、全能的轻量化大模型微调工具库。它帮助开发者提供一个简单易用的平台,可以对大语言模型(LLM)和多模态图文模型(VLM)进行预训练和轻量级微调。XTuner 支持多种微调算法,如 QLoRA、LoRA 和全量参数微调。
项目地址:https://github.com/InternLM/xtuner