Files

9.8 KiB
Raw Permalink Blame History

name, description
name description
exam 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:克隆仓库

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:提交推送

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 的批量脚本以便下次正常使用?」

手动执行参考

读取上下文

cat "$REPO_DIR/topics/index.json"
cat "$REPO_DIR/topics/{group}/{subtopic}/meta.json"
cat "$REPO_DIR/topics/{group}/{subtopic}/{type}.json"  # 如果存在

校验

python3 <skill_dir>/scripts/validate.py /tmp/exam_generated.json

合并

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"

更新元数据

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,与仓库版本一致