摘要

Relevance Scoring 即相关性打分,是 RAG 检索增强生成系统中的核心环节,负责计算用户 Query 与候选文档片段之间的匹配分数,用来评估文档对当前问题的有用程度,完成候选素材过滤与重排序。传统向量检索仅依靠向量库余弦相似度做粗召回,容易出现语义不匹配、噪声文档混入;昇思 MindSpore 大模型生态提供两套相关性打分方案:基于 Embedding 向量相似度打分、基于 Cross‑Encoder 交叉编码器深度相关性打分,运行于昇腾 NPU 硬件之上。通过 Relevance Scoring 可以过滤低相关性文档,提升 RAG 系统的答案准确性,减少大模型幻觉。本文介绍相关性打分业务背景、两种技术方案、昇思端到端架构、完整代码实现、性能调优、常见问题,帮助开发者在昇思 + 昇腾平台落地 RAG 相关性打分模块。

1 背景介绍

RAG 系统分为两个阶段:粗召回、精排序。粗召回借助向量数据库,通过 Embedding 向量相似度快速从海量知识库中取出 Top‑N 候选文档;但向量相似度属于浅层语义匹配,经常出现字面相似但语义无关的结果,直接送入大模型会引入噪声,引发幻觉、答案错误。

Relevance Scoring 相关性打分就是精排序阶段的核心能力,输入用户查询 Query 和候选文档,输出 0‑1 之间相关性分数,分数越高,代表文档对回答问题越有价值。业务上设置分数阈值,过滤掉低于阈值的无效文档,再将高分文档送入大模型做生成。

迁移到昇思 MindSpore + 昇腾 NPU 平台会面临几类痛点:第一,Cross‑Encoder 交叉编码器计算量大,CPU 推理速度慢;第二,大批量 Query‑Document 对打分,需要 NPU 批处理加速;第三,打分模型需要和 Embedding、大模型生成链路打通;第四,打分模型需要支持动态输入序列长度,适配真实业务文档。

昇思 MindSpore 支持 Embedding 模型、Cross‑Encoder 交叉编码器模型的加载、推理、微调,依托昇腾 AI Core 完成加速,Relevance Scoring 模块可以无缝嵌入 RAG 全链路,提升检索质量。

2 昇思平台 Relevance Scoring 整体架构

整套相关性打分模块分为四层,完整融入 RAG 业务链路。

  1. 输入预处理层:对用户 Query、候选文档做文本清洗、tokenizer 分词,生成模型输入 token 序列,支持批量样本打包。

  2. 打分模型层(核心 Relevance Scoring),提供两种实现路径:

    1. 向量相似度打分(轻量):Query 和文档分别经过 Embedding 模型输出向量,计算余弦相似度作为相关性分数,速度快,适合大规模候选集初筛;

    2. Cross‑Encoder 交叉编码器打分(高精度):将[CLS] Query [SEP] Document [SEP]拼接输入 Cross‑Encoder 模型,直接输出相关性概率分数,语义理解更强,精度更高,计算开销更大。

  3. 业务处理层:接收打分分数,执行阈值过滤、文档重排序,输出筛选后的 Top‑K 文档集合。

  4. 输出对接层:将筛选完成的文档上下文送入昇思大模型,执行 Prompt 组装与答案生成。

链路完整流程:用户提问 → 向量库粗召回候选文档 → 昇思 Relevance Scoring 打分 → 过滤重排 → 上下文送入大模型生成答案。

3 两种相关性打分技术方案对比

方案

原理

优势

劣势

适用场景

Embedding 余弦相似度打分

分别编码 Query、文档,向量做余弦距离计算

速度快,支持大批量文档,显存开销低

仅浅层语义,容易出现语义错位

粗召回、百万级知识库初筛

Cross‑Encoder 交叉编码器打分

Query + 文档拼接输入模型,直接预测相关性

语义理解强,打分精度高

计算量大,速度慢

候选集少量文档,精排序阶段

实际工程实践一般采用 “粗召回(Embedding)+ 精打分(Cross‑Encoder Relevance Scoring)” 两级策略,兼顾性能与精度。

4 代码实践:昇思 MindSpore 实现 Relevance Scoring

4.1 环境准备脚本 env.sh

source /usr/local/Ascend/ascend‑toolkit/set_env.sh
# 安装mindspore,mindnlp,transformers
pip install mindspore‑ascend==2.6.0 mindnlp transformers numpy
# NPU环境变量
export ASCEND_GLOBAL_LOG_LEVEL=3
export DEVICE_ID=0

4.2 相关性打分完整 Python 代码 relevance_scoring.py

import mindspore as ms
import mindspore.ops as ops
import numpy as np
from mindnlp.transformers import AutoTokenizer, AutoModel

ms.set_context(mode=ms.GRAPH_MODE, device_target="Ascend", device_id=0)

class RelevanceScoring:
    def __init__(self, emb_model_path, cross_encoder_path=None):
        """
        emb_model_path: embedding模型,用于余弦相似度打分
        cross_encoder_path: cross‑encoder交叉编码器,用于高精度Relevance Scoring,可选
        """
        self.tokenizer_emb = AutoTokenizer.from_pretrained(emb_model_path)
        self.model_emb = AutoModel.from_pretrained(emb_model_path)
        self.model_emb.set_train(False)

        self.cross_encoder = None
        self.tokenizer_cross = None
        if cross_encoder_path:
            self.tokenizer_cross = AutoTokenizer.from_pretrained(cross_encoder_path)
            self.cross_encoder = AutoModel.from_pretrained(cross_encoder_path)
            self.cross_encoder.set_train(False)

    def get_embedding(self, text):
        """获取文本Embedding向量,取CLS输出"""
        inputs = self.tokenizer_emb(text, return_tensors="ms", padding=True, truncation=True, max_length=128)
        out = self.model_emb(**inputs)
        cls_emb = out.last_hidden_state[:, 0, :]
        return cls_emb

    def score_cosine(self, query, doc_list):
        """方案1:Embedding余弦相似度相关性打分,返回每个文档分数"""
        q_emb = self.get_embedding(query)
        scores = []
        for doc in doc_list:
            d_emb = self.get_embedding(doc)
            sim = ops.CosineSimilarity()(q_emb, d_emb)
            scores.append(float(sim.asnumpy()[0]))
        return scores

    def score_cross_encoder(self, query, doc_list):
        """方案2:Cross‑Encoder 高精度Relevance Scoring打分"""
        if self.cross_encoder is None:
            raise ValueError("未加载cross‑encoder模型")
        pairs = [[query, doc] for doc in doc_list]
        inputs = self.tokenizer_cross(pairs, return_tensors="ms", padding=True, truncation=True, max_length=256)
        out = self.cross_encoder(**inputs)
        logits = out.logits
        probs = ops.Sigmoid()(logits)
        scores = probs.squeeze(-1).asnumpy().tolist()
        return scores

    def filter_and_rerank(self, query, doc_list, threshold=0.5, use_cross=False):
        """执行打分、阈值过滤,返回重排后(score,doc)列表,分数降序"""
        if use_cross:
            scores = self.score_cross_encoder(query, doc_list)
        else:
            scores = self.score_cosine(query, doc_list)
        score_doc_pairs = list(zip(scores, doc_list))
        # 阈值过滤
        filter_pairs = [item for item in score_doc_pairs if item[0] >= threshold]
        # 分数降序重排
        filter_pairs.sort(key=lambda x:x[0], reverse=True)
        return filter_pairs

if __name__ == "__main__":
    # 初始化打分器,替换为你的本地模型路径
    rs = RelevanceScoring(
        emb_model_path="./bge‑small‑zh",
        cross_encoder_path="./bge‑reranker‑small‑zh"
    )
    user_query = "昇思MindSpore支持哪些硬件平台"
    candidate_docs = [
        "昇思MindSpore支持Ascend、GPU、CPU多硬件平台",
        "Python是一门解释型编程语言,广泛用于数据分析",
        "MindSpore可以实现自动并行,提升大模型训练效率",
        "橘子富含维C,适合日常食用"
    ]
    # 使用Cross‑Encoder做Relevance Scoring高精度打分重排
    result = rs.filter_and_rerank(user_query, candidate_docs, threshold=0.2, use_cross=True)
    print("=====Relevance Scoring重排结果=====")
    for score, doc in result:
        print(f"相关性分数:{score:.4f} | 文档:{doc}")

4.3 运行命令

source env.sh
python relevance_scoring.py

5 调优要点与性能参考

提示:Embedding 余弦打分适合上千候选文档;Cross‑Encoder 计算成本高,建议只作用于向量库召回后的 Top20‑Top50 候选文档,不适合直接处理全量知识库。

优化项

说明

收益

批量推理

将多个 Query‑Doc 对打包 batch 送入 NPU 推理,减少推理调用次数

打分吞吐提升数倍

图模式执行

MindSpore GRAPH_MODE 静态图编译,加速模型推理

NPU 上推理速度提升 30%‑60%

序列长度截断

业务场景设置合理 max_length,避免超长序列占用显存

降低显存占用,减少推理耗时

打分模型量化

使用金箍棒 Golden‑Stick 对 Cross‑Encoder 做 PTQ 后量化推理

显存下降,吞吐提升,精度损失可控

6 FAQ 常见问题

Q1:Relevance Scoring 打分结果不准,高相关文档分数偏低怎么办? A:优先确认三点:第一,打分模型是否适配业务领域;通用 reranker 在垂直行业效果有限,可以使用业务标注数据微调 Cross‑Encoder;第二,文本预处理,检查输入是否存在多余噪声;第三,区分轻量余弦打分和 Cross‑Encoder,高精度场景不要只用 Embedding 相似度。

Q2:NPU 上 Cross‑Encoder 打分显存占用高,出现 OOM? A:调小 batch_size;缩短 max_sequence_length;使用金箍棒做量化推理;将超长文档做段落切分,分段打分。

Q3:如何微调属于自己业务的 Relevance Scoring 打分模型? A:准备业务标注数据集,样本格式为(query,document,label{0/1}),基于昇思 MindSpore 对 Cross‑Encoder 做微调,损失函数采用二分类交叉熵,微调完成后部署 NPU 推理做相关性打分。

Q4:Relevance Scoring 模块如何对接 RAG 完整链路? A:向量数据库粗召回得到候选文档列表,传入上面filter_and_rerank接口,过滤重排之后取 top‑N 文档,拼接进 Prompt,送入昇思大模型做生成。

Q5:动态图与静态图模式对打分性能差异? A:GRAPH_MODE 静态图会对模型计算图编译优化,NPU 上吞吐更高;调试阶段可以使用 PYNATIVE_MODE 动态图方便定位问题。

7 总结

Relevance Scoring 相关性打分是 RAG 系统中消除检索噪声、降低大模型幻觉的关键模块。昇思 MindSpore 支持两套打分方案:轻量 Embedding 余弦相似度打分适合大规模粗筛选;Cross‑Encoder 交叉编码器实现高精度深度语义打分,用于候选文档精排序。

开发者基于 MindNLP 加载预训练模型,在昇腾 NPU 硬件上完成批量打分、阈值过滤、文档重排,无缝接入 RAG 业务全链路。开发中结合静态图编译、批量推理、模型量化手段提升吞吐;垂直行业场景可基于业务标注数据微调 Cross‑Encoder,进一步提升 Relevance Scoring 打分精度,最终提升 RAG 问答系统的答案质量。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐