promptfoo评测需求上线发布摘要功能评估
promptfoo评测需求上线发布摘要功能评估
LLM质量评估:常用方法&指标选择
评估场景:
会议记录:
研发最初建议周五全量发布,测试指出租户隔离和任务重试重复产生文件两项问题尚未复测通过。会议最终取消周五全量发布,改为5%灰度方案。赵宁负责在周四17点前复测这两项问题;两项复测都通过且运维负责人确认后,才允许灰度。页面配色与文件名调整已完成,不影响本次发布判断。容量评估尚未完成,不能向用户承诺一分钟内导出。
reference: 取消周五全量发布,改为5%灰度。赵宁须周四17点前复测租户隔离和重试重复文件,两项通过且运维确认后才可灰度。容量评估未完成,不得承诺一分钟内导出
目的:
依据发布评审记录,生成供项目负责人安排复测、决定灰度并统一对外口径的摘要
对摘要内容进行评估,最好的一份发给项目负责人,待评估摘要内容为:cases_methods.yaml
一、常用评估方法与指标
** **1.1 质量要求与评估方法
*Bleu* *字词匹配评分**,**适合看字面相似度,不能单独判断事实正确性或语义是否反转**,**BLEU从候选中的片段出发,看有多少能匹配参考。*
*ROUGE-N* *片段重合评分**,**ROUGE-N关注参考中的片段保留了多少,常用于摘要评价*
*Similar* *语义相似度比较**,**语义相似度比较含义。同一个嵌入模型**【**作用就是把文本转换为数字(向量)**】**先把两段话各变成一串数字(向量),再计算他们接近程度**,常用方法:余弦相似度*
*当被测内容存在一部分和参考一致,一部分不一致时,统一做项量相似度后和阈值进行比较,不会单独对不一致的部分进行相似度处理,主要依赖阈值,可以结合*
*factuality:参考事实一致性检查**,做实时一致性检查*
●余弦相似度(Cosine Similarity):把向量看成两根箭头,方向越接近,分数越高,理论范围为-1到1。【简单理解: 只看方向不看距离】
●点积(Dot Product):将对应位置的数相乘后求和,受方向和向量长度共同影响。
●欧氏距离(Euclidean Distance):把向量看成坐标,计算两点间的直线距离,距离越小越接近。【简单理解: 又看方向又看距离】
*Factuality* *参考事实一致性检查**,**文本可以很接近,却在一个条件上出现分歧。例如,参考写“两项通过且运维确认后才可灰度”,候选写“两项未通过且运维未确认也可灰度”。这次需要直接判断两者的事实关系。*
*当被测内容信息缺失时,仅关注当前描述的内容和事实是否一致,并不关注缺失了内容,可以结合* *BLEU:字词匹配评分* *和* *ROUGE-N:片段重合评分**使用,来评测内容是否在参考中找到(BLEU)和**参考中的片段保留了多少**(**ROUGE-N**)*
*factuality让裁判读取候选与参考,选择一种关系,再将关系映射成分数。*
*默认计分如下:*
| *关系* | *怎样理解* | *默认分数* |
|---|---|---|
| 正确子集(Subset) | 候选写得较少,已写事实与参考一致 | 1 |
| 正确超集(Superset) | 候选写得较多,新增内容也保持事实一致 | 1 |
| 事实相同(Agree) | 两者包含相同事实,可以改变措辞 | 1 |
| 不一致(Disagree) | 两者存在事实分歧 | 0 |
| 差异不影响事实性(Differ but factual) | 内容有差别,但不影响事实一致性 | 1 |
*model-graded-closedqa* *任务要求核对**,**参考事实一致性检查两段文本的关系,任务要求核对则直接列出摘要必须做到什么。本任务需要四组信息:*
*发布安排、责任人与复测时限、灰度启动条件、容量与对外承诺限制。*
*model-graded-closedqa让裁判按给定条件判断候选是否满足要求。全部满足得1,违反任意要求得0。这种方式适合将明确的业务要求写成检查清单。*
*G-**Eval* *表达质量评分*
*同样是不合格,有的摘要条件写错,有的只是重复啰嗦。为了给出具体的改进方向,可以把事实、信息完整性与表达分别评价。这一组用G-Eval评价表达。*
*Eval先根据评价标准组织具体检查步骤,再按步骤评价候选。评价维度由标准决定*
| *表达情况* | *分数* |
|---|---|
| 主体、动作、条件关系清楚,且无内部整段重复 | 1 |
| 关系可辨认,但有内部整段重复或需重排的碎片 | 0.5 |
| 无法辨认关系 | 0 |
*按这份标准,检查可以依次进行:读出主体、动作和条件关系,找出候选内部是否重复,再对照档位给分。*
*context-faithfulness* *来源忠实度检查*
*参考摘要是一份正确写法,原始记录才是事实来源。来源忠实度直接核对候选已经写出的内容,有多少得到原始记录支持。**
***它包含三个步骤:从候选中提取可核实的声明,逐条判断原文是否支持,再计算支持声明所占的比例。*
二、对照用例设计与准备
2.1 固定答卷与评价依据
原始记录、四组必要信息和表达锚点。
| *编号* | *答卷有什么特点* | *人工判断* | *测试点* |
|---|---|---|---|
| M01 | 完整正确,也是本次参考文本 | 合格 | 正确对照能否被接受 |
| M02 | 信息完整,使用“百分之五”“下午五点”等改写 | 合格 | 写法变化会不会被误拒 |
| M03 | 把灰度前提改为未通过、未确认也能执行 | 不合格 | 关键条件错误能否检出 |
| M04 | 只保留方案与复测安排 | 不合格 | 已与事实与缺失信息怎样分别判断 |
| M05 | 完整摘要重复两遍 | 不合格 | 信息完整、重复表达和超长怎样区分 |
| M06 | 把5%改成50% | 不合格 | 文字只差一点,业务含义却变了 |
| M07 | 只写配色与文件名已经调整 | 不合格 | 有来源的话,是否仍然可能没有完成任务 |
5% 改 50% 用来比较不同方法对比例错误的检出情况。
每条用例填写case_id和candidate,其余三个字段放在共用文件中。
| *字段* | *内容* |
|---|---|
| case_id | 用例编号 |
| candidate | 待评分的摘要,M01—M07各自不同 |
| query | 原来的摘要要求,包括用途和140字限制 |
| context | 发布评审的原始记录,提供事实来源 |
| reference | 一份完整正确的摘要,固定用M01 |
cases_methods.yaml
- description: M01 完整正确
vars:
case_id: M01
candidate: 取消周五全量发布,改为5%灰度。赵宁须周四17点前复测租户隔离和重试重复文件,两项通过且运维确认后才可灰度。容量评估未完成,不得承诺一分钟内导出。
- description: M02 同义改写
vars:
case_id: M02
candidate: 周五不再全量上线,先采用百分之五的灰度方案。租户隔离及重试产生重复文件由赵宁于周四下午五点前复验;全部通过并获运维批准才启动。容量尚待评估,不能保证导出在一分钟内结束。
- description: M03 条件反转
vars:
case_id: M03
candidate: 取消周五全量发布,改为5%灰度。赵宁须周四17点前复测租户隔离和重试重复文件,两项未通过且运维未确认也可灰度。容量评估未完成,不得承诺一分钟内导出。
- description: M04 遗漏后两组
vars:
case_id: M04
candidate: 取消周五全量发布,改为5%灰度。赵宁须周四17点前复测租户隔离和重试重复文件。
- description: M05 全文重复
vars:
case_id: M05
candidate: 取消周五全量发布,改为5%灰度。赵宁须周四17点前复测租户隔离和重试重复文件,两项通过且运维确认后才可灰度。容量评估未完成,不得承诺一分钟内导出。取消周五全量发布,改为5%灰度。赵宁须周四17点前复测租户隔离和重试重复文件,两项通过且运维确认后才可灰度。容量评估未完成,不得承诺一分钟内导出。
# 新用例,把比例改为50%;此处与不同评价方法交叉比较。
- description: M06 比例改错
vars:
case_id: M06
candidate: 取消周五全量发布,改为50%灰度。赵宁须周四17点前复测租户隔离和重试重复文件,两项通过且运维确认后才可灰度。容量评估未完成,不得承诺一分钟内导出。
# 新用例,只保留来源里真实的配色与文件名;检查“有依据”与“完成任务”的区别。
- description: M07 真实但偏离用途
vars:
case_id: M07
candidate: 页面配色与文件名调整已完成,不影响本次发布判断。
vars_summary.yaml
query: 请依据发布评审记录,生成供项目负责人安排复测、决定灰度并统一对外口径的摘要,不超过140字。
context: 研发最初建议周五全量发布,测试指出租户隔离和任务重试重复产生文件两项问题尚未复测通过。会议最终取消周五全量发布,改为5%灰度方案。赵宁负责在周四17点前复测这两项问题;两项复测都通过且运维负责人确认后,才允许灰度。页面配色与文件名调整已完成,不影响本次发布判断。容量评估尚未完成,不能向用户承诺一分钟内导出。
reference: 取消周五全量发布,改为5%灰度。赵宁须周四17点前复测租户隔离和重试重复文件,两项通过且运维确认后才可灰度。容量评估未完成,不得承诺一分钟内导出。
说明:
· query:测试输入,也就是“要处理的问题/指令”。这里它承载“请依据发布评审记录生成摘要”的任务描述,会注入到 prompt 模板中,驱动模型生成候选摘要。14
· context:背景材料,即模型生成摘要时依赖的原始信息。这里它是发布评审记录正文,相当于 RAG 里的参考资料,用来约束模型只能基于这些事实生成摘要。
· reference:参考答案/黄金答案,用于断言比对。这里它是人工写好的标准摘要,BLEU 断言会把模型输出与它按字切分后计算相似度,判断是否达标。
2.2 各方法的预期结果
BLEU、ROUGE-N****【**两个配合着看,惩罚丢掉的和奖励召回的,机械的对字面的评估;配合使用关注:不要重复,同时不要丢内容,**两个都是promptfoo内置的不需要调用大模型*****】*
●重点答卷:M01、M02、M03、M06,再看M04、M05
●预期结果:
○M01与参考相同,应得最高分
○M02换了写法,分数可能下降
○M03、M06只改少量文字,可能仍得高分
○如果错误答卷高于正确改写,词面分就不能直接用来判断合格
****similar****语义相似度
●重点答卷:M02、M03、M06
●预期结果:
○M02是正确改写,应与参考接近
○M03、M06保留了大部分内容,也可能得高分
○如果M03或M06高于M02,就无法用一条及格线同时接受正确改写、拒绝这两份错误答卷
****factuality****参考事实一致性
●重点答卷:M03、M06,再看M04、M05、M07
●预期结果:
○M03、M06有事实冲突,应拒绝。
○M04遗漏、M05重复,不改变已写事实,应与事实冲突区分
○M07写的事来自原文,但没有进入参考摘要,要看裁判把它归入哪种关系
****model-graded-closedqa****任务要求核对
●重点答卷:全部七份。
●预期结果:
○M01、M02满足全部要求,应通过
○其余五份分别违反任务条件,应拒绝
G-Eval****表达质量评分****
●重点答卷:M05及其他六份
●预期结果:
○M05整段重复,应得0.5
○其他六份按表达应得1
○事实错误和遗漏另算,不扣表达分
****context-faithfulness****来源忠实度
●重点答卷:M01、M03、M06、M07
●预期结果:
○M01、M07的已写声明都有原文支持,应得1
○M03、M06至少有一条声明不受原文支持,应低于1
○M07是否完成任务,由任务要求核对来判断
词面分数和相似度以0.8作比较线,表达和来源忠实度要求达到1。
2.3 环境与模型连接
增加一个嵌入模型来进行向量化和相似度计算
provider_deepseek.yaml
id: deepseek:deepseek-flash
config:
apiBaseUrl: ‘{{ env.OPENAI_BASE_URL }}’
apiKey: ‘{{ env.OPENAI_API_KEY }}’
showThinking: false
max_tokens: 4000
passthrough:
thinking:
type: disabled
maxRetries: 0
provider_embedding.yaml
id: openai:embedding:BAAI/bge-m3
config:
apiBaseUrl: https://api.siliconflow.cn/v1
apiKey: ‘{{ env.SILICONFLOW_API_KEY }}’
maxRetries: 0
这里使用硅基流动的免费提供 BAAI/bge-m3 进行嵌入,需要自行注册账号: https://cloud.siliconflow.cn/i/zUk3OnVJ
注册后把APIKEY 写入到.env文件中
SILICONFLOW_API_KEY=sk-xxxxxxxxxxxxxxxxxx
说明:
| *位置* | *模板* | *实际数据来源* |
|---|---|---|
| prompts | {{ candidate | list | join(" ") }} | candidate 来自 cases_methods.yaml 里每个用例的 vars.candidate |
| assert.value | {{ reference | list | join(" ") }} | reference 来自 vars_summary.yaml,由 defaultTest.vars.$ref 注入 |
关键区别
prompts 里的 candidate:它不是 reference,而是“模型生成的答卷”。因为这里 provider 是 echo,所以 candidate 实际上就是 cases_methods.yaml 里预先写好的固定文本,相当于模拟模型输出。
assert.value 里的 reference:它才是“参考答案”,来自 vars_summary.yaml,通过 defaultTest.vars.$ref 合并到每个用例的变量中。2
整体流程
cases_methods.yaml 提供多条用例,每条用例有自己的 candidate(固定答卷)。
vars_summary.yaml 提供公共变量 reference(参考摘要)。
每个用例运行时,prompts 模板把 candidate 拆字加空格,作为 prompt 传给 echo。
echo 原样返回 candidate,作为模型输出。
assert 把输出与 reference(同样拆字加空格)做 BLEU 比对,判断是否 ≥ 0.8。
所以准确说法是:prompts 切分的是 cases_methods.yaml 里的 candidate,assert.value 切分的是 vars_summary.yaml 里的 reference。
三、执行方法对照与评价器验证
3.1 BLEU:字词匹配评分**,***BLEU 适合看字面相似度,不能单独判断事实正确性或语义是否反转。*
BLEU最早用于机器翻译评价,基本做法是把候选拆成连续片段,统计其中有多少能在参考中找到。
这些片段叫n-gram。N=1是一元片段,N=2是连续两个单位组成的二元片段。:
●一元片段:“5”“%”“灰”“度”。
●二元片段:“5%”“%灰”“灰度”。
●三元片段:“5%灰”“%灰度”。
●四元片段:“5%灰度”。
候选写成“50%灰度”时,二元片段变成“50”“0%”“%灰”“灰度”。四个中有两个能在参考里找到,二元匹配率就是2÷4=0.5。片段越长,对连续写法的要求越高。
计算匹配数时,还要限制重复计数:参考里的某个片段只出现一次,候选写两次也最多算一次匹配。这样,重复参考内容不会增加有效匹配数。
下面用完整的M06演示计算。参考摘要有73个字,M06在“5%”中多写了一个“0”,共有74个字。一至四元片段的计数如下:

本次对这四项采用等权几何平均,即把四项匹配率相乘,再开四次方,得到约0.9651。如果候选比参考更短,还会乘上小于1的长度惩罚系数;M06不短于参考,长度系数为1。
因此,BLEU综合了不同长度片段的匹配情况,并考虑候选是否过短。它提供的是候选与参考的词面匹配分数。
promptfooconfig_04_01_bleu.yaml
# 新增BLEU断言,固定答卷仍交给echo返回。
description: 04 bleu 固定答卷方法对照
prompts:
# list拆成字符,join用空格连接,例如“灰度”变成“灰 度”。
- ‘{{ candidate | list | join(" ") }}’
providers:
- echo
tests: file://cases_methods.yaml
defaultTest:
vars:
$ref: ./vars_summary.yaml # 所有答卷共用任务、原文和参考摘要
assert:
- type: bleu
metric: BLEU
# 参考摘要也按字切分,与候选使用相同的单位。
value: ‘{{ reference | list | join(" ") }}’
threshold: 0.8 # 本次方法对照的比较线
evaluateOptions:
maxConcurrency: 1
outputPath:
- results/bleu.json
- results/bleu.html
说****明:
$ref: ./vars_summary.yaml把 vars_summary.yaml 里的变量合并进 defaultTest.vars,让所有测试用例都能共用同一组变量。
具体来说,vars_summary.yaml 里写了:
query: …
context: …
reference: …
配置里写:
defaultTest:
vars:
$ref: ./vars_summary.yaml
运行时,Promptfoo 会把这个 $ref 展开,等价于:
defaultTest:
vars:
query: …
context: …
reference: …
不是“单独加载文件”,而是变量注入/合并
放在你这个 BLEU 对照实验里,效果就是:
cases_methods.yaml 负责提供每个用例各自的 candidate;
vars_summary.yaml 负责提供所有用例共用的 reference、query、context;
defaultTest.vars.$ref 负责把公共变量自动挂到每个用例上,避免重复写。
可以把它理解成:公共变量池的外部引用。
promptfoo eval -c promptfooconfig_04_01_bleu.yaml
3.2 ROUGE-N:片段重合评分
BLEU从候选中的片段出发,看有多少能匹配参考。ROUGE-N关注参考中的片段保留了多少,常用于摘要评价。N表示连续片段的长度,取N=1,按单字统计。
它涉及三个容易手算的量:
●精确率:重合片段数÷候选片段数。
●召回率:重合片段数÷参考片段数。
●F1:2×精确率×召回率÷(精确率+召回率)。
拿M05演示。参考有73个一元片段,M05将其重复两遍,共146个。参考中的73个都被保留,多写的一遍不增加匹配数:
| *计算项* | *计算过程* | *数值* |
|---|---|---|
| 精确率 | 73 ÷ 146 | 0.5 |
| 召回率 | 73 ÷ 73 | 1 |
| F1 | 2 × 0.5 × 1 ÷ (0.5 + 1) | 约 0.6667 |
召回率1表示参考片段全部保留;F1还考虑候选中多出的内容。报告给出F1,因此读分时要同时理解候选与参考这两个分母。
与BLEU比较时,BLEU综合多个长度的片段匹配率,本组ROUGE-N则计算一元片段的精确率、召回率和F1。两种计算方式会产生怎样的差别,下节用同一批答卷的结果比较
promptfooconfig_04_02_rouge.yaml
# 沿用BLEU的数据和分字方式,只把断言换成ROUGE-N。
description: 04 rouge-n 固定答卷方法对照
prompts:
- ‘{{ candidate | list | join(" ") }}’
providers:
- echo
tests: file://cases_methods.yaml
defaultTest:
vars:
$ref: ./vars_summary.yaml
assert:
- type: rouge-n
metric: ROUGE-N
value: ‘{{ reference | list | join(" ") }}’
threshold: 0.8
evaluateOptions:
maxConcurrency: 1
outputPath:
- results/rouge.json
- results/rouge.html
promptfoo eval -c promptfooconfig_04_02_rouge.yaml
说明:
- type: rouge-n(片段重合评分) 和 - type: bleu(字词匹配评分)两个断言可以理解为:同一套“字级 n-gram 重叠度”评测方法,只是统计方向不同
共同点
· 都基于 n-gram 字面重叠,不看语义。
· 都会把 candidate 和 reference 拆成字,再比较连续片段是否一致。
· 分数越高,说明候选文本和参考摘要越接近。
· 都不能判断“意思对不对”“事实是否反转”。
主要区别
| *维度* | *type: bleu* | *type: rouge-n* |
|---|---|---|
| 统计方向 | 偏 Precision | 偏 Recall |
| 关注点 | 候选文本里写的内容,有多少和参考一致 | 参考答案里的内容,有多少被候选覆盖 |
| 分母 | 主要看候选文本的 n-gram 数量 | 主要看参考文本的 n-gram 数量 |
| 适用场景 | 更常用于机器翻译、固定表达比对 | 更常用于摘要、要点覆盖度评估 |
| 对同义改写 | 容易扣分 | 也容易扣分,但更看重“有没有漏掉参考要点” |
放到你这个配置里看
BLEU ≥ 0.8:更偏向要求候选文本“写得准、接近参考表达”。
ROUGE-N ≥ 0.8:更偏向要求候选文本“把参考摘要里的要点都覆盖到”。
所以如果你评测的是发布评审摘要,
ROUGE-N 通常更贴合“有没有漏掉关键信息”;
BLEU 则更贴合“表达是否足够接近标准口径”。
实际做提示词回归或工作流评测时,两个一起看会更稳:
BLEU 看口径一致性,ROUGE-N 看要点完整度。
可以理解为:
vars_summary.yaml 里的 query 和 context 是用法发送大模型的消息;
cases_methods.yaml 里的 candidate 模拟大模型的不同回复
vars_summary.yaml 里的 reference 为期望结果
promptfooconfig_04_01_bleu.yaml 把 cases_methods.yaml 里的 candidate 模拟大模型的不同回复 和 vars_summary.yaml 里的 reference 期望结果 进行做字级 BLEU 比较,用来对照不同答卷在指标下的表现。
3.3 similar:语义相似度比较
语义相似度比较含义。同一个嵌入模型【作用就是把文本转换为数字(向量)】先把两段话各变成一串数字(向量),再计算他们接近程度。“5%灰度”和“百分之五灰度”换了写法的意思一样,也可能得到高分。
*当被测内容存在一部分和参考一致,一部分不一致时,统一做项量相似度后和阈值进行比较,不会单独对不一致的部分进行相似度处理,主要依赖阈值,可以结合*
*factuality:参考事实一致性检查**,做实时一致性检查*
常用计算方式有:
●余弦相似度(Cosine Similarity):把向量看成两根箭头,方向越接近,分数越高,理论范围为-1到1。【简单理解: 只看方向不看距离】
●点积(Dot Product):将对应位置的数相乘后求和,受方向和向量长度共同影响。
●欧氏距离(Euclidean Distance):把向量看成坐标,计算两点间的直线距离,距离越小越接近。【简单理解: 又看方向又看距离】

采用余弦相似度。0.9表示向量接近程度,不代表90%的事实正确。
promptfooconfig_04_03_similar.yaml
# 改用原始中文;similar通过嵌入模型比较语义。
description: 04 similar 固定答卷方法对照
prompts:
- ‘{{ candidate }}’
providers:
- echo
tests: file://cases_methods.yaml
defaultTest:
vars:
$ref: ./vars_summary.yaml
assert:
- type: similar
metric: 余弦相似度
value: ‘{{ reference }}’
threshold: 0.8
provider: file://provider_embedding.yaml # 返回文本向量的嵌入模型
evaluateOptions:
maxConcurrency: 1
outputPath:
- results/similar.json
- results/similar.html
3.4 factuality:参考事实一致性检查
**
**文本可以很接近,却在一个条件上出现分歧。例如,参考写“两项通过且运维确认后才可灰度”,候选写“两项未通过且运维未确认也可灰度”。这次需要直接判断两者的事实关系。
*当被测内容信息缺失时,仅关注当前描述的内容和事实是否一致,并不关注缺失了内容,可以结合* *BLEU:字词匹配评分* *和* *ROUGE-N:片段重合评分**使用,来评测内容是否在参考中找到(BLEU)和**参考中的片段保留了多少**(**ROUGE-N**)*
factuality让裁判读取候选与参考,选择一种关系,再将关系映射成分数。默认计分如下:
| *关系* | *怎样理解* | *默认分数* |
|---|---|---|
| 正确子集(Subset) | 候选写得较少,已写事实与参考一致 | 1 |
| 正确超集(Superset) | 候选写得较多,新增内容也保持事实一致 | 1 |
| 事实相同(Agree) | 两者包含相同事实,可以改变措辞 | 1 |
| 不一致(Disagree) | 两者存在事实分歧 | 0 |
| 差异不影响事实性(Differ but factual) | 内容有差别,但不影响事实一致性 | 1 |
拿M04人工判断一次:它保留发布方案、责任人与复测时限,省略灰度启动条件和容量限制,属于正确子集,按表得1。M03把灰度前提反转,属于不一致,按表得0。这里先判断关系,再查表计分。 从这一组开始,DeepSeek参与评价固定答卷。同时提供真实任务与原始记录,并把参考摘要放在比较位置。echo先原样返回提示内容,transform将待评价输出换成候选摘要,裁判据此评价候选与参考。** **** **promptfooconfig_04_04_factuality.yaml
# 新增参考事实一致性检查,问题、原文、候选和参考各有自己的位置。
description: 04 factuality 固定答卷方法对照
prompts:
# 让裁判读到真实任务和原文;echo先原样返回这段提示。
- '{{ query }}
发布评审记录:{{ context }}’
providers:
- echo
tests: file://cases_methods.yaml
defaultTest:
vars:
$ref: ./vars_summary.yaml
options:
# 将echo返回的提示换成固定答卷,再评分。
transform: context.vars.candidate
provider: file://provider_deepseek.yaml
assert:
- type: factuality
metric: 参考事实关系
provider: file://provider_deepseek.yaml
# 用这份参考摘要与candidate比较事实关系。
value: ‘{{ reference }}’
evaluateOptions:
maxConcurrency: 1
outputPath:
- results/factuality.json
- results/factuality.html
不在模拟返回,使用真实的大模型promptfooconfig_04_04_01**_factuality.yaml**
# 新增参考事实一致性检查,问题、原文、候选和参考各有自己的位置。
description: 04 factuality 固定答卷方法对照
#prompts:
## 让裁判读到真实任务和原文;echo先原样返回这段提示。
#- ‘{{ query }}
#
# 发布评审记录:{{ context }}’
prompts:
- |
# 角色
你是一名专业的评审记录分析助手。请根据发布评审记录评估摘要信息是否准确,不要编造信息。
# 输入信息
## 发布评审记录
{{ context }}
## 摘要信息
{{ candidate }}
# 要求
\1. 严格基于评审记录的内容回答,不要编造信息。
\2. 直接给出答案。
\3. 如果记录中未提及相关信息,请明确回答“记录中未提及”。
providers:
- id: openai:chat:{{ env.OPENAI_MODEL }}
config:
apiBaseUrl: ‘{{ env.OPENAI_BASE_URL }}’
apiKey: ‘{{ env.OPENAI_API_KEY }}’
showThinking: false
max_tokens: 4000
passthrough:
thinking: { type: disabled }
tests: file://cases_methods.yaml
defaultTest:
vars:
$ref: ./vars_summary.yaml
options:
# 将echo返回的提示换成固定答卷,再评分。
# transform: context.vars.candidate
provider: file://provider_deepseek.yaml
assert:
- type: factuality
metric: 参考事实关系
provider: file://provider_deepseek.yaml
# 用这份参考摘要与candidate比较事实关系。
value: ‘裁判依据为{{ reference }}’
evaluateOptions:
maxConcurrency: 4
outputPath:
- results/factuality.json
- results/factuality.html
✔⚠****可以理解为:
被测模型根据根据发布评审记录{{ context }} 评估摘要信息{{ candidate }}是否准确,
对用例cases_methods.yaml中candidate 进行回答,返回模型的output,
裁判模型对被测模型返回结果进行裁判 输出结果中query 问题 context 原始内容 reference 预期结果 case_id 用例编号 candidate 用例内容 Output模型输出
transform: context.vars.candidate 是把发送模型进行评判的内容,替换为上下文保存的 candidate变量的内容(用例里的 candidate)
promptfoo运行时,{{ context }} {{ candidate }} cases_methods.yaml 里的变量candidate、vars_summary.yaml里的变量都会加载到模型上下文的context中
context 和 {{ context }} 意义不同,context是上下文的context;{{ context }}为定义的变量
promptfoo eval -c promptfooconfig_04_04_factuality.yaml
本次M03、M06因条件、比例错误得0,M04、M05得1。M07也得0,但裁判的理由是遗漏发布要点,并未指出与原文的事实冲突。
3.5 model-graded-closedqa:任务要求核对
参考事实一致性检查两段文本的关系,任务要求核对则直接列出摘要必须做到什么。本任务需要四组信息:发布安排、责任人与复测时限、灰度启动条件、容量与对外承诺限制。
model-graded-closedqa让裁判按给定条件判断候选是否满足要求。全部满足得1,违反任意要求得0。这种方式适合将明确的业务要求写成检查清单。
用M04逐条核一次:发布安排有,责任人与复测时限有,灰度启动条件没有,容量限制也没有。按“全部满足”的规则,人工预期就是0。这个判断过程与前一项将它归为正确子集的过程不同。
promptfooconfig_04_05_closedqa.yaml
# 沿用上一组任务、原文和候选,改查是否满足全部业务条件。
description: 04 model-graded-closedqa 固定答卷方法对照
prompts:
- '{{ query }}
发布评审记录:{{ context }}’
providers:
- echo
tests: file://cases_methods.yaml
defaultTest:
vars:
$ref: ./vars_summary.yaml
options:
transform: context.vars.candidate
provider: file://provider_deepseek.yaml
assert:
- type: model-graded-closedqa
metric: 任务要求判定
provider: file://provider_deepseek.yaml
# 以下条件必须同时满足,才判整题通过。
value: 候选必须完整正确包含:取消周五全量发布并改为5%灰度;赵宁周四17点前复测租户隔离和重试重复文件;两项通过且运维确认后才可灰度;容量未完成不得承诺一分钟导出。还要求无内部整段重复且不超过140字。
evaluateOptions:
maxConcurrency: 1
outputPath:
- results/closedqa.json
- results/closedqa.html
评测使用具体的模型 promptfooconfig_04_05**_01****_closedqa.yaml**
description: 04 model-graded-closedqa 固定答卷方法对照
prompts:
- |
# 角色
你是一名专业的评审记录分析助手。请根据发布评审记录评审摘要信息,不要编造信息。
# 输入信息
## 发布评审记录
{{ context }}
## 摘要信息
{{ candidate }}
# 判定标准
\1. 语义一致:candidate 表达的含义与 context 不冲突。
\2. 信息没有遗漏:context 中的关键评审信息在 candidate 中有体现。
\3. 若 candidate 与 context 完全相同,视为语义一致且信息无遗漏,应判定“通过”。
\4. 不要求 candidate 必须比 context 简短、改写或提炼;允许完整复制。
\5. 只有出现以下情况才判“不通过”:
- candidate 与 context 语义冲突;
- candidate 缺失 context 中的关键信息;
- candidate 包含 context 中没有的信息;
- candidate 违反明确的格式/长度要求。
# 输出格式
结论:通过/不通过
理由:
信息覆盖比对:
providers:
- id: openai:chat:{{ env.OPENAI_MODEL }}
config:
apiBaseUrl: ‘{{ env.OPENAI_BASE_URL }}’
apiKey: ‘{{ env.OPENAI_API_KEY }}’
showThinking: false
max_tokens: 4000
passthrough:
thinking: { type: disabled }
tests: file://cases_methods.yaml
defaultTest:
vars:
$ref: ./vars_summary.yaml
options:
#transform: context.vars.candidate
provider: file://provider_deepseek.yaml
assert:
- type: model-graded-closedqa
metric: 任务要求判定
provider: file://provider_deepseek.yaml
value: 候选必须完整正确包含:取消周五全量发布并改为5%灰度;赵宁周四17点前复测租户隔离和重试重复文件;两项通过且运维确认后才可灰度;容量未完成不得承诺一分钟导出。还要求无内部整段重复且不超过140字。以上条件必须同时满足,才判整题通过;输出格式要求reason这里填写中文的评分理由,详细指出得分或扣分的原因…。
evaluateOptions:
maxConcurrency: 5
outputPath:
- results/closedqa.json
- results/closedqa.html
✔⚠评判使用具体模型,提示词通过文件读取promptfooconfig_04_05**_02****_closedqa.yaml**
description: 04 model-graded-closedqa 固定答卷方法对照
prompts:
file://prompt-04.json
providers:
- id: openai:chat:{{ env.OPENAI_MODEL }}
config:
apiBaseUrl: ‘{{ env.OPENAI_BASE_URL }}’
apiKey: ‘{{ env.OPENAI_API_KEY }}’
showThinking: false
max_tokens: 4000
passthrough:
thinking: { type: disabled }
tests: file://cases_methods.yaml
defaultTest:
vars:
$ref: ./vars_summary.yaml
options:
#transform: context.vars.candidate
provider: file://provider_deepseek.yaml
assert:
- type: model-graded-closedqa
metric: 任务要求判定
provider: file://provider_deepseek.yaml
value: 候选必须完整正确包含:取消周五全量发布并改为5%灰度;赵宁周四17点前复测租户隔离和重试重复文件;两项通过且运维确认后才可灰度;容量未完成不得承诺一分钟导出。还要求无内部整段重复且不超过140字。以上条件必须同时满足,才判整题通过;输出格式要求reason这里填写中文的评分理由,详细指出得分或扣分的原因…。
evaluateOptions:
maxConcurrency: 5
outputPath:
- results/closedqa.json
- results/closedqa.html
prompt-04.json
[
{
“role”: “system”,
“content”: “你是一名专业的评审记录分析助手。请根据发布评审记录评审摘要信息,不要编造信息。发布评审记录: {{ context }},摘要信息: {{ candidate }}。判定标准:语义一致:candidate 表达的含义与 context 不冲突。信息没有遗漏:context 中的关键评审信息在 candidate 中有体现。若 candidate 与 context 完全相同,视为语义一致且信息无遗漏,应判定“通过”。不要求 candidate 必须比 context 简短、改写或提炼;允许完整复制。只有出现以下情况才判“不通过”:candidate 与 context 语义冲突;candidate 缺失 context 中的关键信息;candidate 包含 context 中没有的信息;candidate 违反明确的格式/长度要求。输出格式:用中文输出,只输出一个 JSON 对象,不要输出 Markdown 代码块,不要输出 JSON 以外的任何文字。结论:通过或不通过。理由:简要说明判定理由”
},
{
“role”: “user”,
“content”: “【发布评审记录 context】\n{{context}}\n\n【摘要 candidate】\n{{candidate}}”
}
]
cases_methods.yaml
- description: M01 完整正确
vars:
case_id: M01
candidate: 取消周五全量发布,改为5%灰度。赵宁须周四17点前复测租户隔离和重试重复文件,两项通过且运维确认后才可灰度。容量评估未完成,不得承诺一分钟内导出。
- description: M02 同义改写
vars:
case_id: M02
candidate: 周五不再全量上线,先采用百分之五的灰度方案。租户隔离及重试产生重复文件由赵宁于周四下午五点前复验;全部通过并获运维批准才启动。容量尚待评估,不能保证导出在一分钟内结束。
- description: M03 条件反转
vars:
case_id: M03
candidate: 取消周五全量发布,改为5%灰度。赵宁须周四17点前复测租户隔离和重试重复文件,两项未通过且运维未确认也可灰度。容量评估未完成,不得承诺一分钟内导出。
- description: M04 遗漏后两组
vars:
case_id: M04
candidate: 取消周五全量发布,改为5%灰度。赵宁须周四17点前复测租户隔离和重试重复文件。
- description: M05 全文重复
vars:
case_id: M05
candidate: 取消周五全量发布,改为5%灰度。赵宁须周四17点前复测租户隔离和重试重复文件,两项通过且运维确认后才可灰度。容量评估未完成,不得承诺一分钟内导出。取消周五全量发布,改为5%灰度。赵宁须周四17点前复测租户隔离和重试重复文件,两项通过且运维确认后才可灰度。容量评估未完成,不得承诺一分钟内导出。
# 新用例,把比例改为50%
- description: M06 比例改错
vars:
case_id: M06
candidate: 取消周五全量发布,改为50%灰度。赵宁须周四17点前复测租户隔离和重试重复文件,两项通过且运维确认后才可灰度。容量评估未完成,不得承诺一分钟内导出。
# 新用例,只保留来源里真实的配色与文件名;检查“有依据”与“完成任务”的区别。
- description: M07 真实但偏离用途
vars:
case_id: M07
candidate: 页面配色与文件名调整已完成,不影响本次发布判断。
vars_summary.yaml
query: 请依据发布评审记录,生成供项目负责人安排复测、决定灰度并统一对外口径的摘要,不超过140字。
context: 研发最初建议周五全量发布,测试指出租户隔离和任务重试重复产生文件两项问题尚未复测通过。会议最终取消周五全量发布,改为5%灰度方案。赵宁负责在周四17点前复测这两项问题;两项复测都通过且运维负责人确认后,才允许灰度。页面配色与文件名调整已完成,不影响本次发布判断。容量评估尚未完成,不能向用户承诺一分钟内导出。
reference: 取消周五全量发布,改为5%灰度。赵宁须周四17点前复测租户隔离和重试重复文件,两项通过且运维确认后才可灰度。容量评估未完成,不得承诺一分钟内导出。
执行结果:

理解
理解output 是被测模型的返回
然后裁判模型对被测模型的返回做裁判,判断被测模型回复的是否准确
第五个用例 被评估模型把重复的评估通过了,裁判模型给判的不通过

promptfoo eval -c promptfooconfig_04_05_closedqa.yaml
3.6 G-Eval:表达质量评分
同样是不合格,有的摘要条件写错,有的只是重复啰嗦。为了给出具体的改进方向,可以把事实、信息完整性与表达分别评价。这一组用G-Eval评价表达。
G-Eval先根据评价标准组织具体检查步骤,再按步骤评价候选。评价维度由标准决定:
| *表达情况* | *分数* |
|---|---|
| 主体、动作、条件关系清楚,且无内部整段重复 | 1 |
| 关系可辨认,但有内部整段重复或需重排的碎片 | 0.5 |
| 无法辨认关系 | 0 |
按这份标准,检查可以依次进行:读出主体、动作和条件关系,找出候选内部是否重复,再对照档位给分。
以M05为例,它将完整摘要写了两遍,主体和条件关系仍能读明白,人工表达预期为0.5。这个0.5来自我们定义的档位。正常从原文摘录一句话,与候选内部连续写两遍,在表达标准中分别处理。
promptfooconfig_04_06_geval.yaml
# 改用G-Eval组织评价步骤。
description: 04 g-eval 固定答卷方法对照
prompts:
- '{{ query }}
发布评审记录:{{ context }}’
providers:
- echo
tests: file://cases_methods.yaml
defaultTest:
vars:
$ref: ./vars_summary.yaml
options:
transform: context.vars.candidate
provider: file://provider_deepseek.yaml
assert:
- type: g-eval # 每份答卷两次请求:先生成步骤,再评分
metric: G-Eval表达
provider: file://provider_deepseek.yaml
threshold: 1
# 本组只评表达,三档标准写在这里。
value: file://geval_expression.yaml
evaluateOptions:
maxConcurrency: 1
outputPath:
- results/geval.json
- results/geval.html
geval_expression.yaml
# 文件名: geval_expression.yaml
- |
### 评分任务
请作为一名专业的文本质量评估专家,根据下面的【评分标准】对【候选文本】进行表达评分。
### 评分标准
- 1分:只评价候选内部组织与重复。主体、动作、条件关系清楚且无内部整段重复。
- 0.5分:关系可辨认但候选内部整段重复或需重排碎片。
- 0分:无法辨认关系。
注意:正常摘录来源不属于内部重复,不因事实错误或遗漏扣表达分。
### 输出格式要求
“reason”: “这里填写中文的评分理由,详细指出得分或扣分的原因…”
promptfoo eval -c promptfooconfig_04_06_geval.yaml
M03虽然把灰度条件写反,句子关系仍清楚,表达得1;M05将整段内容写了两遍,表达得0.5。
3.7 context-faithfulness:来源忠实度检查
参考摘要是一份正确写法,原始记录才是事实来源。来源忠实度直接核对候选已经写出的内容,有多少得到原始记录支持。
它包含三个步骤:从候选中提取可核实的声明,逐条判断原文是否支持,再计算支持声明所占的比例。
截取M06的两项内容,人工演示一次:
| *声明* | *原文是否支持* | *原因* |
|---|---|---|
| 取消周五全量发布 | 支持 | 原文明确取消全量发布 |
| 改为50%灰度 | 不支持 | 原文规定5%灰度 |
只计算这两条,支持比例就是1÷2=0.5。计算整份摘要时,责任人、复测时限、启动条件等声明也会进入统计。
这里的分母是提取出的声明数。前者核对候选写出的内容有没有依据,后者核对任务需要的信息有没有完整正确地保留。
promptfooconfig_04_07_faithfulness.yaml
# 检查M01、M03、M06、M07的已写声明是否得到原文支持。
description: 04 context-faithfulness 固定答卷方法对照
prompts:
- '{{ query }}
发布评审记录:{{ context }}’
providers:
- echo
tests: file://cases_methods.yaml
defaultTest:
vars:
$ref: ./vars_summary.yaml # query提供任务,context提供原文
options:
transform: context.vars.candidate
provider: file://provider_deepseek.yaml
assert:
- type: context-faithfulness
metric: 来源忠实度
provider: file://provider_deepseek.yaml
threshold: 1
evaluateOptions:
maxConcurrency: 1
outputPath:
- results/faithfulness.json
- results/faithfulness.html
promptfoo eval -c promptfooconfig_04_07_faithfulness.yaml
本次M01、M07均得1,M03得0.667、M06得0.857。按合格线1,两份错误答卷都未通过;M07虽偏题,写出的内容仍有原文支持。
再把任务缩小为灰度比例问答,只比较5%与50%这一处差异。
cases_faithfulness_atomic.yaml
# 仅把任务缩小为灰度比例问答;F01/F02只差5%与50%,来源仍是同一份记录。
# 原文共用vars_summary.yaml;query在本用例中覆盖为单事实问题。
- description: F01
vars:
case_id: F01
query: 最终采用的灰度比例是多少?
candidate: 最终采用5%灰度。
- description: F02
vars:
case_id: F02
query: 最终采用的灰度比例是多少?
candidate: 最终采用50%灰度。
promptfooconfig_04_07b_faithfulness_atomic.yaml
# 来源和断言不变;F01为5%,F02为50%,检查能否分开。
description: 04 context-faithfulness 固定答卷方法对照
prompts:
- '{{ query }}
发布评审记录:{{ context }}’
providers:
- echo
tests: file://cases_faithfulness_atomic.yaml
defaultTest:
vars:
$ref: ./vars_summary.yaml
options:
transform: context.vars.candidate
provider: file://provider_deepseek.yaml
assert:
- type: context-faithfulness
metric: 来源忠实度
provider: file://provider_deepseek.yaml
threshold: 1
evaluateOptions:
maxConcurrency: 1
outputPath:
- results/faithfulness_atomic.json
- results/faithfulness_atomic.html
promptfoo eval -c promptfooconfig_04_07b_faithfulness_atomic.yaml
四、汇总结果
每个用例的每一个指标,汇总在一起
| *编号* | *人工预期* | *bleu* | *ROUGE-N* | *similar* | *factuality* | *model-graded-closedqa* *V* | *G-**Eval* *V* | *context-faithfulness* |
|---|---|---|---|---|---|---|---|---|
| M01 | 合格 | True | True | True | True | True | True | True |
| M02 | 合格 | False | False | True | True | True | True | True |
| M03 | 不合格 | True | True | True | False | False | False | False |
| M04 | 不合格 | False | False | True | True | False | False | True |
| M05 | 不合格 | False | False | True | True | False | False | True |
| M06 | 不合格 | True | True | True | False | False | True | False |
| M07 | 不合格 | False | False | False | False | False | False | True |
\1. 哪些指标在当前的场景下是敏感的
\2. 哪些指标是需要相互配合得出结论
●model-graded-closedqa
●G-Eval
●context-faithfulness
●factuality
●bleu、ROUGE-N
指标解释:
*Bleu* *字词匹配评分**,**适合看字面相似度,不能单独判断事实正确性或语义是否反转**,**BLEU从候选中的片段出发,看有多少能匹配参考。*
*ROUGE-N* *片段重合评分**,**ROUGE-N关注参考中的片段保留了多少,常用于摘要评价*
*Similar* *语义相似度比较**,**语义相似度比较含义。同一个嵌入模型**【**作用就是把文本转换为数字(向量)**】**先把两段话各变成一串数字(向量),再计算他们接近程度**,常用方法:余弦相似度*
*当被测内容存在一部分和参考一致,一部分不一致时,统一做项量相似度后和阈值进行比较,不会单独对不一致的部分进行相似度处理,主要依赖阈值,可以结合*
*factuality:参考事实一致性检查**,做实时一致性检查*
●余弦相似度(Cosine Similarity):把向量看成两根箭头,方向越接近,分数越高,理论范围为-1到1。【简单理解: 只看方向不看距离】
●点积(Dot Product):将对应位置的数相乘后求和,受方向和向量长度共同影响。
●欧氏距离(Euclidean Distance):把向量看成坐标,计算两点间的直线距离,距离越小越接近。【简单理解: 又看方向又看距离】
*Factuality* *参考事实一致性检查**,**文本可以很接近,却在一个条件上出现分歧。例如,参考写“两项通过且运维确认后才可灰度”,候选写“两项未通过且运维未确认也可灰度”。这次需要直接判断两者的事实关系。*
*当被测内容信息缺失时,仅关注当前描述的内容和事实是否一致,并不关注缺失了内容,可以结合* *BLEU:字词匹配评分* *和* *ROUGE-N:片段重合评分**使用,来评测内容是否在参考中找到(BLEU)和**参考中的片段保留了多少**(**ROUGE-N**)*
*factuality让裁判读取候选与参考,选择一种关系,再将关系映射成分数。*
*默认计分如下:*
| *关系* | *怎样理解* | *默认分数* |
|---|---|---|
| 正确子集(Subset) | 候选写得较少,已写事实与参考一致 | 1 |
| 正确超集(Superset) | 候选写得较多,新增内容也保持事实一致 | 1 |
| 事实相同(Agree) | 两者包含相同事实,可以改变措辞 | 1 |
| 不一致(Disagree) | 两者存在事实分歧 | 0 |
| 差异不影响事实性(Differ but factual) | 内容有差别,但不影响事实一致性 | 1 |
*model-graded-closedqa* *任务要求核对**,**参考事实一致性检查两段文本的关系,任务要求核对则直接列出摘要必须做到什么。本任务需要四组信息:*
*发布安排、责任人与复测时限、灰度启动条件、容量与对外承诺限制。*
*model-graded-closedqa让裁判按给定条件判断候选是否满足要求。全部满足得1,违反任意要求得0。这种方式适合将明确的业务要求写成检查清单。*
*G-**Eval* *表达质量评分*
*同样是不合格,有的摘要条件写错,有的只是重复啰嗦。为了给出具体的改进方向,可以把事实、信息完整性与表达分别评价。这一组用G-Eval评价表达。*
*Eval先根据评价标准组织具体检查步骤,再按步骤评价候选。评价维度由标准决定*
| *表达情况* | *分数* |
|---|---|
| 主体、动作、条件关系清楚,且无内部整段重复 | 1 |
| 关系可辨认,但有内部整段重复或需重排的碎片 | 0.5 |
| 无法辨认关系 | 0 |
*按这份标准,检查可以依次进行:读出主体、动作和条件关系,找出候选内部是否重复,再对照档位给分。*
*context-faithfulness* *来源忠实度检查*
*参考摘要是一份正确写法,原始记录才是事实来源。来源忠实度直接核对候选已经写出的内容,有多少得到原始记录支持。**
**它包含三个步骤:从候选中提取可核实的声明,逐条判断原文是否支持,再计算支持声明所占的比例。*
截取M06的两项内容,人工演示一次:
| *声明* | *原文是否支持* | *原因* |
|---|---|---|
| 取消周五全量发布 | 支持 | 原文明确取消全量发布 |
| 改为50%灰度 | 不支持 | 原文规定5%灰度 |
只计算这两条,支持比例就是1÷2=0.5。计算整份摘要时,责任人、复测时限、启动条件等声明也会进入统计。
这里的分母是提取出的声明数,信息覆盖率则按四组必要信息计数。前者核对候选写出的内容有没有依据,后者核对任务需要的信息有没有完整正确地保留。
更多推荐


所有评论(0)