AgentEvalTool/backend/agenteval/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

74 lines
2.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 findings aggregation (探索发现聚合).
把探索会话的体验记录聚合成探索摘要:会话数、目标达成率、问题清单
blockers / misled 按出现次数降序、judge 复核结论(已就位才纳入,只收
poor 档发现)。这是体验记录这条第一手证据线进入报告 / 分析 / 导出三个
出口前的唯一聚合口径;只含统计与问题清单,不含全量对话。
"""
from collections import Counter
from typing import Any, Optional
from agenteval.exploration.models import ExplorationSession
_POOR_RATING = "poor"
def _issue_list(counter: Counter) -> list[dict[str, Any]]:
return [{"issue": issue, "count": count} for issue, count in counter.most_common()]
def summarize_exploration(sessions: list[ExplorationSession]) -> Optional[dict[str, Any]]:
"""聚合一组探索会话为探索摘要;无会话返回 None缺则无痕"""
if not sessions:
return None
with_experience = [s for s in sessions if s.experience is not None]
blockers: Counter = Counter()
misled: Counter = Counter()
achieved = 0
for session_obj in with_experience:
experience = session_obj.experience
if experience.get("goal_achieved"):
achieved += 1
blockers.update(experience.get("blockers") or [])
misled.update(experience.get("misled") or [])
judge = _summarize_judge_reviews(sessions)
return {
"session_count": len(sessions),
"sessions_with_experience": len(with_experience),
"goal_achieved_count": achieved,
"goal_achievement_rate": round(achieved / len(with_experience), 4) if with_experience else None,
"issues": _issue_list(blockers),
"misled": _issue_list(misled),
"judge_review": judge,
}
def _summarize_judge_reviews(sessions: list[ExplorationSession]) -> Optional[dict[str, Any]]:
"""只纳入复核完成的会话findings 只收 poor 档发现summaries 收复核总体结论。"""
findings: list[dict[str, Any]] = []
summaries: list[str] = []
reviewed = 0
for session_obj in sessions:
review = session_obj.judge_review
if not review or review.get("status") != "completed":
continue
reviewed += 1
if review.get("summary"):
summaries.append(str(review["summary"]))
for item in review.get("dimensions") or []:
if item.get("rating") == _POOR_RATING:
findings.append(
{
"dimension": item.get("dimension"),
"rating": item.get("rating"),
"comment": item.get("comment") or "",
}
)
if reviewed == 0:
return None
return {"reviewed_sessions": reviewed, "findings": findings, "summaries": summaries}