Skip to content

Repository files navigation

Workshop Copy Eval

面向游戏设计对话的 Copy Rewriter 多模型评测工具。它使用同一批固定输入,批量比较不同模型与 System Prompt 组合的文案改写效果,并把自动评分、人工选择和可分享报告收拢到一个本地工作台中。

项目只评测“生成游戏前的用户可见对话文案”,不会启动完整游戏工作台,也不会重新运行 Planner。

目录

项目解决什么问题

仅凭几条示例很难判断一个 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。

界面与使用流程

1. 管理固定 Input 数据集

数据集页面展示用户本轮输入、Planner 原始输出、场景分类和锁定状态。内置核心数据集包含 10 条案例,覆盖模糊需求、用户改需求、继续提问、方案已明确、素材不足、口语输入、重复表达和汇报腔 8 类场景。

已被实验使用的案例不能直接修改。需要调整内容时,可以复制案例,或基于当前数据集创建新版本。

数据集页面

2. 管理 Prompt 版本

Prompt 页面用于保存不同的 Copy Rewriter System Prompt。每个版本包含唯一版本码、名称、正文、备注、内容哈希和基准状态。

项目首次启动会写入:

  • BASELINE:来自核心实现的线上基准 Prompt。
  • NATURAL:偏自然口语,减少汇报腔和机械表达。
  • DIRECT:偏简洁直接,只保留必要信息。

可以继续创建候选版本、复制现有版本、比较两个版本的文本差异,并将任意版本设为基准。已经参与实验的版本仍可查看,历史实验使用的是创建实验时保存的 Prompt 快照。

Prompt 版本页面

3. 创建模型 × Prompt 实验

创建实验时依次选择数据集、模型、Prompt、每案例运行次数和并发数。右侧预检面板会在启动前计算组合数和总调用数:

总运行数 = 案例数 × 模型数 × Prompt 数 × 每案例运行次数

至少需要选择 1 个模型和 1 个 Prompt。前端允许设置更高的并发值,当前服务端为避免供应商限流会将单个实验的有效并发限制在 1–4,并且同一供应商同一时刻只运行一个请求。

创建实验页面

4. 查看实验进度

实验开始后无需手动推进。进度页每秒刷新,展示总任务数、完成数、运行中、失败数、回退字段数、GPT 评分状态,以及按模型、Prompt 和组合拆分的执行进度。

运行期间可以取消实验;失败任务可以单独重试,重试会保留父运行记录并增加 attempt 次数。

实验进度页面

5. 比较、筛选并导出结果

结果页以“案例”为第一层级并排展示模型与 Prompt 输出。可以按场景、模型、Prompt、回退状态、GPT 分数、运行状态和关键词筛选,也可以:

  • 查看用户最终看到的 Reply、PlanProjection 和 Block 文案。
  • 对两条结果进行并排对比。
  • 打开深度检查,查看请求快照、原始响应、结构化结果和回退明细。
  • 为每个案例手动标记一个“人工最佳”。
  • 查看候选 Prompt 相对基准 Prompt 的同案例配对差值。
  • 导出 HTML、CSV 或 JSON。

结果对比页面

6. 完成人工盲测

实验完成后可以创建最多 10 组盲测样本。每组包含所有所选模型各一个结果,选项顺序由固定随机种子打乱。评审者只能看到匿名回答 A、B、C、D,可以选择最佳回答、标记“全部不满意”并填写备注。

整批提交后才会揭晓模型与 Prompt,并显示模型胜率、模型 × Prompt 获胜分布以及人工选择与 GPT 最高分的一致率。

快速开始

环境要求

  • Node.js 22.5 或更高版本(项目使用内置 node:sqlite)。
  • npm 10 或更高版本。
  • Windows、macOS 或 Linux。

1. 安装依赖

npm install

2. 创建本地配置

Windows PowerShell:

Copy-Item .env.example .env

macOS / Linux:

cp .env.example .env

.env.example 默认启用 MOCK_MODE=true,因此不配置任何 API Key 也能完整体验数据集、实验、评分、结果和盲测流程。

3. 启动后端

npm run dev:server

默认地址:http://127.0.0.1:4173

首次启动会自动创建 data/copy-eval.sqlite,并写入核心数据集、基础 Prompt 和四个模型配置。

4. 启动前端

打开第二个终端:

npm run dev

浏览器访问:http://127.0.0.1:3000

5. 验证服务

curl http://127.0.0.1:4173/api/health

Mock 模式下应返回:

{"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 不会改变已有实验。

调度器会:

  1. 在实验有效并发范围内领取待运行任务。
  2. 避免同一供应商并发请求,减少供应商限流和结果抖动。
  3. 为每次请求保存模型、Prompt、参数、输入对象和尝试次数。
  4. 保存原始文本、供应商 JSON、工具调用参数、标准化结果、最终展示文本和 Token 用量。
  5. 将超时、HTTP 错误、无效响应、结构错误和取消分别记录。

严格结构约束

模型只负责改写已有文案,不能新增设计事实,也不能改变数据结构:

  • 必须调用一次 submit_rewrite
  • 顶层字段必须与原始目标一致。
  • blocksparametersoptions 的数量和顺序必须一致。
  • 固定选项和素材 ID 必须保持原值。
  • 文本不能为空、不能超长,也不能包含疑似内部路径或标识泄漏。

结构校验失败时会根据上一次错误反馈自动重试。默认最多尝试 2 次,可通过 REWRITE_MAX_ATTEMPTS 调整为 1–3 次。

字段回退与硬性通过率

如果整体结构正确,但个别字段为空、超长、类型错误或修改了固定选项,系统会将该字段回退到 Planner 原值,并在 fallback_details_json 中记录字段路径、原因、原值和模型尝试值。

结果分析中的“硬性通过率”只统计成功且没有任何字段回退的运行:

硬性通过率 = (完成数 - 有回退的完成数) / 总运行数

GPT 自动评分

模型运行结束后,服务端会自动为每条成功结果启动 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 决策报告

“一键导出 HTML 报告”生成一个不依赖服务器、CSS 或外部脚本的独立文件,适合直接发给项目负责人查看。报告包含:

  • 决策摘要、完成率、平均分、Token 总量。
  • 按模型、Prompt、场景分类的彩色摘要卡片。
  • 人工精选结果。
  • 按问题折叠的全部运行结果。
  • 搜索框和逐层展开的详细信息。
  • GPT 评分理由、错误信息、回退信息和完整原始数据。

所有写入报告的结果文本都会进行 HTML 转义,避免实验内容被当成脚本执行。

CSV 与 JSON

  • CSV:适合在 Excel、Google Sheets 或 BI 工具中做二次统计。
  • JSON:保留完整嵌套结构、请求快照、原始响应、评分和回退明细,适合程序处理或归档。

人工盲测

盲测的目标是把“模型名带来的先入为主”从选择中移除。

  • 单个批次抽取 1–10 个案例,默认 10 个。
  • 至少需要两个模型都有成功结果。
  • 系统按场景轮转抽样,并使用固定随机种子打乱案例和匿名选项。
  • 每组展示全部所选模型各一个结果,并轮换 Prompt 版本。
  • 提交前隐藏模型、Prompt 和 GPT 分数。
  • 所有组都完成后才能提交,提交后不可继续修改。
  • 揭晓后统计模型胜次、模型 × Prompt 胜次、“全部不满意”次数和人机一致率。

数据、隐私与可复现性

SQLite 中保存什么

默认数据库位于 data/copy-eval.sqlite,包含:

  • 数据集与测试案例。
  • Prompt 版本、哈希和基准状态。
  • 实验、模型 × Prompt 变体和每次模型运行。
  • 请求快照、原始响应、规范化结果、最终展示文案和回退明细。
  • GPT 评分。
  • 人工最佳标记、盲测批次、匿名映射和人工选择。

不保存什么

API Key 和 Base URL 从项目根目录 .env 读取。API Key 不会发送到前端,也不会写入 SQLite 或实验请求快照。

为什么使用锁定与快照

如果已经跑过实验的案例或 Prompt 被原地修改,旧结果就无法解释。项目因此采用两层保护:

  1. 已参与实验的案例在界面中锁定,修改前需要复制。
  2. 每个实验保存当时的模型配置和 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-chat
  • anthropic-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 build

项目结构

workshop-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。

主要 API

前端通过 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 获取盲测胜率与一致率。

故障排查

页面没有默认数据集

  1. 确认后端正在运行:

    curl http://127.0.0.1:4173/api/health
  2. 补齐内置数据:

    npm run db:seed
  3. 刷新浏览器。默认数据位于 .envCOPY_EVAL_DB 指向的数据库;如果后端使用了另一个数据库路径,前端看到的内容也会不同。

创建实验时提示模型未配置

  • 确认 .env 位于项目根目录。
  • 确认 MOCK_MODE=false
  • 为所有已选择模型填写非空 API_KEYBASE_URL
  • 修改 .env 后重启后端,运行中的进程不会自动重新读取配置。

GPT 评分只有一部分

  • 结果页顶部会显示 GPT 评分 X / 总数,先确认数字是否仍在增长。
  • 单次评分默认 90 秒超时并自动重试一次,慢请求不会永久占住队列。
  • 如果进程在评分中途重启,后端会保留已完成评分,并自动继续未完成项。
  • 如果实验最终显示评分失败,可以调用 POST /api/experiments/:id/score;服务端只重跑未完成或失败项,不会重复消耗已完成评分。
  • 仍失败时检查 GPT_API_KEYGPT_BASE_URLGPT_MODELGPT_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 报告适合离线查看与交付,但不是实时仪表盘;需要最新数据时应重新导出。
  • 自动评分用于快速筛查和趋势判断,最终文案决策仍建议结合人工最佳标记或匿名盲测。

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages