# 模型评测优化设计方案 ## 1. 现状检查 当前模型评测菜单已经具备以下基础能力: - 创建评测任务:选择训练模型、评测数据集、算力节点和 GPU。 - 任务调度:后端将模型、适配器、数据集准备到目标算力节点,再提交 Compute API 任务。 - 模型推理:Compute Agent 使用 LLaMA-Factory 推理会话逐条生成回答。 - 结果落库:任务完成后读取 `eval_results.json`,写入任务详情、样本结果和指标摘要。 - 报告归档:评测输出目录可以归档到 MinIO,并通过报告接口下载。 - 前端详情:显示综合分、通过率、样本结果、指标摘要,并对运行中的任务进行轮询。 当前缺陷主要集中在评分和进度链路: 1. 创建页面的 BLEU、ROUGE、余弦指标默认全部关闭;未配置 LLM 评委时,样本没有确定性评分,容易得到 0 分。 2. BLEU、ROUGE、余弦、LLM Judge 的返回范围和含义不统一,百分制、0-1、小量程评分混在一起。 3. 评测模型地址直接拼接 `/v1/chat/completions`,当地址已经包含 `/v1` 时会出现 `/v1/v1`。 4. LLM Judge 只解析少量文本格式,无法可靠解析 JSON、Markdown JSON 或 0-1 综合评价。 5. ROUGE 对中文没有采用 `nlp-eval-demo` 的字符级中文分词策略,中文短文本容易得到失真的结果。 6. 后端只在 Compute 任务完成后读取结果文件,运行时没有样本完成数、当前阶段和中间指标。 7. 前端没有雷达图,用户无法直观看到 BLEU、ROUGE、语义相似度、精确匹配和 LLM Judge 等维度。 ## 2. 目标 建立一条可解释、可持续轮询、兼容旧任务的评测闭环: ```text 创建任务 -> 资源准备 -> 模型加载 -> 样本推理 -> 逐样本评分 -> 中间进度文件 -> 后端同步 -> 页面进度与雷达图 -> 完成报告 -> MinIO 归档 -> 详情与下载 ``` 目标结果: - 所有最终展示分数统一为 0-100,避免不同指标之间直接相加造成误解。 - 没有 LLM 评委时,仍然使用确定性指标生成样本得分和综合分,不再因为“未配置评委”自动归零。 - 有 LLM 评委时,保留原有自定义评分区间,同时将其归一化到 0-100 展示。 - 每个评测任务都能看到阶段、总样本数、已完成样本数、百分比和当前指标状态。 - 详情页展示指标雷达图;指标不可用时显示原因,不把“依赖未安装”伪装成 0 分。 - 不新增必需数据库表,继续利用 `eval_tasks.payload` 保存评测结果和进度,兼容现有数据库及离线初始化 SQL。 ## 3. 评分设计 ### 3.1 指标契约 Compute Agent 内部统一使用以下结构: ```json { "enabled": true, "available": true, "score": 82.5, "max_score": 100, "unit": "percent", "sample_count": 3, "error": "" } ``` `score` 永远是 0-100。指标不可用时 `available=false`,`score` 可以为 null,同时保留 `error`。旧报告中只有 `score` 的结构继续兼容,后端读取时按旧结构补齐默认字段。 ### 3.2 确定性指标 参考 `nlp-eval-demo` 的实现,支持: - BLEU:sacrebleu,结果由 0-100 转换为百分制。 - ROUGE-1、ROUGE-2、ROUGE-L:中文按字符切分,英文按词切分,使用 F1 均值并转换为百分制。 - 余弦相似度:TF-IDF 余弦相似度,转换为百分制。 - 精确匹配:标准化空白和大小写后完全一致,百分制。 - 文本相似度:SequenceMatcher,作为无外部模型时的稳定兜底指标。 - BERTScore:仅在 `bert_score` 和模型可用时启用;下载/加载失败只标记不可用,不阻断整个评测任务。 精确匹配和文本相似度始终计算。用户在创建页面选择的 BLEU、ROUGE、余弦作为额外指标;如果没有选择额外指标,也用“文本相似度 + ROUGE-L(可用时)”生成确定性综合分。 ### 3.3 无 LLM 评委时的样本分数 对每条样本使用可用确定性指标的平均值作为样本百分制得分: ```text sample_score = mean(exact_match, text_similarity, rougeL, cosine, bleu, bertscore) ``` 其中未启用或不可用的指标不参与平均。样本通过阈值默认 60 分;如果旧维度配置的 `pass_threshold <= score_max`,先按旧量程换算为百分制。 ### 3.4 LLM Judge - 兼容 OpenAI Chat Completions 接口。 - 自动规范化 `api_url`,避免重复 `/v1`。 - 优先解析 JSON 的 `score`、`综合评价`、`overall_score`、`dimensions` 字段,再解析 Markdown/自然语言中的评分。 - 支持 0-1、0-5、0-100 三种返回量程;最终统一转换为 0-100。 - API 调用失败时记录样本失败原因,不把失败当作正常 0 分;如果所有样本都调用失败,任务状态仍可完成但报告会明确提示评委不可用。 ## 4. 进度设计 Compute Agent 在评测输出目录写入两个文件: - `eval_progress.json`:轻量进度文件,每完成一条样本更新一次。 - `eval_results.json`:运行中写入部分结果,完成后写入完整报告。 进度结构: ```json { "status": "running", "stage": "inference", "total": 20, "completed": 7, "percentage": 35, "current_index": 8, "message": "正在生成第 8 条样本", "updated_at": "2026-08-20T00:00:00Z" } ``` 后端详情接口每次轮询 Compute Agent: 1. 任务运行中读取 `eval_progress.json`,写入 `eval_tasks.payload.progress_detail`。 2. 读取到部分 `eval_results.json` 时同步已完成样本和基础指标,页面可以边运行边展示。 3. Compute 任务完成后读取完整报告,再执行 MinIO 归档。 4. Compute Agent 暂时不可达时保留最后一次进度,不因为一次轮询失败把评测任务误判为失败。 ## 5. 前端设计 - 列表页增加进度列:运行中显示 `已完成/总数` 和百分比,完成后显示最终分数。 - 详情页增加当前阶段、进度消息和进度条。 - 详情页增加“指标雷达图”,雷达轴来自可用的 `dimension_summary` 指标,最大值统一 100。 - 指标卡同时显示分数、通过率、样本数和不可用原因。 - 样本结果在运行中支持逐步出现,保留现有搜索、筛选和分页。 - 不改变已有任务创建、删除、报告下载和权限校验流程。 ## 6. 数据库与兼容性 本次不新增数据库表和必需字段。评测结果继续存放在 `eval_tasks.payload` JSON 中,新增键包括: - `progress_detail` - `basic_metrics` 的统一指标对象 - `metric_summary_version` - 样本的 `raw_score`、`raw_max_score`、`score`、`max_score` 旧任务兼容规则:缺少进度时由 `progress` 和样本数量推导;旧的量程评分按 `score/max_score` 转换为百分制;没有基础指标时显示“历史任务未保存指标明细”。因此无需修改 `000_full_init.sql`。 ## 7. 实施步骤 1. 重构 Compute Agent 评测指标、中文 ROUGE、LLM Judge 解析、评分归一化和中间结果写入。 2. 增加 Compute Agent 进度文件读取能力,后端同步运行中进度和部分结果。 3. 扩展后端评测任务结果兼容、失败信息和进度返回。 4. 扩展前端类型、列表进度列、详情进度区和指标雷达图。 5. 增加单元测试、前端构建测试和接口/运行时冒烟验证。 6. 同步前后端、算力服务到 `docker/offline/src`,确认初始化 SQL 无需变更。 ## 8. 验收标准 - 使用仅包含 `instruction/output` 的小型 JSONL 数据集,未配置 LLM Judge 时综合分不再固定为 0。 - 中文答案能得到可解释的 ROUGE-1/2/L 分数。 - LLM Judge 的地址为 `https://host/v1` 时请求路径仍正确。 - 评测运行期间能看到 `completed/total` 和百分比变化。 - 完成后详情页存在至少 3 个可用指标时显示雷达图,指标少于 3 个时显示明细降级视图。 - 失败、依赖缺失、空答案等情况能在报告中区分,不以正常 0 分掩盖原因。 - 现有权限、GPU 预约、MinIO 归档、报告下载和旧任务查看不受影响。