Files

300 lines
9.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: exam
description: |
CS 知识应试强化 — 题目生成 Skill。
从 examination 仓库生成符合 JSON Schema 的题目文件,自动校验、合并、更新元数据,推送到远程。
当用户提到生成题目、考试题、练习题、CS 知识题、选择题、填空题、判断题时,使用此 skill。
---
# CS 知识应试强化 — 题目生成 Skill
从 `examination` 仓库生成符合 JSON Schema 的题目文件,自动校验、合并、更新元数据,推送到远程。
## 前置条件
- Python 3.8+(用于校验和合并脚本)
- SSH 访问 `git@47.121.181.112:222`(用于 clone/push)
- `topics/index.json` 包含子主题索引
## 仓库结构
```
examination/
├── schema/
│ ├── question.schema.json # 题目 JSON Schema (Draft-07)
│ ├── prompt-template.md # 题目生成提示词模板
│ └── templates/ # 各题型示例 JSON
├── topics/
│ ├── index.json # 主题索引
│ └── {group}/{subtopic}/
│ ├── meta.json # 子主题元信息
│ ├── fill_blank.json # 填空题
│ └── single_choice.json # 单选题
└── exam/ # 本 skill 目录
├── SKILL.md
├── schema/
│ └── question.schema.json
└── scripts/
├── validate.py
├── validate.mjs
├── merge_questions.py
├── update_meta.py
├── read_context.json
└── validate_and_merge.json
```
## 执行流程
> **重要:默认使用子代理(SubAgent)分批次处理。** 生成题目是 token 密集型任务,为避免主会话上下文爆炸,应将每批题目的生成工作委派给子代理执行。主会话负责规划、确认和汇总。
### 阶段 0:与用户确认方案
**在执行任何操作之前,必须先与用户确认以下信息。** 不要假设默认值。
1. **子主题(subtopic)**:读取仓库中的 `topics/index.json`,列出可用的子主题供用户选择。如果用户已经指定了子主题,验证其是否存在。
2. **题型与数量**:询问用户需要生成哪些题型、每种多少道。可以一次性给出建议(如「建议先生成 10 道单选题 + 5 道判断题」),但最终必须等用户确认。
3. **展示确认摘要**:在开始生成前,向用户展示如下摘要并等待确认:
```
📋 生成方案确认
━━━━━━━━━━━━━━
子主题:gc-jvm(JVM 垃圾回收)
分组: qunar-ai-fullstack
题型: 单选 × 10、判断 × 5
━━━━━━━━━━━━━━
确认后开始生成 ✅
```
用户确认后才进入下一阶段。
### 阶段 1:克隆仓库
```bash
REPO_DIR=$(mktemp -d)
git clone --depth 1 ssh://git@47.121.181.112:222/wonder/examination.git "$REPO_DIR"
```
### 阶段 2:读取上下文(子代理)
派发一个子代理,执行以下任务:
- 读取 `topics/index.json` 确认子主题存在
- 读取该子主题的 `meta.json`(获取 tags、已有题目信息)
- 读取同类型已有的题目文件(获取已有 ID,避免重复)
- 将汇总信息返回给主会话
使用本 skill 自带的批量脚本 `scripts/read_context.json` 可以一次完成上述读取:
```
run_tool_batch(
file_path="<skill_dir>/scripts/read_context.json",
args={
"topics_dir": "<REPO_DIR>/topics",
"group": "<用户确认的分组>",
"subtopic": "<用户确认的子主题>",
"question_type": "<用户确认的题型>"
}
)
```
### 阶段 3:生成题目(子代理)
> **这是 token 消耗最大的阶段,务必使用子代理处理。**
根据阶段 2 返回的上下文,**为每种题型分别派发子代理**来生成题目。每个子代理的任务是:
1. 根据子主题内容和已有题目,生成指定数量的新题目
2. 严格遵循 Schema 格式(见下方「题目格式规范」)
3. 将生成的 JSON 写入临时文件(如 `/tmp/exam_gen_{type}_{batch}.json`)
**子代理提示词模板:**
```
你是题目生成专家。请为子主题 "{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 填空数组
【输出】
将完整 JSON 写入文件 /tmp/exam_gen_{type}_{batch}.json,格式:
{
"topic": "{subtopic_slug}",
"type": "{question_type}",
"schema_version": "1.0.0",
"generated": "{ISO 8601 时间戳}",
"questions": [ ... ]
}
```
**如果题目数量较多(如 > 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
━━━━━━━━━━━━━━━━━━━━━━
```
---
## 批量脚本参数
### read_context.json
| 参数 | 说明 | 示例 |
|------|------|------|
| `topics_dir` | 仓库内 `topics/` 目录的绝对路径 | `/tmp/xxxxx/topics` |
| `group` | 主题分组名 | `qunar-ai-fullstack` |
| `subtopic` | 子主题 slug | `gc-jvm` |
| `question_type` | 题型 | `single_choice` |
### validate_and_merge.json
| 参数 | 说明 | 示例 |
|------|------|------|
| `skill_dir` | 本 skill 目录的绝对路径 | `/home/.../skills/exam` |
| `topics_dir` | 同上 | 同上 |
| `group` | 同上 | 同上 |
| `subtopic` | 同上 | 同上 |
| `question_type` | 同上 | 同上 |
| `generated_file` | 生成的题目 JSON 文件绝对路径 | `/tmp/exam_gen_sc_1.json` |
## 批量执行失败处理
如果批量脚本执行失败:
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` 字段
---
## 备注
- 校验脚本优先使用 `jsonschema` 库(Python),不可用时回退到基础校验
- Node.js 校验脚本(`validate.mjs`)为纯内置模块,无外部依赖,可作为备选
- 合并脚本自动去重(基于 question ID),不会覆盖已有题目
- 元数据更新脚本自动计算 `question_files` 和 `stats.by_type` 统计信息
- 所有脚本退出码:0=成功,1=有错误,2=用法错误
- Schema 文件已内置于 `<skill_dir>/schema/question.schema.json`,与仓库版本一致