基于 Ragas 与通义千问实现 RAG 系统答案正确性自动评估
本文基于 Ragas 评估框架与通义千问(qwen-plus)大模型,结合 DashScope text-embedding-v3 向量模型,构建 RAG(检索增强生成)系统的自动化评估流水线。通过 answer_correctness 指标量化评估模型生成答案与标准答案的一致性,并进一步使用 context_recall 和 context_precision 评估检索质量。
一、核心概念:RAG 评估是什么?
RAG(Retrieval-Augmented Generation) 系统将检索与生成结合:先从知识库中检索相关文档,再让 LLM 基于检索结果生成答案。但如何衡量 RAG 系统的输出质量?这就是 Ragas 要解决的问题。
| 评估维度 | 指标 | 说明 |
|---|---|---|
| 答案质量 | answer_correctness | 生成答案与标准答案的一致程度 |
| 检索质量 | context_recall | 检索到的文档覆盖标准答案的程度 |
| 检索精度 | context_precision | 检索到的文档中相关内容的占比 |
为什么需要自动评估? 传统方式依赖人工判断,效率低且主观性强。Ragas 通过 LLM + Embedding 的组合,实现自动化、可量化的评估:
- LLM 判断:让大模型对比生成答案与标准答案的语义差异
- Embedding 相似度:通过向量余弦相似度衡量语义接近程度
- 综合评分:两者加权得到最终分数
二、系统架构
#mermaid-svg-MiC7tM5TLJYalxIk{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-MiC7tM5TLJYalxIk .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-MiC7tM5TLJYalxIk .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-MiC7tM5TLJYalxIk .error-icon{fill:#552222;}#mermaid-svg-MiC7tM5TLJYalxIk .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-MiC7tM5TLJYalxIk .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-MiC7tM5TLJYalxIk .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-MiC7tM5TLJYalxIk .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-MiC7tM5TLJYalxIk .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-MiC7tM5TLJYalxIk .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-MiC7tM5TLJYalxIk .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-MiC7tM5TLJYalxIk .marker{fill:#333333;stroke:#333333;}#mermaid-svg-MiC7tM5TLJYalxIk .marker.cross{stroke:#333333;}#mermaid-svg-MiC7tM5TLJYalxIk svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-MiC7tM5TLJYalxIk p{margin:0;}#mermaid-svg-MiC7tM5TLJYalxIk .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-MiC7tM5TLJYalxIk .cluster-label text{fill:#333;}#mermaid-svg-MiC7tM5TLJYalxIk .cluster-label span{color:#333;}#mermaid-svg-MiC7tM5TLJYalxIk .cluster-label span p{background-color:transparent;}#mermaid-svg-MiC7tM5TLJYalxIk .label text,#mermaid-svg-MiC7tM5TLJYalxIk span{fill:#333;color:#333;}#mermaid-svg-MiC7tM5TLJYalxIk .node rect,#mermaid-svg-MiC7tM5TLJYalxIk .node circle,#mermaid-svg-MiC7tM5TLJYalxIk .node ellipse,#mermaid-svg-MiC7tM5TLJYalxIk .node polygon,#mermaid-svg-MiC7tM5TLJYalxIk .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-MiC7tM5TLJYalxIk .rough-node .label text,#mermaid-svg-MiC7tM5TLJYalxIk .node .label text,#mermaid-svg-MiC7tM5TLJYalxIk .image-shape .label,#mermaid-svg-MiC7tM5TLJYalxIk .icon-shape .label{text-anchor:middle;}#mermaid-svg-MiC7tM5TLJYalxIk .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-MiC7tM5TLJYalxIk .rough-node .label,#mermaid-svg-MiC7tM5TLJYalxIk .node .label,#mermaid-svg-MiC7tM5TLJYalxIk .image-shape .label,#mermaid-svg-MiC7tM5TLJYalxIk .icon-shape .label{text-align:center;}#mermaid-svg-MiC7tM5TLJYalxIk .node.clickable{cursor:pointer;}#mermaid-svg-MiC7tM5TLJYalxIk .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-MiC7tM5TLJYalxIk .arrowheadPath{fill:#333333;}#mermaid-svg-MiC7tM5TLJYalxIk .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-MiC7tM5TLJYalxIk .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-MiC7tM5TLJYalxIk .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-MiC7tM5TLJYalxIk .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-MiC7tM5TLJYalxIk .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-MiC7tM5TLJYalxIk .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-MiC7tM5TLJYalxIk .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-MiC7tM5TLJYalxIk .cluster text{fill:#333;}#mermaid-svg-MiC7tM5TLJYalxIk .cluster span{color:#333;}#mermaid-svg-MiC7tM5TLJYalxIk div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-MiC7tM5TLJYalxIk .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-MiC7tM5TLJYalxIk rect.text{fill:none;stroke-width:0;}#mermaid-svg-MiC7tM5TLJYalxIk .icon-shape,#mermaid-svg-MiC7tM5TLJYalxIk .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-MiC7tM5TLJYalxIk .icon-shape p,#mermaid-svg-MiC7tM5TLJYalxIk .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-MiC7tM5TLJYalxIk .icon-shape .label rect,#mermaid-svg-MiC7tM5TLJYalxIk .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-MiC7tM5TLJYalxIk .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-MiC7tM5TLJYalxIk .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-MiC7tM5TLJYalxIk :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 评估数据集
question + answer + ground_truth
Ragas evaluate 入口
通义千问 qwen-plus
LLM 语义判断
DashScope text-embedding-v3
向量相似度计算
answer_correctness 评分
输出评估报告 DataFrame
核心组件:
| 组件 | 版本/模型 | 职责 |
|---|---|---|
ragas |
评估框架 | 定义评估指标与评估流程 |
langchain_community |
工具库 | 封装 Tongyi LLM 和 DashScope Embeddings |
datasets |
HuggingFace 数据集库 | 构建标准化评估数据集 |
qwen-plus |
通义千问 | 作为裁判 LLM,判断答案语义正确性 |
text-embedding-v3 |
DashScope 向量模型 | 将文本转为向量,计算语义相似度 |
三、环境准备
3.1 依赖安装
bash
pip install langchain_community datasets ragas -i https://pypi.tuna.tsinghua.edu.cn/simple
3.2 环境变量配置
需要配置 DashScope API Key(通义千问的 API 密钥):
env
DASHSCOPE_API_KEY=sk-your-api-key-here
说明: Tongyi LLM 和 DashScopeEmbeddings 会自动从环境变量中读取
DASHSCOPE_API_KEY,无需手动传入。
四、步骤详解
步骤 1:构建评估数据集
评估数据包含三个核心字段:
python
data_samples = {
'question': [
'杭州最值得去的景点有哪些?',
'去成都旅游的话,有哪些特色美食推荐?',
'在西安游览时,参观兵马俑需要提前预约吗?'
],
'answer': [
'杭州西湖、灵隐寺和千岛湖是比较受欢迎的景点。',
'成都有很多好吃的,比如火锅、串串香和担担面。',
'参观兵马俑不需要预约,现场买票就可以进去。'
],
'ground_truth': [
'杭州必游景点包括西湖、灵隐寺、雷峰塔、千岛湖和宋城,其中西湖是国家5A级景区,建议清晨游览以避开人流。',
'成都作为美食之都,推荐品尝火锅、串串香、担担面、龙抄手和钟水饺,宽窄巷子和锦里是集中体验地道小吃的好去处。',
'参观秦始皇兵马俑博物馆必须通过官方平台提前实名预约购票,旺季时需至少提前3天预约,现场不保证有票。'
]
}
各字段含义:
| 字段 | 说明 | 示例 |
|---|---|---|
question |
用户提问 | "杭州最值得去的景点有哪些?" |
answer |
RAG 系统生成的答案 | "杭州西湖、灵隐寺和千岛湖..." |
ground_truth |
人工标注的标准答案 | "杭州必游景点包括西湖、灵隐寺、雷峰塔..." |
设计要点:
answer是不完整或有错误的回答,ground_truth是完整且准确的标准答案。通过对比两者,评估 RAG 系统的生成质量。
步骤 2:初始化 LLM 与 Embedding
python
from langchain_community.llms.tongyi import Tongyi
from langchain_community.embeddings import DashScopeEmbeddings
# 裁判 LLM:通义千问 qwen-plus
llm = Tongyi(model_name="qwen-plus")
# 向量模型:DashScope text-embedding-v3
embeddings = DashScopeEmbeddings(model="text-embedding-v3")
选型说明:
| 组件 | 选型 | 理由 |
|---|---|---|
| 裁判 LLM | qwen-plus | 语义理解能力强,性价比高 |
| 向量模型 | text-embedding-v3 | DashScope 最新向量模型,中文语义表征好 |
步骤 3:执行评估
python
from datasets import Dataset
from ragas import evaluate
from ragas.metrics import answer_correctness
# 构建评估数据集
dataset = Dataset.from_dict(data_samples)
# 执行评估
score = evaluate(
dataset=dataset,
metrics=[answer_correctness],
llm=llm,
embeddings=embeddings
)
# 输出评估结果
print(score.to_pandas())
answer_correctness 的计算原理:

- 语义 F1 分数(权重 75%):LLM 将答案分解为原子陈述,对比 TP/FP/FN
- 向量相似度(权重 25%):通过 Embedding 余弦相似度衡量整体语义接近度
步骤 4:检索质量评估(扩展)
当评估数据包含 contexts(检索到的文档片段)时,可以进一步评估检索质量:
python
from ragas.metrics import context_recall, context_precision
data_samples_with_context = {
'question': [...],
'answer': [...],
'ground_truth': [...],
'contexts': [
['西湖是杭州的核心景区...', '灵隐寺是中国著名的佛教古刹...', '千岛湖以湖泊和岛屿景观著称...'],
['成都被誉为"美食之都"...', '串串香起源于四川街头...', '担担面是川菜经典面食...'],
['秦始皇兵马俑位于陕西省...', '兵马俑博物馆实行实名制预约购票制度...', '旺季参观需至少提前3天预约...']
]
}
score = evaluate(
dataset=Dataset.from_dict(data_samples_with_context),
metrics=[context_recall, context_precision],
llm=Tongyi(model_name="qwen-plus"),
embeddings=DashScopeEmbeddings(model="text-embedding-v3")
)
检索指标说明:
| 指标 | 含义 | 计算方式 |
|---|---|---|
context_recall |
检索覆盖度 | 标准答案中的陈述有多少被检索文档覆盖 |
context_precision |
检索精确度 | 检索到的文档中有多少真正与问题相关 |
五、评估结果分析
评估结果

结果分析:
| 问题 | 预期分数区间 | 分析 |
|---|---|---|
| 杭州景点 | 0.6~0.8 | 答案覆盖了部分景点,但遗漏了雷峰塔、宋城 |
| 成都美食 | 0.7~0.9 | 答案基本正确,但遗漏了龙抄手、钟水饺等 |
| 兵马俑预约 | 0.3~0.5 | 答案事实错误(说不需要预约),与标准答案矛盾 |
关键发现: 第 3 个问题的 answer 声称"不需要预约",而 ground_truth 明确指出"必须提前预约"。answer_correctness 会对这种事实性错误给予严厉扣分。
六、核心技术点总结
| 技术点 | 实现方式 | 作用 |
|---|---|---|
| LLM 裁判 | qwen-plus 判断语义正确性 | 替代人工评估,实现自动化 |
| Embedding 相似度 | text-embedding-v3 向量对比 | 补充语义层面的整体相似度衡量 |
| 原子陈述分解 | LLM 将答案拆解为独立事实 | 精确计算 TP/FP/FN |
| F1 + 相似度加权 | 75% F1 + 25% 向量相似度 | 兼顾事实准确性和整体语义 |
| HuggingFace Datasets | Dataset.from_dict 构建数据 | 标准化数据格式,便于批量评估 |
| 检索质量评估 | context_recall + context_precision | 分离评估生成和检索两个环节 |
七、延伸思考
- 更多评估指标:Ragas 还支持 faithfulness(忠实度)、answer_relevancy(答案相关性)等指标,可全面评估 RAG 系统
- 批量评估:将评估数据集扩大到数百条,统计各指标的平均分和分布
- 自定义指标:基于 Ragas 的 Metric API 实现领域特定的评估标准
- 对比实验:对比不同 LLM(qwen-plus vs qwen-max)作为裁判的评分差异
- 检索优化闭环:通过 context_recall 定位检索不足的 case,针对性补充知识库文档
- CI/CD 集成:将 Ragas 评估集成到 RAG 系统的持续集成流程中,每次更新自动回归测试