微信扫码
添加专属顾问
我要投稿
使用DeepEval框架快速评估RAG系统性能,轻松验证LLM输出的准确性与相关性。核心内容: 1. DeepEval框架安装与基础配置方法 2. 通过LLMTestCase构建测试案例的实战演示 3. GEval指标在输出质量评估中的具体应用
基于deepeval的LLM评估
官网:https://docs.ragas.io/en/stable/concepts/metrics/available_metrics/context_precision/https://deepeval.com/
第一个Demo
参考文档: https://deepeval.com/docs/getting-started
安装DeepEval
python3 -m venv venv
source venv/bin/activate
pip install -U deepeval
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
from deepeval import assert_test
from deepeval.test_case import LLMTestCase, LLMTestCaseParams
from deepeval.metrics import GEval
def test_correctness():
# 定义case : 输入问题 , 实际输出 , 预期输出
test_case = LLMTestCase(
input="I have a persistent cough and fever. Should I be worried?",
# Replace this with the actual output from your LLM application
actual_output="A persistent cough and fever could be a viral infection or something more serious. See a doctor if symptoms worsen or don't improve in a few days.",
expected_output="A persistent cough and fever could indicate a range of illnesses, from a mild viral infection to more serious conditions like pneumonia or COVID-19. You should seek medical attention if your symptoms worsen, persist for more than a few days, or are accompanied by difficulty breathing, chest pain, or other concerning signs."
)
correctness_metric = GEval(
name="Correctness",
criteria="Determine if the 'actual output' is correct based on the 'expected output'.",
evaluation_params=[LLMTestCaseParams.ACTUAL_OUTPUT, LLMTestCaseParams.EXPECTED_OUTPUT],
threshold=0.5
)
assert_test(test_case, [correctness_metric])
deepeval test run test_example.py
定义Case
定义评测指标(默认使用openAi , 需要环境变量中添加openAi key)
运行 , 生成报告
自定义模型实现
指标评估时指定模型
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
from deepeval import assert_test
from deepeval.test_case import LLMTestCase, LLMTestCaseParams
from deepeval.metrics import GEval
from deepeval.models.base_model import DeepEvalBaseLLM
from pydantic import BaseModel
# 创建自定义DeepSeek评估器
class DeepSeekLLM(DeepEvalBaseLLM):
def __init__(self, model="deepseek-reasoner"):
self.model = model
def load_model(self):
return self.model
def generate(self, prompt: str) -> str:
# 这里使用OpenAI SDK连接到DeepSeek API
# 需要设置环境变量OPENAI_API_KEY和OPENAI_API_BASE
from openai import OpenAI
import os
# 使用环境变量或默认值
api_key = os.environ.get("DEEPSEEK_API_KEY")
base_url = os.environ.get("DEEPSEEK_API_BASE", "https://api.deepseek.com/v1")
client = OpenAI(
api_key=api_key,
base_url=base_url
)
response = client.chat.completions.create(
model=self.model,
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": prompt}
]
)
return response.choices[0].message.content
async def a_generate(self, prompt: str) -> str:
# 异步版本的generate方法
from openai import AsyncOpenAI
import os
# 使用环境变量或默认值
api_key = os.environ.get("DEEPSEEK_API_KEY", "your_deepseek_api_key")
base_url = os.environ.get("DEEPSEEK_API_BASE", "https://api.deepseek.com/v1")
client = AsyncOpenAI(
api_key=api_key,
base_url=base_url
)
response = await client.chat.completions.create(
model=self.model,
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": prompt}
]
)
return response.choices[0].message.content
def get_model_name(self) -> str:
return f"DeepSeek-{self.model}"
def test_correctness():
# 创建DeepSeek评估器实例
deepseek_model = DeepSeekLLM()
correctness_metric = GEval(
name="Correctness",
criteria="Determine if the 'actual output' is correct based on the 'expected output'.",
evaluation_params=[LLMTestCaseParams.ACTUAL_OUTPUT, LLMTestCaseParams.EXPECTED_OUTPUT],
threshold=0.5,
model=deepseek_model # 使用DeepSeek模型替代默认的OpenAI
)
test_case = LLMTestCase(
input="I have a persistent cough and fever. Should I be worried?",
# Replace this with the actual output from your LLM application
actual_output="A persistent cough and fever could be a viral infection or something more serious. See a doctor if symptoms worsen or don't improve in a few days.",
expected_output="A persistent cough and fever could indicate a range of illnesses, from a mild viral infection to more serious conditions like pneumonia or COVID-19. You should seek medical attention if your symptoms worsen, persist for more than a few days, or are accompanied by difficulty breathing, chest pain, or other concerning signs."
)
assert_test(test_case, [correctness_metric])
基于RAGAS的LLM评估
官网地址:https://www.ragas.io/
什么是RAGAs评估?
Ragas (Retrieval-Augmented Generation Assessment) 它是一个框架,它可以帮助我们来快速
评估RAG系统的性能,为了评估RAG系统,Ragas需要以下信息:
- question:用户输入的问题。
- answer:从 RAG 系统生成的答案(由LLM给出)。
- contexts:根据用户的问题从外部知识源检索的上下文即与问题相关的文档。
- ground_truths: 人类提供的基于问题的真实(正确)答案。 这是唯一的需要人类提供的信息。
#### 5.2.2. 评估指标
Ragas提供了五种评估指标包括:
- 忠实度(faithfulness)
- 答案相关性(Answer relevancy)
- 上下文精度(Context precision)
- 上下文召回率(Context recall)
- 上下文相关性(Context relevancy)
1. 忠实度(faithfulness)
忠实度(faithfulness)衡量了生成的答案(answer)与给定上下文(context)的事实一致性。
它是根据answer和检索到的context计算得出的。并将计算结果缩放到 (0,1) 范围且越高越好。
如果答案(answer)中提出的所有基本事实(claims)都可以从给定的上下文(context)中推断
出来,则生成的答案被认为是忠实的。为了计算这一点,首先从生成的答案中识别一组claims。
然后,将这些claims中的每一项与给定的context进行交叉检查,以确定是否可以从给定的context中推断出它。
2. 答案相关性(Answer relevancy)
评估指标“答案相关性”重点评估生成的答案(answer)与用户问题(question)之间相关程度。
不完整或包含冗余信息的答案将获得较低分数。该指标是通过计算question和answer获得的,
它的取值范围在 0 到 1 之间,其中分数越高表示相关性越好。
当答案直接且适当地解决原始问题时,该答案被视为相关。重要的是,我们对答案相关性的评
估不考虑真实情况,而是对答案缺乏完整性或包含冗余细节的情况进行惩罚。为了计算这个分数,
LLM会被提示多次为生成的答案生成适当的问题,并测量这些生成的问题与原始问题之间的平均余
弦相似度。基本思想是,如果生成的答案准确地解决了最初的问题,LLM应该能够从答案中生成与
原始问题相符的问题。
3. 上下文精度(Context precision)
上下文精度是一种衡量标准,它评估所有在上下文(contexts)中呈现的与基本事实(ground-truth)
相关的条目是否排名较高。理想情况下,所有相关文档块(chunks)必须出现在顶层。该指标使用
question和计算contexts,值范围在 0 到 1 之间,其中分数越高表示精度越高。
4. 上下文召回率(Context recall)
上下文召回率(Context recall)衡量检索到的上下文(Context)与人类提供的真实答案(ground truth)
的一致程度。它是根据ground truth和检索到的Context计算出来的,取值范围在 0 到 1 之间,值越高
表示性能越好。
为了根据真实答案(ground truth)估算上下文召回率(Context recall),分析真实答案中的每个句子以
确定它是否可以归因于检索到的Context。 在理想情况下,真实答案中的所有句子都应归因于检索到的Context。
5. 上下文相关性(Context relevancy)
该指标衡量检索到的上下文(Context)的相关性,根据用户问题(question)和上下文(Context)计算得到,
并且取值范围在 (0, 1)之间,值越高表示相关性越好。理想情况下,检索到的Context应只包含解答
question的信息。 我们首先通过识别检索到的Context中与回答question相关的句子数量来估计 |S| 的值。
说明:这里的|S|是指Context中存在的与解答question相关的句子数量。
# !pip install pypdf
# !pip install ragas
# !pip install langchain
# !pip install chromadb
import os
from langchain.document_loaders import PyPDFLoader
docs = PyPDFLoader("../files/浦发上海浦东发展银行西安分行个金客户经理考核办法.pdf").load()
print(docs)
from langchain_community.embeddings import DashScopeEmbeddings
from langchain_community.llms import Tongyi
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.retrievers import ParentDocumentRetriever
from langchain.storage import InMemoryStore
from langchain.vectorstores import Chroma
# 初始化大语言模型 阿里模型
DASHSCOPE_API_KEY = "your keys"
llm = Tongyi(
model_name="qwen-max",
dashscope_api_key=DASHSCOPE_API_KEY
)
# 创建嵌入模型
embeddings = DashScopeEmbeddings(
model="text-embedding-v3",
dashscope_api_key=DASHSCOPE_API_KEY
)
# 创建主文档分割器
parent_splitter = RecursiveCharacterTextSplitter(chunk_size=512)
# 创建子文档分割器
child_splitter = RecursiveCharacterTextSplitter(chunk_size=256)
# 创建向量数据库对象
vectorstore = Chroma(
collection_name="split_parents", embedding_function=embeddings
)
# 创建内存存储对象
store = InMemoryStore()
# 创建父文档检索器
retriever = ParentDocumentRetriever(
vectorstore=vectorstore,
docstore=store,
child_splitter=child_splitter,
parent_splitter=parent_splitter,
search_kwargs={"k": 2}
)
# 添加文档集
retriever.add_documents(docs)
# 切割出来主文档的数量
len(list(store.yield_keys()))
print(f"切割文档数量:{len(list(store.yield_keys()))}")
from langchain.prompts import ChatPromptTemplate
from langchain.schema.runnable import RunnableMap
from langchain.schema.output_parser import StrOutputParser
# 创建prompt模板
template = """You are an assistant for question-answering tasks.
Use the following pieces of retrieved context to answer the question.
If you don't know the answer, just say that you don't know.
Use two sentences maximum and keep the answer concise.
Question: {question}
Context: {context}
Answer:
"""
# 由模板生成prompt
prompt = ChatPromptTemplate.from_template(template)
# 创建 chain(LCEL langchain 表达式语言)
chain = RunnableMap({
"context": lambda x: retriever.get_relevant_documents(x["question"]),
"question": lambda x: x["question"]
}) | prompt | llm | StrOutputParser()
query = "客户经理被投诉了,投诉一次扣多少分?"
response = chain.invoke({"question": query})
print(f"问题:{query}\n响应:{response}")
#### 5.3.4. 准备评估的QA数据集
from datasets import Dataset
questions = [
"客户经理被投诉了,投诉一次扣多少分?",
"客户经理每年评聘申报时间是怎样的?",
"客户经理在工作中有不廉洁自律情况的,发现一次扣多少分?",
"客户经理不服从支行工作安排,每次扣多少分?",
"客户经理需要什么学历和工作经验才能入职?",
"个金客户经理职位设置有哪些?"
]
ground_truths = [
"每投诉一次扣2分",
"每年一月份为客户经理评聘的申报时间",
"在工作中有不廉洁自律情况的每发现一次扣50分",
"不服从支行工作安排,每次扣2分",
"须具备大专以上学历,至少二年以上银行工作经验",
"个金客户经理职位设置为:客户经理助理、客户经理、高级客户经理、资深客户经理"
]
answers = []
contexts = []
# Inference
for query in questions:
answers.append(chain.invoke({"question": query}))
contexts.append([docs.page_content for docs in retriever.get_relevant_documents(query)])
# To dict
data = {
"user_input": questions,
"response": answers,
"retrieved_contexts": contexts,
"reference": ground_truths
}
# Convert dict to dataset
dataset = Dataset.from_dict(data)
print(dataset)
# 评测结果
from ragas import evaluate
from ragas.run_config import RunConfig
my_run_config = RunConfig(max_workers=64, timeout=600)
from ragas.metrics import (
faithfulness,
answer_relevancy,
context_recall,
context_precision,
)
result = evaluate(
dataset=dataset,
metrics=[
context_precision,
context_recall,
faithfulness,
answer_relevancy,
],
llm=llm,
embeddings=embeddings,
run_config=my_run_config,
)
print(result)
df = result.to_pandas()
df.to_csv(f"../result/evaluateRes.csv")
res = df.to_dict()
print(res)
基于AutoRAG的LLM评估
Auto-RAG(Autonomous Retrieval-Augmented Generation)是一种基于大型语言模型(LLMs)的自主检索增强生成技术,旨在解决传统检索增强生成(RAG)系统在处理复杂查询和噪声问题时的性能瓶颈。通过自动化迭代检索和利用LLMs的推理能力,Auto-RAG显著提升了生成内容的准确性、可解释性和用户体验。
Auto-RAG原理
它的产生主要用于解决复杂问题,简单问题一般很容易召回,但是复杂问题却不容易召回,比如多跳问题。一个多跳问题,一般内含有多个子问题,直接使用多跳问题进行检索,其中的子问题是相互干扰的,结果就是无法检索到高质量的文本内容。
为解决此类问题,人们也一般想到了将问题拆分,然后进行多路召回,最后将子问题的答案进行汇总,生成最终的答案。但是这种方法具有不稳定性,首先拆分问题的准确性不一定高,比较依赖prompt好坏,而且多个子问题之间可能具有关联关系,他们之间是有先后顺序的,无法进行并行问答。
它的执行过程如下:
解析模块:PDFMiner,PDFPlumber,PyPDFium2,PyPDF,PyMuPDF,UnstructuredPDF,
NaverClovaOCR,llama Parse,Upstage Document Parser,Directory,Unstructured,
csv,json,unstructuredmarkdown,bshtml,unstructuredxml
切块模块:Token,SentenceTransformersToken,Character,RecursiveCharacter,
Sentence,Konlpy ,Semantic_llama_index,SemanticDoubleMerging,SentenceWindow,
SimpleFile
支持40种检索、排序、生成模块
重排:UPR,Tart,MonoT5,Cohere reranker,RankGPT,Jina Reranker,
Sentence Transformer Reranker,Colbert Reranker,Flag Embedding Reranker,
Flag Embedding LLM Reranker,Time Reranker,OpenVINO Reranker,VoyageAI Reranker,
MixedBread AI Reranker,Ko-reranker,pass_reranker
Query理解:query_decompose,hyde,multi_query_expansion,pass_query_expansion
检索:bm25,vectordb,hybrid_rrf,hybrid_cc
论文链接:https://arxiv.org/abs/2411.19443
代码链接:https://github.com/ictnlp/Auto-RAG
文章链接:https://cloud.tencent.com/developer/article/2473520
Auto-RAG优势
1.提高答案的准确性与可靠性
通过动态检索外部知识库并结合LLMs的生成能力,Auto-RAG能够生成更准确、更可靠的答案,
尤其在处理复杂查询和多跳问题时表现突出。
2.增强模型的解释性与用户体验
Auto-RAG以自然语言形式表达迭代检索过程,提高了模型的可解释性。用户可以通过交互界面
直观地了解检索和生成过程,增强了信任感。
3.降低计算成本与人工干预
Auto-RAG通过自动化迭代检索和动态调整检索策略,减少了人工干预的需求,同时优化了计算
资源的利用,显著降低了成本。
4.适应复杂查询与动态调整检索策略
Auto-RAG能够根据问题的复杂性和检索到的知识相关性,动态调整检索次数和策略。这种自适
应性使其在处理复杂任务时表现优异。
总结:
Auto-RAG本质上是一种ReAct范式,LLM决策是否进行下一轮召回,以及下一轮检索的问题。召
回可以理解为工具调用,而下一轮检索的问题可以理解为工具调用的入参。通过这种ReAct范式
的迭代召回,可以提高RAG在复杂问题上的处理能力。
RAG评估工具对比分析表
特征 | Ragas | DeepEval | AutoRAG |
---|---|---|---|
核心目标 | |||
评估方法 | |||
主要产出 | |||
适用阶段 | |||
优点 | |||
缺点 |
开发场景 | 推荐工具 | 理由 |
---|---|---|
深度诊断特定管道组件 | ||
持续集成/回归测试 | ||
快速筛选最优架构 | ||
减少模型API调用成本 | ||
资源有限的小型团队 | ||
大型项目架构优化 |
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费场景POC验证,效果验证后签署服务协议。零风险落地应用大模型,已交付160+中大型企业
2025-07-12
OpenAI 无需向量化的RAG新范例:探索大模型时代的高效知识问答与模型选择之道
2025-07-11
详解RAG评估指标与评估方法
2025-07-11
一文读懂GraphRAG:把知识图谱塞进RAG,AI从“聪明”走向“懂事”
2025-07-11
文档太长模型“吃不下”?试试这15种Chunking策略,轻松搞定RAG!
2025-07-10
Spring Ai RAG 技术让大模型回答更精准
2025-07-09
5分钟了解GraphRAG和Mem0
2025-07-09
AI大模型落地最后一公里:RAG?
2025-07-09
技术总结之RAG用于文档信息抽取及多模态大模型两阶段训练范式
2025-04-19
2025-04-16
2025-05-08
2025-04-23
2025-04-16
2025-06-06
2025-05-30
2025-05-19
2025-04-14
2025-06-05
2025-07-09
2025-07-04
2025-07-01
2025-07-01
2025-07-01
2025-07-01
2025-06-30
2025-06-29