面向游戏设计对话的 Copy Rewriter 多模型评测工具。它使用同一批固定输入,批量比较不同模型与 System Prompt 组合的文案改写效果,并把自动评分、人工选择和可分享报告收拢到一个本地工作台中。
项目只评测“生成游戏前的用户可见对话文案”,不会启动完整游戏工作台,也不会重新运行 Planner。
- 项目解决什么问题
- 核心能力
- 界面与使用流程
- 快速开始
- 接入真实模型
- 实验如何运行
- GPT 自动评分
- 结果分析与导出
- 人工盲测
- 数据、隐私与可复现性
- 配置参考
- 常用命令
- 项目结构
- 主要 API
- 故障排查
- 当前边界
仅凭几条示例很难判断一个 Prompt 是否真的更好:模型差异、案例差异、随机性和人的主观偏好都会干扰结论。本项目把这些变量拆开并保存完整证据链:
固定用户输入 + 固定 Planner 原始输出
│
▼
Model × Prompt 组合矩阵
│
▼
严格结构校验、重试与字段回退
│
▼
GPT 六维评分 + 同案例配对比较
│
▼
人工最佳标记 / 匿名盲测
│
▼
HTML / CSV / JSON 结果交付
它适合以下场景:
- 比较 DeepSeek、Kimi、GLM、豆包在同一批游戏对话上的表现。
- 对比线上基准 Prompt 与候选 Prompt,查看同模型、同案例下的真实增减。
- 定位模型超时、结构错误、字段回退和模板化表达。
- 由文案、策划或项目负责人逐题标记更好的结果。
- 将大量实验数据导出成一份可折叠、可搜索、可直接交付的独立 HTML 报告。
| 能力 | 说明 |
|---|---|
| 固定输入集 | 内置 10 条 Copy Rewriter 核心案例,覆盖 8 类常见游戏设计对话场景。 |
| 数据版本化 | 已参与实验的数据集和案例会锁定;需要调整时复制为新版本,保留历史可复现性。 |
| Prompt 版本管理 | 新建、复制、编辑、查看差异、指定基准版本;实验保存当时的 Prompt 快照。 |
| 多模型矩阵 | 将所选模型与 Prompt 做笛卡尔组合,按案例批量运行。 |
| 严格输出契约 | 模型必须调用 submit_rewrite,保持字段、Block、Parameter 和 Option 的数量与顺序。 |
| 自动重试与回退 | 结构不合规时重试;单个字段不合规时回退到 Planner 原值并记录原因。 |
| GPT 六维评分 | 从自然度、响应质量、语气、流畅度、AI 套话和综合表现六个维度评分。 |
| 人工最佳标记 | 每个案例可以手动选出一个最佳模型与 Prompt 结果。 |
| 匿名盲测 | 随机打乱模型身份,提交前不展示模型和 Prompt,提交后统计胜率与人机一致率。 |
| 多格式导出 | 支持独立 HTML 决策报告、CSV 表格和完整 JSON 数据。 |
| 本地持久化 | 数据、快照、原始响应、评分和人工选择统一保存在 SQLite。 |
数据集页面展示用户本轮输入、Planner 原始输出、场景分类和锁定状态。内置核心数据集包含 10 条案例,覆盖模糊需求、用户改需求、继续提问、方案已明确、素材不足、口语输入、重复表达和汇报腔 8 类场景。
已被实验使用的案例不能直接修改。需要调整内容时,可以复制案例,或基于当前数据集创建新版本。
Prompt 页面用于保存不同的 Copy Rewriter System Prompt。每个版本包含唯一版本码、名称、正文、备注、内容哈希和基准状态。
项目首次启动会写入:
BASELINE:来自核心实现的线上基准 Prompt。NATURAL:偏自然口语,减少汇报腔和机械表达。DIRECT:偏简洁直接,只保留必要信息。
可以继续创建候选版本、复制现有版本、比较两个版本的文本差异,并将任意版本设为基准。已经参与实验的版本仍可查看,历史实验使用的是创建实验时保存的 Prompt 快照。
创建实验时依次选择数据集、模型、Prompt、每案例运行次数和并发数。右侧预检面板会在启动前计算组合数和总调用数:
总运行数 = 案例数 × 模型数 × Prompt 数 × 每案例运行次数
至少需要选择 1 个模型和 1 个 Prompt。前端允许设置更高的并发值,当前服务端为避免供应商限流会将单个实验的有效并发限制在 1–4,并且同一供应商同一时刻只运行一个请求。
实验开始后无需手动推进。进度页每秒刷新,展示总任务数、完成数、运行中、失败数、回退字段数、GPT 评分状态,以及按模型、Prompt 和组合拆分的执行进度。
运行期间可以取消实验;失败任务可以单独重试,重试会保留父运行记录并增加 attempt 次数。
结果页以“案例”为第一层级并排展示模型与 Prompt 输出。可以按场景、模型、Prompt、回退状态、GPT 分数、运行状态和关键词筛选,也可以:
- 查看用户最终看到的 Reply、PlanProjection 和 Block 文案。
- 对两条结果进行并排对比。
- 打开深度检查,查看请求快照、原始响应、结构化结果和回退明细。
- 为每个案例手动标记一个“人工最佳”。
- 查看候选 Prompt 相对基准 Prompt 的同案例配对差值。
- 导出 HTML、CSV 或 JSON。
实验完成后可以创建最多 10 组盲测样本。每组包含所有所选模型各一个结果,选项顺序由固定随机种子打乱。评审者只能看到匿名回答 A、B、C、D,可以选择最佳回答、标记“全部不满意”并填写备注。
整批提交后才会揭晓模型与 Prompt,并显示模型胜率、模型 × Prompt 获胜分布以及人工选择与 GPT 最高分的一致率。
- Node.js 22.5 或更高版本(项目使用内置
node:sqlite)。 - npm 10 或更高版本。
- Windows、macOS 或 Linux。
npm installWindows PowerShell:
Copy-Item .env.example .envmacOS / Linux:
cp .env.example .env.env.example 默认启用 MOCK_MODE=true,因此不配置任何 API Key 也能完整体验数据集、实验、评分、结果和盲测流程。
npm run dev:server默认地址:http://127.0.0.1:4173
首次启动会自动创建 data/copy-eval.sqlite,并写入核心数据集、基础 Prompt 和四个模型配置。
打开第二个终端:
npm run dev浏览器访问:http://127.0.0.1:3000
curl http://127.0.0.1:4173/api/healthMock 模式下应返回:
{"ok":true,"mock":true}将 .env 中的 MOCK_MODE 改为 false,然后只填写本次实验需要使用的模型。未选中的模型可以不配置;如果选中了缺少 Key 或 Base URL 的模型,创建实验时会直接报错,不会静默退回 Mock。
MOCK_MODE=false
DEEPSEEK_API_KEY=your_deepseek_key
KIMI_API_KEY=your_kimi_key
GLM_API_KEY=your_glm_gateway_key
DOUBAO_API_KEY=your_doubao_secret
GPT_API_KEY=your_judge_key
GPT_BASE_URL=https://api.openai.com/v1
GPT_MODEL=gpt-4o-mini
GPT_PROTOCOL=openai-chat不要提交
.env。项目的.gitignore已忽略.env*,只保留可公开的.env.example。
| 界面名称 | 默认模型 | 默认协议 | 请求地址规则 |
|---|---|---|---|
| DeepSeek | deepseek-v4-flash |
OpenAI Chat Completions | <BASE_URL>/chat/completions |
| Kimi | moonshot-v1-8k |
OpenAI Chat Completions | <BASE_URL>/chat/completions |
| GLM | claude-sonnet-4-20250514 |
Anthropic Messages | <BASE_URL>/v1/messages |
| 豆包 | doubao-seed-2-0-lite-260428 |
OpenAI Chat Completions | <BASE_URL>/chat/completions |
GLM 也兼容 Claude Code 风格的环境变量:
ANTHROPIC_AUTH_TOKEN=your_gateway_token
ANTHROPIC_BASE_URL=https://your-anthropic-compatible-gateway.example.com
ANTHROPIC_DEFAULT_SONNET_MODEL=your_model_name豆包只使用 API Key Secret 作为 Bearer Token,API Key ID 不参与数据面请求。
创建实验时,服务端会为每个模型 × Prompt 组合保存模型配置和 Prompt 正文快照,再为每条案例创建运行任务。后续修改 Prompt 不会改变已有实验。
调度器会:
- 在实验有效并发范围内领取待运行任务。
- 避免同一供应商并发请求,减少供应商限流和结果抖动。
- 为每次请求保存模型、Prompt、参数、输入对象和尝试次数。
- 保存原始文本、供应商 JSON、工具调用参数、标准化结果、最终展示文本和 Token 用量。
- 将超时、HTTP 错误、无效响应、结构错误和取消分别记录。
模型只负责改写已有文案,不能新增设计事实,也不能改变数据结构:
- 必须调用一次
submit_rewrite。 - 顶层字段必须与原始目标一致。
blocks、parameters、options的数量和顺序必须一致。- 固定选项和素材 ID 必须保持原值。
- 文本不能为空、不能超长,也不能包含疑似内部路径或标识泄漏。
结构校验失败时会根据上一次错误反馈自动重试。默认最多尝试 2 次,可通过 REWRITE_MAX_ATTEMPTS 调整为 1–3 次。
如果整体结构正确,但个别字段为空、超长、类型错误或修改了固定选项,系统会将该字段回退到 Planner 原值,并在 fallback_details_json 中记录字段路径、原因、原值和模型尝试值。
结果分析中的“硬性通过率”只统计成功且没有任何字段回退的运行:
硬性通过率 = (完成数 - 有回退的完成数) / 总运行数
模型运行结束后,服务端会自动为每条成功结果启动 GPT 评分。评分对象只有最终用户可见文案,用户输入和 Planner 原始文案只作为忠实度依据。
| 维度 | 权重 | 判断重点 |
|---|---|---|
responseQuality |
30% | 是否准确回应用户、完整忠实、结构对应正确。 |
naturalness |
25% | 中文是否自然,是否避免翻译腔和机械拼接。 |
tone |
15% | 是否符合游戏设计共创语境,避免客服腔和公文腔。 |
fluency |
15% | 语法、逻辑、信息组织和术语是否顺畅一致。 |
noAiCliches |
15% | 是否避免复述、空洞开场、泛化赞美和强行总结等 AI 套话。 |
overall |
加权结果 | 1–5 分,保留一位小数;严重失真时最高 2.5。 |
评分器固定使用 4 个 worker。单次请求默认 90 秒超时,失败后自动重试一次;单条失败不会占死整个评分队列。服务重启时,遗留的“评分进行中”实验会恢复为待评分,已完成评分会保留,未完成或失败项会继续处理。
Mock 模式下每项固定返回 3 分,仅用于验证流程,不代表文案质量。
候选 Prompt 与基准 Prompt 的比较固定在“同一模型、同一案例”范围内进行,避免把模型能力或案例难度误判为 Prompt 效果。页面展示:
- 候选 Prompt 相对基准的平均分差。
- 得分高于基准的案例比例。
- 每个模型 × Prompt 组合的完成率、硬性通过率和平均综合分。
每个实验的每条案例只能标记一个最佳运行。再次选择同案例的另一条结果会替换旧选择;点击已选结果可以取消。人工选择保存在 SQLite,并会进入 HTML 报告。
“一键导出 HTML 报告”生成一个不依赖服务器、CSS 或外部脚本的独立文件,适合直接发给项目负责人查看。报告包含:
- 决策摘要、完成率、平均分、Token 总量。
- 按模型、Prompt、场景分类的彩色摘要卡片。
- 人工精选结果。
- 按问题折叠的全部运行结果。
- 搜索框和逐层展开的详细信息。
- GPT 评分理由、错误信息、回退信息和完整原始数据。
所有写入报告的结果文本都会进行 HTML 转义,避免实验内容被当成脚本执行。
- CSV:适合在 Excel、Google Sheets 或 BI 工具中做二次统计。
- JSON:保留完整嵌套结构、请求快照、原始响应、评分和回退明细,适合程序处理或归档。
盲测的目标是把“模型名带来的先入为主”从选择中移除。
- 单个批次抽取 1–10 个案例,默认 10 个。
- 至少需要两个模型都有成功结果。
- 系统按场景轮转抽样,并使用固定随机种子打乱案例和匿名选项。
- 每组展示全部所选模型各一个结果,并轮换 Prompt 版本。
- 提交前隐藏模型、Prompt 和 GPT 分数。
- 所有组都完成后才能提交,提交后不可继续修改。
- 揭晓后统计模型胜次、模型 × Prompt 胜次、“全部不满意”次数和人机一致率。
默认数据库位于 data/copy-eval.sqlite,包含:
- 数据集与测试案例。
- Prompt 版本、哈希和基准状态。
- 实验、模型 × Prompt 变体和每次模型运行。
- 请求快照、原始响应、规范化结果、最终展示文案和回退明细。
- GPT 评分。
- 人工最佳标记、盲测批次、匿名映射和人工选择。
API Key 和 Base URL 从项目根目录 .env 读取。API Key 不会发送到前端,也不会写入 SQLite 或实验请求快照。
如果已经跑过实验的案例或 Prompt 被原地修改,旧结果就无法解释。项目因此采用两层保护:
- 已参与实验的案例在界面中锁定,修改前需要复制。
- 每个实验保存当时的模型配置和 Prompt 正文快照。
这样即使之后继续迭代数据集或 Prompt,历史结果仍可追溯。
| 变量 | 默认值 | 说明 |
|---|---|---|
PORT |
4173 |
后端 API 监听端口。 |
COPY_EVAL_DB |
./data/copy-eval.sqlite |
SQLite 文件路径。 |
MOCK_MODE |
true |
是否使用本地 Mock 模型与 Mock 评分。 |
MODEL_TIMEOUT_MS |
120000 |
单次业务模型请求超时,单位毫秒。 |
MODEL_TEMPERATURE |
0.7 |
支持该参数的模型温度。 |
MODEL_TOP_P |
0.9 |
支持该参数的模型 Top P。 |
MODEL_MAX_TOKENS |
16000 |
业务模型最大输出 Token。 |
MODEL_REASONING_EFFORT |
max |
OpenAI 兼容接口的推理强度。 |
MODEL_THINKING_BUDGET_TOKENS |
2048 |
Anthropic 兼容接口的 Thinking Token 预算。 |
REWRITE_MAX_ATTEMPTS |
2 |
结构校验失败时的最大尝试次数,服务端限制为 1–3。 |
GPT_SCORE_TIMEOUT_MS |
90000 |
单次 GPT 评分请求超时,单位毫秒。 |
每个模型使用一组 <PREFIX>_API_KEY、<PREFIX>_BASE_URL、<PREFIX>_MODEL 和 <PREFIX>_PROTOCOL:
| 前缀 | 模型 |
|---|---|
DEEPSEEK_ |
DeepSeek |
KIMI_ |
Kimi |
GLM_ |
GLM 或 Anthropic 兼容网关 |
DOUBAO_ |
豆包方舟 |
GPT_ |
自动评分模型 |
*_PROTOCOL 当前支持:
openai-chatanthropic-messages
| 命令 | 用途 |
|---|---|
npm run dev |
启动 Vite 前端,默认端口 3000。 |
npm run dev:server |
启动 Express + SQLite 后端,默认端口 4173。 |
npm run mock |
强制以 Mock 模式启动后端。 |
npm run db:seed |
补齐内置数据集、Prompt 和模型配置;不会清空已有实验。 |
npm run lint |
执行 TypeScript 类型检查,不生成文件。 |
npm test |
运行核心结构、模型协议、评分恢复和 HTML 报告测试。 |
npm run build |
构建生产版前端到 dist/。 |
npm run preview |
本地预览生产构建。 |
提交代码前建议运行:
npm run lint
npm test
npm run buildworkshop-copy-eval/
├─ core/
│ ├─ copy-rewriter.ts # 改写目标、结构校验、字段回退与展示文本
│ └─ SOURCE.md # 核心 Prompt 的来源说明
├─ server/
│ ├─ index.ts # Express API、实验分析与评分触发
│ ├─ db.ts # SQLite 表结构与迁移
│ ├─ seed.ts # 10 条默认案例、Prompt 与模型配置
│ ├─ models.ts # OpenAI / Anthropic 协议适配器
│ ├─ scheduler.ts # 实验并发调度、重试、取消和结果持久化
│ └─ scoring.ts # GPT 六维评分与人工盲测抽样
├─ src/
│ ├─ components/ # 六个主页面和通用组件
│ ├─ context/AppContext.tsx # 前端状态、API 调用和每秒轮询
│ ├─ lib/exportHtml.ts # 独立 HTML 决策报告生成器
│ ├─ types.ts # 前后端共享业务类型
│ └─ App.tsx # 页面入口
├─ tests/ # 核心、模型、评分恢复与报告测试
├─ page/ # README 使用的页面截图
├─ data/ # 本地 SQLite 数据,已被 Git 忽略
├─ .env.example # 可公开的配置模板
└─ vite.config.ts # 前端开发服务与 /api 代理
技术栈:React 19、TypeScript 5.8、Vite 6、Tailwind CSS 4、Express 4、Node.js 内置 SQLite。
前端通过 Vite 将 /api 代理到 http://127.0.0.1:4173。常用接口如下:
| 方法 | 路径 | 作用 |
|---|---|---|
GET |
/api/health |
查看后端与 Mock 模式状态。 |
GET/POST |
/api/datasets |
查询或创建数据集版本。 |
GET/POST |
/api/datasets/:id/cases |
查询或创建测试案例。 |
PUT |
/api/cases/:id |
修改尚未被实验使用的案例。 |
GET/POST |
/api/prompts |
查询或创建 Prompt 版本。 |
POST |
/api/prompts/:id/clone |
复制 Prompt 版本。 |
POST |
/api/prompts/:id/benchmark |
设置基准 Prompt。 |
GET |
/api/models |
查看模型协议和是否已配置。 |
GET/POST |
/api/experiments |
查询或创建实验。 |
POST |
/api/experiments/:id/cancel |
取消未完成任务。 |
POST |
/api/experiments/:id/retry-failed |
为失败任务创建重试运行。 |
GET |
/api/experiments/:id/results |
获取完整运行结果。 |
GET |
/api/experiments/:id/analysis |
获取组合统计和基准配对分析。 |
POST |
/api/experiments/:id/score |
手动重新处理未完成或失败的 GPT 评分。 |
POST |
/api/runs/:id/preferred |
设置或取消某案例的人工最佳结果。 |
POST |
/api/experiments/:id/blind-batches |
创建盲测批次。 |
POST |
/api/blind-batches/:id/submit |
提交并揭晓盲测。 |
GET |
/api/blind-batches/:id/summary |
获取盲测胜率与一致率。 |
-
确认后端正在运行:
curl http://127.0.0.1:4173/api/health
-
补齐内置数据:
npm run db:seed
-
刷新浏览器。默认数据位于
.env中COPY_EVAL_DB指向的数据库;如果后端使用了另一个数据库路径,前端看到的内容也会不同。
- 确认
.env位于项目根目录。 - 确认
MOCK_MODE=false。 - 为所有已选择模型填写非空
API_KEY和BASE_URL。 - 修改
.env后重启后端,运行中的进程不会自动重新读取配置。
- 结果页顶部会显示
GPT 评分 X / 总数,先确认数字是否仍在增长。 - 单次评分默认 90 秒超时并自动重试一次,慢请求不会永久占住队列。
- 如果进程在评分中途重启,后端会保留已完成评分,并自动继续未完成项。
- 如果实验最终显示评分失败,可以调用
POST /api/experiments/:id/score;服务端只重跑未完成或失败项,不会重复消耗已完成评分。 - 仍失败时检查
GPT_API_KEY、GPT_BASE_URL、GPT_MODEL、GPT_PROTOCOL,以及网关是否返回符合要求的 JSON。
SCHEMA_ERROR:模型没有返回完整、顺序一致的submit_rewrite参数。TIMEOUT:业务模型超过MODEL_TIMEOUT_MS。- 回退字段:整体运行成功,但部分字符串不满足长度、类型、固定选项或泄漏检查。
- 在结果页打开“深度检查”,查看原始响应、工具参数和具体字段路径。
修改 .env:
PORT=4175同时修改 vite.config.ts 中 /api 的代理目标,再重启前后端。
不要直接删除数据库。可以创建新的数据集版本、Prompt 版本和实验,系统会把它们与历史结果隔离。npm run db:seed 只补齐内置数据,不会清空已有实验。
- 项目聚焦 Copy Rewriter 文案评测,不负责重新生成 Planner 输出。
- 当前模型列表固定为 DeepSeek、Kimi、GLM、豆包;新增供应商需要扩展共享类型、种子数据和模型适配器。
- 前端为本地单用户工具,没有登录、权限、远程数据库和多人协作。
- HTML 报告适合离线查看与交付,但不是实时仪表盘;需要最新数据时应重新导出。
- 自动评分用于快速筛查和趋势判断,最终文案决策仍建议结合人工最佳标记或匿名盲测。