微信扫码
添加专属顾问
我要投稿
RAG应用落地难在评估?这份指南帮你建立科学的评估体系,确保应用稳定可控。 核心内容: 1. RAG应用评估的必要性与四大挑战 2. 评估依据与关键指标解析 3. 评估流程设计与实施方法
一、为什么RAG应用需要评估
随着大模型技术的发展,我们已经具备了开发完整 RAG(Retrieval-Augmented Generation,检索增强生成)应用的技术能力。借助 LlamaIndex、LangChain 等成熟框架,可以在较短时间内实现从原型到应用的快速构建。然而,真正将 RAG 应用推向生产环境,远不只是“搭建起来”那么简单,仍有许多问题值得提前思考与应对。
1. 大模型输出的不确定性
大模型的回答往往带有不确定性,这种特性会造成结果的不可预知性。如果缺乏充分测试,上线后可能引发严重的应用风险。因此,在部署之前,必须通过科学的方法对系统进行全面评估,尽可能量化和控制这种不确定性。
2. 持续评估与改进机制
应用上线只是起点。在后续的迭代中,需要建立科学、快速且可复用的评估机制,用于衡量改进是否真正带来价值。例如,某次优化后,回答的置信度是上升了 10%,还是下降了 5%?只有通过系统化的度量,才能避免“盲目调优”。
3. 知识库的动态变化
RAG 应用依赖的知识库并非一成不变。在持续更新与维护过程中,可能会引入新的噪声甚至错误信息。为了确保应用长期稳定运行,定期检测与重新评估知识库的质量就显得尤为重要。
4. 底层模型的选择与升级
RAG 应用高度依赖底层大模型。面对市面上众多商业与开源模型,企业需要明确如何选择最适合自身需求的版本。同时,模型升级是否会带来性能提升,还是引入新的不确定性,也是必须提前纳入评估体系的关键问题。
RAG 应用的快速开发并非难事,真正的挑战在于如何在生产环境中保持其稳定性、可控性和持续改进的能力。唯有建立起科学的评估与运维体系,才能让 RAG 应用真正发挥价值。
二、RAG应用的评估依据与指标
RAG 应用的评估依据,即评估模块的输入一般包括以下要素。
输入问题(question):用户在使用 RAG 应用时的输入问题。
生成的答案(answer):需要评估的 RAG 应用的输出,即问题的答案。
上下文(context):用于增强 RAG 应用输出的参考上下文,通常在检索阶段生成。
参考答案(reference_answer):输入问题的真实的正确答案,通常需要人类标注。
基于这些评估依据,对 RAG 应用进行评估的常见指标见表1 。
三、RAG应用的评估流程与方法
确定评估的目的、维度与指标。
准备评估数据集,可以自行准备与标注,也可以使用大模型生成。根
据 评 估 指 标 , 你 可 能 需 要 准 备 不 同 的 输 入 问 题 ( question ) 与 参 考 答 案(reference_answer)。
将评估数据集输入 RAG 应用,获得检索结果(即上下文,context)与生成的答案(answer)。
将评估依据输入评估器,计算各类评估指标,分析 RAG 应用的整体性能。
对 RAG 应用的组件级评估通常侧重于检索与生成两个最关键的阶段。通过对这两个阶段单独评估,可以更细致地观察与分析问题,从而有针对性地优化与增强 RAG 应用。
四、评估检索质量
利用检索评估组件 RetrieverEvaluator 可以对任何检索模块进行质量评估。
该评估的主要指标如下。
命中率(hit_rate):表示检索出的上下文对期望的上下文的命中率。
平均倒数排名(mrr):衡量检索出的上下文的排名质量。
cohere 重排相关性(cohere-rerank-relevancy):用 Cohere Rerank 模型的排名结果衡量检索的排名质量。
评估检索质量的主要依据为输入问题与期望的上下文(检索出的 Node)。
1、生成检索评估数据集
# 读取文档,构造 Node,用于生成检索评估数据集from pathlib import Pathfrom llama_index.core import SimpleDirectoryReader, VectorStoreIndexfrom llama_index.core.node_parser import SentenceSplitterfrom llama_index.core.evaluation import (generate_question_context_pairs,EmbeddingQAFinetuneDataset,)# 加载大模型的代码,请勿删除 startfrom common.llm_model_helper import llm_settings# 加载大模型的代码,请勿删除 enddocuments = SimpleDirectoryReader(input_files=[r"D:\muxue\common_docs\jianlai.txt"]).load_data()node_parser = SentenceSplitter(chunk_size=1024)nodes = node_parser.get_nodes_from_documents(documents)for idx, node in enumerate(nodes):node.id_ = f"node_{idx}"# 准备一个检索器,后面使用# vector_index = VectorStoreIndex(nodes)# retriever = vector_index.as_retriever(similarity_top_k=2)QA_GENERATE_PROMPT_TMPL = """以下是上下文:---------------------{context_str}---------------------你是一位专业教授。你的任务是基于以上的上下文,为即将到来的考试设置{num_questions_per_chunk} 个问题。这些问题必须基于提供的上下文生成,并确保上下文能够回答这些问题。确保每一行都只有一个独立的问题。不要有多余解释。不要给问题编号。"""print("Generating question-context pairs...")qa_dataset = generate_question_context_pairs(nodes,# llm=llm_Ollama,num_questions_per_chunk=1,qa_generate_prompt_tmpl=QA_GENERATE_PROMPT_TMPL)print("Saving dataset...")qa_dataset.save_json("retriever_eval_dataset.json")
在这段代码中,手工设置了中文的 Prompt,一方面有助于了解生成原理与调试生成结果,另一方面用于生成中文问题。最后,把生成的检索评估数据集保存到本地的 JSON 文档中,以减少不必要的重复生成,后面只需要从本地文档中加载即可。
2、运行评估检索过程的程序
我们已经构造了一个检索器,并且借助大模型生成了检索评估数据集。下面构造与运行检索评估器。基本的流程如下。
加载检索评估数据集。
构造检索评估器( RetrieverEvaluator 对象),设置评估指标。
调用 evaluate 方法,查看评估结果。
# 读取文档,构造 Node,用于生成检索评估数据集
# 读取文档,构造 Node,用于生成检索评估数据集from pathlib import Pathfrom llama_index.core import SimpleDirectoryReader, VectorStoreIndexfrom llama_index.core.node_parser import SentenceSplitterfrom llama_index.core.evaluation import (generate_question_context_pairs,EmbeddingQAFinetuneDataset,)from llama_index.core.evaluation import RetrieverEvaluatorfrom evaluation_comm import get_retrieverprint("Loading dataset...")# 从保存的 JSON 文档中加载检索评估数据集qa_dataset = EmbeddingQAFinetuneDataset.from_json("retriever_eval_dataset.json")eval_querys = list(qa_dataset.queries.items())# 构造一个检索评估器,设定两个评估指标metrics = ["mrr", "hit_rate"]retriever_evaluator = RetrieverEvaluator.from_metric_names(metrics, retriever=get_retriever())# 简单评估前 10 个评估用例for eval_id, eval_query in eval_querys[:10]:expect_docs = qa_dataset.relevant_docs[eval_id]print(f"Query: {eval_query}, Expected docs: {expect_docs}")# 评估,输入评估问题与预期检索出的 Nodeeval_result = retriever_evaluator.evaluate(query=eval_query, expected_ids=expect_docs)print(eval_result)# 对整个评估数据集进行评估# eval_results = retriever_evaluator.evaluate_dataset(qa_dataset)
从打印的结果中可以看到评估指标,你可以对这些评估指标进行汇总计算,得出检索评估器的质量评估结果。如果需要对整个检索评估数据集直接进行评估,那么可以使用更简单的方式:
eval_results = retriever_evaluator.evaluate_dataset(qa_dataset)
直接在检索评估数据集上调用 evaluate_dataset 方法,其效果与逐个循环调用 evaluate 方法的效果是一致的。
五、评估响应质量
1、 生成响应评估数据集
from pathlib import Pathfrom llama_index.core import SimpleDirectoryReader, VectorStoreIndexfrom llama_index.core.llama_dataset.generator import RagDatasetGeneratorfrom llama_index.core.llama_dataset import LabelledRagDataset# 加载大模型的代码from common.llm_model_helper import llm_settings# build documentsdocs = SimpleDirectoryReader(input_files=[r'D:\muxue\common_docs\jianlai.txt']).load_data()# define generator, generate questionsdataset_generator = RagDatasetGenerator.from_documents(documents=docs,#llm=llm_ollama,num_questions_per_chunk=1, # 设置每个 Node 都生成的问题数量show_progress=True,question_gen_query="您是一位老师。您的任务是为即将到来的考试设置{num_questions_per_chunk}个问题。这些问题必须基于提供的上下文生成,并确保上下文能够回答这些问题。确保每一行都只有一个独立的问题。不要有多余解释。不要给问题编号。")# 以下代码只需要运行一次save_json_name='rag_eval_dataset_jianlai.json'print('Generating questions from nodes...\n')rag_dataset = dataset_generator.generate_dataset_from_nodes()rag_dataset.save_json(save_json_name)# 从本地文档中加载并查看print('Loading dataset...\n')rag_dataset = LabelledRagDataset.from_json(save_json_name)for example in rag_dataset.examples:print(f'query: {example.query}')print(f'answer: {example.reference_answer}')
在运行代码后,你可以在当前目录中看到一个 rag_eval_dataset_jianlai.json 数据集文档,打开该文档,可以看到生成的每个评估用例的数据格式。其中:
query:生成的问题。
reference_contexts:检索出的参考上下文。
reference_answers:参考答案。
这些内容都可能被输入到后面的响应评估器中,作为评估响应质量的输入依据,如下所示。
2、单次响应评估
要想对 RAG 应用的某一次查询的响应过程进行不同维度的评估,那么只需要构造对应的评估器组件(Evaluator),然后输入必需的数据,即可获得评估结果。单次响应评估的输入参数有以下几个。
query:输入问题。
response:RAG 应用的响应结果。如果使用 evaluate_response 方法评估,那么可以直接输入 response;如果使用 evaluate 方法评估,那么需要从response 中提取上下文与文本内容,将其分别作为参数输入。
reference:参考答案。它在正确性与相似度评估中会用到,对应响应评估数据集中的 reference_answer 字段。
from llama_index.core import (VectorStoreIndex,SimpleDirectoryReader,Response,)from llama_index.core.node_parser import SentenceSplitterfrom llama_index.core.evaluation import (FaithfulnessEvaluator,RelevancyEvaluator,ContextRelevancyEvaluator,AnswerRelevancyEvaluator,CorrectnessEvaluator,SemanticSimilarityEvaluator)# 加载大模型的代码,请勿删除 startfrom common.llm_model_helper import llm_settings# 加载大模型的代码,请勿删除 end# ......这里省略构造查询引擎的过程......documents = SimpleDirectoryReader(input_files=[r"D:\muxue\common_docs\jianlai.txt"]).load_data()# create vector indexsplitter = SentenceSplitter(chunk_size=512)vector_index = VectorStoreIndex.from_documents(documents, transformations=[splitter])query_engine = vector_index.as_query_engine()# 两个重要的输入参数query = "陈平安对中年光棍的尖酸刻薄言语有何反应?"response = query_engine.query(query)# 评估忠实度的评估器evaluator = FaithfulnessEvaluator()eval_result = evaluator.evaluate_response(query=query,response=response)print(f'faithfulness score: {eval_result.score}\n')# 评估相关性的评估器(综合了上下文相关性与答案相关性)evaluator = RelevancyEvaluator()eval_result =evaluator.evaluate_response(query=query, response=response)print(f'relevancy score: {eval_result.score}\n')# 评估上下文相关性的评估器evaluator = ContextRelevancyEvaluator()eval_result =evaluator.evaluate_response(query=query, response=response)print(f'context relevancy score: {eval_result.score}\n')# 评估答案相关性的评估器evaluator = AnswerRelevancyEvaluator()eval_result =evaluator.evaluate_response(query=query, response=response)print(f'answer relevancy score: {eval_result.score}\n')# 评估正确性的评估器,注意输入了 referenceevaluator = CorrectnessEvaluator()eval_result =evaluator.evaluate_response(query=query, response=response,reference='根据提供的上下文信息,陈平安对中年光棍的尖酸刻薄言语反应如下:他翻了个白眼,但并不以为意。原因有二:一是他生活在这座乡野地方,早已习惯此类言语,认为若因此恼火反而显得可笑;二是这中年光棍本身也是小镇百姓经常取笑的对象,陈平安对此人并无太多计较。')print(f'correctness score: {eval_result.score}\n')# 评估答案与标准答案的语义相似度(基于 embedding)的评估器,注意输入了 referenceevaluator = SemanticSimilarityEvaluator()eval_result =evaluator.evaluate_response(query=query, response=response,reference='陈平安翻了个白眼,但并不以为意,对此人并无太多计较。')print(f'semantic similarity score: {eval_result.score}\n')
评估过程非常简单,各个评估指标可参考表 1中的说明。必须再次强调,有的评估器需要输入参考答案(正确性与语义相似度),否则会出现异常。在正常运行评估代码后,可以看到输出的评估结果,如下图所示。
3、批量响应评估
你可以借助批量评估器,在评估数据集的基础上并行运行多个响应评估器,并通过计算与统计获得综合的性能评估结果。以 (五-1)节生成的响应评估数据集为基础,对构造的查询引擎进行综合评估:
from llama_index.core import (VectorStoreIndex,SimpleDirectoryReader,Response,)from llama_index.core.node_parser import SentenceSplitterfrom llama_index.core.llama_dataset import LabelledRagDatasetfrom llama_index.core.evaluation import (FaithfulnessEvaluator, RelevancyEvaluator, ContextRelevancyEvaluator, AnswerRelevancyEvaluator, CorrectnessEvaluator, SemanticSimilarityEvaluator)from llama_index.core.evaluation import BatchEvalRunnerimport asyncio# 打印评估结果import pandas as pd# 加载大模型的代码,请勿删除 startfrom common.llm_model_helper import llm_settings# 加载大模型的代码,请勿删除 end# ......这里造查询引擎......documents = SimpleDirectoryReader(input_files=[r"D:\muxue\common_docs\jianlai.txt"]).load_data()# create vector indexsplitter = SentenceSplitter(chunk_size=512)vector_index = VectorStoreIndex.from_documents(documents, transformations=[splitter])query_engine = vector_index.as_query_engine()# 构造多个响应评估器faithfulness_evaluator = FaithfulnessEvaluator()relevancy_evaluator = RelevancyEvaluator()correctness_evaluator = CorrectnessEvaluator()similartiy_evaluator = SemanticSimilarityEvaluator()# 加载数据集rag_dataset = LabelledRagDataset.from_json('rag_eval_dataset_jianlai.json')# 构造一个批量评估器runner = BatchEvalRunner({"faithfulness": faithfulness_evaluator,"relevancy": relevancy_evaluator,"correctness": correctness_evaluator,"similarity": similartiy_evaluator},workers=4)async def evaluate_queries():"""为了提高性能,采用异步并行的评估方法,调用批量评估器输入:查询引擎、批量的 query,批量的 reference这里对响应评估数据集中的前十个评估用例进行评估"""eval_results = await runner.aevaluate_queries(query_engine,queries=[example.query for example in rag_dataset.examples][:10],reference=[example.reference_answer for example in rag_dataset.examples][:10],)return eval_resultseval_results = asyncio.run(evaluate_queries())def display_results(eval_results):data = {}for key, results in eval_results.items():scores = [result.score for result in results]scores.append(sum(scores) / len(scores))data[key] = scoresdata["query"] = [result.query for result in eval_results["faithfulness"]]data["query"].append("【Average】")df = pd.DataFrame(data)print(df)display_results(eval_results)
借助 BatchEvalRunner 组件,在调用 aevaluate_queries 方法进行批量评估时可以设置 workers 参数并行运行,从而缩短评估的时间。最后,我们把评估结果用表格的形式展示,以便更直观地观察(也可以输出 Excel 文档),输出结果如图所示。
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业
2025-10-28
“生成幻觉”(Hallucination)和“知识时效性”不足引发的架构范式变革
2025-10-27
RAG优化技巧
2025-10-26
关于RAG系统在多轮对话中的问题改写(优化)方法—使用历史记录改写问题
2025-10-26
你的RAG知识库,真的“喂”对数据了吗?拆解dify分段策略,告别无效召回
2025-10-16
基于大模型的智能问答场景解决方案——RAG提升召回率的关键
2025-10-16
用合成数据评测 RAG 系统:一份可直接上手的 DeepEval 实操指南
2025-10-16
2025 年 RAG 最佳 Reranker 模型
2025-10-16
HiRAG问答流程深入分析
2025-09-15
2025-09-02
2025-08-05
2025-08-18
2025-08-25
2025-08-25
2025-08-25
2025-09-03
2025-08-20
2025-09-08
2025-10-04
2025-09-30
2025-09-10
2025-09-10
2025-09-03
2025-08-28
2025-08-25
2025-08-20