2026-09-03 21:32:38 +08:00
|
|
|
|
---
|
|
|
|
|
|
name: exam
|
|
|
|
|
|
description: |
|
|
|
|
|
|
CS 知识应试强化 — 题目生成 Skill。
|
|
|
|
|
|
从 examination 仓库生成符合 JSON Schema 的题目文件,自动校验、合并、更新元数据,推送到远程。
|
|
|
|
|
|
当用户提到生成题目、考试题、练习题、CS 知识题、选择题、填空题、判断题时,使用此 skill。
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-09-02 20:42:54 +08:00
|
|
|
|
# CS 知识应试强化 — 题目生成 Skill
|
|
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
从 `examination` 仓库生成符合 JSON Schema 的题目文件,自动校验、合并、更新元数据,推送到远程。
|
|
|
|
|
|
|
|
|
|
|
|
## 前置条件
|
|
|
|
|
|
|
|
|
|
|
|
- Python 3.8+(用于校验和合并脚本)
|
|
|
|
|
|
- SSH 访问 `git@47.121.181.112:222`(用于 clone/push)
|
|
|
|
|
|
- `topics/index.json` 包含子主题索引
|
2026-09-02 20:42:54 +08:00
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
## 仓库结构
|
2026-09-02 20:42:54 +08:00
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
examination/
|
|
|
|
|
|
├── schema/
|
|
|
|
|
|
│ ├── question.schema.json # 题目 JSON Schema (Draft-07)
|
2026-09-02 21:43:53 +08:00
|
|
|
|
│ ├── prompt-template.md # 题目生成提示词模板
|
|
|
|
|
|
│ └── templates/ # 各题型示例 JSON
|
2026-09-02 20:42:54 +08:00
|
|
|
|
├── topics/
|
|
|
|
|
|
│ ├── index.json # 主题索引
|
|
|
|
|
|
│ └── {group}/{subtopic}/
|
|
|
|
|
|
│ ├── meta.json # 子主题元信息
|
|
|
|
|
|
│ ├── fill_blank.json # 填空题
|
|
|
|
|
|
│ └── single_choice.json # 单选题
|
2026-09-02 20:49:29 +08:00
|
|
|
|
└── exam/ # 本 skill 目录
|
|
|
|
|
|
├── SKILL.md
|
2026-09-02 21:43:53 +08:00
|
|
|
|
├── schema/
|
|
|
|
|
|
│ └── question.schema.json
|
|
|
|
|
|
└── scripts/
|
|
|
|
|
|
├── validate.py
|
|
|
|
|
|
├── validate.mjs
|
|
|
|
|
|
├── merge_questions.py
|
|
|
|
|
|
├── update_meta.py
|
|
|
|
|
|
├── read_context.json
|
|
|
|
|
|
└── validate_and_merge.json
|
2026-09-02 20:42:54 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
## 执行流程
|
2026-09-02 20:42:54 +08:00
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
> **重要:默认使用子代理(SubAgent)分批次处理。** 生成题目是 token 密集型任务,为避免主会话上下文爆炸,应将每批题目的生成工作委派给子代理执行。主会话负责规划、确认和汇总。
|
2026-09-02 20:42:54 +08:00
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
### 阶段 0:与用户确认方案
|
2026-09-02 20:42:54 +08:00
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
**在执行任何操作之前,必须先与用户确认以下信息。** 不要假设默认值。
|
2026-09-02 20:42:54 +08:00
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
1. **子主题(subtopic)**:读取仓库中的 `topics/index.json`,列出可用的子主题供用户选择。如果用户已经指定了子主题,验证其是否存在。
|
|
|
|
|
|
2. **题型与数量**:询问用户需要生成哪些题型、每种多少道。可以一次性给出建议(如「建议先生成 10 道单选题 + 5 道判断题」),但最终必须等用户确认。
|
|
|
|
|
|
3. **展示确认摘要**:在开始生成前,向用户展示如下摘要并等待确认:
|
2026-09-02 20:42:54 +08:00
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
```
|
|
|
|
|
|
📋 生成方案确认
|
|
|
|
|
|
━━━━━━━━━━━━━━
|
|
|
|
|
|
子主题:gc-jvm(JVM 垃圾回收)
|
|
|
|
|
|
分组: qunar-ai-fullstack
|
|
|
|
|
|
题型: 单选 × 10、判断 × 5
|
|
|
|
|
|
━━━━━━━━━━━━━━
|
|
|
|
|
|
确认后开始生成 ✅
|
2026-09-02 20:42:54 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
用户确认后才进入下一阶段。
|
2026-09-02 20:42:54 +08:00
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
### 阶段 1:克隆仓库
|
2026-09-02 20:42:54 +08:00
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-09-02 21:43:53 +08:00
|
|
|
|
REPO_DIR=$(mktemp -d)
|
|
|
|
|
|
git clone --depth 1 ssh://git@47.121.181.112:222/wonder/examination.git "$REPO_DIR"
|
2026-09-02 20:42:54 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
### 阶段 2:读取上下文(子代理)
|
2026-09-02 20:42:54 +08:00
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
派发一个子代理,执行以下任务:
|
|
|
|
|
|
- 读取 `topics/index.json` 确认子主题存在
|
|
|
|
|
|
- 读取该子主题的 `meta.json`(获取 tags、已有题目信息)
|
|
|
|
|
|
- 读取同类型已有的题目文件(获取已有 ID,避免重复)
|
|
|
|
|
|
- 将汇总信息返回给主会话
|
2026-09-02 20:42:54 +08:00
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
使用本 skill 自带的批量脚本 `scripts/read_context.json` 可以一次完成上述读取:
|
2026-09-02 20:42:54 +08:00
|
|
|
|
|
|
|
|
|
|
```
|
2026-09-02 21:43:53 +08:00
|
|
|
|
run_tool_batch(
|
|
|
|
|
|
file_path="<skill_dir>/scripts/read_context.json",
|
|
|
|
|
|
args={
|
|
|
|
|
|
"topics_dir": "<REPO_DIR>/topics",
|
|
|
|
|
|
"group": "<用户确认的分组>",
|
|
|
|
|
|
"subtopic": "<用户确认的子主题>",
|
|
|
|
|
|
"question_type": "<用户确认的题型>"
|
|
|
|
|
|
}
|
|
|
|
|
|
)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 阶段 3:生成题目(子代理)
|
2026-09-02 20:42:54 +08:00
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
> **这是 token 消耗最大的阶段,务必使用子代理处理。**
|
2026-09-02 20:42:54 +08:00
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
根据阶段 2 返回的上下文,**为每种题型分别派发子代理**来生成题目。每个子代理的任务是:
|
2026-09-02 20:42:54 +08:00
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
1. 根据子主题内容和已有题目,生成指定数量的新题目
|
|
|
|
|
|
2. 严格遵循 Schema 格式(见下方「题目格式规范」)
|
|
|
|
|
|
3. 将生成的 JSON 写入临时文件(如 `/tmp/exam_gen_{type}_{batch}.json`)
|
2026-09-02 20:42:54 +08:00
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
**子代理提示词模板:**
|
2026-09-02 20:42:54 +08:00
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
```
|
|
|
|
|
|
你是题目生成专家。请为子主题 "{subtopic_name}" 生成 {count} 道 {type_name} 题。
|
|
|
|
|
|
|
|
|
|
|
|
【上下文】
|
|
|
|
|
|
{从阶段 2 获取的 meta.json 和已有题目摘要}
|
|
|
|
|
|
|
|
|
|
|
|
【要求】
|
|
|
|
|
|
- 严格遵循 JSON Schema(见下方规范)
|
|
|
|
|
|
- ID 从 {next_id} 开始递增(如 fb-001, fb-002...)
|
|
|
|
|
|
- 难度分布在 1-5 之间,合理分布
|
|
|
|
|
|
- tags 参考子主题已有的 tags
|
|
|
|
|
|
- explanation 必须详细,解释为什么对/错
|
|
|
|
|
|
- source 填 null,related 填空数组
|
2026-09-02 20:42:54 +08:00
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
【输出】
|
|
|
|
|
|
将完整 JSON 写入文件 /tmp/exam_gen_{type}_{batch}.json,格式:
|
2026-09-02 20:42:54 +08:00
|
|
|
|
{
|
2026-09-02 21:43:53 +08:00
|
|
|
|
"topic": "{subtopic_slug}",
|
2026-09-02 20:42:54 +08:00
|
|
|
|
"type": "{question_type}",
|
|
|
|
|
|
"schema_version": "1.0.0",
|
2026-09-02 21:43:53 +08:00
|
|
|
|
"generated": "{ISO 8601 时间戳}",
|
2026-09-02 20:42:54 +08:00
|
|
|
|
"questions": [ ... ]
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
**如果题目数量较多(如 > 15 道),建议拆分成多个批次**,每批 5-10 道,分别派发子代理并行处理。
|
|
|
|
|
|
|
|
|
|
|
|
### 阶段 4:校验、合并、更新元数据(子代理)
|
|
|
|
|
|
|
|
|
|
|
|
所有批次的题目生成完成后,派发子代理执行校验与合并:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
run_tool_batch(
|
|
|
|
|
|
file_path="<skill_dir>/scripts/validate_and_merge.json",
|
|
|
|
|
|
args={
|
|
|
|
|
|
"skill_dir": "<skill_dir>",
|
|
|
|
|
|
"topics_dir": "<REPO_DIR>/topics",
|
|
|
|
|
|
"group": "<group>",
|
|
|
|
|
|
"subtopic": "<subtopic>",
|
|
|
|
|
|
"question_type": "<question_type>",
|
|
|
|
|
|
"generated_file": "/tmp/exam_gen_{type}_{batch}.json"
|
|
|
|
|
|
}
|
|
|
|
|
|
)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
如果是多批次生成,需要对每个批次依次执行合并,或者先合并各批次为一个临时文件,再统一合并到已有文件。
|
|
|
|
|
|
|
|
|
|
|
|
### 阶段 5:提交推送
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
cd "$REPO_DIR"
|
|
|
|
|
|
git add -A
|
|
|
|
|
|
git commit -m "feat: add {count} {type} questions for {subtopic}"
|
|
|
|
|
|
git push origin main
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 阶段 6:汇报结果
|
|
|
|
|
|
|
|
|
|
|
|
向用户展示生成结果摘要:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
✅ 题目生成完成
|
|
|
|
|
|
━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
|
|
子主题:gc-jvm
|
|
|
|
|
|
新增: 单选 × 10、判断 × 5
|
|
|
|
|
|
累计: 35 题(单选 20、判断 10、填空 5)
|
|
|
|
|
|
提交: feat: add 15 questions for gc-jvm
|
|
|
|
|
|
━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
2026-09-02 20:42:54 +08:00
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
## 批量脚本参数
|
2026-09-02 20:42:54 +08:00
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
### read_context.json
|
2026-09-02 20:42:54 +08:00
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
| 参数 | 说明 | 示例 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `topics_dir` | 仓库内 `topics/` 目录的绝对路径 | `/tmp/xxxxx/topics` |
|
|
|
|
|
|
| `group` | 主题分组名 | `qunar-ai-fullstack` |
|
|
|
|
|
|
| `subtopic` | 子主题 slug | `gc-jvm` |
|
|
|
|
|
|
| `question_type` | 题型 | `single_choice` |
|
2026-09-02 20:42:54 +08:00
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
### validate_and_merge.json
|
2026-09-02 20:42:54 +08:00
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
| 参数 | 说明 | 示例 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `skill_dir` | 本 skill 目录的绝对路径 | `/home/.../skills/exam` |
|
|
|
|
|
|
| `topics_dir` | 同上 | 同上 |
|
|
|
|
|
|
| `group` | 同上 | 同上 |
|
|
|
|
|
|
| `subtopic` | 同上 | 同上 |
|
|
|
|
|
|
| `question_type` | 同上 | 同上 |
|
|
|
|
|
|
| `generated_file` | 生成的题目 JSON 文件绝对路径 | `/tmp/exam_gen_sc_1.json` |
|
2026-09-02 20:42:54 +08:00
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
## 批量执行失败处理
|
2026-09-02 20:42:54 +08:00
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
如果批量脚本执行失败:
|
|
|
|
|
|
|
|
|
|
|
|
1. 首先检查所有参数是否正确传入,尤其是 `args` 不能为空
|
|
|
|
|
|
2. 根据错误信息修正参数后重试
|
|
|
|
|
|
3. 如果脚本方式持续失败,回退到手动逐步执行(见下方「手动执行参考」)
|
|
|
|
|
|
4. 完成任务后告知用户:「批量执行遇到了问题,已手动完成。是否需要调整 skill 的批量脚本以便下次正常使用?」
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 手动执行参考
|
|
|
|
|
|
|
|
|
|
|
|
### 读取上下文
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
cat "$REPO_DIR/topics/index.json"
|
|
|
|
|
|
cat "$REPO_DIR/topics/{group}/{subtopic}/meta.json"
|
|
|
|
|
|
cat "$REPO_DIR/topics/{group}/{subtopic}/{type}.json" # 如果存在
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 校验
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
python3 <skill_dir>/scripts/validate.py /tmp/exam_generated.json
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 合并
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
python3 <skill_dir>/scripts/merge_questions.py \
|
|
|
|
|
|
"$REPO_DIR/topics/{group}/{subtopic}/{type}.json" \
|
|
|
|
|
|
/tmp/exam_generated.json \
|
|
|
|
|
|
/tmp/exam_merged.json
|
|
|
|
|
|
|
|
|
|
|
|
cp /tmp/exam_merged.json "$REPO_DIR/topics/{group}/{subtopic}/{type}.json"
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 更新元数据
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
python3 <skill_dir>/scripts/update_meta.py \
|
|
|
|
|
|
"$REPO_DIR/topics" {group} {subtopic} {type}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 题目格式规范
|
|
|
|
|
|
|
|
|
|
|
|
ID 格式:`{type_short}-{seq}`,序号从已有最大值 +1 开始,三位数补零。
|
|
|
|
|
|
|
|
|
|
|
|
| 题型 | type | type_short | 关键字段 |
|
|
|
|
|
|
|------|------|------------|----------|
|
|
|
|
|
|
| 填空 | `fill_blank` | `fb` | `answer: string[]`, `answer_rule: "any"/"all"/"ordered"` |
|
|
|
|
|
|
| 单选 | `single_choice` | `sc` | `options: {A-D}`, `answer: string` |
|
|
|
|
|
|
| 多选 | `multiple_choice` | `mc` | `options: {A-D}`, `answer: string[]` |
|
|
|
|
|
|
| 判断 | `true_false` | `tf` | `answer: boolean` |
|
|
|
|
|
|
| 简答 | `short_answer` | `sa` | `answer: string`, `keywords: string[]`, `scoring_rubric: string` |
|
|
|
|
|
|
| 代码阅读 | `code_reading` | `cr` | `code`, `language`, `sub_questions[]` |
|
|
|
|
|
|
| 场景分析 | `scenario` | `sn` | `context`, `sub_questions[]` |
|
|
|
|
|
|
|
|
|
|
|
|
### 通用字段
|
|
|
|
|
|
|
|
|
|
|
|
每道题必须包含:
|
|
|
|
|
|
|
|
|
|
|
|
- `id` — 唯一标识,格式 `type_short-NNN`
|
|
|
|
|
|
- `type` — 题型枚举值
|
|
|
|
|
|
- `difficulty` — 1 到 5 的整数
|
|
|
|
|
|
- `tags` — 标签数组,参考子主题 meta.json
|
|
|
|
|
|
- `question` — 题目文本
|
|
|
|
|
|
- `explanation` — 详细解析
|
|
|
|
|
|
- `source` — 填 `null`
|
|
|
|
|
|
- `related` — 填空数组 `[]`
|
|
|
|
|
|
|
|
|
|
|
|
### sub_questions 规范
|
|
|
|
|
|
|
|
|
|
|
|
`code_reading` 和 `scenario` 题型使用 `sub_questions` 数组,每个子问题需要:
|
|
|
|
|
|
|
|
|
|
|
|
- `index` — 从 1 开始的序号
|
|
|
|
|
|
- `type` — 子问题的题型(通常是 `single_choice` 或 `short_answer`)
|
|
|
|
|
|
- `question` — 子问题文本
|
|
|
|
|
|
- `answer` — 答案
|
|
|
|
|
|
- `explanation` — 解析
|
|
|
|
|
|
- 选择题类子问题还需 `options` 字段
|
|
|
|
|
|
|
|
|
|
|
|
---
|
2026-09-02 20:42:54 +08:00
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
## 备注
|
2026-09-02 20:42:54 +08:00
|
|
|
|
|
2026-09-02 21:43:53 +08:00
|
|
|
|
- 校验脚本优先使用 `jsonschema` 库(Python),不可用时回退到基础校验
|
|
|
|
|
|
- Node.js 校验脚本(`validate.mjs`)为纯内置模块,无外部依赖,可作为备选
|
|
|
|
|
|
- 合并脚本自动去重(基于 question ID),不会覆盖已有题目
|
|
|
|
|
|
- 元数据更新脚本自动计算 `question_files` 和 `stats.by_type` 统计信息
|
|
|
|
|
|
- 所有脚本退出码:0=成功,1=有错误,2=用法错误
|
|
|
|
|
|
- Schema 文件已内置于 `<skill_dir>/schema/question.schema.json`,与仓库版本一致
|