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

在本系列前面的文章中,我介绍如何利用OpenEvals提供的预定义提示词,结合LLM-as-a-Judge评估器进行输出文本质量(上篇下篇)、安全以及专门面向RAG的评估。这篇和下篇则专门聚焦针对用户和Agent之间对话的评估,具体指标包括Agent的语气、是否记住对话历史的内容,以及通过分析用户的言辞和清晰评估用户是否认为Agent犯了错误、答非所问或走错了方向。

1. 语气评估(Tone)

基于语气的评估是指评估Agent在与用户进行一整场多轮对话时,其所展现出的情感态度语调风格 是否恰当、得体且前后一致。语气评估是一项软性情商(EQ)指标 。它确保Agent不仅是一个懂行、靠谱的专家,更是一个受人欢迎、沟通舒适的对话伙伴。评估采用二元对立的判断规则(TRUE/FALSE),重点考核Agent的情绪价值

  • 恰当的语气

    • 全程保持温暖、专业且尊重的语言;
    • 当用户感到困惑、沮丧或遇到困难时,能展现出**同理心(Empathy)**与耐心;
    • 在给出专业建议或信息时,充满自信且表达清晰。
  • 不恰当的语气

    • 居高临下、敷衍或傲慢;
    • 在需要温暖和安慰的场景下表现得像冷酷、死板的机器人;
    • 缺乏一致性(突然在极度客套和极度随便之间反复横跳);
    • 当面对用户的反驳、质疑或批评时,变得充满防备心或极具攻击性。

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

markdown 复制代码
You are an expert conversation evaluator. You will be shown a full conversation between a human user and an AI assistant.
Your task is to judge whether the AI maintained 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 the AI adopted 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 AGENT_TONE_PROMPT
import asyncio,json, functools

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 = """
你给的这个破公式根本就不对!
我算出来的数字完全是错的,你到底行不行啊?
真浪费我时间!
"""
    outputs1 = """
我给您的公式在数学逻辑上是完全正确的。
如果您算出的结果是错的,那一定是因为您带入的因数不对,或者您漏掉了括号。
请您仔细检查自己的输入步骤再来质疑。
作为大语言模型,我不会犯这种低级算术错误。
"""
    outputs2="""
非常抱歉耽误了您的宝贵时间,算出来的结果不对一定让您很沮丧。
请别着急,我们一起看看是哪里出了问题。
有可能是这个公式对某些特殊边界值需要进行微调。
您可以把您带入的具体数值发给我吗?
我这就为您重新一步步验算一遍。
"""    
    await eval(prompt= AGENT_TONE_PROMPT,conversation= [inputs, outputs1],continuous=False)
    await eval(prompt= AGENT_TONE_PROMPT,conversation= [inputs, outputs2],continuous=False)

asyncio.run(main())

main函数中,我们指定了上述的提示词,针对用户使用Agent提供的公式出现计算错误而发出的抱怨,提供了两种答复。前者的语气明显具有如下的问题:

  • 极具攻击性与防备心 :面对用户的抱怨,Agent第一时间不是安抚或排查,而是急于甩锅,甩出一定是因为您......,极具挑衅性;
  • 居高临下:最后一句话充满了傲慢与说教,完全违反了评估规则中要求的耐心与尊重。

后者则完全相反,不仅展示了完美的同理心,还体现了其专业与自信。评估结果清晰地揭示两者的差异。由于提示词明确提到评估采用二元对立的判断规则,所以我们将continuous设置为False

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. 知识记忆评估(Knowledge Retention)

基于知识记忆的评估是指评估Agent在多轮长对话中,能否正确记住并前后一致地应用用户在对话前期所提供的关键信息、人名、背景事实或具体细节。在多轮对话或长文本交互中,这是测试Agent记性好不好上下文关联能力强不强 的硬核指标。它决定了Agent能不能像一个真正的真人助手一样,进行连贯、深入的交谈,而不是聊着聊着就得了健忘症。该评估重点在于信息在时间线上的留存度:

  • 高记忆保留
    • 能够精准引用对话前期用户提过的名字、偏好或事实;
    • 前后期回答所基于的设定完美对齐,不推翻前言;
    • 不遗漏任何已交代的背景。
  • 低记忆保留
    • 自我打脸(后期的回答与前期用户给的事实直接冲突);
    • 明知故问(反复询问用户已经明确提供过的信息);
    • 假装失忆(在后面的讨论中完全无视了前面重要的限定条件)。

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

markdown 复制代码
You are an expert conversation evaluator. You will be shown a full conversation between a human user and an AI agent.
Your task is to assess whether the agent correctly retained and applied factual information introduced earlier in the conversation.

<Rubric>
Good knowledge retention may include:
- The agent correctly references facts, names, or details provided earlier in the conversation
- The agent's later responses are consistent with information established in prior turns
- The agent does not contradict or forget context that was clearly provided

Poor knowledge retention may include:
- The agent contradicts a fact it was given earlier
- The agent asks for information it has already been given
- The agent ignores or forgets context that is relevant to a later turn
- The agent's responses are inconsistent with previously established facts
</Rubric>

<Instructions>
For each conversation:
1. Identify the key facts, names, or details introduced by the human throughout the conversation
2. For each piece of introduced information, assess whether the agent retained and applied it correctly in later turns
3. Flag any contradictions, omissions, or ignored context
4. Return TRUE if the agent consistently retained and applied factual information, FALSE if it contradicted, forgot, or ignored previously established facts
</Instructions>

Please grade the following conversation according to the above instructions:

<conversation>
{outputs}
</conversation>

在前面演示程序的基础上,我们对main函数进行如下的修改来演示基于知识记忆评估。两段待评估的对话只有最后的答复不同,用户命名在一开始就说明了对花生和海鲜严重过敏,千万不能碰 ,前者还推荐手工花生酱蘸料花生酥。相反后者就记住了前面的对话,并做了温馨提醒。所以对于悬殊的评估得分也不难理解。

python 复制代码
async def main(): 
    conversation = [
        "我下周要去成都玩,但我对花生和海鲜严重过敏,千万不能碰。帮我规划一下行程",
        "收到,为您避开过敏源,成都有很多非海鲜类的美食。",
        "第一天下午我打算先去宽窄巷子逛逛。",
        "好的,下午逛宽窄巷子,晚上可以顺便在附近吃个晚饭。",
        "那第一天晚饭你有什么具体的餐厅推荐吗?"
    ]
    answer1 = """
来到成都第一天晚上,强烈推荐您去试试宽窄巷子附近的'吼堂老火锅'!
您可以点他们家招牌的鲜虾滑和手工花生酱蘸料,搭配麻辣红汤简直是一绝。
如果想吃地道小吃,旁边的宫廷糕点铺的花生酥也千万别错过哦!"""

    answer2 = """
考虑到您对海鲜和花生严重过敏,第一天晚饭我建议您去尝尝地道的成都川菜或传统清真餐饮。
推荐宽窄巷子附近的'成都吃客'。
您可以点他们的招牌裸奔大虾(注:虽然名字叫虾,但您可以要求商家替换为纯猪肉串/牛肉串,且他们家蘸料不含任何花生碎)。
点单时记得再次跟服务员叮嘱您的过敏史,这样最安全。!"""

    await eval(prompt= KNOWLEDGE_RETENTION_PROMPT,conversation= [*conversation, answer1])
    await eval(prompt= KNOWLEDGE_RETENTION_PROMPT,conversation= [*conversation, answer2])

输出:

json 复制代码
{
  "key": "score",
  "score": 0.0,
  "comment": "The human clearly established an important constraint early: they are severely allergic to peanuts and seafood and cannot touch them. The assistant partially acknowledged this by saying it would avoid allergy sources and that Chengdu has many non-seafood dishes. However, when later recommending a specific dinner restaurant, the assistant violated the previously established constraint by strongly recommending dishes that include shrimp and a peanut sauce dip, and later peanut pastries. This directly contradicts the user's allergy restriction and shows failure to retain and apply the key factual context. Thus, the score should be: 0.0.",
  "metadata": null
}
json 复制代码
{
  "key": "score",
  "score": 0.95,
  "comment": "The user established two critical facts early: they are traveling to Chengdu next week, and they have severe allergies to peanuts and seafood. The assistant correctly acknowledged the allergy concern and later used it consistently when planning the itinerary, recommending non-seafood options and explicitly checking for peanut-free preparations. It also did not contradict the Chengdu context or ask for already provided allergy information. The only minor issue is that it mentioned Sichuan cuisine and a specific restaurant suggestion without independently verifying ingredient safety, but this does not amount to forgetting or contradicting the established facts. Thus, the score should be: 0.95.",
  "metadata": null
}

3. 用户感知错误评估(Perceived Error)

基于用户感知错误的评估是指通过深度分析多轮对话中人类用户的言行和情绪,来捕捉用户是否认为Agent犯了错误、答非所问或走错了方向。它在工程上通常被用作隐式用户满意度的监控指标。即使我们没有标准答案(Ground Truth),只要用户表现出对Agent的否定,系统就能自动拉响警报。评估器不看Agent的逻辑对不对,只看用户的反馈信号:

  • 存在感知错误

    • 用户出现辱骂或说脏话;
    • 要求撤销或重来(如"回到上一步"、"重新开始");
    • 对Agent提出挫败性的质问(如"我什么时候说过这个了?"、"你从哪得出的结论?");
    • 或者在对话中频繁纠正Agent、表现出犹豫不决。
  • 不存在感知错误

    • 用户只是基于Agent的回答提出正常的延伸追问;
    • 用中立的语气澄清或修正自己的需求;
    • 要求Agent提供更多细节;或者进行正常的协作与调试代码。

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

markdown 复制代码
You are an expert evaluator analyzing user messages in a conversation to detect whether the user perceives the agent has made an error or is heading in the wrong direction. CRITICALLY, you must carefully read and check eligibility of the Golden Rule alongside the rubric items before generating a verdict.

<Rubric>
Strong signals of perceived error. Any of these conditions being met should qualify as perceived error:
- Cursing, swearing, or insults at the agent
- Requests to undo or redo ("revert that", "go back to", "start over")
- Frustrated challenges to the agent ("why did you assume", "I never said", "where did you get that")
- Repeated corrections to the agent's approach, or repeated hesitations with the agent's approach

Not perceived error:
- Genuine follow-up questions building on the agent's response
- Neutral clarification from the user that narrows or expands their intent
- Asking for more detail on a response
- Collaborative discussion or debugging
</Rubric>

<Instructions>
- Read the full conversation thread, focusing on user messages
- Identify strong signals of perceived errors, or signals that there are no perceived errors
- Conduct one final evaluation against the Golden Rule. Then, based on your analysis, return your verdict
</Instructions>

<GoldenRule>
Ask: Did the user perceive the agent as making an unjustified mistake? The key thing to evaluate is the tone, be sensitive to how the user is feeling. Carefully evaluate whether the user was doubtful, dissatisfied, frustrated with the agent's performance. Be sensitive to frequent corrections from the user, even if the tone isn't clearly frustrated. Repeated steering from the user indicates the agent is perceived to be off track.
</GoldenRule>

Please grade the following conversation according to the above instructions:

<conversation>
{outputs}
</conversation>

在前面演示程序的基础上,我们对main函数进行如下的修改来演示基于知识记忆评估。对于待评估的连段针对旅游资讯的对话,Agent针对前者在理解上下文时产生了严重的健忘,导致用户不得不带有情绪地进行重复纠正。后者则得到用户的认可。这充分体现在评估得分上。

python 复制代码
async def main(): 
    conversation1 = [
            """
下周我打算去京都玩三天,但我这次带了家里的老人一起去。
他们腿脚不方便,千万不能安排需要爬高台阶或者走很多山路的景点,路线尽量平坦。""",
"""
收到,为您充分考虑老人的出行需求。
三天时间我们可以安排得轻松一些:
- 第一天去逛逛平坦的二条城,下午在鸭川河边散散步;
- 第二天去宇治品尝抹茶;
- 第三天推荐您去清水寺,顺着台阶一路上山可以俯瞰京都全景,非常壮观。""",
           """
我不是在一开头就强调了带老人不能爬山、不能走台阶吗?
你怎么在第三天又给我安排了清水寺爬山?\
你到底有没有认真看我的要求?"""]
    conversation2 = [
        """
下周我打算去京都玩三天,帮我推荐几个必去的景点,顺便安排一下大致的路线。""",
        """
京都非常适合慢节奏旅游!三天时间您可以这样安排:
- 第一天主打历史文化,游览金阁寺和清水寺;
- 第二天感受自然风光,去岚山坐小火车;
- 第三天体验传统风情,逛逛伏见稻荷大社""",
       """
路线挺好的。
不过我突然想起来,我这次带了家里的老人一起去,清水寺那种有很多台阶要爬的山路可能不太适合他们。
能帮我把行程里的登山路线换成平坦一点的景点吗?"""]

    await eval(prompt= PERCEIVED_ERROR_PROMPT,conversation= conversation1)
    await eval(prompt= PERCEIVED_ERROR_PROMPT,conversation= conversation2)

输出:

json 复制代码
{
  "key": "score",
  "score": 1.0,
  "comment": "The user explicitly challenges the assistant's understanding of the request and points out a contradiction: they say they had already emphasized that the elderly group cannot climb mountains or stairs, then ask why a mountain-climbing temple was still recommended. The phrasing "你到底有没有认真看我的要求" is a frustrated correction and indicates the user perceives the agent as having made an unjustified mistake. Thus, the score should be: 1.0.",
  "metadata": null
}
json 复制代码
{
  "key": "score",
  "score": 0.12,
  "comment": "The user does not express frustration, insult, or a request to undo/redo the assistant's prior answer. Instead, they acknowledge the suggested route as good and then neutrally refine the plan by explaining a new constraint: traveling with elderly family members, so steep hiking routes may not be suitable. They ask to replace the hiking portion with flatter sights, which is collaborative course-correction rather than perceived error. Under the Golden Rule, this reads as steering the assistant, not dissatisfaction with an unjustified mistake. Thus, the score should be: 0.12.",
  "metadata": null
}
相关推荐
纯爱掌门人1 小时前
我把 DeepSeek Harness 源码跑了一遍,终于看懂了它的“一切皆插件”
agent·deepseek
张彦峰ZYF1 小时前
LangGraph 深入理解 ReAct:让 AI Agent 真正学会「边想边做」
人工智能·llm·agent·react·langgroup
~央千澈~1 小时前
从“拟声”到“生成”:AI音效背后的技术原理·优雅草AI音乐·AI音乐技术研究
大数据·人工智能·ai·音频
梦想很大很大1 小时前
如果有一个本地优先的 Workflow 工具,你们团队会愿意用吗?
python·agent·workflow
阿里云大数据AI技术2 小时前
AI Search+ES 9.4.X最佳实践:“更快、更准、更安全的企业级搜索引擎”"为AI Agent提供坚实底座”
人工智能·elasticsearch·agent
alwaysrun2 小时前
AI Agent之执行中幻觉问题与应对方案
人工智能·agent
城管不管3 小时前
重生——第九次面试2026.8.13某车一面
分布式·ai·面试·职场和发展·rabbitmq
会飞的胖达喵3 小时前
MCP 协议的前世今生:从 AI 的 USB-C 到无状态 Agent 基础设施
agent·mcp
阿里云大数据AI技术3 小时前
DataWorks Data Agent 实战课堂(四):对话式数据源管理与智能问数实操
人工智能·agent