基于 RAGAS 的检索增强效果评估实战

#前言

RAGAS (R etrieval A ugmented G eneration Assessment), 是一个关于检索增加效果评估的框架。最近尝试了使用这个框架自动评估大模型检索增强的效果。由于官方文档写的比较简单,而且使用的是 GPT 的API,最近,GPT4 相关的 API 不太稳定,因此尝试了自己定制 LLM 去进行评估。

本文主要使用的向量模型是 BGE,然后实现了自己调用 LLM 去进行评估的全流程,API调用部分做了删减,替换之后,代码可以正常执行。 代码测试基于 ragas 版本 0.0.19

新建数据集

RAGAS 需要使用 HuggingFace 标准的 dataset 的格式,因此我们可以根据现有的格式去构建自己的数据集或者读取 HF 上现有的数据集。

读取 HF 上的数据集

from datasets import load_dataset
 
fiqa_eval = load_dataset("explodinggradients/fiqa", "ragas_eval")['baseline']
fiqa_eval

自己定义数据集

数据集包含下面四个列:

  • question: list[str], 这个是 RAG 系统中希望评测的问题。

  • answer: list[str],由 RAG 系统生成,并提供给用户的答案,也就是需要评测的答案。

  • contexts: list[list[str]], 传入 LLM 并回答问题的上下文。

  • ground_truths: list[list[str]]],问题的真实答案,这个在线评估的时候,可以忽略,因为我们无法有效获取真实的答案数据。

    from datasets import Dataset

    questions, answers, contexts, ground_truths = [], [], [], []

    The dataset in the format of ragas which the metrics will use to score the RAG pipeline with

    evalsets = {
    "question": questions,
    "answer": answers,
    "contexts": contexts,
    "ground_truths": ground_truths
    }
    evalsets = Dataset.from_dict(evalsets)

导入外部依赖

将我们使用的langchain、ragas以及bge和一些基础的包都导入。

import typing as t
import os
from typing import List
from datasets import load_dataset, load_from_disk
from ragas.metrics import faithfulness, context_recall, context_precision
from ragas.metrics import AnswerRelevancy
from ragas import evaluate
from ragas.llms import BaseRagasLLM
from langchain.schema import LLMResult
from langchain.schema import Generation
from langchain.callbacks.base import Callbacks
from langchain.schema.embeddings import Embeddings
from FlagEmbedding import FlagModel

自定义 LLM

自定义 LLM 需要导入 ragas 中的 BaseRagasLLM 这个类,然后复写相关的 generate 方法 和 llm 方法。在这里值得注意的是,如果我们采用 API 调用,base_llm 变量实际只是为了复写 llm 方法而添加的,并没有实际意义。如果是传递了模型本身,则 llm 方法会返回这个模型。

另外,在 generate 方法中,输入的 prompts 实际上的类型是 langchain 中的 ChatPromptTemplate ,因此我们在获取实际的字符串时需要按照指定的格式进行获取,同时最后返回的结果要包装成 LLMResult 的形式。

class MyLLM(BaseRagasLLM):

    def __init__(self, llm):
        self.base_llm = llm

    @property
    def llm(self):
        return self.base_llm

    def generate(
            self,
            prompts: List[str],
            n: int = 1,
            temperature: float = 0,
            callbacks: t.Optional[Callbacks] = None,
    ) -> LLMResult:
        generations = []
        llm_output = {}
        token_total = 0
        for prompt in prompts:
            content = prompt.messages[0].content
            text = api.main(content)  // 修改为自己的API方式调用即可
            generations.append([Generation(text=text)])
            token_total += len(text)
        llm_output['token_total'] = token_total

        return LLMResult(generations=generations, llm_output=llm_output)

自定义 Embedding

有一些指标,比如问题相关性,需要对 llm 生成的问题和原始问题计算相似度,这里我们使用自定义的 BGE 模型去计算 embedding。同样,需要继承 langchain 中的 Embeddings,然后复写几个方法就可以。

class BaaiEmbedding(Embeddings):

    def __init__(self,model_path, max_length=512, batch_size=256):
        self.model = FlagModel(model_path, query_instruction_for_retrieval="为这个句子生成表示以用于检索相关文章:")
        self.max_length = max_length
        self.batch_size = batch_size

    def embed_documents(self, texts: List[str]) -> List[List[float]]:
        return self.model.encode_corpus(texts, self.batch_size, self.max_length).tolist()

    def embed_query(self, text: str) -> List[float]:
        return self.model.encode_queries(text, self.batch_size, self.max_length).tolist()

最终代码

评价的时候就比较简单了,可以直接把需要的指标传递到 evaluate 类中,但是需要注意将对应指标的 llm 替换为我们自定义的 llm。

从实际体验的结果来说,整个框架的调用还算比较简单,但是如果想自己定制一些组件则需要对其中的代码比较熟悉才可以。而且这个代码和 langchain 耦合程度比较多,好多东西比较冗余,一旦出现了问题可能不好定位。但好在,从目前的使用来看,没发现这方面的问题。

import typing as t
import os
from typing import List
from datasets import load_dataset, load_from_disk
from ragas.metrics import faithfulness, context_recall, context_precision
from ragas.metrics import AnswerRelevancy
from ragas import evaluate
from ragas.llms import BaseRagasLLM
from langchain.schema import LLMResult
from langchain.schema import Generation
from langchain.callbacks.base import Callbacks
from langchain.schema.embeddings import Embeddings
from FlagEmbedding import FlagModel

class MyLLM(BaseRagasLLM):

    def __init__(self, llm):
        self.base_llm = llm

    @property
    def llm(self):
        return self.base_llm

    def generate(
            self,
            prompts: List[str],
            n: int = 1,
            temperature: float = 0,
            callbacks: t.Optional[Callbacks] = None,
    ) -> LLMResult:
        generations = []
        llm_output = {}
        token_total = 0
        for prompt in prompts:
            content = prompt.messages[0].content
            text = api.main(content)  // 修改为自己的API方式调用即可
            generations.append([Generation(text=text)])
            token_total += len(text)
        llm_output['token_total'] = token_total

        return LLMResult(generations=generations, llm_output=llm_output)

class BaaiEmbedding(Embeddings):

    def __init__(self,model_path, max_length=512, batch_size=256):
        self.model = FlagModel(model_path, query_instruction_for_retrieval="为这个句子生成表示以用于检索相关文章:")
        self.max_length = max_length
        self.batch_size = batch_size

    def embed_documents(self, texts: List[str]) -> List[List[float]]:
        return self.model.encode_corpus(texts, self.batch_size, self.max_length).tolist()

    def embed_query(self, text: str) -> List[float]:
        return self.model.encode_queries(text, self.batch_size, self.max_length).tolist()

# fiqa_eval = load_dataset("explodinggradients/fiqa", "ragas_eval")
fiqa_eval = load_from_disk("./fiqa_eval")
print(fiqa_eval)

my_llm = MyLLM("")
ans_relevancy = AnswerRelevancy(embeddings=BaaiEmbedding())
faithfulness.llm = my_llm
context_recall.llm = my_llm
context_precision.llm = my_llm
ans_relevancy.llm = my_llm

result = evaluate(
    fiqa_eval["baseline"].select(range(3)),
    metrics=[context_recall, context_precision, ans_relevancy, faithfulness]

)

df = result.to_pandas()
print(df.head())
df.to_csv("result.csv", index=False)

那么,我们该如何学习大模型?

作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

一、大模型全套的学习路线

学习大型人工智能模型,如GPT-3、BERT或任何其他先进的神经网络模型,需要系统的方法和持续的努力。既然要系统的学习大模型,那么学习路线是必不可少的,下面的这份路线能帮助你快速梳理知识,形成自己的体系。

L1级别:AI大模型时代的华丽登场

L2级别:AI大模型API应用开发工程

L3级别:大模型应用架构进阶实践

L4级别:大模型微调与私有化部署

一般掌握到第四个级别,市场上大多数岗位都是可以胜任,但要还不是天花板,天花板级别要求更加严格,对于算法和实战是非常苛刻的。建议普通人掌握到L4级别即可。

以上的AI大模型学习路线,不知道为什么发出来就有点糊 ,高清版可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

二、640套AI大模型报告合集

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

三、大模型经典PDF籍

随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。

四、AI大模型商业化落地方案

作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量。

相关推荐
PyAIGCMaster13 分钟前
ubuntu装P104
服务器·网络·ubuntu
云云3211 小时前
云手机服务器如何做到群控多台手机的?
服务器·线性代数·安全·智能手机·矩阵
小李不想输啦1 小时前
什么是微服务、微服务如何实现Eureka,网关是什么,nacos是什么
java·spring boot·微服务·eureka·架构
张铁铁是个小胖子1 小时前
微服务学习
java·学习·微服务
ggs_and_ddu1 小时前
Android--java实现手机亮度控制
android·java·智能手机
sp_fyf_20242 小时前
【大语言模型】ACL2024论文-35 WAV2GLOSS:从语音生成插值注解文本
人工智能·深度学习·神经网络·机器学习·语言模型·自然语言处理·数据挖掘
AITIME论道2 小时前
论文解读 | EMNLP2024 一种用于大语言模型版本更新的学习率路径切换训练范式
人工智能·深度学习·学习·机器学习·语言模型
敲代码娶不了六花3 小时前
jsp | servlet | spring forEach读取不了对象List
java·spring·servlet·tomcat·list·jsp
彩虹糖_haha3 小时前
Linux高并发服务器开发 第五天(压缩解压缩/vim编辑器/查找替换/分屏操作/vim的配置)
linux·运维·服务器
Yhame.3 小时前
深入理解 Java 中的 ArrayList 和 List:泛型与动态数组
java·开发语言