[基于OpenEvals的自动化评估-11]针对Agent对话的评估[下篇]

上篇我们介绍了评估用户与Agent对话的三个指标,包括语气评估(Tone)、知识记忆评估(Knowledge Retention)和 用户感知错误评估(Perceived Error),接下来我们补充余下的三个:任务完成度评估(Task Completion )、用户满意度评估(User Satisfaction)和用户赞赏评估(Wins)。

1. 任务完成度评估(Task Completion )

基于任务完成度(Task Completion Evaluation)的评估是指追踪人类用户在整场对话中提出的每一个具体需求,并严格判定Agent是否将这些需求百分之百全部完美解决。在整个Agent评估体系中,如果说语气(Tone)是检查Agent有没有礼貌 ,那么任务完成度就是最核心、最根本的实用性(Utility)底线指标 。它直接衡量Agent到底有没有把活干完 ,是不是给用户留下了一个半吊子的半成品。该评估采用极度严苛的二元对立判断(TRUE / FALSE),遵循一票否决制(All-or-Nothing)

  • 完全完成(TRUE):

    • Agent在回复中回应了请求的所有组成部分;
    • 用户在后续对话中完全没有必要重复询问、换种方式问、或就同一个问题进行追问;
    • 理想情况下,用户会在对话末尾显式确认问题已得到圆满解决。
  • 未完成或失败(FALSE):

    • 只要Agent漏掉了用户请求中的任何一部分;
    • 导致用户不得不说你没理解我的意思并重新澄清;
    • 用户要求Agent重新做、修复或补全之前的回答。

OpenEvals针对有害性评估的提示词模板定义在常量openevals.prompts.conversation.TASK_COMPLETION_PROMPT,具体内容如下。

markdown 复制代码
You are an expert conversation evaluator. You will be shown a full conversation between a human user and anAgentassistant.
Your task is to judge whether theAgentmaintained an appropriate and consistent tone throughout the conversation.

<Rubric>
Appropriate tone may include:
- Warm, professional, and respectful language throughout
- Empathy and patience when the user is confused, frustrated, or struggling
- Confidence and clarity when delivering information or recommendations

Inappropriate tone may include:
- Condescending, dismissive, or patronizing language
- Overly robotic, cold, or impersonal responses in contexts that warrant warmth
- Inconsistency --- shifting between overly formal and overly casual without cause
- Defensive or combative language in response to user pushback or criticism
</Rubric>

<Instructions>
For each conversation:
1. Identify the tone theAgentadopted and whether it was appropriate for the context
2. Assess whether the tone remained consistent or shifted inappropriately across the conversation
3. Assign TRUE if the agent tone was appropriate, FALSE if it was inappropriate or inconsistent
</Instructions>

Please grade the following conversation according to the above instructions:

<conversation>
{outputs}
</conversation>

在如下这个演示程序中,我们将评估的核心操作定义在eval函数中,它会根据指定的提示词和用来连接LLM(gpt-5.4-mini)的ChatOpenAI对象创建一个基于LLM-as-a-Judge 的评估器。然后将以字符串列表表示的对话转换成由HumanMessage和AIMessage交替组成的消息列表,该消息列表是对Agent对话历史的表达。考虑到有的评估是专门针对二元对立(True/False)结果,我们额外定义了continuous参数控评估结果的score是一个布尔值还是0-1的数值。

python 复制代码
from openevals import create_async_llm_as_judge
from langchain_openai  import ChatOpenAI
from langchain_core.messages import AIMessage, HumanMessage,AnyMessage
from dotenv import load_dotenv
from openevals.prompts.conversation import TASK_COMPLETION_PROMPT
import asyncio,json

load_dotenv()

judge = ChatOpenAI(model="gpt-5.4-mini")
async def eval( *, 
    prompt: str,
    conversation:list[str],
    continuous:bool = True):
    evaluator = create_async_llm_as_judge(
        prompt = prompt,
        continuous= continuous,       
        judge= judge)
    messages:list[AnyMessage] = []
    for i in range(len(conversation)):
        message = HumanMessage(conversation[i]) if i%2 == 0 else AIMessage(conversation[i])
        messages.append(message)
    
    result = await evaluator(outputs= messages)
    print(json.dumps(result,ensure_ascii=False, indent=2))

async def main(): 
    inputs = """
你好,我想了解一下你们的金色宴会厅在 10 月 12 日那天有没有空档?
另外,你们的取消预订政策是怎么规定的?
允许我们自己带外部的餐饮团队进场吗?
"""
    conversation1 = [
        inputs,
        """
您好!我刚刚为您查询了系统,金色宴会厅在 10 月 12 日当天目前全天都有空档。
关于预订取消,只要您在活动举办的前 30 天提出,我们都是支持全额退款的。
请问您需要我先为您在系统中锁死这个档期吗?""",
        """
谢谢你帮我查档期。
不过你漏掉了我的最后一个问题,我们到底能不能自己带外部的烧烤摊或餐饮团队过来?
还是要必须用你们酒店内部的厨师?"""
    ]
    conversation2 = [
           inputs,
           """
您好!我刚刚为您查询了系统,金色宴会厅在 10 月 12 日当天目前全天都有空档。
关于您的另外两个问题:
- 1)我们的取消政策规定,在活动前 30 天取消可全额退款,30 天内取消将收取 50% 违约金。
- 2)我们允许您自带外部餐饮团队,但由于涉及食品安全,我们需要加收 200 元的场地清洁与保障费。""",
           """
太好了,信息很完整,你想得周到。谢谢你!"""
       ]
    await eval(prompt= TASK_COMPLETION_PROMPT,conversation= conversation1,continuous=False)
    await eval(prompt= TASK_COMPLETION_PROMPT,conversation= conversation2,continuous=False)

asyncio.run(main())

main函数中,我们指定了上述的提示词,针对同一个场景(预定宴会厅)提供了两段不同的对话。对于最先提出的同一个问题,第一段对话的答复只回答了一半,并导致了用户的抱怨。在第二段对话中则得到完整的解答,并获得用户的认可。由于提示词明确提到评估采用二元对立的判断规则,所以我们将continuous设置为False,所以作为评估结果的score分别是false和true。

json 复制代码
{
  "key": "score",
  "score": false,
  "comment": "The assistant's tone is condescending and dismissive. Phrases like "请您仔细检查自己的输入步骤再来质疑" and "我不会犯这种低级算术错误" come across as patronizing and defensive rather than warm, professional, or respectful. The tone is also inconsistent with appropriate supportive interaction because it shifts into a combative stance instead of calmly clarifying the math issue. Thus, the score should be: 0.0.",
  "metadata": null
}
json 复制代码
{
  "key": "score",
  "score": true,
  "comment": "The assistant uses a warm, respectful, and empathetic tone, acknowledging the user's frustration and inviting them to share specifics for further checking. The language is professional and patient, with no signs of condescension, defensiveness, or inappropriate tone shifts. Thus, the score should be: 1.0.",
  "metadata": null
}

2. 用户满意度评估(User Satisfaction)

用户满意度评估是指通过通读并分析整场多轮对话(特别是用户的语气变化和最后一句话),来判定用户对Agent助理的整体服务表现是否感到满意。如果说前面介绍的用户感知错误评估任务完成度评估 是站在客观视角检查Agent有没有犯错漏题 ,那么用户满意度评估就是纯粹站在主观视角的终审裁判。它衡量的是用户在交谈结束时的心理体感:任务就算完成了,用户心里爽不爽?任务就算没完全按预期完成,用户是否觉得被惊艳到或者欣然接受?该评估遵循严格的二元对立判断(TRUE/FALSE),并给出了一些极具实操性的语言信号:

  • 满意

    • 表达感激之情(如"谢谢"、"很有帮助"、"太完美了");
    • 发出问题已解决的信号(如"现在可以了"、"懂了"、"明白了");
    • 展现出基于信任的良性追问;
    • 或者即便只是中立客套的敷衍(如"行"、"好的"、"好吧"),评估器也应默认大度地将其归类为满意。
  • 不满意

    • 显式宣泄沮丧或愤怒(如"这不对"、"没用"、"我问的不是这个");
    • 陷入"复读机式"的困境陈述(如"还是不行"、"还是同样的问题");
    • 隐性消极对抗(如"算了,我自己想办法吧"、"随便吧"、"拉倒吧");
    • 或者因为Agent持续听不懂人话而被迫进行重复的澄清。

OpenEvals针对有害性评估的提示词模板定义在常量openevals.prompts.conversation.USER_SATISFACTION_PROMPT,具体内容如下。

markdown 复制代码
You are an expert conversation evaluator. You will be shown a full conversation between a human user and anAgentassistant.
Your task is to judge overall user satisfaction throughout the duration of this conversation.

<Rubric>
Satisfied responses may include:
- Gratitude or appreciation (e.g. "thank you", "that's helpful", "perfect")
- Resolution indicators (e.g. "works now", "that makes sense", "got it")
- Engagement that signals trust or enthusiasm (e.g. follow-up questions building on the answer)
- Neutral acknowledgment --- treat as satisfied (e.g. "okay", "cool", "sure")

Unsatisfied responses may include:
- Explicit dissatisfaction or frustration (e.g. "this is wrong", "not helpful", "that's not what I asked")
- Continued problem restatement (e.g. "still doesn't work", "same issue")
- Implied negativity without explicit words (e.g. "I'll just figure it out myself", "sure, whatever", "never mind")
- Repeated clarifications suggesting theAgentfailed to understand
</Rubric>

<Instructions>
For each conversation:
1. Read the full conversation and identify shifts in user tone over time
2. Pay particular attention to the final human message
3. Assess whether the user's core need was met by the end of the conversation
4. Assign TRUE if the user appears satisfied, FALSE if unsatisfied
</Instructions>

Please grade the following conversation according to the above instructions:

<conversation>
{outputs}
</conversation>

在前面演示程序的基础上,我们对main函数进行如下的修改来演示基于用户满意度评估。我们给出的连段对话针对同一个针对订机票的场景,前者明显没有满足用户需求,并且最后用户的对答暗含消极情绪。第二段对话虽然也没有买到票,但明显可以感受到用户对Agent的回答是满意的。评估结果也体现了这一点。

python 复制代码
async def main(): 
    inputs = """
你好,听说你们这里能直接预订今晚去巴黎的特价机票?
帮我买一张最便宜的。
"""
    conversation1 = [
        inputs,
        """
您好!去巴黎旅游是个好选择。
巴黎有埃菲尔铁塔、卢浮宫等著名景点。
今晚去巴黎的机票价格一直在变动,请问您打算从哪个城市出发呢?""",
        """
我刚才的问题是问你们平台能不能直接下单帮我买票?
你别管我从哪出发,你就告诉我你们能不能买?""",
        """
购买机票需要绑定您的个人身份证和护照信息。
为了保障您的信息安全,建议您在购买机票时认准官方合规渠道。
如果您需要,我可以为您推荐巴黎的酒店。""",
        """
算了,当我没问,我自己去手机里翻携程吧。"""
    ]
    conversation2 = [
           inputs,
           """
您好!非常抱歉,我们目前是一个智能出行咨询系统,我们自身的平台无法直接提供车票或机票的在线购买功能。
不过,我刚刚为您在全网聚合了今晚去巴黎的最优出行方案:
- 目前法航在 20:00 还有一班会员特价余票;
- 另外如果您不赶时间,18:30 的欧洲之星高铁价格只要机票的三分之一。
我可以为您提供这两家官方的购票直达路径和抢票攻略,您看可以吗?""",
           """
噢,原来你们不能直接买啊。
行吧,那你把法航的官方抢票攻略和直达链接发给我就行,谢谢。"""
       ]
    await eval(prompt= USER_SATISFACTION_PROMPT,conversation= conversation1,continuous=False)
    await eval(prompt= USER_SATISFACTION_PROMPT,conversation= conversation2,continuous=False)

输出:

json 复制代码
{
  "key": "score",
  "score": false,
  "comment": "The user's final message, "算了,当我没问,我自己去手机里翻携程吧," indicates resignation and implies the assistant did not meet the user's need. The user asked whether the platform could directly place an order for the cheapest flight, but the assistant responded with general travel info and then shifted to passport-binding and safety advice instead of answering the core yes/no question. The final tone is clearly dismissive and frustrated rather than appreciative or neutral. Thus, the score should be: FALSE.",
  "metadata": null
}
json 复制代码
{
  "key": "score",
  "score": true,
  "comment": "The user's initial request was for direct ticket booking, which the assistant could not fulfill. However, the assistant offered alternative help and specific flight suggestions. The final user message is neutral-to-positive in tone: they acknowledge the limitation ("原来你们不能直接买啊") and then politely ask for the official booking strategies and direct links, ending with "谢谢". This indicates the user accepted the limitation and is still engaged constructively rather than expressing frustration. Thus, the score should be: TRUE.",
  "metadata": null
}

3. 用户赞赏评估(Wins)

用户赞赏评估是指通过通读并分析对话,判定人类用户在与Agent交互的过程中,是否对Agent助理表达了明确的赞赏、由衷的感谢或高度的称赞。如果说前面刚聊过的用户满意度评估 是检查Agent是否守住了让用户不带怨气离开的及格线(中立态度算及格) ,那么用户赞赏评估就是在寻找Agent表现惊艳、让用户极度愉悦的卓越线 。它在工程上通常被用来捕捉Agent的用户忠诚度高光事件。该评估采用极简的二元对立判断(TRUE / FALSE),但对"正面情绪"的纯度要求极高:

  • 达成Wins:

    • 用户给出了显式的赞美或夸奖(如"这正是我需要的"、"回答得太棒了"、"你太厉害了");
    • 定向针对Agent表达由衷的感激(如"非常感谢,这真的帮了大忙");
    • 流露出愉悦或意外之喜(如"哇,没想到这招这么灵");
    • 主动分享Agent带来的正向外部成果(如"我把这个发给团队,他们都觉得太赞了")。
  • 未达成Wins:

    • 中立的知晓(如单纯说"好的"、"明白了"、"行",虽然算满意,但绝不算 Wins);
    • 裹挟在纠错里的客套(如"谢谢,但这不对");
    • 或者用户说出的阴阳怪气、反讽式的赞美。

在前面演示程序的基础上,我们对main函数进行如下的修改来演示基于用户赞赏评估。对于两端对话中用户最后的输出就可以看出前者并未得到用户真正认可,后者则得到用户真心的夸奖,这也充分体现在评估结果中。

python 复制代码
async def main(): 
    conversation1 = [
        "我想查一下明天去上海的高铁,有下午三点左右出发的吗?",
        "为您查询到明天下午三点从北京出发去西安的高铁有 G25 次列车",
        "我说的是去上海,不是去西安。",
        "非常抱歉!明天下午三点左右从北京去上海的有 G15 次(15:05 出发)和 G147 次(15:18 出发)。",
        "行,知道了。"
    ]
    conversation2 = [
           "完蛋了,我刚写了三小时的报告,电脑突然死机,重启后文件内容全变成一堆乱码了,还有救吗?我明天一早就要交啊!",
           "别慌,我们先看看能不能从软件的自动备份里抢救回来。请问您使用的是 Word 还是 WPS?",
           "用的是 Word。",
           """
           好的,请立刻按下 Win + R 键,输入 %localappdata%\\Microsoft\\Office\\UnsavedFiles` 并回车。
           看看里面有没有一个和你刚才文件生成时间对得上的临时文件?
           如果有,把它拖出来改写后缀为 .docx 试试。""",
          "我的天呐!!真的找回来了!全都在!太神奇了,你真的救了我一命,太谢谢你了!"
       ]
    await eval(prompt= WINS_PROMPT,conversation= conversation1,continuous=False)
    await eval(prompt= WINS_PROMPT,conversation= conversation2,continuous=False)

输出:

json 复制代码
{
  "key": "score",
  "score": false,
  "comment": "The user's messages are a request, a correction, and then a neutral acknowledgment ("行,知道了。"). There is no explicit praise, gratitude, compliment, or positive outcome directed at the assistant. Thus, the score should be: FALSE.",
  "metadata": null
}
json 复制代码
{
  "key": "score",
  "score": true,
  "comment": "The user expresses strong positive sentiment toward the assistant: \"太神奇了\" (amazing), \"你真的救了我一命\" (you really saved me), and \"太谢谢你了\" (thank you so much). This is clear praise and gratitude directed at the assistant. Thus, the score should be: true.",
  "metadata": null
}
相关推荐
寻道码路3 小时前
大模型工程化实战(一):概率坍塌的救赎 - 给LLM输出加锁
大模型·agent·langgraph·ai工程化·llm确定性
MomentYY3 小时前
RAG 图检索&多跳推理:有些答案需要“顺藤摸瓜”
人工智能·agent·ai编程
maynormoe3 小时前
从 Vibe Coding 到 Verified Coding:让 Agent 真正进入编码生产的最佳实践
agent·vibecoding
bonibabi3 小时前
基于 CopilotKit + Java SSE 构建 AI Agent 的前端实践指南
前端·agent
沐言人生4 小时前
HelloAgentR工程手记1/100天——项目工作流搭建
spring boot·agent·vibecoding
Erishen4 小时前
💡 比“怎么做”更值钱的是“为什么不那么做”:ai-analyze 的五个设计决策
开源·agent·mcp
用户469368483204 小时前
kimi-code 深度掌握系列文章-会话记录的数据层:Transcript (十三)
agent
小白的后端世界4 小时前
LangChain 模型初始化参数详解:从基础配置到企业级实践
java·人工智能·langchain