本文档定义当前后台 /admin-api/evals/upload-run 期望接收的 eval run zip 结构。
适用场景:
- 向后台导入一整批测评结果
- 让
/evals页面能看到新的 run - 为后续高分题推荐和公开高分 Prompt API 准备
scores/数据
参考样例:
- 仓库内已有一份真实样例目录:
docs/eval_handoff/remote/evals/2026-03-25_231448_rwkv7-2-9b-g1e-20260312-ctx8192-mlx-6bit-zip/
GET /public-api/evals/high-score-samples 会直接读取导入后的 eval 数据。
这里和公开 Prompt API 直接相关的规则是:
items[].score对应样本的averageWeightedScoreaverageWeightedScore是同一样本所有已评分 attempt 的weighted_score算术平均值,保留 2 位小数- 如果公开接口请求里没有传
minScore,后端默认使用当前passThreshold做筛选阈值;代码默认值是8.5,但后台管理员可以调整 - 如果 zip 里没有
scores/*.json,高分推荐和公开 Prompt API 都不会有可用结果
详细的公开接口调用方式见:
- 每次只能上传
1个.zip - 单个 zip 最大
64 MB - zip 根目录可以直接放文件,也可以外面再包一层总目录
__MACOSX和.DS_Store会被忽略- 路径里不能出现
.. - 去掉最外层公共目录后,如果出现重复路径,导入会失败
成功导入至少需要:
manifest.jsongeneration_summary.json- 至少一个
samples/*.json
scores/ 不是导入成功的硬性必需项,但如果没有 scores/*.json,所有和评分、高分题、推荐题相关的结果都会为空。
推荐结构:
my-run.zip
└── 2026-04-07_my_eval_run/ # 可选:最外层总目录
├── manifest.json
├── generation_summary.json
├── samples/
│ ├── 0001_completed_en_chat.json
│ ├── 0002_completed_en_chat.json
│ └── ...
└── scores/
├── 0001_score.json
├── 0002_score.json
└── ...
说明:
samples/和scores/下只要是.json文件都会被读取,文件名本身不是强校验项scores/里的sample_index必须能在samples/里找到对应样本
通用约定:
- 所有数字字段都应为 JSON number,不要写成字符串
- 时间字段建议使用 ISO 8601 字符串
- 文本字段应为非空字符串,除非本文档明确写了可选
- 后台只会读取下文列出的关键字段;额外字段允许存在,但不会参与导入逻辑
manifest.json 用于描述整个 run 的元信息。
必填字段:
run_idstatusendpointtask_typelanguagesource_filesource_total_itemssample_count_requestedrepeat_count
可选字段:
created_atupdated_atbase_urlmodel_requestmodel_name_reported_by_serverselection_modemax_tokensseedeval_device_labeleval_device_cpueval_device_gpueval_device_memory_gbeval_device_vram_gb
最小示例:
{
"run_id": "2026-04-07_english_eval_run",
"status": "completed",
"created_at": "2026-04-07T10:00:00Z",
"updated_at": "2026-04-07T10:30:00Z",
"base_url": "http://localhost:8080",
"endpoint": "http://localhost:8080/v1/chat/completions",
"task_type": "chat",
"language": "en",
"source_file": "docs/requirements/prompt/prebuilt-prompt-en.json",
"model_request": "rwkv",
"model_name_reported_by_server": "rwkv7-2.9B-example.zip",
"selection_mode": "sequential",
"source_total_items": 340,
"sample_count_requested": 340,
"repeat_count": 5,
"max_tokens": 4000,
"seed": 20260407,
"eval_device_label": "MacBook Pro 16-inch",
"eval_device_cpu": "Apple M4 Pro",
"eval_device_gpu": "Apple M4 Pro",
"eval_device_memory_gb": 48,
"eval_device_vram_gb": null
}补充说明:
- 历史 handoff 文件里常见的
total_samples、done_attempts、samples_dir等汇总字段可以保留,但当前导入器不会依赖它们 - 最终写入数据库的样本数、attempt 数会以
samples/*.json和scores/*.json为准重新计算
generation_summary.json 目前只强依赖很少的字段。
必填字段:
run_id
可选字段:
statuslatest_completed_sample_indexlatest_completed_category
最小示例:
{
"run_id": "2026-04-07_english_eval_run",
"status": "completed",
"latest_completed_sample_index": 340,
"latest_completed_category": "mathematics"
}补充说明:
- 如果
status存在,它必须和manifest.json.status一致 - 其他汇总字段如
category_stats、attempt_stats、total_categories可以保留,但当前导入器不会使用它们
每个样本文件表示一个问题及其多次回答尝试。
必填字段:
run_idstatussample_indexrendering_namepromptsource_filesource_categorysource_category_display_namesource_category_indexsource_item_indexendpointrepeat_count_targetrepeat_count_done
可选字段:
languagetask_typebase_urlmodel_requestmodel_name_reported_by_servermax_tokensstarted_atupdated_ateval_device_labeleval_device_cpueval_device_gpueval_device_memory_gbeval_device_vram_gbattempts
最小示例:
{
"run_id": "2026-04-07_english_eval_run",
"language": "en",
"task_type": "chat",
"status": "completed",
"sample_index": 1,
"rendering_name": "How do I stay motivated when progress feels slow?",
"prompt": "Please answer in a calm, practical tone and avoid generic motivational clichés.",
"source_file": "docs/requirements/prompt/prebuilt-prompt-en.json",
"source_category": "life",
"source_category_display_name": "Life",
"source_category_index": 0,
"source_item_index": 0,
"base_url": "http://localhost:8080",
"endpoint": "http://localhost:8080/v1/chat/completions",
"model_request": "rwkv",
"model_name_reported_by_server": "rwkv7-2.9B-example.zip",
"max_tokens": 4000,
"repeat_count_target": 5,
"repeat_count_done": 5,
"started_at": "2026-04-07T10:00:00Z",
"updated_at": "2026-04-07T10:02:00Z",
"attempts": [
{
"attempt": 1,
"status": "completed",
"started_at": "2026-04-07T10:00:00Z",
"ended_at": "2026-04-07T10:00:10Z",
"duration_ms": 10000,
"response_chars": 512,
"response": "A practical answer...",
"error_type": null,
"error_message": null,
"error_body": null
}
]
}attempts[] 内部字段约定:
attempt必填,且同一个样本内不能重复status可选,缺省时后端会按completed处理started_at、ended_at、duration_ms、response_chars、response、error_type、error_message、error_body都是可选
补充说明:
- 当前导入器不会强制校验样本文件里的
language和task_type,但建议和manifest.json保持一致 - 同一个 run 内,
sample_index不能重复
每个评分文件对应一个样本的多次评分结果。
必填字段:
sample_indexrendering_namepromptsource_categoryattempt_evals
attempt_evals[] 内部必填字段:
attemptscores.relevancescores.qualityscores.fluencyscores.satisfactionweighted_score
attempt_evals[] 内部可选字段:
brief_note
最小示例:
{
"sample_index": 1,
"rendering_name": "How do I stay motivated when progress feels slow?",
"prompt": "Please answer in a calm, practical tone and avoid generic motivational clichés.",
"source_category": "life",
"attempt_evals": [
{
"attempt": 1,
"scores": {
"relevance": 9,
"quality": 8,
"fluency": 9,
"satisfaction": 8
},
"weighted_score": 8.35,
"brief_note": "Helpful and grounded, though still slightly repetitive."
}
]
}补充说明:
scores/*.json故意不带run_id- 同一个评分文件内,
attempt不能重复 rendering_name、prompt、source_category必须和对应的samples/*.json完全一致,否则导入会失败
当前后台会做这些关键校验:
generation_summary.json.run_id必须等于manifest.json.run_id- 如果
generation_summary.json.status存在,它必须等于manifest.json.status - 每个样本文件里的
run_id必须等于manifest.json.run_id - 同一个 run 内不能出现重复的
sample_index - 同一个样本内不能出现重复的
attempt - 评分文件里的
attempt必须能在对应样本的attempts[]里找到 - 如果有
scores/0001_score.json,那就必须存在对应的样本文件 - 压缩包归一化后的路径不能重复
如果你要上传的是英文测评,建议至少满足以下约定:
manifest.json.language写成ensamples/*.json里的language也写成enrendering_name、prompt、source_category_display_name使用英文source_file指向英文题库来源,而不是继续保留中文题库路径scores/*.json里的brief_note可以直接用英文
- zip 里没有
manifest.json - zip 里没有
generation_summary.json - zip 里没有任何
samples/*.json run_id前后不一致status前后不一致sample_index重复attempt重复scores/*.json引用了不存在的样本或不存在的 attemptrendering_name、prompt、source_category和对应样本不一致- 打包时混入了多层目录,导致归一化后路径冲突
- 一个 zip 只放一个 run
manifest.json、generation_summary.json在 zip 根层或唯一外层目录下samples/里每个样本都有唯一sample_indexrepeat_count_done和attempts[]的数量一致- 如果要做评分展示或高分推荐,确保每个已评分样本都存在对应的
scores/*.json - 英文 run 确认
language = en