前言

上一篇介绍了大模型 RAG 的原理并且也说明了测试人员同样可以利用大模型 RAG 来完成模型评估的工作,今天我来补充一些典型的测试场景的操作方法。

BTW: 这周又被派去采集数据了, 不仅采集电动车,也开始采集垃圾相关的数据(场景是杂物检测,卫生检查,还有垃圾桶满溢,也就是摄像头监控到垃圾桶满了,就会告警。小区的保安和保洁手机上安装了一个 APP, 这个 app 就会提示他们赶紧到现场处理)。所以我和数据组的妹子这周化身环卫工人,奔走于多个小区的各种垃圾桶之间收集素材。由于我不会骑电动车, 所以是同事驮着我,我们俩个身上背着拎着各种垃圾坐在电动车上,堪称一个移动的垃圾堡垒在小区中移动,回头率非常高。还要跟小区的大爷大妈们斗智斗勇(每个小区都有一批大爷大妈喜欢捡垃圾卖钱),稍一不注意就被大爷大妈偷走宝贵的垃圾素材。

利用大模型来生成标注数据

在我讲解 AI 的文章中, 一直在强调数据的重要性。 大量的高质量的标注数据不仅对模型的效果起到了决定性的作用, 也直接影响到了测试团队针对模型效果评估的精准性。但数据标注的成本又非常的高, 尤其在 NLP 领域中(大模型基本 9 成以上是 NLP 的模型)数据标注的成本高到了令人发指的程度。它不同于计算机视觉场景下数据标注的门槛很低,工作量也低。比如我这两周一直在做的电动车和垃圾,它的标注场景属于简单易懂容易操作的类型,毕竟谁不知道图片里的物体是不是电动车或者垃圾。 但在 NLP 里,想要标注数据的前提往往是得读懂语料,比如为一款机器翻译模型标注数据,那么前提就是标注人员需要精通两种目标语言(比如英语和中文)。而如果目标语料是一个专业性很强的论文,那就需要标注人员拥有相当的专业知识。 这也是为什么我们隔壁标注组的妹子专门招了两个英语专八的人。

综上所述在 NLP 领域标注成本是非常高昂的,尤其在大模型场景下往往需要海量高质量标注数据,算法团队有各种各样的方法来获取数据,包括采买,爬取,蒸馏等等。 那测试团队要如何获取标注数据呢,最简单的方法就是直接把语料发给标注组,按流程确实是这样的。但现实里很多团队是没有足够的标注人力的,即便我现在就职于一家顶级公司中的 AI 团队,标注人力也同样捉襟见肘。往往算法团队的需求都很难完成,所以更难以把人力分配给测试团队。

所以预标注技术在 AI 领域内就成为了一个常见的手段。 比如我们在知识引擎这个例子中, 我们已经知道了在知识引擎里,原始数据是一篇篇文档,测试人员需要读懂这篇文档然后在从中提炼出问题和标准答案。测试的时候把问题输入给系统,然后评估系统的答案和标准答案之间的相关性。鉴于读懂文档并提炼问答的成本非常高,所以我们往往也会利用一些大模型来帮助我们来生成问答数据。

上图是我在百川大模型上随便用一段文本来进行的实验,实际上在业界很多人把这种用大模型来生成标注数据的方法叫做蒸馏法。这种方法生成的数据质量当然要比人工来的要差,毕竟模型本身也有局限性。 但在没有海量的专业标注人力下,这是大多数团队会选择的没办法中的办法。而且这种方法在一些厂商的规定中是违规的, 比如 openai 明确声明任何公司或者组织使用这种方式大量的调用旗下的大模型都会被封禁账号, 前段时间封禁字节跳动的 openai 账号就是用的这个理由。 不过测试人员一般不用担心这个,因为我们要生成的数据量还是比较少的。

利用 API 来调用大模型

现在中文大模型比较流行的有百川,文心一言,通义千问等等,我们都可以到官网中注册账号来使用它的大模型。 为什么不用 openai 的呢? 因为他们在中文语境中的表现确实没那么好。所以如果我们就是自己玩一玩,那么用国外的模型是没什么问题的。 但如果真的用在工作中, 往往需要使用国内的一些中文大模型才能满足需要。
下图是我在百川的官网上注册的账号,我们在工作台中的 API key 管理中创建自己的 key 后就可以通过 API 来调用了。

curl -X POST https://api.baichuan-ai.com/v1/chat/completions\
     -H "Content-Type: application/json"\
     -H "Authorization: Bearer sk-c96bda2d14224b3434f9f7732c6aea93"\
     -d '{
          "model": "Baichuan2-Turbo",
          "messages": [
            { "role": "user", "content": "给出一段文本:我日薪8块钱,在闰年的二月,我月薪232元。     请根据这个文本生成一个问答题目,要求附带答案" }
          ],
          "temperature": 0.3,
          "stream": false
        }'

{"id":"chatcmpl-Mc0ba015JHcNon3","object":"chat.completion","created":1716111503,"model":"Baichuan2-Turbo","choices":[{"index":0,"message":{"role":"assistant","content":"题目:如果某人的日薪是8块钱,那么在闰年的二月份,他或她的月薪是多少?\n\n答案:232元。"},"finish_reason":"stop"}],"usage":{"prompt_tokens":39,"completion_tokens":33,"total_tokens":72}}

通过 API 我们就可以封装一些自动化的数据生成工具和测试工具。 当然, 这是要交钱的,我记得百川的模型一个最高的是 0.03 元/token,最低的是 0.0018/token, token 是啥呢, 就是可以理解为一个词吧,所以还是很贵的,我个人的账号, 冲了 10 块钱,没玩多一会就消费光了(当然我用的是 ragas,它内部会调用很多次所以消费的比较快)。 大家自己玩玩的话可以用挺长时间的。 在公司做测试都是要申请独立账号然后每个项目都去报销的。 不想用在线的模型,也可以把大模型下载下来然后在本地使用。 比如:


from langchain.llms.base import LLM
from typing import Any, List, Optional
from langchain.callbacks.manager import CallbackManagerForLLMRun
from transformers import AutoTokenizer, AutoModelForCausalLM, GenerationConfig
import os
import torch


class baichuan2_LLM(LLM):
    # 基于本地 Baichuan 自定义 LLM 类
    tokenizer: AutoTokenizer = None
    model: AutoModelForCausalLM = None

    def __init__(self, model_path: str):
        # model_path: Baichuan-7B-chat模型路径
        # 从本地初始化模型
        super().__init__()
        print("正在从本地加载模型...")
        self.tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
        self.model = AutoModelForCausalLM.from_pretrained(model_path, trust_remote_code=True,torch_dtype=torch.bfloat16)
        self.model.generation_config = GenerationConfig.from_pretrained(model_path)
        self.model = self.model.eval()
        print("完成本地模型的加载")

    def _call(self, prompt: str, stop: Optional[List[str]] = None,
              run_manager: Optional[CallbackManagerForLLMRun] = None,
              **kwargs: Any):
        # 重写调用函数
        messages = [
            {"role": "user", "content": prompt}
        ]
        # 重写调用函数
        response = self.model.chat(self.tokenizer, messages)
        return response

    @property
    def _llm_type(self) -> str:
        return "baichuan2_LLM"



if __name__ == "__main__":
    llm = baichuan2_LLM('/root/autodl-tmp/baichuan-inc/Baichuan2-7B-Chat')
    res = llm('你是谁')
    print(res)




# 运行结果
正在从本地加载模型...
Xformers is not installed correctly. If you want to use memory_efficient_attention to accelerate training use the following command to install Xformers
pip install xformers.
Loading checkpoint shards:   0%|                                                                                                                | 0/2 [00:00<?, ?it/s]/root/miniconda3/envs/lavis/lib/python3.8/site-packages/torch/_utils.py:831: UserWarning: TypedStorage is deprecated. It will be removed in the future and UntypedStorage will be the only storage class. This should only matter to you if you are using storages directly.  To access UntypedStorage directly, use tensor.untyped_storage() instead of tensor.storage()
  return self.fget.__get__(instance, owner)()
Loading checkpoint shards: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [01:51<00:00, 55.82s/it]
完成本地模型的加载
/root/miniconda3/envs/lavis/lib/python3.8/site-packages/langchain_core/_api/deprecation.py:119: LangChainDeprecationWarning: The method `BaseLLM.__call__` was deprecated in langchain-core 0.1.7 and will be removed in 0.2.0. Use invoke instead.
  warn_deprecated(



我是百川大模型,是由百川智能的工程师们创造的大语言模型,我可以和人类进行自然交流、解答问题、协助创作,帮助大众轻松、普惠的获得世界知识和专业服务。如果你有任何问题,可以随时向我提问


虽然模型下载到本地调用不需要再花钱了, 但是得需要你本地有很大的内存和 GPU,并且能下载的公开模型毕竟是有限的。 我记得我下载的是百川 12B 的模型,16G 的内存是不够的, 扩到了 32G 才加载的起来。而且为了保证计算速度, 还需要申请 GPU。 所以相信我,从花的钱的角度来看, 还不如在官网上充值付费的,这年头 GPU 太贵了。

ragas 测试框架

ragas 是一款专门利用大模型来评估大模型的测试框架,实际上也是利用大模型 rag 的形式来进行测试(跟我上篇帖子介绍的测试方法是差不多的),只不过他封装了很多好用的能力,比如不需要用户自己封装 prompt 了,提供了接口兼容不同的大模型,提供了多维度的评估指标等等。

from langchain_community.chat_models.huggingface import ChatHuggingFace
from langchain_community.llms import HuggingFaceHub, BaichuanLLM
from langchain_core.language_models.chat_models import BaseChatModel
from langchain_community.embeddings import BaichuanTextEmbeddings
from ragas.metrics import Faithfulness
from ragas import evaluate
from ragas.llms import LangchainLLMWrapper
import os
from langchain_community.document_loaders import DirectoryLoader, TextLoader
from ragas.testset.generator import TestsetGenerator
from ragas.metrics import (
    faithfulness,
    answer_relevancy,
    context_recall,
    context_precision,
    answer_similarity,
    answer_correctness
)
from ragas.testset.evolutions import simple, reasoning, multi_context


from pydantic import SecretStr
generator_llm = BaichuanLLM()
generator_llm.baichuan_api_key = SecretStr('xxxxxxxxxx')
critic_llm = BaichuanLLM()
embeddings_model = BaichuanTextEmbeddings()
embeddings_model.baichuan_api_key = SecretStr('xxxxxxxxxxxxxx')


from datasets import Dataset
data_samples = {
    'question': ['When was the first super bowl?', 'Who won the most super bowls?'],
    'answer': ['The first superbowl was held on Jan 15, 1967', 'The most super bowls have been won by The New England Patriots'],
    'contexts' : [['The First AFL–NFL World Championship Game was an American football game played on January 15, 1967, at the Los Angeles Memorial Coliseum in Los Angeles,'],
    ['The Green Bay Packers...Green Bay, Wisconsin.','The Packers compete...Football Conference']],
    'ground_truth': ['The first superbowl was held on January 15, 1967', 'The New England Patriots have won the Super Bowl a record six times']
}

dataset = Dataset.from_dict(data_samples)

metrics = [
        context_precision,
        context_recall,
        faithfulness,
        answer_relevancy,
        answer_similarity,
        answer_correctness
    ]

result = evaluate(
        llm=generator_llm,
        embeddings=embeddings_model,
        dataset=dataset,
        metrics=metrics,
    )

df = result.to_pandas()
df.to_csv('test_result.csv')

最后针对这些问题的评估结果就保存在 csv 文件里了。

总结

今天有点仓促,就先写这么多吧, ragas 后面有机会再详细介绍吧。 最后再宣传一下我的星球:


↙↙↙阅读原文可查看相关链接,并与作者交流