AgentEvalTool/tests/unit/test_exploration_summary.py
sinohqb 2484c207af feat(exploration): findings flow into report, analysis and export
Exploration sessions aggregate into a single exploration summary
(session counts, goal-achievement rate, issue lists from experience
records, judge conclusions when reviewed) that feeds three exits:
the campaign report gains an exploration dimension, the v0.7 analysis
stage-two input gains the summary (stats only, never full dialogues),
and the Markdown export appends a findings appendix after analysis and
comparison. With no exploration data every output stays unchanged.
2026-08-03 19:16:33 +08:00

104 lines
3.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Exploration summary aggregation (v0.9 票据 05).
体验记录聚合成探索摘要会话数、目标达成率、问题清单blockers/misled
按出现次数降序、judge 复核结论(已就位才纳入,只收 poor 档发现)。
缺则无痕:无会话返回 None。纯函数不落库。
"""
from agenteval.exploration.models import ExplorationSession, ExplorationSessionStatus
from agenteval.exploration.summary import summarize_exploration
def _session(experience=None, judge_review=None, status=ExplorationSessionStatus.COMPLETED) -> ExplorationSession:
return ExplorationSession(
campaign_id="c-1",
target_id="t-1",
persona={"name": "x"},
goal="查询账单",
status=status,
experience=experience,
judge_review=judge_review,
)
def _experience(goal_achieved: bool, blockers=None, misled=None) -> dict:
return {
"goal_achieved": goal_achieved,
"blockers": blockers or [],
"misled": misled or [],
"emotion": "neutral",
"notes": "",
}
def test_no_sessions_returns_none():
assert summarize_exploration([]) is None
def test_aggregates_counts_rate_and_issue_lists():
sessions = [
_session(_experience(True, blockers=["缴费入口难找"])),
_session(_experience(False, blockers=["缴费入口难找", "验证码收不到"], misled=["被误导选了错误套餐"])),
_session(_experience(False, blockers=["验证码收不到"])),
]
summary = summarize_exploration(sessions)
assert summary["session_count"] == 3
assert summary["sessions_with_experience"] == 3
assert summary["goal_achieved_count"] == 1
assert summary["goal_achievement_rate"] == round(1 / 3, 4)
# 问题清单按出现次数降序(同频按首次出现顺序)
assert summary["issues"] == [
{"issue": "缴费入口难找", "count": 2},
{"issue": "验证码收不到", "count": 2},
]
assert summary["misled"] == [{"issue": "被误导选了错误套餐", "count": 1}]
def test_sessions_without_experience_excluded_from_rate_denominator():
sessions = [
_session(_experience(True)),
_session(), # 未关闭/无体验记录
]
summary = summarize_exploration(sessions)
assert summary["session_count"] == 2
assert summary["sessions_with_experience"] == 1
assert summary["goal_achievement_rate"] == 1.0
assert summary["issues"] == []
def test_no_experience_at_all_rate_is_none():
summary = summarize_exploration([_session(), _session()])
assert summary["goal_achievement_rate"] is None
assert summary["issues"] == [] and summary["misled"] == []
def test_judge_review_included_only_when_completed():
good_review = {
"status": "completed",
"dimensions": [
{"dimension": "attitude", "rating": "good", "comment": "友好"},
{"dimension": "hallucination", "rating": "poor", "comment": "编造了政策"},
],
"summary": "存在幻觉",
}
failed_review = {"status": "failed", "error": "解析失败"}
sessions = [
_session(_experience(True), judge_review=good_review),
_session(_experience(False), judge_review=failed_review),
_session(_experience(True)), # 未复核
]
summary = summarize_exploration(sessions)
judge = summary["judge_review"]
assert judge["reviewed_sessions"] == 1
# 只收 poor 档发现(问题清单口径)
assert judge["findings"] == [
{"dimension": "hallucination", "rating": "poor", "comment": "编造了政策"}
]
# 复核总体结论一并纳入
assert judge["summaries"] == ["存在幻觉"]
def test_judge_review_absent_when_none_reviewed():
summary = summarize_exploration([_session(_experience(True))])
assert summary["judge_review"] is None