init: edu-content 内容库骨架(L1-L4 四层数据模型 + B类迁移 + lint/CI 工具)

这个提交包含在:
2026-08-22 00:16:49 +08:00
当前提交 f18264111b
共有 79 个文件被更改,包括 7182 次插入 和 0 次删除

查看文件

@@ -0,0 +1,11 @@
# exams/amc8 — 结构化数据(L3)
本目录存放清洗后的可用数据。每条记录须带 `source.source_id`(指向 `sources/`)与 `schema` 版本。
## 消费须知
- 数据来源与 license:见 `sources/` 与根 `LICENSES.md`
- 格式 schema:见 `../../schemas/`(qb-1.1 / vocab-1.1)
- 新增记录请先确认 source 已在 `sources/` 登记
## 当前内容
(待填充)

查看文件

@@ -0,0 +1,11 @@
# exams/amc8/questions — 结构化数据(L3)
本目录存放清洗后的可用数据。每条记录须带 `source.source_id`(指向 `sources/`)与 `schema` 版本。
## 消费须知
- 数据来源与 license:见 `sources/` 与根 `LICENSES.md`
- 格式 schema:见 `../../schemas/`(qb-1.1 / vocab-1.1)
- 新增记录请先确认 source 已在 `sources/` 登记
## 当前内容
(待填充)

查看文件

@@ -0,0 +1,11 @@
# exams/cspj — 结构化数据(L3)
本目录存放清洗后的可用数据。每条记录须带 `source.source_id`(指向 `sources/`)与 `schema` 版本。
## 消费须知
- 数据来源与 license:见 `sources/` 与根 `LICENSES.md`
- 格式 schema:见 `../../schemas/`(qb-1.1 / vocab-1.1)
- 新增记录请先确认 source 已在 `sources/` 登记
## 当前内容
(待填充)

查看文件

@@ -0,0 +1,11 @@
# exams/cspj/knowledge — 结构化数据(L3)
本目录存放清洗后的可用数据。每条记录须带 `source.source_id`(指向 `sources/`)与 `schema` 版本。
## 消费须知
- 数据来源与 license:见 `sources/` 与根 `LICENSES.md`
- 格式 schema:见 `../../schemas/`(qb-1.1 / vocab-1.1)
- 新增记录请先确认 source 已在 `sources/` 登记
## 当前内容
(待填充)

查看文件

@@ -0,0 +1,11 @@
# exams/cspj/questions — 结构化数据(L3)
本目录存放清洗后的可用数据。每条记录须带 `source.source_id`(指向 `sources/`)与 `schema` 版本。
## 消费须知
- 数据来源与 license:见 `sources/` 与根 `LICENSES.md`
- 格式 schema:见 `../../schemas/`(qb-1.1 / vocab-1.1)
- 新增记录请先确认 source 已在 `sources/` 登记
## 当前内容
(待填充)

查看文件

@@ -0,0 +1,11 @@
# exams/fce — 结构化数据(L3)
本目录存放清洗后的可用数据。每条记录须带 `source.source_id`(指向 `sources/`)与 `schema` 版本。
## 消费须知
- 数据来源与 license:见 `sources/` 与根 `LICENSES.md`
- 格式 schema:见 `../../schemas/`(qb-1.1 / vocab-1.1)
- 新增记录请先确认 source 已在 `sources/` 登记
## 当前内容
(待填充)

查看文件

查看文件

@@ -0,0 +1,11 @@
# exams/fce/questions — 结构化数据(L3)
本目录存放清洗后的可用数据。每条记录须带 `source.source_id`(指向 `sources/`)与 `schema` 版本。
## 消费须知
- 数据来源与 license:见 `sources/` 与根 `LICENSES.md`
- 格式 schema:见 `../../schemas/`(qb-1.1 / vocab-1.1)
- 新增记录请先确认 source 已在 `sources/` 登记
## 当前内容
(待填充)

查看文件

查看文件

@@ -0,0 +1,11 @@
# exams/fce/vocab — 结构化数据(L3)
本目录存放清洗后的可用数据。每条记录须带 `source.source_id`(指向 `sources/`)与 `schema` 版本。
## 消费须知
- 数据来源与 license:见 `sources/` 与根 `LICENSES.md`
- 格式 schema:见 `../../schemas/`(qb-1.1 / vocab-1.1)
- 新增记录请先确认 source 已在 `sources/` 登记
## 当前内容
(待填充)

查看文件

@@ -0,0 +1,11 @@
# exams/ket — 结构化数据(L3)
本目录存放清洗后的可用数据。每条记录须带 `source.source_id`(指向 `sources/`)与 `schema` 版本。
## 消费须知
- 数据来源与 license:见 `sources/` 与根 `LICENSES.md`
- 格式 schema:见 `../../schemas/`(qb-1.1 / vocab-1.1)
- 新增记录请先确认 source 已在 `sources/` 登记
## 当前内容
(待填充)

查看文件

@@ -0,0 +1,44 @@
# 题库 INDEX — 数据总览与使用指南
> 更新:2026-08-21 | 格式规范见 [SCHEMA.md](SCHEMA.md)(qb-1.0)
## 一、现有数据
| 文件 | 级别 | 套数 | 空格/小题 | 多答案小题 | 来源 | 许可 |
|---|---|---|---|---|---|---|
| `cepoc-a2-key.jsonl` | A2 Key | 6 | 68 | 14 | CEPOC(剑桥 ALTA 官方开源) | `cc-nc-education` |
| `cepoc-b1-preliminary.jsonl` | B1 Preliminary | 21 | 150 | 24 | CEPOC | `cc-nc-education` |
| `p2/out/*.jsonl`(6 份) | A2+B1 | 6 卷 | 131 | — | 剑桥官方 2022 样卷 | `official-free` |
| **合计** | | **33** | **349** | | | |
> P2 详情(成功率 112/112 对账、token 成本、风险点)见 [p2/P2-REPORT.md](p2/P2-REPORT.md)。解析器:pymupdf4llm。
## 二、待入库(已规划)
| 优先级 | 数据 | 预估规模 | 许可 |
|---|---|---|---|
| ~~P3~~ | ~~官方词表 → 词库~~ **已完成** → 见 [../vocab/INDEX.md](../vocab/INDEX.md)(A2 1740 + B1 3172 词条) | — | `official-free` |
| ~~P3.5~~ | ~~词库中文释义+音标~~ **已完成** → 见 [../vocab/INDEX.md](../vocab/INDEX.md) §三·五(ECDICT 4804 + LLM 98,音标覆盖 93.3%) | 4902 条 | ECDICT `CC-BY-SA-4.0` / LLM 生成 |
| P4 | tape script + mp3 精听语料 | 2 套对齐文本 | `official-free` |
| P5 | SkoolPlus 教材(ECS 下载后) | 20+ 套模拟题 | `restricted`(仅本地) |
## 三、下游 agent 使用须知
1. **读库**:JSONL 逐行 `json.loads`;一条记录 = 一个任务(语篇+多小题),不是单题
2. **判题**:必须按 SCHEMA.md 第二节规则——`strip` + 大小写不敏感 + `answers_accept` 集合匹配;38 个空有多个可接受答案(如 `["because","as","since"]`),字符串全等会误判
3. **许可红线**(按 `license` 字段过滤):
- `official-free` → 可进部署的英语门户
- `cc-nc-education`(CEPOC 全部数据)→ 自用/练习工具可以,**禁止商业化与再分发**
- `restricted` → 任何对外输出都不允许出现
4. **完形上下文切分**:`passage.split(blank_token)`,段数 = 空数 + 1
5. **CEPOC 的 `part` 为 null**:数据混有 2020 改版前真题(KET 11-12 空/套、PET 6-8 空/套),与新版题型空数不符,见记录内 `note` 字段
6. **P2 记录的媒体引用**:`meta.media[].path` 与 `meta.audio` 为相对路径(前者相对 question-bank 目录,后者相对 english-site 目录);图片选项题(听力 Part 1)`options=null`,必须渲染 `meta.media` 图片作答
## 四、复现
```bash
cd data/question-bank
python3 scripts/convert_cepoc.py <cepoc-main 绝对路径> .
```
转换脚本内置校验:空格数与小题数一致、题号不重复、答案非空、id 唯一。2026-08-21 校验全部通过。

查看文件

@@ -0,0 +1,6 @@
{"schema": "qb-1.1", "id": "a2k-cepoc-0001", "exam": "A2 Key", "cefr": "A2", "paper": "reading_writing", "part": null, "type": "open_cloze", "task_prompt": "For each gap, write ONE word which best completes the text.", "title": null, "passage": "Dear Melissa\n\nHow are things _ London? I had a great time staying with you. Thank you for looking after _ . You are _ great cook and your family were really kind to me. And my English is much better now _ it was before. \n\nMy flight home was fine – there were _ delays at all. It’s good to be back, but I miss you all very _ !\n\n_ you remember my friend Jenny? I think she came _ visit me at your house once _ twice. Well, she took some great photos _ us on our last day at the language school. I’m sending you one with this email. I hope you like \n\n_ .\n\nRosario", "blank_token": "_", "items": [{"no": 1, "stem": null, "options": null, "answers_accept": ["in"], "answer_official": "in", "explain": null, "tags": []}, {"no": 2, "stem": null, "options": null, "answers_accept": ["me"], "answer_official": "me", "explain": null, "tags": []}, {"no": 3, "stem": null, "options": null, "answers_accept": ["a"], "answer_official": "a", "explain": null, "tags": []}, {"no": 4, "stem": null, "options": null, "answers_accept": ["than"], "answer_official": "than", "explain": null, "tags": []}, {"no": 5, "stem": null, "options": null, "answers_accept": ["no"], "answer_official": "no", "explain": null, "tags": []}, {"no": 6, "stem": null, "options": null, "answers_accept": ["much"], "answer_official": "much", "explain": null, "tags": []}, {"no": 7, "stem": null, "options": null, "answers_accept": ["Do"], "answer_official": "Do", "explain": null, "tags": []}, {"no": 8, "stem": null, "options": null, "answers_accept": ["to"], "answer_official": "to", "explain": null, "tags": []}, {"no": 9, "stem": null, "options": null, "answers_accept": ["or"], "answer_official": "or", "explain": null, "tags": []}, {"no": 10, "stem": null, "options": null, "answers_accept": ["of"], "answer_official": "of", "explain": null, "tags": []}, {"no": 11, "stem": null, "options": null, "answers_accept": ["it"], "answer_official": "it", "explain": null, "tags": []}], "source": {"origin": "cepoc", "file": "assets/open-source/cepoc-main/KET.json", "orig_id": 1, "url": "https://github.com/CambridgeALTA/cepoc", "retrieved": "2026-08-21", "source_id": "cepoc", "source_item_id": "cepoc-ket-json"}, "license": "cc-nc-education", "tags": ["cloze", "open_cloze"], "note": "CEPOC 未标注套题年份与卷内 Part 号;空格数与 2020 版题型不完全对应(KET 11-12空/套、PET 6-8空/套),推断混有 2020 改版前真题。完形题型本身对应 A2 Key Reading & Writing / B1 Preliminary Reading 的 open cloze 题型。", "meta": {"multi_answer_items": 0}}
{"schema": "qb-1.1", "id": "a2k-cepoc-0002", "exam": "A2 Key", "cefr": "A2", "paper": "reading_writing", "part": null, "type": "open_cloze", "task_prompt": "For each gap, write ONE word which best completes the text.", "title": null, "passage": "Dear Aunt Fabienne,\n\nMum asked _ to let you know that I arrived home okay. I enjoyed travelling back _ the train, and I was surprised that _ only took me three hours to get home. Thank you very _ for looking after me _ I was in France. \n\nI’m going back to school _ week. My French is a lot better _ it was before, so I hope my marks will improve!\n\nI _ like to keep practising French and I’m looking _ a pen friend. I thought of your friend’s son Elian. We could email each _ once a week. Let me know _ you think.\n\nI hope _ see you soon. \n\nDaniel", "blank_token": "_", "items": [{"no": 1, "stem": null, "options": null, "answers_accept": ["me"], "answer_official": "me", "explain": null, "tags": []}, {"no": 2, "stem": null, "options": null, "answers_accept": ["on"], "answer_official": "on", "explain": null, "tags": []}, {"no": 3, "stem": null, "options": null, "answers_accept": ["it"], "answer_official": "it", "explain": null, "tags": []}, {"no": 4, "stem": null, "options": null, "answers_accept": ["much"], "answer_official": "much", "explain": null, "tags": []}, {"no": 5, "stem": null, "options": null, "answers_accept": ["when", "while"], "answer_official": "when", "explain": null, "tags": []}, {"no": 6, "stem": null, "options": null, "answers_accept": ["next", "this"], "answer_official": "next", "explain": null, "tags": []}, {"no": 7, "stem": null, "options": null, "answers_accept": ["than"], "answer_official": "than", "explain": null, "tags": []}, {"no": 8, "stem": null, "options": null, "answers_accept": ["would", "'d"], "answer_official": "would", "explain": null, "tags": []}, {"no": 9, "stem": null, "options": null, "answers_accept": ["for"], "answer_official": "for", "explain": null, "tags": []}, {"no": 10, "stem": null, "options": null, "answers_accept": ["other"], "answer_official": "other", "explain": null, "tags": []}, {"no": 11, "stem": null, "options": null, "answers_accept": ["what"], "answer_official": "what", "explain": null, "tags": []}, {"no": 12, "stem": null, "options": null, "answers_accept": ["to", "I'll", "we'll"], "answer_official": "to", "explain": null, "tags": []}], "source": {"origin": "cepoc", "file": "assets/open-source/cepoc-main/KET.json", "orig_id": 2, "url": "https://github.com/CambridgeALTA/cepoc", "retrieved": "2026-08-21", "source_id": "cepoc", "source_item_id": "cepoc-ket-json"}, "license": "cc-nc-education", "tags": ["cloze", "open_cloze"], "note": "CEPOC 未标注套题年份与卷内 Part 号;空格数与 2020 版题型不完全对应(KET 11-12空/套、PET 6-8空/套),推断混有 2020 改版前真题。完形题型本身对应 A2 Key Reading & Writing / B1 Preliminary Reading 的 open cloze 题型。", "meta": {"multi_answer_items": 4}}
{"schema": "qb-1.1", "id": "a2k-cepoc-0003", "exam": "A2 Key", "cefr": "A2", "paper": "reading_writing", "part": null, "type": "open_cloze", "task_prompt": "For each gap, write ONE word which best completes the text.", "title": null, "passage": "Hi Marta,\n\nI hope _ are well. I was trying _ call you yesterday but you didn’t answer. Is your phone broken, _ have you lost it again? \n\nAnyway, I wanted to ask _ you can come to my birthday party next Saturday. My birthday was actually two weeks _ , but I couldn’t have the party then _ lots of people were _ holiday. \n\nI’ve invited _ few people from our swimming club, as well as my friends from school. _ you think your brother _ free that day? Please invite _ to come too. The party’s at my house and starts at 8p.m. \n\nParveen", "blank_token": "_", "items": [{"no": 1, "stem": null, "options": null, "answers_accept": ["you"], "answer_official": "you", "explain": null, "tags": []}, {"no": 2, "stem": null, "options": null, "answers_accept": ["to"], "answer_official": "to", "explain": null, "tags": []}, {"no": 3, "stem": null, "options": null, "answers_accept": ["or"], "answer_official": "or", "explain": null, "tags": []}, {"no": 4, "stem": null, "options": null, "answers_accept": ["if", "whether"], "answer_official": "if", "explain": null, "tags": []}, {"no": 5, "stem": null, "options": null, "answers_accept": ["ago"], "answer_official": "ago", "explain": null, "tags": []}, {"no": 6, "stem": null, "options": null, "answers_accept": ["because", "as"], "answer_official": "because", "explain": null, "tags": []}, {"no": 7, "stem": null, "options": null, "answers_accept": ["on"], "answer_official": "on", "explain": null, "tags": []}, {"no": 8, "stem": null, "options": null, "answers_accept": ["a"], "answer_official": "a", "explain": null, "tags": []}, {"no": 9, "stem": null, "options": null, "answers_accept": ["Do"], "answer_official": "Do", "explain": null, "tags": []}, {"no": 10, "stem": null, "options": null, "answers_accept": ["is"], "answer_official": "is", "explain": null, "tags": []}, {"no": 11, "stem": null, "options": null, "answers_accept": ["him"], "answer_official": "him", "explain": null, "tags": []}], "source": {"origin": "cepoc", "file": "assets/open-source/cepoc-main/KET.json", "orig_id": 3, "url": "https://github.com/CambridgeALTA/cepoc", "retrieved": "2026-08-21", "source_id": "cepoc", "source_item_id": "cepoc-ket-json"}, "license": "cc-nc-education", "tags": ["cloze", "open_cloze"], "note": "CEPOC 未标注套题年份与卷内 Part 号;空格数与 2020 版题型不完全对应(KET 11-12空/套、PET 6-8空/套),推断混有 2020 改版前真题。完形题型本身对应 A2 Key Reading & Writing / B1 Preliminary Reading 的 open cloze 题型。", "meta": {"multi_answer_items": 2}}
{"schema": "qb-1.1", "id": "a2k-cepoc-0004", "exam": "A2 Key", "cefr": "A2", "paper": "reading_writing", "part": null, "type": "open_cloze", "task_prompt": "For each gap, write ONE word which best completes the text.", "title": null, "passage": "Hi Marcia, \n\nDo you remember I wanted _ invite you, Sasha and John to my new house? Well, _ about next Saturday evening? We _ a beautiful garden with lots _ trees. We may have a barbeque outside _ it doesn’t rain. My mother is _ really good cook and I _ going to help her make the food. \n\nAfterwards, _ don’t we watch a film? _ you bring a DVD with you as I haven’t got many here? \n\nJohn’s coming _ bike and Sasha is getting a lift _ her father. I hope you’ll be able to come too. \n\nLet me know soon!\n\nConny", "blank_token": "_", "items": [{"no": 1, "stem": null, "options": null, "answers_accept": ["to"], "answer_official": "to", "explain": null, "tags": []}, {"no": 2, "stem": null, "options": null, "answers_accept": ["what", "how"], "answer_official": "what", "explain": null, "tags": []}, {"no": 3, "stem": null, "options": null, "answers_accept": ["have"], "answer_official": "have", "explain": null, "tags": []}, {"no": 4, "stem": null, "options": null, "answers_accept": ["of"], "answer_official": "of", "explain": null, "tags": []}, {"no": 5, "stem": null, "options": null, "answers_accept": ["if"], "answer_official": "if", "explain": null, "tags": []}, {"no": 6, "stem": null, "options": null, "answers_accept": ["a"], "answer_official": "a", "explain": null, "tags": []}, {"no": 7, "stem": null, "options": null, "answers_accept": ["am", "'m"], "answer_official": "am", "explain": null, "tags": []}, {"no": 8, "stem": null, "options": null, "answers_accept": ["why"], "answer_official": "why", "explain": null, "tags": []}, {"no": 9, "stem": null, "options": null, "answers_accept": ["Can", "Could"], "answer_official": "Can", "explain": null, "tags": []}, {"no": 10, "stem": null, "options": null, "answers_accept": ["by"], "answer_official": "by", "explain": null, "tags": []}, {"no": 11, "stem": null, "options": null, "answers_accept": ["from", "with"], "answer_official": "from", "explain": null, "tags": []}], "source": {"origin": "cepoc", "file": "assets/open-source/cepoc-main/KET.json", "orig_id": 4, "url": "https://github.com/CambridgeALTA/cepoc", "retrieved": "2026-08-21", "source_id": "cepoc", "source_item_id": "cepoc-ket-json"}, "license": "cc-nc-education", "tags": ["cloze", "open_cloze"], "note": "CEPOC 未标注套题年份与卷内 Part 号;空格数与 2020 版题型不完全对应(KET 11-12空/套、PET 6-8空/套),推断混有 2020 改版前真题。完形题型本身对应 A2 Key Reading & Writing / B1 Preliminary Reading 的 open cloze 题型。", "meta": {"multi_answer_items": 4}}
{"schema": "qb-1.1", "id": "a2k-cepoc-0005", "exam": "A2 Key", "cefr": "A2", "paper": "reading_writing", "part": null, "type": "open_cloze", "task_prompt": "For each gap, write ONE word which best completes the text.", "title": null, "passage": "How _ you? I’m writing to you _ I need your help.\n\nI’m starting a business course at college _ term. The teacher has asked us to do some office work during _ summer. Your Dad’s _ manager, isn’t he? Can you ask him _ I can work with him? I only need to work _ a few weeks, and he will _ have to pay me anything.\n\nAlso, can I stay _ you while I’m working? Mum says it’s much _ far to go by bike _ day. Tell your mum that I can make _ own meals, so she won’t have to cook for me.\n\nThanks.", "blank_token": "_", "items": [{"no": 1, "stem": null, "options": null, "answers_accept": ["are"], "answer_official": "are", "explain": null, "tags": []}, {"no": 2, "stem": null, "options": null, "answers_accept": ["because", "as", "since"], "answer_official": "because", "explain": null, "tags": []}, {"no": 3, "stem": null, "options": null, "answers_accept": ["this", "next"], "answer_official": "this", "explain": null, "tags": []}, {"no": 4, "stem": null, "options": null, "answers_accept": ["the"], "answer_official": "the", "explain": null, "tags": []}, {"no": 5, "stem": null, "options": null, "answers_accept": ["a"], "answer_official": "a", "explain": null, "tags": []}, {"no": 6, "stem": null, "options": null, "answers_accept": ["if"], "answer_official": "if", "explain": null, "tags": []}, {"no": 7, "stem": null, "options": null, "answers_accept": ["for"], "answer_official": "for", "explain": null, "tags": []}, {"no": 8, "stem": null, "options": null, "answers_accept": ["not"], "answer_official": "not", "explain": null, "tags": []}, {"no": 9, "stem": null, "options": null, "answers_accept": ["with"], "answer_official": "with", "explain": null, "tags": []}, {"no": 10, "stem": null, "options": null, "answers_accept": ["too"], "answer_official": "too", "explain": null, "tags": []}, {"no": 11, "stem": null, "options": null, "answers_accept": ["each", "every"], "answer_official": "each", "explain": null, "tags": []}, {"no": 12, "stem": null, "options": null, "answers_accept": ["my"], "answer_official": "my", "explain": null, "tags": []}], "source": {"origin": "cepoc", "file": "assets/open-source/cepoc-main/KET.json", "orig_id": 5, "url": "https://github.com/CambridgeALTA/cepoc", "retrieved": "2026-08-21", "source_id": "cepoc", "source_item_id": "cepoc-ket-json"}, "license": "cc-nc-education", "tags": ["cloze", "open_cloze"], "note": "CEPOC 未标注套题年份与卷内 Part 号;空格数与 2020 版题型不完全对应(KET 11-12空/套、PET 6-8空/套),推断混有 2020 改版前真题。完形题型本身对应 A2 Key Reading & Writing / B1 Preliminary Reading 的 open cloze 题型。", "meta": {"multi_answer_items": 3}}
{"schema": "qb-1.1", "id": "a2k-cepoc-0006", "exam": "A2 Key", "cefr": "A2", "paper": "reading_writing", "part": null, "type": "open_cloze", "task_prompt": "For each gap, write ONE word which best completes the text.", "title": null, "passage": "Welcome _ my blog! My name’s Lauren and I’m 22 years old. I come from\n\nIllinois in the USA, but _ the moment I’m studying in Florence, in Italy.\n\nI’m living _ a friend of mine from university. Our apartment _ in the centre of town, so we don’t _ to use the buses – we can walk everywhere. I have classes most days, but in _ afternoon, I explore the city or _ swimming. When _ is sunny I visit the Boboli Gardens. _ are beautiful views of Florence from here.\n\nI _ you enjoy my blog. _ you have any questions, please leave me a message.", "blank_token": "_", "items": [{"no": 1, "stem": null, "options": null, "answers_accept": ["to"], "answer_official": "to", "explain": null, "tags": []}, {"no": 2, "stem": null, "options": null, "answers_accept": ["at"], "answer_official": "at", "explain": null, "tags": []}, {"no": 3, "stem": null, "options": null, "answers_accept": ["with"], "answer_official": "with", "explain": null, "tags": []}, {"no": 4, "stem": null, "options": null, "answers_accept": ["is"], "answer_official": "is", "explain": null, "tags": []}, {"no": 5, "stem": null, "options": null, "answers_accept": ["have", "need"], "answer_official": "have", "explain": null, "tags": []}, {"no": 6, "stem": null, "options": null, "answers_accept": ["the"], "answer_official": "the", "explain": null, "tags": []}, {"no": 7, "stem": null, "options": null, "answers_accept": ["go"], "answer_official": "go", "explain": null, "tags": []}, {"no": 8, "stem": null, "options": null, "answers_accept": ["it"], "answer_official": "it", "explain": null, "tags": []}, {"no": 9, "stem": null, "options": null, "answers_accept": ["There"], "answer_official": "There", "explain": null, "tags": []}, {"no": 10, "stem": null, "options": null, "answers_accept": ["hope"], "answer_official": "hope", "explain": null, "tags": []}, {"no": 11, "stem": null, "options": null, "answers_accept": ["If"], "answer_official": "If", "explain": null, "tags": []}], "source": {"origin": "cepoc", "file": "assets/open-source/cepoc-main/KET.json", "orig_id": 6, "url": "https://github.com/CambridgeALTA/cepoc", "retrieved": "2026-08-21", "source_id": "cepoc", "source_item_id": "cepoc-ket-json"}, "license": "cc-nc-education", "tags": ["cloze", "open_cloze"], "note": "CEPOC 未标注套题年份与卷内 Part 号;空格数与 2020 版题型不完全对应(KET 11-12空/套、PET 6-8空/套),推断混有 2020 改版前真题。完形题型本身对应 A2 Key Reading & Writing / B1 Preliminary Reading 的 open cloze 题型。", "meta": {"multi_answer_items": 1}}

查看文件

@@ -0,0 +1,101 @@
# 词库 INDEX — 数据总览与使用指南
> 更新:2026-08-21 | 解析器:`scripts/parse_vocab.py`(pymupdf,纯规则解析,零 LLM 成本)
> 对应计划:题库路线 P3(官方词表 → 结构化词库)+ P3.5(词库增补:中文释义 + IPA 音标)
> 增补管线:`scripts/enrich_gloss.py`(ECDICT 匹配)+ `scripts/make_llm.py`(LLM 增补)+ `scripts/finalize_vocab.py`(音标格式统一 + 补常用词音标)
## 一、现有数据
| 文件 | 级别 | 主表词条 | 仅主题表补充词 | 合计 | 其中 B1 新增 | 来源 | 许可 |
|---|---|---|---|---|---|---|---|
| `a2-key-vocab.jsonl` | A2 Key / for Schools | 1727 | 13 | **1740** | — | 剑桥官方词汇表(2025-08 版) | `official-free` |
| `b1-preliminary-vocab.jsonl` | B1 Preliminary / for Schools | 3055 | 117 | **3172** | 1517(`new_at_b1=true`) | 剑桥官方词汇表(2020 版) | `official-free` |
| `word-sets.json` | A2+B1 通用 | — | — | 6 个词集 | — | Appendix 1(规则生成) | `official-free` |
主题(topic)覆盖:A2 25 个 / B1 23 个(Clothes、Education、Food and Drink、Travel and Transport、Work and Jobs 等)。
## 二、记录结构(每行一个词条)
```json
{
"id": "a2k-vocab-0091",
"level": "A2",
"headword": "attractive", // 原样保留, 含变体斜杠 "café/cafe"、缩写 "(kg)"
"pos": ["adj"], // 词性数组; 多词词性整体保留: "phr v"/"prep phr"/"aux v"
"pos_notes": null, // 用法/地区注记: ["+ ing"], ["(Br Eng) (Am Eng: bathing suit)"], ["unc (uncountable)"]
"examples": [{"text": "The walls are an attractive colour.", "pos": null}],
"phrases": null, // 子短语/搭配: "(be) bad for somebody", "bright pink"
"topics": ["Clothes and Accessories"], // 来自 Appendix 2 主题表
"origin": "main_list", // main_list=字母序主表 / topic_list=仅出现在主题表
"no_pos": true, // 仅少数: PDF 原文无词性标注 (如 "film star")
"new_at_b1": false, // 仅 B1 文件: 该词不在 A2 词表 = B1 新增
"source": {"file": "...", "url": "...", "publisher": "Cambridge English / UCLES", "licence": "official-free"},
"gloss": { // P3.5 增补: 中文释义 + IPA 音标
"zh": "n. 苹果", // 带词性前缀的中文释义
"phonetic": "/ˈæpl/", // 英式 IPA, 统一包裹为 /.../
"source": "ecdict", // ★ 来源标注: "ecdict"=ECDICT 开源词典 / "llm"=LLM 生成
"licence": "CC-BY-SA-4.0", // ecdict 对应 CC-BY-SA-4.0; llm 对应 llm-generated
"phonetic_source": "llm" // 可选: 仅当音标由 LLM 补、释义来自 ECDICT 时出现
}
}
```
## 三、下游 agent 使用须知
1. **背单词优先序**(推荐):A2 全部 → B1 中 `new_at_b1=true` 的 1517 词 → topic_list 补充词。两级共约 3257 去重词条。
2. **例句仍是稀缺资源**:官方词表仅约 11% 词条带例句(A2 170 / B1 218 条),主要标注多义词的分用法。**中文释义与音标已通过 P3.5 增补进 `gloss` 字段**(见 §三·五),但例句本身未生成。
3. **主题背诵**:`topics` 字段支持按场景刷词(如先攻 Food and Drink);同一词可属多个主题。
4. **词性坑**:`be` 的词性是 `["aux v","v"]`(PDF 原文缩写 "av",按剑桥缩写表解释为助动词);不可数名词注记在 `pos_notes`(如 rubbish)。
5. **topic_only 词**(A2 13 / B1 117):官方明确为"考生还应知道的补充词"(如 get dressed、climate change),无例句无主表词性,但 `pos` 可能来自主题表标注。
6. **变体词头**:`trainers`(topic)与 `trainer`(主表)已按复数回退匹配;但 A2 主表无 trainer,故 A2 里 trainers 仍是独立补充词。
7. **word-sets.json**:基数/序数/星期/月份/季节/大洲为确定性生成集;国家·语言·民族开放集合未枚举(官方用 etc.),需要时另行补表。
8. **许可**:全部 `official-free`,可进部署门户;但 PDF 内的 "Additions in green"(2025 新增词标记)在文本层无颜色信息,未能结构化。
## 三·五、P3.5 增补说明(中文释义 + IPA 音标)
官方 PDF 无中文释义、无音标,本步补齐 `gloss` 字段(每条记录已写入,无遗漏)。
**来源标注(用户要求:区分「原词条」与「LLM 增补」)**
- `gloss.source = "ecdict"`:中文释义来自 **ECDICT** 开源英汉词典(CC-BY-SA-4.0),词典级数据,覆盖约 98%。
- `gloss.source = "llm"`:ECDICT 未命中的残余词头(多为短语/复合词/剑桥多义分项,如 `deal with`、`smart (clever)`、`social media`),由 **LLM 生成**中文释义 + 音标(`licence: llm-generated`)。共 98 条记录(83 个去重词头)。
- `gloss.phonetic_source = "llm"`(可选):仅 97 条「释义来自 ECDICT、但 ECDICT 原条目缺音标」的常用单词,音标由 LLM 补、释义 provenance 不变。
**覆盖统计(4902 条)**
| 指标 | 数值 |
|---|---|
| `gloss` 覆盖率 | 100%(4902/4902) |
| `source=ecdict` | 4804 条 |
| `source=llm` | 98 条 |
| 有音标 | 4576 条(93.3%) |
| 无音标 | 326 条(6.7%,**全部为短语/多词**,如 `a few`、`alarm clock`) |
**为什么短语留空音标**:学习者已掌握组成单词的发音,短语整体音标优先级低;若后续需要可单独补(g2p 模型或 LLM)。
**管线与复现**
```bash
cd english-site
python scripts/enrich_gloss.py match # ECDICT 匹配 -> _gloss_cache/ecdict.json
python scripts/make_llm.py # LLM 增补 83 词 -> _gloss_cache/llm.json
python scripts/enrich_gloss.py merge # 合并写回 *.jsonl
python scripts/finalize_vocab.py # 音标统一 /.../ + 补 71 常用单词音标
```
> ECDICT 原始数据:`assets/vocab/ecdict/`(StarDict 格式,67MB,从 github release 经 gh-proxy 镜像下载)。清洗规则见 `enrich_gloss.py: clean_entry`(剥离词频/考试标签、西里尔 ә→ə、ASCII 撇号→IPA 重音符等)。
## 四、已知局限(诚实披露)
- ~~官方 PDF 无中文释义、无音标~~ → 已在 P3.5 通过 ECDICT + LLM 增补进 `gloss` 字段(见 §三·五);仅 326 条短语(6.7%)因 ECDICT 无音标而留空,释义仍在。
- `film star`、`zebra` 等 2 个 B1 词条原文无词性(`no_pos=true`),非解析丢失。
- `driving/driver's licence` 等极少数跨行词头的地区变体注记可能不完整(已抽查主流 5 例均正确)。
- B1 词表基于 2018 © 版本(2020 起生效),A2 基于 2025-08 版,两版之间 A2 的新增词(若 B1 版本更旧)不影响 `new_at_b1` 的判断方向,但个别词的归属可能滞后。
## 五、复现
```bash
cd english-site
python scripts/parse_vocab.py # 输出到 data/vocab/, 隔离区 0 条, id 唯一校验通过
```
## 六、素材勘误(相对调研报告)
- `assets/vocab/b1-preliminary-vocabulary-booklet.pdf`(8MB)**不是词表**,是《B1 for Schools 词汇教学活动手册》(教师用),保留作教学设计参考。
- B1 官方词表直链 `cambridgeenglish.org/Images/506887-*.pdf` 已 404,改用 **cambridgeenglish.cn 域名**下载成功(文件已存 `assets/vocab/b1-preliminary-2020-vocabulary-list.pdf`)。

文件差异内容过多而无法显示 加载差异

查看文件

@@ -0,0 +1,201 @@
{
"note": "Appendix 1 Word sets 为开放集合(官方原文用 etc.), 此处按规则生成确定词集。国家/语言/民族名开放集合未枚举, 需另行补表。",
"levels": [
"A2",
"B1"
],
"sets": [
{
"name": "Cardinal numbers (one to one hundred + hundred/thousand)",
"words": [
"eight",
"eighteen",
"eighty",
"eighty-eight",
"eighty-five",
"eighty-four",
"eighty-nine",
"eighty-one",
"eighty-seven",
"eighty-six",
"eighty-three",
"eighty-two",
"eleven",
"fifteen",
"fifty",
"fifty-eight",
"fifty-five",
"fifty-four",
"fifty-nine",
"fifty-one",
"fifty-seven",
"fifty-six",
"fifty-three",
"fifty-two",
"five",
"forty",
"forty-eight",
"forty-five",
"forty-four",
"forty-nine",
"forty-one",
"forty-seven",
"forty-six",
"forty-three",
"forty-two",
"four",
"fourteen",
"hundred",
"nine",
"nineteen",
"ninety",
"ninety-eight",
"ninety-five",
"ninety-four",
"ninety-nine",
"ninety-one",
"ninety-seven",
"ninety-six",
"ninety-three",
"ninety-two",
"one",
"seven",
"seventeen",
"seventy",
"seventy-eight",
"seventy-five",
"seventy-four",
"seventy-nine",
"seventy-one",
"seventy-seven",
"seventy-six",
"seventy-three",
"seventy-two",
"six",
"sixteen",
"sixty",
"sixty-eight",
"sixty-five",
"sixty-four",
"sixty-nine",
"sixty-one",
"sixty-seven",
"sixty-six",
"sixty-three",
"sixty-two",
"ten",
"thirteen",
"thirty",
"thirty-eight",
"thirty-five",
"thirty-four",
"thirty-nine",
"thirty-one",
"thirty-seven",
"thirty-six",
"thirty-three",
"thirty-two",
"thousand",
"three",
"twelve",
"twenty",
"twenty-eight",
"twenty-five",
"twenty-four",
"twenty-nine",
"twenty-one",
"twenty-seven",
"twenty-six",
"twenty-three",
"twenty-two",
"two"
]
},
{
"name": "Ordinal numbers (first to thirty-first)",
"words": [
"first",
"second",
"third",
"fourth",
"fifth",
"sixth",
"seventh",
"eighth",
"ninth",
"tenth",
"eleventh",
"twelfth",
"thirteenth",
"fourteenth",
"fifteenth",
"sixteenth",
"seventeenth",
"eighteenth",
"nineteenth",
"twentyth",
"twenty-first",
"twenty-second",
"twenty-third",
"twenty-fourth",
"twenty-fifth",
"twenty-sixth",
"twenty-seventh",
"twenty-eighth",
"twenty-ninth",
"thirtieth",
"thirty-first"
]
},
{
"name": "Days of the week",
"words": [
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday"
]
},
{
"name": "Months of the year",
"words": [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
]
},
{
"name": "Seasons of the year",
"words": [
"spring",
"summer",
"autumn",
"winter"
]
},
{
"name": "Continents",
"words": [
"Africa",
"Antarctica",
"Asia",
"Australia",
"Europe",
"North America",
"South America"
]
}
]
}

查看文件

@@ -0,0 +1,11 @@
# exams/pet — 结构化数据(L3)
本目录存放清洗后的可用数据。每条记录须带 `source.source_id`(指向 `sources/`)与 `schema` 版本。
## 消费须知
- 数据来源与 license:见 `sources/` 与根 `LICENSES.md`
- 格式 schema:见 `../../schemas/`(qb-1.1 / vocab-1.1)
- 新增记录请先确认 source 已在 `sources/` 登记
## 当前内容
(待填充)

查看文件

@@ -0,0 +1,44 @@
# 题库 INDEX — 数据总览与使用指南
> 更新:2026-08-21 | 格式规范见 [SCHEMA.md](SCHEMA.md)(qb-1.0)
## 一、现有数据
| 文件 | 级别 | 套数 | 空格/小题 | 多答案小题 | 来源 | 许可 |
|---|---|---|---|---|---|---|
| `cepoc-a2-key.jsonl` | A2 Key | 6 | 68 | 14 | CEPOC(剑桥 ALTA 官方开源) | `cc-nc-education` |
| `cepoc-b1-preliminary.jsonl` | B1 Preliminary | 21 | 150 | 24 | CEPOC | `cc-nc-education` |
| `p2/out/*.jsonl`(6 份) | A2+B1 | 6 卷 | 131 | — | 剑桥官方 2022 样卷 | `official-free` |
| **合计** | | **33** | **349** | | | |
> P2 详情(成功率 112/112 对账、token 成本、风险点)见 [p2/P2-REPORT.md](p2/P2-REPORT.md)。解析器:pymupdf4llm。
## 二、待入库(已规划)
| 优先级 | 数据 | 预估规模 | 许可 |
|---|---|---|---|
| ~~P3~~ | ~~官方词表 → 词库~~ **已完成** → 见 [../vocab/INDEX.md](../vocab/INDEX.md)(A2 1740 + B1 3172 词条) | — | `official-free` |
| ~~P3.5~~ | ~~词库中文释义+音标~~ **已完成** → 见 [../vocab/INDEX.md](../vocab/INDEX.md) §三·五(ECDICT 4804 + LLM 98,音标覆盖 93.3%) | 4902 条 | ECDICT `CC-BY-SA-4.0` / LLM 生成 |
| P4 | tape script + mp3 精听语料 | 2 套对齐文本 | `official-free` |
| P5 | SkoolPlus 教材(ECS 下载后) | 20+ 套模拟题 | `restricted`(仅本地) |
## 三、下游 agent 使用须知
1. **读库**:JSONL 逐行 `json.loads`;一条记录 = 一个任务(语篇+多小题),不是单题
2. **判题**:必须按 SCHEMA.md 第二节规则——`strip` + 大小写不敏感 + `answers_accept` 集合匹配;38 个空有多个可接受答案(如 `["because","as","since"]`),字符串全等会误判
3. **许可红线**(按 `license` 字段过滤):
- `official-free` → 可进部署的英语门户
- `cc-nc-education`(CEPOC 全部数据)→ 自用/练习工具可以,**禁止商业化与再分发**
- `restricted` → 任何对外输出都不允许出现
4. **完形上下文切分**:`passage.split(blank_token)`,段数 = 空数 + 1
5. **CEPOC 的 `part` 为 null**:数据混有 2020 改版前真题(KET 11-12 空/套、PET 6-8 空/套),与新版题型空数不符,见记录内 `note` 字段
6. **P2 记录的媒体引用**:`meta.media[].path` 与 `meta.audio` 为相对路径(前者相对 question-bank 目录,后者相对 english-site 目录);图片选项题(听力 Part 1)`options=null`,必须渲染 `meta.media` 图片作答
## 四、复现
```bash
cd data/question-bank
python3 scripts/convert_cepoc.py <cepoc-main 绝对路径> .
```
转换脚本内置校验:空格数与小题数一致、题号不重复、答案非空、id 唯一。2026-08-21 校验全部通过。

查看文件

@@ -0,0 +1,21 @@
{"schema": "qb-1.1", "id": "b1-cepoc-0001", "exam": "B1 Preliminary", "cefr": "B1", "paper": "reading", "part": null, "type": "open_cloze", "task_prompt": "For each gap, write ONE word which best completes the text.", "title": "A trip to the theatre", "passage": "We had a class day out today. We went on a theatre trip _ see Shakespeare’s play Hamlet. A friend of mine, _ has always been really into Shakespeare, had already told me the story. Basically, Hamlet discovers a terrible secret about his family, but he can’t decide _ to do about it. I won’t say any more about the story, in _ you decide to go and see it as well. I’d hate to spoil it _ you! The only thing I didn’t like about the play was _ fact that it lasted four hours. For me, that was far _ long, and the seats were quite uncomfortable. Afterwards, my mum asked me _ I’d go and see another Shakespeare play. I said yes, probably, but I’d take a cushion next time!", "blank_token": "_", "items": [{"no": 1, "stem": null, "options": null, "answers_accept": ["to"], "answer_official": "to", "explain": null, "tags": []}, {"no": 2, "stem": null, "options": null, "answers_accept": ["who"], "answer_official": "who", "explain": null, "tags": []}, {"no": 3, "stem": null, "options": null, "answers_accept": ["what"], "answer_official": "what", "explain": null, "tags": []}, {"no": 4, "stem": null, "options": null, "answers_accept": ["case"], "answer_official": "case", "explain": null, "tags": []}, {"no": 5, "stem": null, "options": null, "answers_accept": ["for"], "answer_official": "for", "explain": null, "tags": []}, {"no": 6, "stem": null, "options": null, "answers_accept": ["the"], "answer_official": "the", "explain": null, "tags": []}, {"no": 7, "stem": null, "options": null, "answers_accept": ["too"], "answer_official": "too", "explain": null, "tags": []}, {"no": 8, "stem": null, "options": null, "answers_accept": ["if", "whether"], "answer_official": "if", "explain": null, "tags": []}], "source": {"origin": "cepoc", "file": "assets/open-source/cepoc-main/PET.json", "orig_id": 1, "url": "https://github.com/CambridgeALTA/cepoc", "retrieved": "2026-08-21", "source_id": "cepoc", "source_item_id": "cepoc-b1-json"}, "license": "cc-nc-education", "tags": ["cloze", "open_cloze"], "note": "CEPOC 未标注套题年份与卷内 Part 号;空格数与 2020 版题型不完全对应(KET 11-12空/套、PET 6-8空/套),推断混有 2020 改版前真题。完形题型本身对应 A2 Key Reading & Writing / B1 Preliminary Reading 的 open cloze 题型。", "meta": {"multi_answer_items": 1}}
{"schema": "qb-1.1", "id": "b1-cepoc-0002", "exam": "B1 Preliminary", "cefr": "B1", "paper": "reading", "part": null, "type": "open_cloze", "task_prompt": "For each gap, write ONE word which best completes the text.", "title": "School Jazz Band", "passage": "Do you play a jazz instrument – maybe the trumpet, guitar or drums? Do you want to have some musical fun with other students in the school _ have similar interests to yours? If you do, come and join us on Tuesdays after school in the music room. At the moment, there are eight of us playing quite a wide range of instruments. We’re having such _ great time and Mr Jones is an amazing jazz teacher, but we need more people, especially electric guitarists!\n\nWe’re hoping _ perform in the end-of-term show and Mr Jones said he’ll deal _ all the technical arrangements and the sound system, which is great! \n\nEither come and ask me _ more details during one of the lunch breaks, _ just turn up on the day. But don’t forget to bring your instrument! See you there!\n\nSam (from the School Jazz Band)", "blank_token": "_", "items": [{"no": 1, "stem": null, "options": null, "answers_accept": ["who", "that"], "answer_official": "who", "explain": null, "tags": []}, {"no": 2, "stem": null, "options": null, "answers_accept": ["a"], "answer_official": "a", "explain": null, "tags": []}, {"no": 3, "stem": null, "options": null, "answers_accept": ["to"], "answer_official": "to", "explain": null, "tags": []}, {"no": 4, "stem": null, "options": null, "answers_accept": ["with"], "answer_official": "with", "explain": null, "tags": []}, {"no": 5, "stem": null, "options": null, "answers_accept": ["for"], "answer_official": "for", "explain": null, "tags": []}, {"no": 6, "stem": null, "options": null, "answers_accept": ["or"], "answer_official": "or", "explain": null, "tags": []}], "source": {"origin": "cepoc", "file": "assets/open-source/cepoc-main/PET.json", "orig_id": 2, "url": "https://github.com/CambridgeALTA/cepoc", "retrieved": "2026-08-21", "source_id": "cepoc", "source_item_id": "cepoc-b1-json"}, "license": "cc-nc-education", "tags": ["cloze", "open_cloze"], "note": "CEPOC 未标注套题年份与卷内 Part 号;空格数与 2020 版题型不完全对应(KET 11-12空/套、PET 6-8空/套),推断混有 2020 改版前真题。完形题型本身对应 A2 Key Reading & Writing / B1 Preliminary Reading 的 open cloze 题型。", "meta": {"multi_answer_items": 1}}
{"schema": "qb-1.1", "id": "b1-cepoc-0003", "exam": "B1 Preliminary", "cefr": "B1", "paper": "reading", "part": null, "type": "open_cloze", "task_prompt": "For each gap, write ONE word which best completes the text.", "title": "A wildlife boat tour", "passage": "When I was on holiday with my parents, we went on a wildlife tour. The trip involved sailing round some islands off the coast, not too far _ our hotel. Some other guests had been on the tour, and recommended it to my parents, who immediately decided we should go.\n\nIn the morning our guide, Jake, picked us _ in his boat and off we went. Jake knew lots about the wildlife on the islands and we saw everything we were hoping to, apart from one bird, called a harrier, which didn’t appear. But that didn’t matter _ we saw many other amazing birds.\n\nMy parents especially liked the fact that _ were very few people on the tour. Jake had time to answer all our questions, so we felt we learnt _ than we’d expected. And we agreed this wildlife experience was _ of the best we’d ever had.", "blank_token": "_", "items": [{"no": 1, "stem": null, "options": null, "answers_accept": ["from"], "answer_official": "from", "explain": null, "tags": []}, {"no": 2, "stem": null, "options": null, "answers_accept": ["up"], "answer_official": "up", "explain": null, "tags": []}, {"no": 3, "stem": null, "options": null, "answers_accept": ["because", "as", "since"], "answer_official": "because", "explain": null, "tags": []}, {"no": 4, "stem": null, "options": null, "answers_accept": ["there"], "answer_official": "there", "explain": null, "tags": []}, {"no": 5, "stem": null, "options": null, "answers_accept": ["more"], "answer_official": "more", "explain": null, "tags": []}, {"no": 6, "stem": null, "options": null, "answers_accept": ["one"], "answer_official": "one", "explain": null, "tags": []}], "source": {"origin": "cepoc", "file": "assets/open-source/cepoc-main/PET.json", "orig_id": 3, "url": "https://github.com/CambridgeALTA/cepoc", "retrieved": "2026-08-21", "source_id": "cepoc", "source_item_id": "cepoc-b1-json"}, "license": "cc-nc-education", "tags": ["cloze", "open_cloze"], "note": "CEPOC 未标注套题年份与卷内 Part 号;空格数与 2020 版题型不完全对应(KET 11-12空/套、PET 6-8空/套),推断混有 2020 改版前真题。完形题型本身对应 A2 Key Reading & Writing / B1 Preliminary Reading 的 open cloze 题型。", "meta": {"multi_answer_items": 1}}
{"schema": "qb-1.1", "id": "b1-cepoc-0004", "exam": "B1 Preliminary", "cefr": "B1", "paper": "reading", "part": null, "type": "open_cloze", "task_prompt": "For each gap, write ONE word which best completes the text.", "title": "My city", "passage": "by Harry Salter\n\nDo you live in a nice place? I do! The city _ I live is called Bristol, and it’s in the south west of England. It’s not very big, but there are loads of things for teenagers to do here.\n\n_ you’re interested in television, you should go to the Bristol TV and Radio Studios. On the tour of the studios, you can have a go at presenting and appear _ your own radio drama.\n\nOr if you’re into sport, why _ try canoeing? The best place is a very pretty local section of the Kennet and Avon canal. It connects Bristol to London and it _ built in the early 18th century, so you can experience some local history at the same time.\n\nThese are just two _ the many things you can do here. It really is a great place.", "blank_token": "_", "items": [{"no": 1, "stem": null, "options": null, "answers_accept": ["where"], "answer_official": "where", "explain": null, "tags": []}, {"no": 2, "stem": null, "options": null, "answers_accept": ["If"], "answer_official": "If", "explain": null, "tags": []}, {"no": 3, "stem": null, "options": null, "answers_accept": ["in"], "answer_official": "in", "explain": null, "tags": []}, {"no": 4, "stem": null, "options": null, "answers_accept": ["not"], "answer_official": "not", "explain": null, "tags": []}, {"no": 5, "stem": null, "options": null, "answers_accept": ["was"], "answer_official": "was", "explain": null, "tags": []}, {"no": 6, "stem": null, "options": null, "answers_accept": ["of"], "answer_official": "of", "explain": null, "tags": []}], "source": {"origin": "cepoc", "file": "assets/open-source/cepoc-main/PET.json", "orig_id": 4, "url": "https://github.com/CambridgeALTA/cepoc", "retrieved": "2026-08-21", "source_id": "cepoc", "source_item_id": "cepoc-b1-json"}, "license": "cc-nc-education", "tags": ["cloze", "open_cloze"], "note": "CEPOC 未标注套题年份与卷内 Part 号;空格数与 2020 版题型不完全对应(KET 11-12空/套、PET 6-8空/套),推断混有 2020 改版前真题。完形题型本身对应 A2 Key Reading & Writing / B1 Preliminary Reading 的 open cloze 题型。", "meta": {"multi_answer_items": 0}}
{"schema": "qb-1.1", "id": "b1-cepoc-0005", "exam": "B1 Preliminary", "cefr": "B1", "paper": "reading", "part": null, "type": "open_cloze", "task_prompt": "For each gap, write ONE word which best completes the text.", "title": "Review of Amazing", "passage": "By Gina Thomann\n\nA new play called Amazing is now on at the Town Theatre, and it’s really worth seeing. The action takes _ in a school, and the play starts by showing a group of students at the school inventing an extraordinary machine. They then use this machine to travel backwards through time in order _ learn about history and other school subjects. _ example, they see exactly what happened when important medicines _ discovered.\n\n_ the story is extremely interesting, some of the acting is not so good. None _ the actors are very well-known, and I think the play would be a bit better _ it had more experienced people in the main roles.\n\nDespite _ , I would definitely recommend you to go and see it because of the fantastic story, and the rather surprising ending.", "blank_token": "_", "items": [{"no": 1, "stem": null, "options": null, "answers_accept": ["place"], "answer_official": "place", "explain": null, "tags": []}, {"no": 2, "stem": null, "options": null, "answers_accept": ["to"], "answer_official": "to", "explain": null, "tags": []}, {"no": 3, "stem": null, "options": null, "answers_accept": ["For"], "answer_official": "For", "explain": null, "tags": []}, {"no": 4, "stem": null, "options": null, "answers_accept": ["were"], "answer_official": "were", "explain": null, "tags": []}, {"no": 5, "stem": null, "options": null, "answers_accept": ["Although", "Though", "While"], "answer_official": "Although", "explain": null, "tags": []}, {"no": 6, "stem": null, "options": null, "answers_accept": ["of"], "answer_official": "of", "explain": null, "tags": []}, {"no": 7, "stem": null, "options": null, "answers_accept": ["if"], "answer_official": "if", "explain": null, "tags": []}, {"no": 8, "stem": null, "options": null, "answers_accept": ["this", "that", "everything"], "answer_official": "this", "explain": null, "tags": []}], "source": {"origin": "cepoc", "file": "assets/open-source/cepoc-main/PET.json", "orig_id": 5, "url": "https://github.com/CambridgeALTA/cepoc", "retrieved": "2026-08-21", "source_id": "cepoc", "source_item_id": "cepoc-b1-json"}, "license": "cc-nc-education", "tags": ["cloze", "open_cloze"], "note": "CEPOC 未标注套题年份与卷内 Part 号;空格数与 2020 版题型不完全对应(KET 11-12空/套、PET 6-8空/套),推断混有 2020 改版前真题。完形题型本身对应 A2 Key Reading & Writing / B1 Preliminary Reading 的 open cloze 题型。", "meta": {"multi_answer_items": 2}}
{"schema": "qb-1.1", "id": "b1-cepoc-0006", "exam": "B1 Preliminary", "cefr": "B1", "paper": "reading", "part": null, "type": "open_cloze", "task_prompt": "For each gap, write ONE word which best completes the text.", "title": "Match report: National Schools Tournament", "passage": "By William Jacobs, football captain\n\nLast Saturday, our school football team took part in the National Schools Tournament. It was a long day – we got to school very early as the bus _ would take us to the tournament had to leave by 7 a.m. _ an hour’s drive we arrived at the City Stadium, where the competition was taking _ . Playing in such _ famous stadium was an experience we will never forget. \n\nWe played against some _ the top teams from around the country, and we came first! This was amazing, because the other teams were much stronger this year _ they were last year. \n\nWe were given our prize, a beautiful silver cup, and then we went on a tour around the stadium. We all agreed that it _ been an incredible day, and we hope to _ able to return next year!", "blank_token": "_", "items": [{"no": 1, "stem": null, "options": null, "answers_accept": ["which", "that"], "answer_official": "which", "explain": null, "tags": []}, {"no": 2, "stem": null, "options": null, "answers_accept": ["After"], "answer_official": "After", "explain": null, "tags": []}, {"no": 3, "stem": null, "options": null, "answers_accept": ["place"], "answer_official": "place", "explain": null, "tags": []}, {"no": 4, "stem": null, "options": null, "answers_accept": ["a"], "answer_official": "a", "explain": null, "tags": []}, {"no": 5, "stem": null, "options": null, "answers_accept": ["of"], "answer_official": "of", "explain": null, "tags": []}, {"no": 6, "stem": null, "options": null, "answers_accept": ["than"], "answer_official": "than", "explain": null, "tags": []}, {"no": 7, "stem": null, "options": null, "answers_accept": ["had"], "answer_official": "had", "explain": null, "tags": []}, {"no": 8, "stem": null, "options": null, "answers_accept": ["be"], "answer_official": "be", "explain": null, "tags": []}], "source": {"origin": "cepoc", "file": "assets/open-source/cepoc-main/PET.json", "orig_id": 6, "url": "https://github.com/CambridgeALTA/cepoc", "retrieved": "2026-08-21", "source_id": "cepoc", "source_item_id": "cepoc-b1-json"}, "license": "cc-nc-education", "tags": ["cloze", "open_cloze"], "note": "CEPOC 未标注套题年份与卷内 Part 号;空格数与 2020 版题型不完全对应(KET 11-12空/套、PET 6-8空/套),推断混有 2020 改版前真题。完形题型本身对应 A2 Key Reading & Writing / B1 Preliminary Reading 的 open cloze 题型。", "meta": {"multi_answer_items": 1}}
{"schema": "qb-1.1", "id": "b1-cepoc-0007", "exam": "B1 Preliminary", "cefr": "B1", "paper": "reading", "part": null, "type": "open_cloze", "task_prompt": "For each gap, write ONE word which best completes the text.", "title": "Book review", "passage": "I’ve just finished reading Sara Tyler’s latest book, Gold River. I think that it’s even better _ her last book. If you’re looking _ an interesting book to read, then this _ the perfect choice.\n\nThe main characters are described in a lot of detail, and I really cared about _ happened to them. If you’re one of the thousands of people who have enjoyed other books _ Sara Tyler, you’ll already know that some of her novels were made into films _ few years ago. I wouldn’t be surprised if this happens to Gold River too. Although this book has new characters, _ is set in the same place _ her other stories, so you might recognise some of the locations. Go and read it – I promise you won’t regret it!", "blank_token": "_", "items": [{"no": 1, "stem": null, "options": null, "answers_accept": ["than"], "answer_official": "than", "explain": null, "tags": []}, {"no": 2, "stem": null, "options": null, "answers_accept": ["for"], "answer_official": "for", "explain": null, "tags": []}, {"no": 3, "stem": null, "options": null, "answers_accept": ["is"], "answer_official": "is", "explain": null, "tags": []}, {"no": 4, "stem": null, "options": null, "answers_accept": ["what"], "answer_official": "what", "explain": null, "tags": []}, {"no": 5, "stem": null, "options": null, "answers_accept": ["by"], "answer_official": "by", "explain": null, "tags": []}, {"no": 6, "stem": null, "options": null, "answers_accept": ["a"], "answer_official": "a", "explain": null, "tags": []}, {"no": 7, "stem": null, "options": null, "answers_accept": ["it"], "answer_official": "it", "explain": null, "tags": []}, {"no": 8, "stem": null, "options": null, "answers_accept": ["as"], "answer_official": "as", "explain": null, "tags": []}], "source": {"origin": "cepoc", "file": "assets/open-source/cepoc-main/PET.json", "orig_id": 7, "url": "https://github.com/CambridgeALTA/cepoc", "retrieved": "2026-08-21", "source_id": "cepoc", "source_item_id": "cepoc-b1-json"}, "license": "cc-nc-education", "tags": ["cloze", "open_cloze"], "note": "CEPOC 未标注套题年份与卷内 Part 号;空格数与 2020 版题型不完全对应(KET 11-12空/套、PET 6-8空/套),推断混有 2020 改版前真题。完形题型本身对应 A2 Key Reading & Writing / B1 Preliminary Reading 的 open cloze 题型。", "meta": {"multi_answer_items": 0}}
{"schema": "qb-1.1", "id": "b1-cepoc-0008", "exam": "B1 Preliminary", "cefr": "B1", "paper": "reading", "part": null, "type": "open_cloze", "task_prompt": "For each gap, write ONE word which best completes the text.", "title": "Science fiction film", "passage": "Hi Sam,\n\nHave you seen the new science fiction film Rocket? I was really interested in seeing it because it was based _ the book called Spacemen, which is _ of my favourite novels. To be honest, I always find _ difficult when something that I’ve read and enjoyed is turned into a film, because it’s never exactly the same _ I imagined! But _ time I really wasn’t disappointed – the acting was great, and the main characters were very similar to how the author described them in the novel.\n\n_ you haven’t seen it yet, why don’t you come round to my house and watch it online _ me? I know you love science fiction, so it would be great to hear _ you think of the film!\n\nI’m looking forward to seeing you then! \n\nCarys", "blank_token": "_", "items": [{"no": 1, "stem": null, "options": null, "answers_accept": ["on"], "answer_official": "on", "explain": null, "tags": []}, {"no": 2, "stem": null, "options": null, "answers_accept": ["one"], "answer_official": "one", "explain": null, "tags": []}, {"no": 3, "stem": null, "options": null, "answers_accept": ["it"], "answer_official": "it", "explain": null, "tags": []}, {"no": 4, "stem": null, "options": null, "answers_accept": ["as"], "answer_official": "as", "explain": null, "tags": []}, {"no": 5, "stem": null, "options": null, "answers_accept": ["this"], "answer_official": "this", "explain": null, "tags": []}, {"no": 6, "stem": null, "options": null, "answers_accept": ["If"], "answer_official": "If", "explain": null, "tags": []}, {"no": 7, "stem": null, "options": null, "answers_accept": ["with"], "answer_official": "with", "explain": null, "tags": []}, {"no": 8, "stem": null, "options": null, "answers_accept": ["what"], "answer_official": "what", "explain": null, "tags": []}], "source": {"origin": "cepoc", "file": "assets/open-source/cepoc-main/PET.json", "orig_id": 8, "url": "https://github.com/CambridgeALTA/cepoc", "retrieved": "2026-08-21", "source_id": "cepoc", "source_item_id": "cepoc-b1-json"}, "license": "cc-nc-education", "tags": ["cloze", "open_cloze"], "note": "CEPOC 未标注套题年份与卷内 Part 号;空格数与 2020 版题型不完全对应(KET 11-12空/套、PET 6-8空/套),推断混有 2020 改版前真题。完形题型本身对应 A2 Key Reading & Writing / B1 Preliminary Reading 的 open cloze 题型。", "meta": {"multi_answer_items": 0}}
{"schema": "qb-1.1", "id": "b1-cepoc-0009", "exam": "B1 Preliminary", "cefr": "B1", "paper": "reading", "part": null, "type": "open_cloze", "task_prompt": "For each gap, write ONE word which best completes the text.", "title": "My hobby", "passage": "By Jenny Winter\n\nI love playing the guitar. I started playing a _ weeks ago, and my teacher is really good. Even though I _ only had six lessons so far, I can already play some tunes! I was quite surprised really, because I also play the violin, which is much harder.\n\nI have an electric guitar. _ best thing about playing this instrument is being able to use headphones when I practise, which I do for _ least thirty minutes every day. Wearing the headphones means that _ is really easy to concentrate.\n\nMy teacher asked me _ enter a competition for new players next month, so I _ working hard for that right now. I’d be really happy _ I won!", "blank_token": "_", "items": [{"no": 1, "stem": null, "options": null, "answers_accept": ["few"], "answer_official": "few", "explain": null, "tags": []}, {"no": 2, "stem": null, "options": null, "answers_accept": ["have", "'ve"], "answer_official": "have", "explain": null, "tags": []}, {"no": 3, "stem": null, "options": null, "answers_accept": ["The"], "answer_official": "The", "explain": null, "tags": []}, {"no": 4, "stem": null, "options": null, "answers_accept": ["at"], "answer_official": "at", "explain": null, "tags": []}, {"no": 5, "stem": null, "options": null, "answers_accept": ["it"], "answer_official": "it", "explain": null, "tags": []}, {"no": 6, "stem": null, "options": null, "answers_accept": ["to"], "answer_official": "to", "explain": null, "tags": []}, {"no": 7, "stem": null, "options": null, "answers_accept": ["am", "'m"], "answer_official": "am", "explain": null, "tags": []}, {"no": 8, "stem": null, "options": null, "answers_accept": ["if"], "answer_official": "if", "explain": null, "tags": []}], "source": {"origin": "cepoc", "file": "assets/open-source/cepoc-main/PET.json", "orig_id": 9, "url": "https://github.com/CambridgeALTA/cepoc", "retrieved": "2026-08-21", "source_id": "cepoc", "source_item_id": "cepoc-b1-json"}, "license": "cc-nc-education", "tags": ["cloze", "open_cloze"], "note": "CEPOC 未标注套题年份与卷内 Part 号;空格数与 2020 版题型不完全对应(KET 11-12空/套、PET 6-8空/套),推断混有 2020 改版前真题。完形题型本身对应 A2 Key Reading & Writing / B1 Preliminary Reading 的 open cloze 题型。", "meta": {"multi_answer_items": 2}}
{"schema": "qb-1.1", "id": "b1-cepoc-0010", "exam": "B1 Preliminary", "cefr": "B1", "paper": "reading", "part": null, "type": "open_cloze", "task_prompt": "For each gap, write ONE word which best completes the text.", "title": "Learning to ski", "passage": "I’ll always remember skiing for the first time. Until I went on a trip to Queenstown, New Zealand, I _ never seen snow!\n\nOn the first day, I signed _ for a skiing lesson for complete beginners. During the lesson I only learnt some basic techniques, but I still thought I was good enough to go skiing all by _ !\n\nLuckily, I managed _ reach the peak without falling off the ski lift. Then I had to ski down the mountain, even _ I didn’t know how to stop or turn very well. As _ as I pointed my skis towards the track I began gaining speed. _ few minutes later, I started shouting at skiers to move out of my way! \n\nNot surprisingly, I crashed into a tree. I didn’t get hurt, but I lost my sunglasses. I didn’t go near skis for a very long time _ that!", "blank_token": "_", "items": [{"no": 1, "stem": null, "options": null, "answers_accept": ["had", "'d"], "answer_official": "had", "explain": null, "tags": []}, {"no": 2, "stem": null, "options": null, "answers_accept": ["up"], "answer_official": "up", "explain": null, "tags": []}, {"no": 3, "stem": null, "options": null, "answers_accept": ["myself"], "answer_official": "myself", "explain": null, "tags": []}, {"no": 4, "stem": null, "options": null, "answers_accept": ["to"], "answer_official": "to", "explain": null, "tags": []}, {"no": 5, "stem": null, "options": null, "answers_accept": ["though"], "answer_official": "though", "explain": null, "tags": []}, {"no": 6, "stem": null, "options": null, "answers_accept": ["soon"], "answer_official": "soon", "explain": null, "tags": []}, {"no": 7, "stem": null, "options": null, "answers_accept": ["A"], "answer_official": "A", "explain": null, "tags": []}, {"no": 8, "stem": null, "options": null, "answers_accept": ["after"], "answer_official": "after", "explain": null, "tags": []}], "source": {"origin": "cepoc", "file": "assets/open-source/cepoc-main/PET.json", "orig_id": 10, "url": "https://github.com/CambridgeALTA/cepoc", "retrieved": "2026-08-21", "source_id": "cepoc", "source_item_id": "cepoc-b1-json"}, "license": "cc-nc-education", "tags": ["cloze", "open_cloze"], "note": "CEPOC 未标注套题年份与卷内 Part 号;空格数与 2020 版题型不完全对应(KET 11-12空/套、PET 6-8空/套),推断混有 2020 改版前真题。完形题型本身对应 A2 Key Reading & Writing / B1 Preliminary Reading 的 open cloze 题型。", "meta": {"multi_answer_items": 1}}
{"schema": "qb-1.1", "id": "b1-cepoc-0011", "exam": "B1 Preliminary", "cefr": "B1", "paper": "reading", "part": null, "type": "open_cloze", "task_prompt": "For each gap, write ONE word which best completes the text.", "title": "Moving house", "passage": "Hi Alex,\n\nHow are you? This week’s been a very busy one for me – I finally moved house! _ wasn’t until I started to pack a few days ago that I realised how much stuff I had. I really think moving house is one of the _ stressful things I’ve ever done! I was sad to leave my old house – after _ , I’d lived there my whole life so I have lots of good memories. \n\nAnyway, I’m looking _ to being in this new house. It’s not as big as the old one, but _ least it’s got a great garden. I’m planning to have a small party on Saturday night. Are you free then? Why don’t you come along _ you are? I hope you can make it. Let me know.\n\nAll the best,\n\nSam", "blank_token": "_", "items": [{"no": 1, "stem": null, "options": null, "answers_accept": ["It"], "answer_official": "It", "explain": null, "tags": []}, {"no": 2, "stem": null, "options": null, "answers_accept": ["most"], "answer_official": "most", "explain": null, "tags": []}, {"no": 3, "stem": null, "options": null, "answers_accept": ["all"], "answer_official": "all", "explain": null, "tags": []}, {"no": 4, "stem": null, "options": null, "answers_accept": ["forward"], "answer_official": "forward", "explain": null, "tags": []}, {"no": 5, "stem": null, "options": null, "answers_accept": ["at"], "answer_official": "at", "explain": null, "tags": []}, {"no": 6, "stem": null, "options": null, "answers_accept": ["if"], "answer_official": "if", "explain": null, "tags": []}], "source": {"origin": "cepoc", "file": "assets/open-source/cepoc-main/PET.json", "orig_id": 11, "url": "https://github.com/CambridgeALTA/cepoc", "retrieved": "2026-08-21", "source_id": "cepoc", "source_item_id": "cepoc-b1-json"}, "license": "cc-nc-education", "tags": ["cloze", "open_cloze"], "note": "CEPOC 未标注套题年份与卷内 Part 号;空格数与 2020 版题型不完全对应(KET 11-12空/套、PET 6-8空/套),推断混有 2020 改版前真题。完形题型本身对应 A2 Key Reading & Writing / B1 Preliminary Reading 的 open cloze 题型。", "meta": {"multi_answer_items": 0}}
{"schema": "qb-1.1", "id": "b1-cepoc-0012", "exam": "B1 Preliminary", "cefr": "B1", "paper": "reading", "part": null, "type": "open_cloze", "task_prompt": "For each gap, write ONE word which best completes the text.", "title": "The Westway Cinema", "passage": "The new Westway Cinema is finally open! I went last night with my brother, and we both agreed it’s much better than the old one _ to be. Although the ticket prices are higher, the extra cost is worth paying.\n\nThe new owners _ now taken out all the old seats and put in brand new ones that are really comfortable. There’s also new air conditioning. This is fantastic because in the past it was sometimes _ hot that it was difficult to concentrate on the film!\n\nThere are also special offers available. For example, _ you buy two tickets, you can choose something for free – either a snack or a drink. I’m sure this _ be popular, as you can’t bring _ own food into the cinema. \n\nI’d really recommend going to the Westway Cinema – it’s a great night out.", "blank_token": "_", "items": [{"no": 1, "stem": null, "options": null, "answers_accept": ["used"], "answer_official": "used", "explain": null, "tags": []}, {"no": 2, "stem": null, "options": null, "answers_accept": ["have"], "answer_official": "have", "explain": null, "tags": []}, {"no": 3, "stem": null, "options": null, "answers_accept": ["so"], "answer_official": "so", "explain": null, "tags": []}, {"no": 4, "stem": null, "options": null, "answers_accept": ["if", "when", "whenever", "provided"], "answer_official": "if", "explain": null, "tags": []}, {"no": 5, "stem": null, "options": null, "answers_accept": ["will"], "answer_official": "will", "explain": null, "tags": []}, {"no": 6, "stem": null, "options": null, "answers_accept": ["your"], "answer_official": "your", "explain": null, "tags": []}], "source": {"origin": "cepoc", "file": "assets/open-source/cepoc-main/PET.json", "orig_id": 12, "url": "https://github.com/CambridgeALTA/cepoc", "retrieved": "2026-08-21", "source_id": "cepoc", "source_item_id": "cepoc-b1-json"}, "license": "cc-nc-education", "tags": ["cloze", "open_cloze"], "note": "CEPOC 未标注套题年份与卷内 Part 号;空格数与 2020 版题型不完全对应(KET 11-12空/套、PET 6-8空/套),推断混有 2020 改版前真题。完形题型本身对应 A2 Key Reading & Writing / B1 Preliminary Reading 的 open cloze 题型。", "meta": {"multi_answer_items": 1}}
{"schema": "qb-1.1", "id": "b1-cepoc-0013", "exam": "B1 Preliminary", "cefr": "B1", "paper": "reading", "part": null, "type": "open_cloze", "task_prompt": "For each gap, write ONE word which best completes the text.", "title": null, "passage": "From: Harry \n\nTo: Oliver\n\nSubject: Piano lessons \n\nHi Oliver,\n\nGuess what? I’ve finally started piano lessons, like you! As you know, it’s something I’ve wanted to do ever _ I was young. Anyway, a couple of months ago I saw someone playing the piano on TV – he was brilliant. And when I found out he’d only started playing quite recently, that encouraged _ to start lessons. \n\nI’ve got a really good teacher, and I go to her house _ lessons twice a week. She’s very patient. _ time I make a mistake, she explains what I did wrong. Also, I couldn’t read music when I started, so it’s been hard to learn to read the notes on the page at the _ time as deciding which piano keys to use! But _ I finally play something that other people recognise, it really makes me happy. Maybe _ day, I’ll become an even better piano player _ you!", "blank_token": "_", "items": [{"no": 1, "stem": null, "options": null, "answers_accept": ["since"], "answer_official": "since", "explain": null, "tags": []}, {"no": 2, "stem": null, "options": null, "answers_accept": ["me"], "answer_official": "me", "explain": null, "tags": []}, {"no": 3, "stem": null, "options": null, "answers_accept": ["for"], "answer_official": "for", "explain": null, "tags": []}, {"no": 4, "stem": null, "options": null, "answers_accept": ["Every", "Each"], "answer_official": "Every", "explain": null, "tags": []}, {"no": 5, "stem": null, "options": null, "answers_accept": ["same"], "answer_official": "same", "explain": null, "tags": []}, {"no": 6, "stem": null, "options": null, "answers_accept": ["when", "whenever", "if"], "answer_official": "when", "explain": null, "tags": []}, {"no": 7, "stem": null, "options": null, "answers_accept": ["one", "some"], "answer_official": "one", "explain": null, "tags": []}, {"no": 8, "stem": null, "options": null, "answers_accept": ["than"], "answer_official": "than", "explain": null, "tags": []}], "source": {"origin": "cepoc", "file": "assets/open-source/cepoc-main/PET.json", "orig_id": 13, "url": "https://github.com/CambridgeALTA/cepoc", "retrieved": "2026-08-21", "source_id": "cepoc", "source_item_id": "cepoc-b1-json"}, "license": "cc-nc-education", "tags": ["cloze", "open_cloze"], "note": "CEPOC 未标注套题年份与卷内 Part 号;空格数与 2020 版题型不完全对应(KET 11-12空/套、PET 6-8空/套),推断混有 2020 改版前真题。完形题型本身对应 A2 Key Reading & Writing / B1 Preliminary Reading 的 open cloze 题型。", "meta": {"multi_answer_items": 3}}
{"schema": "qb-1.1", "id": "b1-cepoc-0014", "exam": "B1 Preliminary", "cefr": "B1", "paper": "reading", "part": null, "type": "open_cloze", "task_prompt": "For each gap, write ONE word which best completes the text.", "title": "My travel blog", "passage": "This summer, I travelled to Copenhagen, the capital of Denmark, on my own. I am only 20 and to _ honest, I was nervous about exploring a new city alone. I decided to go on a free walking tour the first day I was there. I hoped the tour would help me to become more familiar _ the city. \n\nUnfortunately, the weather wasn’t great, but the tour was still absolutely fantastic! Magnus, our tour guide, knew all about the city’s history. We also learnt loads _ interesting facts about Danish culture. At the end of the tour, he gave _ all suggestions for the best places _ eat and visit.\n\nApart from learning so much, I actually had a lot more fun on the walking tour _ I’d expected. It was an excellent way to experience the city, and learn about its culture and history.", "blank_token": "_", "items": [{"no": 1, "stem": null, "options": null, "answers_accept": ["be"], "answer_official": "be", "explain": null, "tags": []}, {"no": 2, "stem": null, "options": null, "answers_accept": ["with"], "answer_official": "with", "explain": null, "tags": []}, {"no": 3, "stem": null, "options": null, "answers_accept": ["of"], "answer_official": "of", "explain": null, "tags": []}, {"no": 4, "stem": null, "options": null, "answers_accept": ["us"], "answer_official": "us", "explain": null, "tags": []}, {"no": 5, "stem": null, "options": null, "answers_accept": ["to"], "answer_official": "to", "explain": null, "tags": []}, {"no": 6, "stem": null, "options": null, "answers_accept": ["than"], "answer_official": "than", "explain": null, "tags": []}], "source": {"origin": "cepoc", "file": "assets/open-source/cepoc-main/PET.json", "orig_id": 14, "url": "https://github.com/CambridgeALTA/cepoc", "retrieved": "2026-08-21", "source_id": "cepoc", "source_item_id": "cepoc-b1-json"}, "license": "cc-nc-education", "tags": ["cloze", "open_cloze"], "note": "CEPOC 未标注套题年份与卷内 Part 号;空格数与 2020 版题型不完全对应(KET 11-12空/套、PET 6-8空/套),推断混有 2020 改版前真题。完形题型本身对应 A2 Key Reading & Writing / B1 Preliminary Reading 的 open cloze 题型。", "meta": {"multi_answer_items": 0}}
{"schema": "qb-1.1", "id": "b1-cepoc-0015", "exam": "B1 Preliminary", "cefr": "B1", "paper": "reading", "part": null, "type": "open_cloze", "task_prompt": "For each gap, write ONE word which best completes the text.", "title": "Starting at college", "passage": "Hi, my name’s Emma. Welcome to the college! I’ve been studying here for a year now. Starting at college isn’t easy, but I’m sure you’ll soon feel at home. When I first started studying here last year, I was _ nervous that I couldn’t even ask anyone for help. I got lost five times on my first day!\n\nRemember that _ student at the college has been new at one time, and understands how you feel. So _ you’re not sure where to go, just ask – we’re all happy to help!\n\nYou probably don’t know many people here. To make some friends, _ not spend break times with some of your new classmates in the café? Or how _ joining one of the many clubs we have at the college? _ are lots to choose from.\n\nGood luck on your new course!", "blank_token": "_", "items": [{"no": 1, "stem": null, "options": null, "answers_accept": ["so"], "answer_official": "so", "explain": null, "tags": []}, {"no": 2, "stem": null, "options": null, "answers_accept": ["every", "each"], "answer_official": "every", "explain": null, "tags": []}, {"no": 3, "stem": null, "options": null, "answers_accept": ["if", "when", "whenever"], "answer_official": "if", "explain": null, "tags": []}, {"no": 4, "stem": null, "options": null, "answers_accept": ["why"], "answer_official": "why", "explain": null, "tags": []}, {"no": 5, "stem": null, "options": null, "answers_accept": ["about"], "answer_official": "about", "explain": null, "tags": []}, {"no": 6, "stem": null, "options": null, "answers_accept": ["There"], "answer_official": "There", "explain": null, "tags": []}], "source": {"origin": "cepoc", "file": "assets/open-source/cepoc-main/PET.json", "orig_id": 15, "url": "https://github.com/CambridgeALTA/cepoc", "retrieved": "2026-08-21", "source_id": "cepoc", "source_item_id": "cepoc-b1-json"}, "license": "cc-nc-education", "tags": ["cloze", "open_cloze"], "note": "CEPOC 未标注套题年份与卷内 Part 号;空格数与 2020 版题型不完全对应(KET 11-12空/套、PET 6-8空/套),推断混有 2020 改版前真题。完形题型本身对应 A2 Key Reading & Writing / B1 Preliminary Reading 的 open cloze 题型。", "meta": {"multi_answer_items": 2}}
{"schema": "qb-1.1", "id": "b1-cepoc-0016", "exam": "B1 Preliminary", "cefr": "B1", "paper": "reading", "part": null, "type": "open_cloze", "task_prompt": "For each gap, write ONE word which best completes the text.", "title": "Letter to a restaurant", "passage": "Dear Mrs Cutter,\n\nI am writing to complain about a recent visit I made to your restaurant. I went there last Tuesday with my parents, _ were celebrating their wedding anniversary. We have _ to your restaurant many times before and always enjoyed it. _ time, however, there was a problem with the service. \n\nYour restaurant was not very busy on Tuesday evening. In spite _ that, it took a long time for anyone to come and take our order. We then had to wait for at _ an hour before the food arrived. As we _ already arranged to meet some family friends after our meal, we were late meeting them in _ end because of the slow service at your restaurant.\n\nI suggest that you discuss the issue _ your staff to prevent it happening again.\n\nYours sincerely,\n\nPeter Hamilton", "blank_token": "_", "items": [{"no": 1, "stem": null, "options": null, "answers_accept": ["who"], "answer_official": "who", "explain": null, "tags": []}, {"no": 2, "stem": null, "options": null, "answers_accept": ["been"], "answer_official": "been", "explain": null, "tags": []}, {"no": 3, "stem": null, "options": null, "answers_accept": ["This"], "answer_official": "This", "explain": null, "tags": []}, {"no": 4, "stem": null, "options": null, "answers_accept": ["of"], "answer_official": "of", "explain": null, "tags": []}, {"no": 5, "stem": null, "options": null, "answers_accept": ["least"], "answer_official": "least", "explain": null, "tags": []}, {"no": 6, "stem": null, "options": null, "answers_accept": ["had"], "answer_official": "had", "explain": null, "tags": []}, {"no": 7, "stem": null, "options": null, "answers_accept": ["the"], "answer_official": "the", "explain": null, "tags": []}, {"no": 8, "stem": null, "options": null, "answers_accept": ["with"], "answer_official": "with", "explain": null, "tags": []}], "source": {"origin": "cepoc", "file": "assets/open-source/cepoc-main/PET.json", "orig_id": 16, "url": "https://github.com/CambridgeALTA/cepoc", "retrieved": "2026-08-21", "source_id": "cepoc", "source_item_id": "cepoc-b1-json"}, "license": "cc-nc-education", "tags": ["cloze", "open_cloze"], "note": "CEPOC 未标注套题年份与卷内 Part 号;空格数与 2020 版题型不完全对应(KET 11-12空/套、PET 6-8空/套),推断混有 2020 改版前真题。完形题型本身对应 A2 Key Reading & Writing / B1 Preliminary Reading 的 open cloze 题型。", "meta": {"multi_answer_items": 0}}
{"schema": "qb-1.1", "id": "b1-cepoc-0017", "exam": "B1 Preliminary", "cefr": "B1", "paper": "reading", "part": null, "type": "open_cloze", "task_prompt": "For each gap, write ONE word which best completes the text.", "title": "Becoming more active", "passage": "Last year, I decided that I wasn’t active enough. I was spending too long sitting in _ of a screen every day and I wasn’t getting as _ exercise as I needed. So I decided that I would feel a lot better _ I actually started doing some kind _ sport. But to be honest, I’m not really into team games. _ I needed was an outdoor hobby that I could do on my own. Then a friend said I should have a go at mountain-biking, and _ first time I tried it, I absolutely loved it. There’s a beautiful forest about 5 kilometres _ my home which is really popular with mountain-bikers. These days, I usually go there twice _ week. Mountain-biking is a great way to stay fit, and it’s great fun, too!", "blank_token": "_", "items": [{"no": 1, "stem": null, "options": null, "answers_accept": ["front"], "answer_official": "front", "explain": null, "tags": []}, {"no": 2, "stem": null, "options": null, "answers_accept": ["much"], "answer_official": "much", "explain": null, "tags": []}, {"no": 3, "stem": null, "options": null, "answers_accept": ["if", "when"], "answer_official": "if", "explain": null, "tags": []}, {"no": 4, "stem": null, "options": null, "answers_accept": ["of"], "answer_official": "of", "explain": null, "tags": []}, {"no": 5, "stem": null, "options": null, "answers_accept": ["What", "All"], "answer_official": "What", "explain": null, "tags": []}, {"no": 6, "stem": null, "options": null, "answers_accept": ["the"], "answer_official": "the", "explain": null, "tags": []}, {"no": 7, "stem": null, "options": null, "answers_accept": ["from"], "answer_official": "from", "explain": null, "tags": []}, {"no": 8, "stem": null, "options": null, "answers_accept": ["a"], "answer_official": "a", "explain": null, "tags": []}], "source": {"origin": "cepoc", "file": "assets/open-source/cepoc-main/PET.json", "orig_id": 17, "url": "https://github.com/CambridgeALTA/cepoc", "retrieved": "2026-08-21", "source_id": "cepoc", "source_item_id": "cepoc-b1-json"}, "license": "cc-nc-education", "tags": ["cloze", "open_cloze"], "note": "CEPOC 未标注套题年份与卷内 Part 号;空格数与 2020 版题型不完全对应(KET 11-12空/套、PET 6-8空/套),推断混有 2020 改版前真题。完形题型本身对应 A2 Key Reading & Writing / B1 Preliminary Reading 的 open cloze 题型。", "meta": {"multi_answer_items": 2}}
{"schema": "qb-1.1", "id": "b1-cepoc-0018", "exam": "B1 Preliminary", "cefr": "B1", "paper": "reading", "part": null, "type": "open_cloze", "task_prompt": "For each gap, write ONE word which best completes the text.", "title": "College careers fair", "passage": "Last week, I went with forty students on my college course to attend a careers fair in the capital city. During the coach journey most of _ either slept or listened to music, and four hours later we arrived _ the careers fair. _ the early departure and long journey it was definitely worth going, as we all found the fair really exciting and interesting. _ were around sixty education and job stalls, and so much careers information available. I am keen _ learning as much as possible about business and hope to open _ own health food company one day, so I also went to a short talk about how _ start up a business. I returned to college with several brochures _ are full of facts and helpful advice. If any students are thinking of going to next year’s fair, I would definitely recommend it!", "blank_token": "_", "items": [{"no": 1, "stem": null, "options": null, "answers_accept": ["us", "them"], "answer_official": "us", "explain": null, "tags": []}, {"no": 2, "stem": null, "options": null, "answers_accept": ["at"], "answer_official": "at", "explain": null, "tags": []}, {"no": 3, "stem": null, "options": null, "answers_accept": ["Despite"], "answer_official": "Despite", "explain": null, "tags": []}, {"no": 4, "stem": null, "options": null, "answers_accept": ["There"], "answer_official": "There", "explain": null, "tags": []}, {"no": 5, "stem": null, "options": null, "answers_accept": ["on"], "answer_official": "on", "explain": null, "tags": []}, {"no": 6, "stem": null, "options": null, "answers_accept": ["my"], "answer_official": "my", "explain": null, "tags": []}, {"no": 7, "stem": null, "options": null, "answers_accept": ["to"], "answer_official": "to", "explain": null, "tags": []}, {"no": 8, "stem": null, "options": null, "answers_accept": ["which", "that"], "answer_official": "which", "explain": null, "tags": []}], "source": {"origin": "cepoc", "file": "assets/open-source/cepoc-main/PET.json", "orig_id": 18, "url": "https://github.com/CambridgeALTA/cepoc", "retrieved": "2026-08-21", "source_id": "cepoc", "source_item_id": "cepoc-b1-json"}, "license": "cc-nc-education", "tags": ["cloze", "open_cloze"], "note": "CEPOC 未标注套题年份与卷内 Part 号;空格数与 2020 版题型不完全对应(KET 11-12空/套、PET 6-8空/套),推断混有 2020 改版前真题。完形题型本身对应 A2 Key Reading & Writing / B1 Preliminary Reading 的 open cloze 题型。", "meta": {"multi_answer_items": 2}}
{"schema": "qb-1.1", "id": "b1-cepoc-0019", "exam": "B1 Preliminary", "cefr": "B1", "paper": "reading", "part": null, "type": "open_cloze", "task_prompt": "For each gap, write ONE word which best completes the text.", "title": "Spanish conversation club", "passage": "We’re a group of people aged 16-25 who meet every week for two hours of chat in Spanish. You don’t have to be able to speak much Spanish: we welcome beginners, too. We talk about anything _ may interest people, from food people enjoy _ literature and politics. \n\nWe meet between 4.30 _ 6.30 p.m. every Tuesday, in a large, comfortable room in the Central Library. The sessions are free, but we do ask people to pay £1 a session for coffee or juice. Staff from the School of Tourism at the University set _ the group three years ago, but it’s now organised _ volunteers. The number of members _ grown a lot during this time. As well as allowing people to practise their Spanish, the club brings people from different backgrounds together in order to enjoy each other’s company.", "blank_token": "_", "items": [{"no": 1, "stem": null, "options": null, "answers_accept": ["which", "that"], "answer_official": "which", "explain": null, "tags": []}, {"no": 2, "stem": null, "options": null, "answers_accept": ["to"], "answer_official": "to", "explain": null, "tags": []}, {"no": 3, "stem": null, "options": null, "answers_accept": ["and"], "answer_official": "and", "explain": null, "tags": []}, {"no": 4, "stem": null, "options": null, "answers_accept": ["up"], "answer_official": "up", "explain": null, "tags": []}, {"no": 5, "stem": null, "options": null, "answers_accept": ["by"], "answer_official": "by", "explain": null, "tags": []}, {"no": 6, "stem": null, "options": null, "answers_accept": ["has"], "answer_official": "has", "explain": null, "tags": []}], "source": {"origin": "cepoc", "file": "assets/open-source/cepoc-main/PET.json", "orig_id": 19, "url": "https://github.com/CambridgeALTA/cepoc", "retrieved": "2026-08-21", "source_id": "cepoc", "source_item_id": "cepoc-b1-json"}, "license": "cc-nc-education", "tags": ["cloze", "open_cloze"], "note": "CEPOC 未标注套题年份与卷内 Part 号;空格数与 2020 版题型不完全对应(KET 11-12空/套、PET 6-8空/套),推断混有 2020 改版前真题。完形题型本身对应 A2 Key Reading & Writing / B1 Preliminary Reading 的 open cloze 题型。", "meta": {"multi_answer_items": 1}}
{"schema": "qb-1.1", "id": "b1-cepoc-0020", "exam": "B1 Preliminary", "cefr": "B1", "paper": "reading", "part": null, "type": "open_cloze", "task_prompt": "For each gap, write ONE word which best completes the text.", "title": "A rainy day", "passage": "One summer’s day, my family decided to visit a waterfall in the countryside near our town. As we walked across the fields towards the waterfall, we _ see it in the distance. It was quite _ long way, but we got there after about an hour. We sat down near the pool at the bottom of the waterfall to enjoy the picnic that we _ taken with us. Then we noticed some black clouds in the sky, and some large drops _ rain fell on us, so we quickly started to collect our things together. Soon the rain began _ fall heavily. Carrying our bags, we ran as fast as we could, and when we reached the town, we went into the first café we saw. In _ of our wet clothes, we soon felt better after a delicious drink of hot chocolate!", "blank_token": "_", "items": [{"no": 1, "stem": null, "options": null, "answers_accept": ["could"], "answer_official": "could", "explain": null, "tags": []}, {"no": 2, "stem": null, "options": null, "answers_accept": ["a"], "answer_official": "a", "explain": null, "tags": []}, {"no": 3, "stem": null, "options": null, "answers_accept": ["had", "'d"], "answer_official": "had", "explain": null, "tags": []}, {"no": 4, "stem": null, "options": null, "answers_accept": ["of"], "answer_official": "of", "explain": null, "tags": []}, {"no": 5, "stem": null, "options": null, "answers_accept": ["to"], "answer_official": "to", "explain": null, "tags": []}, {"no": 6, "stem": null, "options": null, "answers_accept": ["spite"], "answer_official": "spite", "explain": null, "tags": []}], "source": {"origin": "cepoc", "file": "assets/open-source/cepoc-main/PET.json", "orig_id": 20, "url": "https://github.com/CambridgeALTA/cepoc", "retrieved": "2026-08-21", "source_id": "cepoc", "source_item_id": "cepoc-b1-json"}, "license": "cc-nc-education", "tags": ["cloze", "open_cloze"], "note": "CEPOC 未标注套题年份与卷内 Part 号;空格数与 2020 版题型不完全对应(KET 11-12空/套、PET 6-8空/套),推断混有 2020 改版前真题。完形题型本身对应 A2 Key Reading & Writing / B1 Preliminary Reading 的 open cloze 题型。", "meta": {"multi_answer_items": 1}}
{"schema": "qb-1.1", "id": "b1-cepoc-0021", "exam": "B1 Preliminary", "cefr": "B1", "paper": "reading", "part": null, "type": "open_cloze", "task_prompt": "For each gap, write ONE word which best completes the text.", "title": "How to hold a fun party", "passage": "Are you thinking about holding a party? Then you need _ make sure it’s lots of fun! Invite plenty _ people and include a few surprises. For example, if you’re serving food, try ordering ten pizzas _ are the same flavour but come from different restaurants in your area. Then have a ‘taste test’ and vote on _ best one. Or _ about playing games? You could have a video games tournament and offer prizes for the winners. You could also have a singing competition and ask _ guest to sing a song.\n\nIf your party includes a meal around a table, for each new course, ask your guests to sit next to someone different, in _ to talk to as many different people _ possible. Finally, play fun music: your guests might even get up and dance!", "blank_token": "_", "items": [{"no": 1, "stem": null, "options": null, "answers_accept": ["to"], "answer_official": "to", "explain": null, "tags": []}, {"no": 2, "stem": null, "options": null, "answers_accept": ["of"], "answer_official": "of", "explain": null, "tags": []}, {"no": 3, "stem": null, "options": null, "answers_accept": ["that", "which"], "answer_official": "that", "explain": null, "tags": []}, {"no": 4, "stem": null, "options": null, "answers_accept": ["the"], "answer_official": "the", "explain": null, "tags": []}, {"no": 5, "stem": null, "options": null, "answers_accept": ["how", "what"], "answer_official": "how", "explain": null, "tags": []}, {"no": 6, "stem": null, "options": null, "answers_accept": ["every", "each"], "answer_official": "every", "explain": null, "tags": []}, {"no": 7, "stem": null, "options": null, "answers_accept": ["order"], "answer_official": "order", "explain": null, "tags": []}, {"no": 8, "stem": null, "options": null, "answers_accept": ["as"], "answer_official": "as", "explain": null, "tags": []}], "source": {"origin": "cepoc", "file": "assets/open-source/cepoc-main/PET.json", "orig_id": 21, "url": "https://github.com/CambridgeALTA/cepoc", "retrieved": "2026-08-21", "source_id": "cepoc", "source_item_id": "cepoc-b1-json"}, "license": "cc-nc-education", "tags": ["cloze", "open_cloze"], "note": "CEPOC 未标注套题年份与卷内 Part 号;空格数与 2020 版题型不完全对应(KET 11-12空/套、PET 6-8空/套),推断混有 2020 改版前真题。完形题型本身对应 A2 Key Reading & Writing / B1 Preliminary Reading 的 open cloze 题型。", "meta": {"multi_answer_items": 3}}

查看文件

@@ -0,0 +1,101 @@
# 词库 INDEX — 数据总览与使用指南
> 更新:2026-08-21 | 解析器:`scripts/parse_vocab.py`(pymupdf,纯规则解析,零 LLM 成本)
> 对应计划:题库路线 P3(官方词表 → 结构化词库)+ P3.5(词库增补:中文释义 + IPA 音标)
> 增补管线:`scripts/enrich_gloss.py`(ECDICT 匹配)+ `scripts/make_llm.py`(LLM 增补)+ `scripts/finalize_vocab.py`(音标格式统一 + 补常用词音标)
## 一、现有数据
| 文件 | 级别 | 主表词条 | 仅主题表补充词 | 合计 | 其中 B1 新增 | 来源 | 许可 |
|---|---|---|---|---|---|---|---|
| `a2-key-vocab.jsonl` | A2 Key / for Schools | 1727 | 13 | **1740** | — | 剑桥官方词汇表(2025-08 版) | `official-free` |
| `b1-preliminary-vocab.jsonl` | B1 Preliminary / for Schools | 3055 | 117 | **3172** | 1517(`new_at_b1=true`) | 剑桥官方词汇表(2020 版) | `official-free` |
| `word-sets.json` | A2+B1 通用 | — | — | 6 个词集 | — | Appendix 1(规则生成) | `official-free` |
主题(topic)覆盖:A2 25 个 / B1 23 个(Clothes、Education、Food and Drink、Travel and Transport、Work and Jobs 等)。
## 二、记录结构(每行一个词条)
```json
{
"id": "a2k-vocab-0091",
"level": "A2",
"headword": "attractive", // 原样保留, 含变体斜杠 "café/cafe"、缩写 "(kg)"
"pos": ["adj"], // 词性数组; 多词词性整体保留: "phr v"/"prep phr"/"aux v"
"pos_notes": null, // 用法/地区注记: ["+ ing"], ["(Br Eng) (Am Eng: bathing suit)"], ["unc (uncountable)"]
"examples": [{"text": "The walls are an attractive colour.", "pos": null}],
"phrases": null, // 子短语/搭配: "(be) bad for somebody", "bright pink"
"topics": ["Clothes and Accessories"], // 来自 Appendix 2 主题表
"origin": "main_list", // main_list=字母序主表 / topic_list=仅出现在主题表
"no_pos": true, // 仅少数: PDF 原文无词性标注 (如 "film star")
"new_at_b1": false, // 仅 B1 文件: 该词不在 A2 词表 = B1 新增
"source": {"file": "...", "url": "...", "publisher": "Cambridge English / UCLES", "licence": "official-free"},
"gloss": { // P3.5 增补: 中文释义 + IPA 音标
"zh": "n. 苹果", // 带词性前缀的中文释义
"phonetic": "/ˈæpl/", // 英式 IPA, 统一包裹为 /.../
"source": "ecdict", // ★ 来源标注: "ecdict"=ECDICT 开源词典 / "llm"=LLM 生成
"licence": "CC-BY-SA-4.0", // ecdict 对应 CC-BY-SA-4.0; llm 对应 llm-generated
"phonetic_source": "llm" // 可选: 仅当音标由 LLM 补、释义来自 ECDICT 时出现
}
}
```
## 三、下游 agent 使用须知
1. **背单词优先序**(推荐):A2 全部 → B1 中 `new_at_b1=true` 的 1517 词 → topic_list 补充词。两级共约 3257 去重词条。
2. **例句仍是稀缺资源**:官方词表仅约 11% 词条带例句(A2 170 / B1 218 条),主要标注多义词的分用法。**中文释义与音标已通过 P3.5 增补进 `gloss` 字段**(见 §三·五),但例句本身未生成。
3. **主题背诵**:`topics` 字段支持按场景刷词(如先攻 Food and Drink);同一词可属多个主题。
4. **词性坑**:`be` 的词性是 `["aux v","v"]`(PDF 原文缩写 "av",按剑桥缩写表解释为助动词);不可数名词注记在 `pos_notes`(如 rubbish)。
5. **topic_only 词**(A2 13 / B1 117):官方明确为"考生还应知道的补充词"(如 get dressed、climate change),无例句无主表词性,但 `pos` 可能来自主题表标注。
6. **变体词头**:`trainers`(topic)与 `trainer`(主表)已按复数回退匹配;但 A2 主表无 trainer,故 A2 里 trainers 仍是独立补充词。
7. **word-sets.json**:基数/序数/星期/月份/季节/大洲为确定性生成集;国家·语言·民族开放集合未枚举(官方用 etc.),需要时另行补表。
8. **许可**:全部 `official-free`,可进部署门户;但 PDF 内的 "Additions in green"(2025 新增词标记)在文本层无颜色信息,未能结构化。
## 三·五、P3.5 增补说明(中文释义 + IPA 音标)
官方 PDF 无中文释义、无音标,本步补齐 `gloss` 字段(每条记录已写入,无遗漏)。
**来源标注(用户要求:区分「原词条」与「LLM 增补」)**
- `gloss.source = "ecdict"`:中文释义来自 **ECDICT** 开源英汉词典(CC-BY-SA-4.0),词典级数据,覆盖约 98%。
- `gloss.source = "llm"`:ECDICT 未命中的残余词头(多为短语/复合词/剑桥多义分项,如 `deal with`、`smart (clever)`、`social media`),由 **LLM 生成**中文释义 + 音标(`licence: llm-generated`)。共 98 条记录(83 个去重词头)。
- `gloss.phonetic_source = "llm"`(可选):仅 97 条「释义来自 ECDICT、但 ECDICT 原条目缺音标」的常用单词,音标由 LLM 补、释义 provenance 不变。
**覆盖统计(4902 条)**
| 指标 | 数值 |
|---|---|
| `gloss` 覆盖率 | 100%(4902/4902) |
| `source=ecdict` | 4804 条 |
| `source=llm` | 98 条 |
| 有音标 | 4576 条(93.3%) |
| 无音标 | 326 条(6.7%,**全部为短语/多词**,如 `a few`、`alarm clock`) |
**为什么短语留空音标**:学习者已掌握组成单词的发音,短语整体音标优先级低;若后续需要可单独补(g2p 模型或 LLM)。
**管线与复现**
```bash
cd english-site
python scripts/enrich_gloss.py match # ECDICT 匹配 -> _gloss_cache/ecdict.json
python scripts/make_llm.py # LLM 增补 83 词 -> _gloss_cache/llm.json
python scripts/enrich_gloss.py merge # 合并写回 *.jsonl
python scripts/finalize_vocab.py # 音标统一 /.../ + 补 71 常用单词音标
```
> ECDICT 原始数据:`assets/vocab/ecdict/`(StarDict 格式,67MB,从 github release 经 gh-proxy 镜像下载)。清洗规则见 `enrich_gloss.py: clean_entry`(剥离词频/考试标签、西里尔 ә→ə、ASCII 撇号→IPA 重音符等)。
## 四、已知局限(诚实披露)
- ~~官方 PDF 无中文释义、无音标~~ → 已在 P3.5 通过 ECDICT + LLM 增补进 `gloss` 字段(见 §三·五);仅 326 条短语(6.7%)因 ECDICT 无音标而留空,释义仍在。
- `film star`、`zebra` 等 2 个 B1 词条原文无词性(`no_pos=true`),非解析丢失。
- `driving/driver's licence` 等极少数跨行词头的地区变体注记可能不完整(已抽查主流 5 例均正确)。
- B1 词表基于 2018 © 版本(2020 起生效),A2 基于 2025-08 版,两版之间 A2 的新增词(若 B1 版本更旧)不影响 `new_at_b1` 的判断方向,但个别词的归属可能滞后。
## 五、复现
```bash
cd english-site
python scripts/parse_vocab.py # 输出到 data/vocab/, 隔离区 0 条, id 唯一校验通过
```
## 六、素材勘误(相对调研报告)
- `assets/vocab/b1-preliminary-vocabulary-booklet.pdf`(8MB)**不是词表**,是《B1 for Schools 词汇教学活动手册》(教师用),保留作教学设计参考。
- B1 官方词表直链 `cambridgeenglish.org/Images/506887-*.pdf` 已 404,改用 **cambridgeenglish.cn 域名**下载成功(文件已存 `assets/vocab/b1-preliminary-2020-vocabulary-list.pdf`)。

文件差异内容过多而无法显示 加载差异