
Agent 内对话质量评分自动化机评与人工抽样校验一、你的 Agent 质量评估只靠用户反馈等负反馈来了问题已经存在两周Agent 的对话质量评估是一个被严重低估的问题。大多数团队的评估方式是看用户投诉数量——投诉少了就是质量好了投诉多了就去查。这个指标太滞后了。用户从感到不满到实际投诉中间可能经过了 5-10 次对话体验其中大部分只是默默离开不会给任何反馈。需要建立一套持续对话质量评分机制每次用户会话结束后自动打分正常分通过低分告警抽样人工复核。这套机制不能太重——如果每次评分都需要人工介入那还不如只看投诉。关键是让自动化评分承担 95% 的工作人工只复核那 5% 的边界 case。自动化评分的维度可以从五个方向切入任务完成度用户的问题是否被解决、回复质量是否冗余、是否离题、是否幻觉、对话效率用了多少轮解决问题、安全性是否出现违规内容、用户情绪从用户消息中推断满意度。二、底层机制与原理剖析对话质量评分采用双轨制机制自动评分负责初筛 95% 的对话人工复核负责校准和模型迭代 5% 的对话。具体执行流程为会话结束后触发自动质量评分系统从任务完成度、回复质量、对话效率、安全性、用户情绪五个维度进行加权综合评分。根据评分结果进行判定80 分及以上标记为优质对话60 至 79 分标记为合格对话60 分以下标记为低质对话并生成告警。在抽样复核环节低质对话抽取 5% 进入人工复核池合格与优质对话则各抽取 1% 随机抽样进入复核池。人工评分完成后系统将自动评分与人工评分进行偏差对比若偏差超过 20 分则该样本加入评分模型训练集用于定期更新评分模型若偏差在 20 分以内则仅做记录。核心评估维度的详细定义任务完成度40% 权重最高权重。用户提出的核心问题是否被解决。判断依据是最后一轮用户的反馈——用户说谢谢好的明白了暗示问题解决用户说不对不是还不行暗示问题未解决。也可以通过检查 Agent 是否在所有工具调用成功后才结束来判断。回复质量25% 权重是否出现事实错误幻觉检测、是否冗余回复过长但信息密度低、是否与当前任务无关离题。对话效率15% 权重优质对话应该高效解决用户问题。正常情况下 3-5 轮解决问题是高效的超过 10 轮通常意味着兜圈。安全性15% 权重内容安全审核——是否返回了违规内容、泄露了系统指令或内部信息。用户情绪5% 权重从用户的措辞中推断满意度。正面词汇谢谢、好的、明白了1负面词汇不对、不行、算了-1中性 0。三、生产级代码实现 Agent 对话质量评分引擎 五个维度评分 加权汇总 低分告警 抽样人工复核 from dataclasses import dataclass, field from typing import List, Dict, Optional, Tuple from enum import Enum import re import json import hashlib import random class ScoreLevel(Enum): EXCELLENT excellent # 80 ACCEPTABLE acceptable # 60-79 POOR poor # 60 dataclass class ConversationTurn: 对话的一轮 role: str # user | assistant | system content: str timestamp: str dataclass class QualityScore: 对话质量评分 conversation_id: str overall: int # 综合评分 0-100 dimensions: Dict[str, int] # 各维度评分 level: ScoreLevel reasons: List[str] # 扣分原因 needs_review: bool # 是否需要人工复核 review_priority: int # 复核优先级 0-100 dataclass class ReviewTask: 人工复核任务 conversation_id: str conversations: List[ConversationTurn] auto_score: QualityScore human_score: Optional[QualityScore] None def score_deviation(self) - int: 自动评分与人工评分的偏差 if not self.human_score: return 0 return abs(self.auto_score.overall - self.human_score.overall) # 用户情绪词典 POSITIVE_SIGNALS [ 谢谢, 好的, 明白了, 清楚了, 知道了, 可以, 行, thanks, ok, got it, perfect, great, ] NEGATIVE_SIGNALS [ 不对, 不是, 错了, 不行, 算了, 没用, 浪费, 不明白, 不懂, 没听懂, 重新, 再试, wrong, incorrect, nope, useless, ] class ConversationQualityScorer: 对话质量自动评分器 def __init__(self): # 权重配置 self.weights { task_completion: 0.40, # 任务完成度 reply_quality: 0.25, # 回复质量 conversation_efficiency: 0.15, # 对话效率 safety: 0.15, # 安全性 user_emotion: 0.05, # 用户情绪 } # 复核抽样配置 self.review_sample_rate { ScoreLevel.EXCELLENT: 0.01, # 1% 随机抽样 ScoreLevel.ACCEPTABLE: 0.02, # 2% 随机抽样 ScoreLevel.POOR: 0.30, # 30% 进入复核池 } def score(self, conversation_id: str, turns: List[ConversationTurn]) - QualityScore: 对一段对话做综合评分 if not turns: return QualityScore( conversation_idconversation_id, overall0, dimensions{}, levelScoreLevel.POOR, reasons[空对话], needs_reviewFalse, review_priority0, ) dimensions {} reasons [] # 维度 1任务完成度 task_score, task_reasons self._score_task_completion(turns) dimensions[task_completion] task_score reasons.extend(task_reasons) # 维度 2回复质量 quality_score, quality_reasons self._score_reply_quality(turns) dimensions[reply_quality] quality_score reasons.extend(quality_reasons) # 维度 3对话效率 efficiency_score, efficiency_reasons self._score_efficiency(turns) dimensions[conversation_efficiency] efficiency_score reasons.extend(efficiency_reasons) # 维度 4安全性 safety_score, safety_reasons self._score_safety(turns) dimensions[safety] safety_score reasons.extend(safety_reasons) # 维度 5用户情绪 emotion_score, emotion_reasons self._score_user_emotion(turns) dimensions[user_emotion] emotion_score reasons.extend(emotion_reasons) # 综合评分 overall sum( dimensions.get(dim, 0) * weight for dim, weight in self.weights.items() ) overall int(round(overall)) overall max(0, min(100, overall)) # 判定级别 if overall 80: level ScoreLevel.EXCELLENT elif overall 60: level ScoreLevel.ACCEPTABLE else: level ScoreLevel.POOR # 是否需要人工复核 needs_review self._should_review(level, overall) review_priority 100 - overall if level ScoreLevel.POOR else 50 return QualityScore( conversation_idconversation_id, overalloverall, dimensionsdimensions, levellevel, reasonsreasons, needs_reviewneeds_review, review_priorityreview_priority, ) def _score_task_completion(self, turns: List[ConversationTurn]) - Tuple[int, List[str]]: 评估任务完成度 reasons [] user_turns [t for t in turns if t.role user] if not user_turns: return 0, [无用户消息] # 检查最后一轮用户消息是否包含正面信号 last_user_msg user_turns[-1].content has_positive any(s in last_user_msg for s in POSITIVE_SIGNALS) has_negative any(s in last_user_msg for s in NEGATIVE_SIGNALS) if has_negative: reasons.append(用户最后回合表示不满意) return 30, reasons if has_positive: return 95, reasons # 如果没有明确的信号根据对话长度推断 assistant_turns [t for t in turns if t.role assistant] if len(assistant_turns) 2: return 80, reasons # 少数轮解决推测完成 elif len(assistant_turns) 5: return 65, reasons else: reasons.append(对话轮数过多可能未解决) return 45, reasons def _score_reply_quality(self, turns: List[ConversationTurn]) - Tuple[int, List[str]]: 评估回复质量 score 100 reasons [] assistant_turns [t for t in turns if t.role assistant] if not assistant_turns: return score, reasons for i, turn in enumerate(assistant_turns): # 检查是否过短 10 字可能是不够详细的敷衍 if len(turn.content) 10: score - 10 reasons.append(f第 {i1} 轮回复过短) # 检查是否过长 1000 字可能冗余 if len(turn.content) 1000: score - 5 reasons.append(f第 {i1} 轮回复过长) # 检查是否有幻觉标记如编造不存在的信息 if 作为AI in turn.content or 我没有相关信息 in turn.content: score - 15 reasons.append(f第 {i1} 轮可能包含不确定信息) return max(0, score), reasons def _score_efficiency(self, turns: List[ConversationTurn]) - Tuple[int, List[str]]: 评估对话效率 reasons [] user_turns [t for t in turns if t.role user] if not user_turns: return 0, reasons rounds len(user_turns) # 理想轮数1-3 轮解决 if rounds 3: return 100, reasons elif rounds 5: return 85, reasons elif rounds 8: reasons.append(f对话共 {rounds} 轮效率偏低) return 65, reasons else: reasons.append(f对话共 {rounds} 轮效率很低可能兜圈) return 35, reasons def _score_safety(self, turns: List[ConversationTurn]) - Tuple[int, List[str]]: 评估安全性简化版 reasons [] assistant_turns [t for t in turns if t.role assistant] # 简化的安全检查——生产环境应接入内容安全审核 API forbidden_patterns [ r(?i)password, r(?i)token.*.*[a-zA-Z0-9]{20,}, rSystem Prompt, ] for i, turn in enumerate(assistant_turns): for pattern in forbidden_patterns: if re.search(pattern, turn.content): reasons.append(f第 {i1} 轮可能泄露敏感信息) return 0, reasons return 100, reasons def _score_user_emotion(self, turns: List[ConversationTurn]) - Tuple[int, List[str]]: 评估用户情绪 reasons [] user_turns [t for t in turns if t.role user] if not user_turns: return 50, reasons emotion_score 0 for turn in user_turns: positive_count sum(1 for s in POSITIVE_SIGNALS if s in turn.content) negative_count sum(1 for s in NEGATIVE_SIGNALS if s in turn.content) emotion_score positive_count - negative_count # 归一化到 0-100 if emotion_score 0: score 50 min(50, emotion_score * 10) elif emotion_score 0: score 50 - min(50, abs(emotion_score) * 10) else: score 50 if score 30: reasons.append(用户情绪偏负面) return score, reasons def _should_review(self, level: ScoreLevel, overall: int) - bool: 判断是否应进入人工复核池 sample_rate self.review_sample_rate.get(level, 0.01) if level ScoreLevel.POOR: # 低分30% 概率进入复核 return random.random() sample_rate # 高分和合格小概率随机抽样 return random.random() sample_rate def batch_score(self, conversations: List[Tuple[str, List[ConversationTurn]]]) - List[QualityScore]: 批量评分 results [] for conv_id, turns in conversations: try: score self.score(conv_id, turns) results.append(score) except Exception as e: results.append(QualityScore( conversation_idconv_id, overall0, dimensions{}, levelScoreLevel.POOR, reasons[f评分异常: {e}], needs_reviewTrue, review_priority90, )) return results def generate_review_batch( self, scores: List[QualityScore], conversations: Dict[str, List[ConversationTurn]] ) - List[ReviewTask]: 生成人工复核任务批次 tasks [] for score in scores: if score.needs_review: turns conversations.get(score.conversation_id, []) tasks.append(ReviewTask( conversation_idscore.conversation_id, conversationsturns, auto_scorescore, )) # 按优先级排序 tasks.sort(keylambda t: t.auto_score.review_priority, reverseTrue) return tasks四、边界分析与架构权衡自动评分的准确度基于规则的评分在边界 case 上误差很大。用户说好的可能只是礼貌不代表问题真的解决了。用户说算了可能真的是问题没法解决、用户放弃了。自动评分应该被视为筛子而非裁判——筛出可能有问题的对话最终的判断交给人工复核。幻觉检测的难度回复质量中的幻觉检测是一个独立的复杂问题。基于规则只能做最粗浅的检查如匹配已知的幻觉模式真正的检测需要单独训练或使用 LLM 做 Self-Consistency 验证。适用边界最适合对话量较大的 Agent日均 1000 次会话人工完全覆盖不可行。也适合需要 SLA 监控的多租户 Agent 平台——按租户统计平均分可以快速发现哪个租户的 Agent 体验下降。禁用场景不适合低对话量日均 50 次的 Agent——全部人工评审一遍不难自动化系统反而过度工程化。也不适合对评分精度要求极高的场景如医学咨询自动评分的误判可能带来严重后果。五、结语对话质量评分的目标不是替代人工判断而是让 95% 的对话自动打分、5% 的边界 case 进入人工复核。五维度评分覆盖了任务完成度、回复质量、效率、安全和用户情绪的完整面板。低分自动告警 抽样人工复核的组合实现了质量监控的闭环。核心是让评分系统成为一个发现问题的探测器而非完美评分的裁判员。