评测报告生成系统设计
文档版本:参见 changelog
目录
1. Context
1.1 背景
评测框架运行后生成原始评测数据(EvalOperatorResult),需要将其转化为结构化、可读的报告,
供人工审核和归档。报告需同时满足机器可解析(JSON)、人类可读(Markdown)和
正式呈现(HTML)三种场景。
1.2 报告生成架构
┌─────────────────────────────────────────────────────────────────────────────┐
│ 评测数据层 │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ EvalOperatorResult (per-operator) │ │
│ │ ├── rel_path, operator │ │
│ │ ├── total_cases, passed_cases, failed_cases │ │
│ │ ├── pass_rate, avg_speedup │ │
│ │ └── results: List[EvalCaseResult] │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 报告生成层 (src/kernel_eval/report/) │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────────────┐ │
│ │ scoring.py │ │setup_info.py │ │ report_generator.py │ │
│ │ ScoringCalculator│ │ collect_setup() │ │ ReportGenerator │ │
│ │ (Eq.3/4/5 评分) │ │ (metadata + env) │ │ ├── generate() │ │
│ │ │ │ │ │ ├── save_json() │ │
│ └──────────────────┘ └──────────────────┘ │ ├── save_markdown() │ │
│ │ └── save_html() │ │
│ ┌──────────────────┐ ┌──────────────────┐ └──────────────────────────┘ │
│ │summary_generator │ │html_generator.py │ │
│ │ EvaluationSummary│ │ render_html_report│ │
│ │ (几何平均加速比) │ │ (模板拼接渲染) │ │
│ └──────────────────┘ └──────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 输出产物 (reports/cann/) │
│ │
│ eval_YYYYMMDD_HHMMSS.json 结构化评测数据 + setup_info │
│ eval_YYYYMMDD_HHMMSS.md Markdown 文本报告 │
│ eval_YYYYMMDD_HHMMSS.html 完整 HTML 报告 │
└─────────────────────────────────────────────────────────────────────────────┘
2. 方案设计
2.1 HTML 报告拼接策略
HTML 报告由静态模板片段与动态数据拼接生成,避免整个报告在代码中硬编码 HTML 结构:
tasks/description.html ← 静态模板 (CSS + Header + Abstract + Section 1)
│
│ render_html_report()
│ ├── 1. 读取 description.html
│ ├── 2. 正则替换摘要中的硬编码值为实际评测数据
│ │ ├── Agent/Skill、BaseModel(有值则替换,无值则删除)
│ │ ├── 通过率、得分(从 report.summary 获取)
│ │ └── 算子数、用例数、等级(从 report.operators 统计)
│ ├── 3. 渲染 Section 2: Experiment Setup(setup_info)
│ ├── 4. 渲染 Section 3: Results Analysis(KPI / Level Table / Bar Charts)
│ ├── 5. 渲染 Section 4: Operator Details(算子详情表)
│ └── 6. 追加认证印章
│
▼
eval_YYYYMMDD_HHMMSS.html ← 完整 HTML 报告
设计原则:
description.html作为评测集描述的单一事实来源,描述 53 算子/4 等级/1060 用例的基准范围- 报告生成时通过正则替换将模板中的示例值替换为实际评测数据
- Section 2 环境信息通过
setup_info.py运行时采集,不写死在模板中 - Section 3/4 由
html_generator.py根据EvalReport数据动态渲染
2.2 报告生成入口
两种方式生成报告:
方式一:评测运行时自动生成(run_evaluation.sh)
./scripts/run_evaluation.sh --source-dir examples/aclnn_launch_example
→ reports/cann/eval_xxx.{json,md,html}(三份同时输出)
方式二:从已有 JSON 重新生成(gen_report.sh)
./scripts/utils/gen_report.sh reports/cann/eval_xxx.json
→ reports/cann/eval_xxx.html(独立生成,不重新评测)
# 指定自定义摘要/第一章模板
./scripts/utils/gen_report.sh --json eval.json --template custom/template.html
2.3 摘要数据替换
description.html 中的摘要段落包含示例数据,html_generator.py 通过正则表达式
将以下字段替换为实际评测数据:
| 模板字段 | 替换来源 | 示例(替换前 → 替换后) |
|---|---|---|
Agent/Skill为CANNBot-skill |
setup_info.metadata.agent_skill |
有值则替换,无值则删除整段 |
BaseModel为DeepSeek V4 Pro |
setup_info.metadata.base_model |
同上 |
针对 53 个算子…1,060 个评测用例 |
report.total_operators / total_cases |
→ 本次对 1 个算子…20 个评测用例 |
整体通过率为 48.9%(518/1,060) |
report.summary.pass_rate / passed_cases |
→ 整体通过率为 85.0%(17/20) |
总得分为 131(满分 5,300) |
report.overall_score |
→ 总得分为 79(满分 100) |
3. 报告输出格式
3.1 JSON 报告 (eval_xxx.json)
{
"version": "1.0",
"eval_code": "eval_20260601_114121",
"timestamp": "2026-06-01T11:41:21",
"device": "npu:0",
"total_operators": 1,
"total_cases": 20,
"passed_cases": 17,
"failed_cases": 3,
"overall_score": 78.81,
"summary": {
"pass_rate": 0.85,
"overall_score": 78.81
},
"setup_info": {
"metadata": {
"framework": "CANN-Bench V0.1.0",
"date": "2026-06-01 11:41:21",
"agent_skill": "",
"base_model": "",
"benchmark": "CANN-Bench tasks",
"license": "CANN Open Software License v2.0"
},
"environment": {
"npu": "Ascend950PR_9579 × 1",
"cpu": "x86_64",
"cann": "9.0.0-beta.2",
"driver": "cann-9.0.0-beta.2",
"pytorch": "2.7.1+cpu",
"pytorch_npu": "2.7.1.post5",
"torchvision": "0.22.1+cpu",
"python": "3.12.9",
"os": "Linux-6.6.0-132.0.0.111.oe2403sp3.x86_64",
"docker": "cake-ci / CANN 9.0.0"
}
},
"operators": [
{
"rel_path": "level1/mish",
"operator": "Mish",
"total_cases": 20,
"passed_cases": 17,
"pass_rate": 0.85,
"avg_speedup": 2.69,
"score": 78.81,
"cases": [...]
}
]
}
3.2 Markdown 报告 (eval_xxx.md)
基于固定模版生成,包含:
- 概览表(算子数、用例数、通过率、综合得分)
- 每个算子的详情表(通过数、加速比、得分)
- 每个用例的执行状态与精度误差
3.3 HTML 报告 (eval_xxx.html)
完整的独立 HTML 文件,包含:
- Header Bar:报告标题与版本
- Abstract:摘要(动态数据替换)
- Section 1:评测集概述(静态,来自
description.html) - Section 2:评测配置(动态,来自
setup_info) - Section 3:结果分析(KPI 条 / 等级汇总表 / 柱状图 / Top 算子表)
- Section 4:算子详情表(所有评测算子列表)
- 认证印章:CANN-Bench 认证章
4. 核心模块设计
4.1 setup_info.py — 配置信息采集
┌─────────────────────────────────────────┐
│ collect_setup_info(config) → Dict │
├─────────────────────────────────────────┤
│ │
│ metadata: │
│ framework ← "CANN-Bench V0.1.0" │
│ date ← datetime.now() │
│ agent_skill← config.agent_skill │
│ base_model ← config.base_model │
│ benchmark ← "CANN-Bench tasks" │
│ license ← 固定 │
│ │
│ environment: │
│ npu ← torch_npu.get_device_ │
│ name(0) × device_count │
│ cpu ← platform.machine() │
│ cann ← ASCEND_TOOLKIT_HOME/ │
│ compiler/version.info │
│ driver ← "cann-{cann_version}" │
│ pytorch ← torch.__version__ │
│ pytorch_npu← torch_npu.__version__ │
│ torchvision← torchvision.__version__ │
│ python ← sys.version │
│ os ← platform.platform() │
│ docker ← "cake-ci / CANN 9.0.0" │
│ (硬编码,后续改软编码) │
└─────────────────────────────────────────┘
CANN 版本读取策略:
- 优先从
ASCEND_TOOLKIT_HOME/compiler/version.info读取Version=行 - 回退到
ASCEND_TOOLKIT_HOME/version.info - 回退到
/usr/local/Ascend/ascend-toolkit/version.cfg - 最后从
ASCEND_TOOLKIT_HOME路径中正则提取cann-<version>
4.2 html_generator.py — HTML 渲染
核心函数 render_html_report(report, setup_info, index_path):
render_html_report()
│
├── 1. 读取 tasks/description.html(CSS + Header + Abstract + Section 1)
│
├── 2. 正则替换摘要动态字段
│ ├── Agent/Skill: re.sub(r'Agent/Skill为[...]', ...)
│ ├── BaseModel: re.sub(r'BaseModel为[...]', ...)
│ ├── 通过率/得分: re.sub(r'整体通过率为...', ...)
│ └── 算子/用例数: re.sub(r'针对 53 个算子...', ...)
│
├── 3. 渲染 Section 2: _render_section2(setup_info)
│ ├── Metadata 表: framework/date/agent/base_model/benchmark/license
│ └── Environment 表: npu/cpu/cann/driver/pytorch/pytorch_npu/...
│
├── 4. 渲染 Section 3: Results Analysis
│ ├── KPI strip (_render_kpi)
│ ├── Level 汇总表 (_render_level_table)
│ ├── 柱状图: 得分 / 精度 / 加速比 (_render_bars)
│ └── Top 算子表: 通过率 Top / 加速比 Top (_render_top_tables)
│
├── 5. 渲染 Section 4: Operator Details
│ └── 单表列出所有评测算子 (_render_operator_table)
│
└── 6. 追加认证印章 (SEAL_HTML 常量)
4.3 report_generator.py — 报告生成器(扩展)
原有功能保留,新增 save_html() 方法:
class ReportGenerator:
def save_all(self, report: EvalReport) -> Dict[str, Path]:
return {
'json': self.save_json(report),
'markdown': self.save_markdown(report),
'html': self.save_html(report), # 新增
}
def save_html(self, report, filename=None) -> Path:
# 读取 tasks/description.html
# 调用 render_html_report()
# 写入 reports/cann/{eval_code}.html
4.4 Config 扩展
@dataclass
class Config:
# 新增字段
agent_skill: str = "" # AI Agent/Skill 标识,为空时摘要不显示
base_model: str = "" # AI BaseModel 标识,为空时摘要不显示
4.5 description.html — 评测集描述模板
位于 tasks/description.html,作为报告的前缀模板,包含:
- HTML5 文档声明与完整 CSS 样式
- Header Bar(报告标题栏)
- Title Area(评测报告主标题与元信息)
- Abstract(摘要,含示例数据,运行时由 html_generator 替换)
- Section 1(评测集概述,Table 1 难度分级,1.2 评分体系)
模板末端有 <!-- INSERTION POINT --> 注释标记,Section 2 起由代码动态生成。
5. 数据流
评测运行
│
├── Evaluator 执行算子评测
│ └── EvalOperatorResult (per operator)
│
▼
ReportGenerator.generate()
│
├── ScoringCalculator → OperatorScoreInfo (per operator)
├── collect_setup_info(config) → setup_info dict
│
▼
EvalReport (dataclass)
├── summary
├── setup_info ← 来自 collect_setup_info()
└── operators: List[OperatorReport]
│
▼
ReportGenerator.save_all(report)
│
├── save_json(report)
│ └── reports/cann/eval_xxx.json
│ ├── summary
│ ├── setup_info ← 嵌入 JSON
│ └── operators[]
│
├── save_markdown(report)
│ └── reports/cann/eval_xxx.md
│
└── save_html(report)
└── reports/cann/eval_xxx.html
└── render_html_report(report, setup_info, "tasks/description.html")
├── description.html (CSS + Header + Abstract + Section 1)
├── 正则替换摘要动态字段
├── Section 2 (setup_info)
├── Section 3 (KPI + 表格 + 柱状图)
├── Section 4 (算子详情)
└── 认证印章
# 或通过 gen_report.sh 从已有 JSON 重新生成 HTML:
gen_report.sh
│
└── 读取 eval_xxx.json
├── 反序列化为 EvalReport + OperatorReport
└── render_html_report(report, setup_info, template)
└── reports/cann/eval_xxx.html
6. 实施步骤
6.1 已完成
- 创建
tasks/description.html评测集描述模板 - 实现
setup_info.py:metadata + environment 采集 - 实现
html_generator.py:正则替换 + HTML 拼接渲染 - 扩展
report_generator.py:新增save_html()输出 - 扩展
config.py:新增agent_skill/base_model字段 - 创建
scripts/utils/gen_report.sh:从 JSON 独立生成评测报告,支持--template自定义模板 - 集成测试通过(
./scripts/run_evaluation.sh --source-dir examples/aclnn_launch_example)
6.2 待完成
- Docker 环境检测改为软编码(从环境变量或 Dockerfile 注入)
- HTML 报告标题栏日期动态替换(
<title>中的 2026-05-25 → 实际时间戳) - 认证印章日期动态替换
- 算子 Category 列从
proto.yaml动态获取 - 支持
--bench-name stanford等多 bench 的报告生成 - 报告增加评测趋势图(历史多次评测对比)