从 0 打造私有知识库 RAG Benchmark 完整实践

背景介绍

最近从 0 构建了一个大模型知识库 RAG 服务的自动化 Benchmark 评估服务,可以基于私有知识库对 RAG 服务进行批量自动化测试与评估。本文是对这个过程的详细记录。

本文实际构建的是医疗行业知识库,基于高质量的医学指南和专家共识进行构建。而实际的问答对也基础知识库已有文档生成,避免参考源不存在导致的大模型幻觉,可以更加客观反映 RAG 服务的能力。当然整体的构建流程是与行业无关的,可以参考构建其他的测评知识库。

RAG Benchmark 评估

为什么需要 RAG 评估

从早期实现 从开发到部署,搭建离线私有大模型知识库 时就提到过 RAG 的评估体系的构建,RAG 评估体系不可或缺的原因如下:

  1. RAG 服务的质量评估困难,因为 RAG 服务最终输出的就是一段针对问题的文本回答,开发人员可能会缺乏行业背景知识,无法给出客观评估;
  2. RAG 服务是一个需要持续迭代的服务,优化手段多种多样。如何验证优化手段的有效性,需要存在一个量化的判断标准,否则可能会负优化;
为什么不用通用 Benchmark

目前针对 RAG 服务的部分环节的 Benchmark 是存在的,比如针对大模型有 Lmsys Benchmark,针对 Embedding 模型有 mteb leaderboard,但是很少有完整的针对 RAG 提供的 Benchmark,我理解原因如下:

  1. RAG 服务的质量与知识库内容存在很大关系,RAG 服务目前没有完全标准的知识库以及对应的高质量问答对;
  2. RAG 服务的自动化文本评测相对困难,很难根据问题和答案给出完全客观的打分;

同时考虑到外部的公共 Benchmark 数据集缺失行业信息,无法基于我们期望的行业知识进行评测,最终选择了自建大模型知识库自动化 Benchmark 评测服务。

自动化评估构建流程

自动化评估 Benchmark 构建流程如下所示:
请添加图片描述

构建测试问答对

为了构建自动化测试,首先需要筛选出合适的行业文档信息,期望文档本身的质量比较高。在医疗领域,我们选择的是医学指南和专家共识,这样可以避免原始文档质量差带来的结果不佳的问题。

接下来需要根据这些文档生成对应的问答对。问答对需要能根据知识库可以得到正确答案,否则就很难验证 RAG 服务的能力了。

但是构建问答对十分耗时,最终选择了提供文档给线上大模型,基于线上的大模型自动生成问题,答案以及答案参考的原文片段。通过这种方式可以大幅减轻人工总结文档生成问题和答案的工作量。人工只需要参考大模型给出的原文片段判断问题和答案的合理性即可。实际的问答对如下所示:
请添加图片描述

人工过滤掉不合适的问题,以及答案有误的情况,这样就得到了一份可用的知识库,以及对应的问答对。我利用这种方式构建了包含 100 份高质量行业文档的知识库和 1000 个标准问答对。

批量测试

批量的自动化测试是基于 ragas 实现的,如果期望选择其他 RAG 自动化评测库,可以参考 之前的文章 查看其他可选方案。

批量测试基于下面的代码生成自动化测试的数据集:

import asyncio

from datasets import Dataset

async def batch_evaluate_chat(questions: list[str], ground_truths: Optional[list] = None):
    # 批量调用 RAG 服务接口获取回答与对应的上下文

    tasks = [
        search_knowledge_base_iter(q, ground_truth)
        for q, ground_truth in zip(questions, ground_truths)
    ]
    results = await asyncio.gather(*tasks)

    question_list, answer_list, contexts_list, ground_truth_list = [], [], [], []
    for question, answer, contexts, ground_truth in results:
        question_list.append(question)
        answer_list.append(answer)
        contexts_list.append(contexts)
        ground_truth_list.append(ground_truth)

    # 构建测试获得的问题,答案,上下文以及标准答案

    data_samples = {
        "question": question_list,
        "answer": answer_list,
        "contexts": contexts_list,
        "ground_truth": ground_truth_list,
    }

    return Dataset.from_dict(data_samples), data_samples
大模型评分

在实际测试时,我期望获得所有测试问答对的详细信息,包括测试项中的问题,答案,上下文,正确答案以及各个评分项的得分。但是 ragas 只会给出测试数据集整体的平均得分,因此实际调用上面的 batch_evaluate_chat() 构建测试数据集时,会基于单个问题构建了自动化测试数据集,之后所有问题独立进行评分。具体如下所示:

from ragas import evaluate
from ragas.metrics import (
    answer_correctness,
    answer_relevancy,
    context_precision,
    context_recall,
    context_relevancy,
    faithfulness,
)

# 每个问题构造对应的数据集,独立评分,得到每个问题详细评分

async def do_evaluate(question, ground_truth, llm, embedding_model):
    questions = [question]
    ground_truths = [ground_truth] if ground_truth else None

    dataset, original_dataset = await batch_evaluate_chat(questions, ground_truths)

    result = evaluate(
        dataset,
        # 设置相关评测指标 https://docs.ragas.io/en/stable/concepts/metrics/index.html

        metrics=[
            context_relevancy,
            faithfulness,
            answer_relevancy,
            answer_correctness,
            context_recall,
            context_precision,
        ],
        llm=llm,
        embeddings=embedding_model,
    )

    # 将原始的问答对与结果合并在一起,方便后续生成详细结果

    evaluate_detail = dict()
    for key in original_dataset:
        evaluate_detail[key] = original_dataset[key][0]

    evaluate_detail.update(result)
    return evaluate_detail

实际选择的指标除了经典的三维度的指标 context_relevancy, faithfulnessanswer_relevancy,从实用角度出发,补充了下面指标:

  • answer_correctness: 根据生成答案与标准答案相比,得出生成答案的准确性,可以整体了解 RAG 服务的可靠性;
  • context_recall: 根据上下文与标准答案相比,用于衡量正确答案是否被正确召回,可以判断 RAG 的检索能力;
  • context_precision: 根据上下文与标准答案以及问题综合判断,确认召回的正确内容是否排名靠前,可以判断 RAG 检索的排序是否合适;

最终整体的评估维度如下所示:
请添加图片描述

测试结果分析

在完成构建了自动化测试之后,最终得到的结果导出为 excel,类似如下所示:
请添加图片描述
在得到大模型完整的自动化测试的结论后,还是需要人工进行分析,主要关注两部分的优化:

  1. 自动化测试指标的表征能力,现有的自动化测试指标是否正确反映 RAG 服务本身存在的问题,这一部分主要涉及自动化测试流程的优化;
  2. RAG 模块的优化,通过指标以及人工归因,确定 RAG 服务各个模块中存在的待优化问题,并根据影响范围确定优化的优先级;

总结

本文是对构建完整的 RAG 自动化评估 benchmark 的介绍,通过上面的流程,可以从 0 构建一个符合要求的自动化评估服务,在客观的数据的指导下定位 RAG 服务中存在的问题,从而迭代优化重点问题,提升 RAG 服务的质量。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/723197.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

8K Stars!Text2SQL还不够?试试更精准的RAG2SQL开源工具

▼618钜惠专场直播,点击预约按钮免费预约。 SQL 是查询数据库的关键,但如何高效地构建满足个人需求的 SQL 语句呢?随着 AI 大模型的进步,我们现在已经拥有了 Text2SQL 的技术,这一技术已被多款产品广泛应用。 今天&…

考研数学|做完《660》,做《880》还是吃力,怎么办?

880吃力说明基础还是不太扎实,建议配合知能行再刷880。 强化之前做660,然后在强化的时候再做880。 660整体难度属于基础阶段到强化阶段。而且是选填部分的题目,所以还是要做一些其他题 然后说一下推荐的习题册:基础不好先做1800、…

如何学习 Java 中的 Socket 编程,进行网络通信

Socket编程是网络编程的核心技术之一,它使得不同主机之间可以进行数据通信。Java提供了丰富的网络编程API,使得编写网络应用程序变得相对简单和直观。本文将详细讲解如何学习Java中的Socket编程,并通过示例代码展示如何实现网络通信。 一、S…

船舶能源新纪元:智能管理引领绿色航运潮流

在蓝色的大海上,无数船只乘风破浪,为全球的贸易和文化交流贡献着力量。然而,随着环保意识的提升和可持续发展的要求,船舶的能源消耗和排放问题逐渐成为了人们关注的焦点。在这个关键时刻,船舶能源管理系统应运而生&…

智能合约开发的过程

智能合约是一种运行在区块链上的程序,可以自动执行预先设定的条款和条件。智能合约具有去中心化、透明、不可篡改等特点,因此被广泛应用于金融、供应链、物联网等领域。北京木奇移动技术有限公司,专业的软件外包开发公司,欢迎交流…

西门子学习笔记12 - BYTE-REAL互相转化

这是针对于前面MQTT协议的接收和发送数组只能是BYTE数组做出的对应的功能块封装。 1、BYTE-REAL转化 1、把byte数组转成字符串形式 2、把字符串转成浮点数 2、REAL-BYTE转化 1、把浮点数转成字符串 2、把字符串转成Byte数组

通过编辑器工具改变Inspector锁定状态

是在看一系列视频的时候,看到的,感觉挺有用,就记录下来。 就是这个小锁的按钮,后续可以通过快捷键,快速锁定和解锁。代码里没有加入快捷键控制,有需要用到的可以自己加一下,比较简单 using Uni…

前端上传minio

参考【GitCode - 全球开发者的开源社区,开源代码托管平台】 注意事项:nodejs服务,文件扩展名为mjs,版本号8.0,引入的时候 import * as Minio from minio import Minio as * from minio// 实例化对象存储服务的MinIO客户端 // p…

c语言字符串函数详解(全)

字符串函数 1.strlen函数 求字符串长度的 //求字符串长度 int my_strlen(char* str) {int count 0;while (*str ! \0){count;*str;}return count; } int main() {char arr[] "abcdef";int red my_strlen(arr);printf("%d\n", red);return 0; } 2. st…

【MySQL】(基础篇十二) —— 子查询

分组数据 本文介绍什么是子查询以及如何使用它们。 SQL允许我们创建子查询(subquery),即嵌套在其他查询中的查询。这样可以实现更复杂的查询,理解这个概念的最好方法是考察几个例子。 利用子查询进行过滤 需求:查询…

一行超长日志引发的 “血案” - Containerd 频繁 OOM 背后的真相

案发现场:混沌初现 2024年6月10日,本应是平静的一天。但从上午 9 点开始,Sealos 公有云的运维监控告警就开始不停地响。北京可用区服务器节点突然出现大量 “not ready” 告警,紧接着,系统自动触发 004 节点重启&…

重学java 75.JDK新特性 ① Lambda表达式

你所做的事情,也许暂时看不到成果,你不是没有成长,而是在扎根 —— 24.6.19 一、函数式编程思想和Lambda表达式定义格式 1.面向对象思想:是Java的核心编程思想 强调的是找对象,帮我们做事儿 比如:去北京 -> 强调的是怎么去,火车,高铁,飞机…

为什么人们对即将推出的 Go 1.23 迭代器感到愤怒

原文:gingerBill - 2024.06.17 TL;DR 它让 Go 变得太“函数式”,而不再是不折不扣的命令式语言。 最近,我在 Twitter 上看到一篇帖子,展示了 Go 1.23(2024 年 8 月)即将推出的 Go 迭代器设计。据我所知&a…

35 Debian如何配置Postfix+Dovecot

作者:网络傅老师 特别提示:未经作者允许,不得转载任何内容。违者必究! Debian如何配置Postfix+Dovecot 《傅老师Debian知识库系列之35》——原创 ==前言== 傅老师Debian知识库特点: 1、拆解Debian实用技能; 2、所有操作在VMware虚拟机实测完成; 3、致力于最终形成Deb…

网安人必备!开源网络安全工具TOP 10(附下载地址)

工欲善其事,必先利其器。对于广大的网络安全从业者,以及未来想要从事网络安全的人来说,选择并善用合适的网络安全工具,能有效提升工作效率。 开源网络安全工具之所以能够在众多安全解决方案中脱颖而出,不仅是因为它们…

1.22 LeetCode总结(基本算法)_位运算

进制的概念 进制即进位计数制,是利用固定的数字符号和统一的规则的带进位的计数方法。 任何一种进位计数制都有一个基数,基数为 X 的进位计数制称为 X 进制,表示每一个数位上的数运算时都是逢 X 进一。 504. 七进制数 手法1:当…

小林图解系统-二.硬件结构 2.4CPU缓存一致性

CPU Cache的数据写入 CPU和内存的访问性能越差越大,于是在CPU内部嵌入CPU Cache(高速缓存)。 CPU Cache由Cache Line组成,Cache Line由头标志Tag数据块Data Block组成。 如果数据写入Cache,内存和Cache相对应的数据将不同,需要…

排序(3)【归并排序】【计数排序】【排序算法度及其稳定性分析】

一.归并排序 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有…

CCAA质量管理【学习笔记】​​ 备考知识点笔记(六)质量改进系统方法与工具

第七节 质量改进系统方法与工具 1 质 量 改 进 方 法 概 述 可以说几乎每种质量管理领域的方法与工具都可以用于质量改进,但是一个组织在改进的整体推进中,往往不是采用单一的方法,会涉及多种改进的工具和手段,并依据一定的模式…

虹科免拆诊断案例 | 2022款问界M5增程式混合动力车充电口盖指示灯不工作

故障现象 一辆2022款问界M5增程式混合动力车,搭载1.5T发动机和发电机作为增程器,累计行驶里程约为3.6万km。该车因尾部受到碰撞进厂维修,维修后进行慢充,发现充电口盖指示灯不点亮(图1),但仪表…