auto backup: 2026-06-11 08:10:01
This commit is contained in:
parent
78dc45d3fd
commit
a399a80b48
39
AGENTS.md
39
AGENTS.md
@ -246,6 +246,45 @@ Skills 按四层架构组织:
|
||||
|
||||
> **示例:** 用户发来飞书 wiki 链接说「组件生产」→ 调用 `script-component-production`,读剧本表 → 生成互动组件内容 → 回填对应列
|
||||
|
||||
**组件生产模块目录结构:**
|
||||
|
||||
```
|
||||
组件生产/
|
||||
├── skills/ # 8 个技能
|
||||
│ ├── script-component-production/ # 主技能(生产 pipeline)
|
||||
│ │ └── assets/ # component_rules.yaml / review_checklist.yaml / skill.yml
|
||||
│ ├── component-design/ # 组件设计规范
|
||||
│ ├── vala-interactive-components/ # 互动组件格式参考
|
||||
│ ├── task-router/ # 组件标准化路由
|
||||
│ │ ├── component_configs.yaml # 组件类型配置映射
|
||||
│ │ ├── agents/openai.yaml # LLM agent 配置
|
||||
│ │ └── scripts/ # generate / review / route
|
||||
│ ├── dialogue-interaction-config/ # 对话类互动配置规范(被主技能引用)
|
||||
│ ├── dialogue-selective-reading-config/ # 对话选读配置(被 task-router 引用)
|
||||
│ ├── info-sentence-building-config/ # 信息组句配置(被 task-router 引用)
|
||||
│ └── info-word-spelling-config/ # 信息拼词配置(被 task-router 引用)
|
||||
├── scripts/ # 2 个核心脚本
|
||||
│ ├── produce_components.py # 主 pipeline:读 Sheet → LLM 生成 → 校验 → 回填 H 列
|
||||
│ └── validate_format.py # 格式校验:通用规则 + 题型专属规则(27 中互动 + 15 核心互动)
|
||||
├── backup/scripts/ # 历史脚本归档(15 个单次任务脚本)
|
||||
├── final/ # 历史交付产物(xlsx/md)
|
||||
├── output/ # 运行时临时输出(JSON)
|
||||
└── memory/ # 模块专属记忆
|
||||
```
|
||||
|
||||
**子技能引用关系:**
|
||||
- `script-component-production` → 引用 `dialogue-interaction-config`
|
||||
- `task-router` → 引用 `dialogue-selective-reading-config` / `info-sentence-building-config` / `info-word-spelling-config`
|
||||
- `component-design` / `vala-interactive-components` → 独立触发,不引用其他子技能
|
||||
|
||||
**校验流程(pipeline 内置):**
|
||||
```
|
||||
LLM 生成组件内容 → validate_format.py 校验
|
||||
├─ ERROR → 跳过回填,标记 validation_failed
|
||||
└─ WARN → 打印提示,继续回填
|
||||
```
|
||||
校验脚本也可独立调用:`python3 validate_format.py --type "对话挖空" --stdin < config.txt`
|
||||
|
||||
#### 组件配置(Component JSON Config)
|
||||
|
||||
| 触发词 | 技能 | 路径 |
|
||||
|
||||
@ -96,7 +96,8 @@
|
||||
1. **禁止 Markdown 标记**:生成单元挑战的音频文本、阅读文本等任何内容文本时,禁止使用 `**` `*` `__` `_` 等 Markdown 加粗/斜体标识,也禁止使用 `#` `>` `-` 等块级 Markdown 语法。输出纯文本即可。
|
||||
2. **适用场景**:单元挑战所有文本输出(音频台词、阅读理解文章、写作提示、口语话题等),以及任何需要嵌入题目 jsonData 的文本内容
|
||||
3. **英式拼写优先**:单词涉及英美式拼写差异时(如 colour/color、centre/center、travelling/traveling),统一选择英式拼写
|
||||
4. **标点符号规范**:严格区分全角/半角符号,中文内容使用全角标点(,。!?),英文内容使用半角标点(. , ! ?),不得混用
|
||||
4. **标点符号规范**:严格区分全角/半角符号,中文内容使用全角标点(,。!?:),英文内容使用半角标点(. , ! ? :),不得混用。特别注意:英文冒号必须用半角 `:`,不得用全角 `:`
|
||||
5. **中英文混排空格规范**:中文与英文/数字之间加半角空格(如"汇报 Jay 不配合"、"Tom 说 hello"),纯中文或纯英文内容不加额外空格
|
||||
|
||||
### 【教研规则】剧本定稿审校通用规范
|
||||
1. 标点符号规范:禁止使用「~」「!!!」等非标准标点,统一使用标准英文标点符号
|
||||
|
||||
@ -1,42 +0,0 @@
|
||||
|
||||
import pandas as pd
|
||||
|
||||
file_l2 = r'/root/.openclaw/workspace-xiaoyan/business_knowledge/L2单词表/L2新版独有单词.xlsx'
|
||||
file_kb = r'/root/.openclaw/workspace-xiaoyan/business_knowledge/L2单词表/L2知识库-三级+A2.xlsx'
|
||||
|
||||
df_l2 = pd.read_excel(file_l2)
|
||||
df_kb = pd.read_excel(file_kb)
|
||||
|
||||
available = df_l2[df_l2['可用'] == 1].copy()
|
||||
|
||||
new_rows = []
|
||||
for _, row in available.iterrows():
|
||||
new_rows.append({
|
||||
'单词': row['单词'],
|
||||
'词性': row['词性'],
|
||||
'中文释义': row['词义'],
|
||||
'KET/三级重合': '',
|
||||
'分类': '',
|
||||
'Unnamed: 5': '',
|
||||
'与L1重复': row['是否为L1单词'],
|
||||
'L1词性': row['L1词性'] if pd.notna(row['L1词性']) else '',
|
||||
'L1词义': row['L1词义'] if pd.notna(row['L1词义']) else '',
|
||||
'在L1中的行数': row['L1行数'] if pd.notna(row['L1行数']) else '',
|
||||
'删除': ''
|
||||
})
|
||||
|
||||
df_new = pd.DataFrame(new_rows)
|
||||
|
||||
df_kb = pd.concat([df_kb, df_new], ignore_index=True)
|
||||
|
||||
df_kb = df_kb.sort_values(by='单词', key=lambda x: x.str.lower(), ignore_index=True)
|
||||
|
||||
output_path = r'/root/.openclaw/workspace-xiaoyan/business_knowledge/L2单词表/L2知识库-三级+A2.xlsx'
|
||||
df_kb.to_excel(output_path, index=False)
|
||||
|
||||
print(f"已添加 {len(new_rows)} 个单词")
|
||||
print(f"L2知识库总单词数: {len(df_kb)}")
|
||||
print(f"\n已保存至: {output_path}")
|
||||
print("\n添加的单词(按字母顺序):")
|
||||
for i, row in df_new.sort_values(by='单词', key=lambda x: x.str.lower()).iterrows():
|
||||
print(f" {row['单词']:<15} {str(row['词性']):<10} {row['中文释义']:<25} L1:{row['与L1重复']} L1词性:{row['L1词性']} L1词义:{row['L1词义']}")
|
||||
@ -1,53 +0,0 @@
|
||||
|
||||
import pandas as pd
|
||||
|
||||
# 文件路径
|
||||
file_path = r'/root/.openclaw/workspace-xiaoyan/business_knowledge/L2单词表/L2知识库-三级+A2.xlsx'
|
||||
|
||||
# 要添加的16个单词
|
||||
words_to_add = [
|
||||
('supper', 'n.', '晚餐'),
|
||||
('cafeteria', 'n.', '食堂'),
|
||||
('tidy up', 'v.', '收拾'),
|
||||
('all sorts of', 'phr.', '各种各样的'),
|
||||
('all the time', 'phr.', '一直'),
|
||||
('bring back', 'v.', '拿回'),
|
||||
('turn off', 'v.', '关掉'),
|
||||
('cabinet', 'n.', '橱柜'),
|
||||
('get back', 'v.', '拿回'),
|
||||
('costume', 'n.', '服装'),
|
||||
('equipment', 'n.', '装备'),
|
||||
('explorer', 'n.', '探险家'),
|
||||
('upload', 'v.', '上传'),
|
||||
('dot', 'n.', '点'),
|
||||
('successful', 'adj.', '成功的'),
|
||||
('give back', 'v.', '归还'),
|
||||
]
|
||||
|
||||
# 按字母顺序排序
|
||||
words_to_add_sorted = sorted(words_to_add, key=lambda x: x[0].lower())
|
||||
|
||||
# 读取文件
|
||||
df = pd.read_excel(file_path)
|
||||
|
||||
print(f"现有行数: {len(df)}")
|
||||
|
||||
# 创建新行DataFrame
|
||||
new_rows = pd.DataFrame(words_to_add_sorted, columns=['单词', '词性', '中文释义'])
|
||||
|
||||
# 合并
|
||||
df_updated = pd.concat([df, new_rows], ignore_index=True)
|
||||
|
||||
# 按字母顺序排序
|
||||
df_updated = df_updated.sort_values(by='单词', key=lambda x: x.astype(str).str.lower())
|
||||
|
||||
# 保存
|
||||
df_updated.to_excel(file_path, index=False)
|
||||
|
||||
print(f"\n添加完成!")
|
||||
print(f"添加了 {len(words_to_add)} 个新单词")
|
||||
print(f"更新后总行数: {len(df_updated)}")
|
||||
|
||||
print("\n新添加的单词(按字母顺序):")
|
||||
for i, (word, pos, meaning) in enumerate(words_to_add_sorted, 1):
|
||||
print(f"{i:2d}. {word:20s} {pos:8s} {meaning}")
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
339
business_knowledge/interactive_component_reference.md
Normal file
339
business_knowledge/interactive_component_reference.md
Normal file
@ -0,0 +1,339 @@
|
||||
# 互动组件内容库参考
|
||||
|
||||
> 来源:飞书知识库「互动内容库」43 个多维表格(bitable)
|
||||
> Wiki 空间 ID: `7487521512283799556`
|
||||
> 节点 token: `TbbGwZLIVizXeGkMEKQc2hKRnCc`
|
||||
> 生成时间:2026-06-10
|
||||
|
||||
## 概述
|
||||
|
||||
互动内容库包含 **43 个多维表格**,覆盖全部 **42 种组件类型**(27 中互动 + 16 核心互动,写作互动与邮件组句共用 `core_writing_questionMakeSentence`)。
|
||||
|
||||
每个 bitable 按 Season/Unit 分表(L1-Demo、S0U0、S1U1~S1U12、S2、S3 等),包含实际生产数据。
|
||||
|
||||
### 数据读取方式
|
||||
|
||||
所有 bitable 通过飞书开放 API(Bot 身份)读取:
|
||||
- API Base: `https://open.feishu.cn/open-apis/bitable/v1/apps/{app_token}/tables/{table_id}/records`
|
||||
- 需 tenant_access_token(有效期 2 小时)
|
||||
- App ID: `cli_a931175d41799cc7`
|
||||
|
||||
---
|
||||
|
||||
## 一、中互动(27 种)
|
||||
|
||||
### 1.1 对话类(7 种)
|
||||
|
||||
| # | 名称 | cType | app_token | 字段数 |
|
||||
|---|------|-------|-----------|--------|
|
||||
| 1 | 对话互动 | `mid_sentence_dialogue` | `LhU4wpeNKi0uV0kPI8TclEpSnfd` | 20 |
|
||||
| 2 | 对话朗读互动 | `mid_dialog_repeat` | `XOxewswJ4icydHk6ED8c8HOWnRb` | 18 |
|
||||
| 3 | 对话表达互动 | `mid_dialog_express` | `BMyCwJDBvi4EckkkErFcQerrnOb` | 20 |
|
||||
| 4 | 对话选择互动 | `mid_dialog_choose` | `Q8p2w8k0ui1DmikWiKYcYwGsnOd` | 18 |
|
||||
| 5 | 对话选读互动 | `mid_dialog_select` | `R11ZwjwvOiLLxPkzYl6cD31fntz` | 18 |
|
||||
| 6 | 对话挖空互动 | `mid_dialog_fillin` | `UoFdwE5BRiVZYUk3BdBcP1NPnWb` | 19 |
|
||||
| 7 | 对话组句互动 | `mid_dialog_sentence` | `McS1wfB6UibdEVkKFZgceQl0nKb` | 19 |
|
||||
|
||||
**公共字段:**
|
||||
```
|
||||
ID, dataStatus, jsonData, kpInfo, kpListSentence, kpListVocab, kpStatus,
|
||||
单元 Unit, 关联知识点, 教研配置, 标题, 情境引入, 互动内容, 后置对话,
|
||||
父记录, 角色物品配置, 隔离区
|
||||
```
|
||||
|
||||
**差异字段:**
|
||||
- 对话互动/表达/挖空/组句:额外有 `互动反馈`、`语音识别热词`
|
||||
- 对话朗读/选择/选读:额外有 `资源配置`
|
||||
- 对话互动独有:`学习意义构建`
|
||||
|
||||
**jsonData 结构示例(对话互动):**
|
||||
```json
|
||||
{
|
||||
"cType": "mid_sentence_dialogue",
|
||||
"cId": "0500001",
|
||||
"title": "表达自己的感受",
|
||||
"sceneDesc": "...",
|
||||
"dialogList": [...],
|
||||
"feedback": {...},
|
||||
"postDialog": [...],
|
||||
"learningMeaning": "..."
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 1.2 信息类(6 种)
|
||||
|
||||
| # | 名称 | cType | app_token | 字段数 |
|
||||
|---|------|-------|-----------|--------|
|
||||
| 8 | 信息描写 | `mid_message_trace` | `UJq1wEn8pikOcpkWmHVcPbp3nrc` | 14 |
|
||||
| 9 | 信息拼词 | `mid_message_spell` | `C7jnwPtShiaY74kZYgKcl5L7n6b` | 14 |
|
||||
| 10 | 信息组句 | `mid_message_combine` | `T0mTwpwx8iBdA5k7CsYcnmLjndh` | 14 |
|
||||
| 11 | 信息补词 | `mid_message_fillin` | `T1muwEylIiIjvBkU4fRc5dntnNt` | 14 |
|
||||
| 12 | 信息填词 | `mid_message_word` | `RPI6wMCEribBuFkcQewcCavdnNf` | 14 |
|
||||
| 13 | 信息填句 | `mid_message_sentence` | `HJ58wR5imixNBzkttticVYEanSb` | 14 |
|
||||
|
||||
**公共字段(14 个,完全统一):**
|
||||
```
|
||||
ID, dataStatus, jsonData, kpInfo, kpListSentence, kpListVocab, kpStatus,
|
||||
单元 Unit, 关联知识点, 教研配置, 标题, 互动内容, 互动描述,
|
||||
父记录, 角色物品配置, 隔离区
|
||||
```
|
||||
|
||||
> ⚠️ 信息类 6 种目前数据均为"测试数据1"(ID: 0325001),尚未正式投产。
|
||||
|
||||
---
|
||||
|
||||
### 1.3 图片类(5 种)
|
||||
|
||||
| # | 名称 | cType | app_token | 字段数 |
|
||||
|---|------|-------|-----------|--------|
|
||||
| 14 | 图片互动 | `mid_vocab_image` | `QU1rwIIcgiucJjkq9TmcPZ1enSd` | 15 |
|
||||
| 15 | 图片单选 | `mid_image_choose` | `EZ4Rw6kXeiVsTiko688cCMIkn3d` | 19 |
|
||||
| 16 | 图片多选 | `mid_image_multiple` | `VqFcwLKa2iSbEFk2jZUceRtnnyf` | 18 |
|
||||
| 17 | 图片有序 | `mid_image_sequence` | `K8CQwPudPiTccFkn76YcztEQnBg` | 18 |
|
||||
| 18 | 图片拖拽 | `mid_image_drag` | `WfK6wRnKaiLcfUk41DgcAcnPnId` | 18 |
|
||||
|
||||
**公共字段:**
|
||||
```
|
||||
ID, dataStatus, jsonData, kpInfo, kpListSentence, kpListVocab, kpStatus,
|
||||
单元 Unit, 关联知识点, 教研配置, 任务标题, 情境引入, 互动内容,
|
||||
互动反馈, 互动描述, 后置对话, 学习意义, 隔离区
|
||||
```
|
||||
|
||||
**差异:**
|
||||
- 图片互动独有:无 `角色物品配置`、`父记录`
|
||||
- 图片单选独有:`角色物品配置`、`父记录`
|
||||
- 图片多选/有序/拖拽:有 `角色物品配置`,无 `父记录`
|
||||
|
||||
---
|
||||
|
||||
### 1.4 其他中互动(9 种)
|
||||
|
||||
| # | 名称 | cType | app_token | 字段数 |
|
||||
|---|------|-------|-----------|--------|
|
||||
| 19 | 物品互动 | `mid_vocab_item` | `VkcIw2ajii87Z7kHKhEc443qnKe` | 13 |
|
||||
| 20 | 材料互动 | `mid_sentence_material` | `NSjmwmASBiyPkBkdk2CcakKlnSd` | 16 |
|
||||
| 21 | 指令互动 | `mid_vocab_instruction` | `YA8NwTcSbiR7yakFP4kcOmzbnlg` | 17 |
|
||||
| 22 | 挖空互动 | `mid_grammar_cloze` | `GkzRwX4QGiAoZzkfiRrcV0svn1f` | 18 |
|
||||
| 23 | 组句互动 | `mid_grammar_sentence` | `EJJiwsTQ7iYg0bkG2PEcjYfNnOd` | 17 |
|
||||
| 24 | 填词互动 | `mid_vocab_fillBlank` | `UpSJwR6yJic8FTkn7b2chK4Nntc` | 15 |
|
||||
| 25 | 语音互动 | `mid_sentence_voice` | `UMp0wGpruicY5skBAbrcC6Usnxc` | 19 |
|
||||
| 26 | 造句互动 | `mid_sentence_makeSentence` | `I7mWwwWPVieCJLkhgU4cSr7XnPs` | 19 |
|
||||
| 27 | 发音互动 | `mid_pron_pron` | `Zi9AwZb8LiMgtHk5xCXc0vuNnIb` | 15 |
|
||||
|
||||
**各类型特有字段:**
|
||||
|
||||
| 类型 | 特有字段 |
|
||||
|------|---------|
|
||||
| 物品互动 | `学习意义` |
|
||||
| 材料互动 | `互动反馈`、`后置对话`、`学习意义构建`、`情境引入` |
|
||||
| 指令互动 | `指令互动`、`指令反馈`、`后置对话`、`学习意义构建`、`情境引入` |
|
||||
| 挖空互动 | `互动反馈`、`挖空整句`、`后置对话`、`学习意义构建`、`情境引入` |
|
||||
| 组句互动 | `互动反馈`、`后置对话`、`学习意义构建`、`情境引入` |
|
||||
| 填词互动 | `学习意义构建` |
|
||||
| 语音互动 | `互动反馈`、`录音文本`、`后置对话`、`学习意义构建`、`情境引入` |
|
||||
| 造句互动 | `互动反馈`、`后置对话`、`学习意义构建`、`情境引入` |
|
||||
| 发音互动 | `学习意义构建`(注:kpListVoacb 拼写为 Voacb 非 Vocab) |
|
||||
|
||||
---
|
||||
|
||||
## 二、核心互动(16 种)
|
||||
|
||||
### 2.1 听力类(3 种)
|
||||
|
||||
| # | 名称 | cType | app_token | 字段数 |
|
||||
|---|------|-------|-----------|--------|
|
||||
| 28 | 听力拖拽 | `core_listening_drag` | `K3QrwQnWqiPBm1krhnNcWDTqnhe` | 28 |
|
||||
| 29 | 听力选择 | `core_listening_choose` | `Kwrcw6A4jip2sxkdLn4czd1knvf` | 23 |
|
||||
| 30 | 合作听力 | `core_listening_order` | `FrxtwNRQDizqiikPkATcBzTCnYe` | 24 |
|
||||
|
||||
**听力拖拽字段:**
|
||||
```
|
||||
ID, dataStatus, taskData, dialogList, questionList, learningData,
|
||||
kpInfo, kpListSentence, kpListVocab, kpStatus,
|
||||
单元 Unit, 关联知识点, 专有名词, 互动描述,
|
||||
听力材料, 学习过程, 学习过程配置, 开场语,
|
||||
教研配置-互动配置, 教研配置-导览配置,
|
||||
用户任务描述, 用户任务知识, 角色配置,
|
||||
父记录, 隔离区, 题目
|
||||
```
|
||||
|
||||
**听力选择字段:**
|
||||
```
|
||||
ID, dataStatus, taskData, questionGroup, learningData,
|
||||
kpInfo, kpListSentence, kpListVocab, kpStatus,
|
||||
单元 Unit, 关联知识点, 专有名词, 互动描述,
|
||||
学习过程, 学习过程配置,
|
||||
教研配置-互动配置, 教研配置-导览配置,
|
||||
用户任务描述, 用户任务知识, 角色配置,
|
||||
父记录, 隔离区, 题目组
|
||||
```
|
||||
|
||||
**合作听力字段:**
|
||||
```
|
||||
ID, dataStatus, taskData, textData, sequenceData, learningData,
|
||||
kpInfo, kpListSentence, kpListVocab, kpStatus,
|
||||
单元 Unit, 关联知识点, 互动描述,
|
||||
听力材料, 学习过程, 学习过程配置,
|
||||
教研配置-任务, 教研配置-材料, 流程编排,
|
||||
用户任务描述, 用户任务知识, 角色配置,
|
||||
隔离区, 题目
|
||||
```
|
||||
|
||||
**taskData 结构示例(听力拖拽):**
|
||||
```json
|
||||
{
|
||||
"cType": "core_listening_drag",
|
||||
"cId": "1000113",
|
||||
"title": "收拾书包",
|
||||
"sceneDesc": "上学前,爸爸要和你一起收拾书包...",
|
||||
"key": [{"desc": "", "keyList": [{"type": "default", "content": "red", "desc": "adj. 红色的"}]}],
|
||||
"resourceMapping": {"Dad": 648},
|
||||
"cDesc": "You listened to Dad's instructions..."
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.2 阅读类(2 种)
|
||||
|
||||
| # | 名称 | cType | app_token | 字段数 |
|
||||
|---|------|-------|-----------|--------|
|
||||
| 31 | 合作阅读 | `core_reading_order` | `H6DJweNkpigCbak2Y5LcTZ8Vnfb` | 29 |
|
||||
| 32 | 看图选词 | `core_reading_imageDrag` | `MVo7wugWfimJPIkxhJCcqppFnyf` | 20 |
|
||||
|
||||
**合作阅读字段:**
|
||||
```
|
||||
ID, dataStatus, taskData, textData, sequenceData, learningData,
|
||||
kpInfo, kpListSentence, kpListVocab, kpStatus,
|
||||
单元 Unit, 关联知识点, 互动描述, 互动题目, 任务信息,
|
||||
分界线, 学习材料, 学习材料格式化, 学习过程配置,
|
||||
教研配置-任务, 教研配置-材料, 流程编排,
|
||||
角色配置, 通关知识, 阅读材料, 阅读材料格式化
|
||||
```
|
||||
|
||||
**看图选词字段:**
|
||||
```
|
||||
ID, dataStatus, taskInfo, questionGroup, studyInfo,
|
||||
kpInfo, kpListSentence, kpListVocab, kpStatus,
|
||||
单元 Unit, 关联知识点, 专有名词, 互动描述,
|
||||
分界线, 学习流程配置,
|
||||
教研-互动配置, 教研-导览配置,
|
||||
用户任务描述, 用户任务知识, 角色配置
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.3 口语类(6 种)
|
||||
|
||||
| # | 名称 | cType | app_token | 字段数 |
|
||||
|---|------|-------|-----------|--------|
|
||||
| 33 | 口语快答 | `core_speaking_reply` | `TSwcw0nFmi21khkpUndchNMsn6f` | 30 |
|
||||
| 34 | 口语独白 | `core_speaking_monologue` | `G20HwcF1uideNokLsHWcBs3znvg` | 28 |
|
||||
| 35 | 口语妙问 | `core_speaking_inquiry` | `GJUVwNSEkis3EXkrVj0ccbqdn8c` | 29 |
|
||||
| 36 | 看图说话 | `core_speaking_image` | `KBOXwzVHfin6ORkKbA3c3eWEnoh` | 29 |
|
||||
| 37 | 口语探讨 | `core_speaking_explore` | `HoidwhEBWiWjaokQnz0cHbhTn6e` | 27 |
|
||||
|
||||
**口语类公共字段:**
|
||||
```
|
||||
ID, dataStatus, taskData, configData, settingData, learningData,
|
||||
kpInfo, kpListSentence, kpListVocab, kpStatus,
|
||||
单元 Unit, 关联知识点, 分界线,
|
||||
用户任务描述, 用户任务知识, 角色配置,
|
||||
语音识别热词, 通过规则
|
||||
```
|
||||
|
||||
**各类型特有字段:**
|
||||
|
||||
| 类型 | 特有字段 |
|
||||
|------|---------|
|
||||
| 口语快答 | `exampleDialog`、`promptInfo配置`、`专有名词`、`任务背景`、`任务设定`、`学习流程配置`、`对话角色及回合设定`、`教研-任务规则与NPC设定`、`教研-用户视角任务信息`、`示例对话` |
|
||||
| 口语独白 | `npclistData`、`npc站位列表`、`专有名词`、`互动描述`、`切分句数`、`学习流程配置`、`教研-任务信息`、`教研-独白配置`、`示例独白` |
|
||||
| 口语妙问 | `exampleDialog`、`promptInfo配置`、`任务背景`、`任务设定`、`学习流程配置`、`对话角色及回合设定`、`教研-任务规则与NPC设定`、`教研-用户视角任务信息`、`知识库`、`示例对话`、`角色物品配置`、`隔离区` |
|
||||
| 看图说话 | `imageInfo`、`optionList`、`questionList`、`专有名词`、`互动问题`、`学习流程配置`、`对话信息`、`教研-对话配置`、`教研-导览配置`、`示例对话` |
|
||||
| 口语探讨 | `exampleDialog`、`promptInfo配置`、`任务背景`、`任务设定`、`学习内容`、`对话角色及回合设定`、`教研-任务规则与NPC设定`、`教研-用户视角任务信息`、`示例对话`、`角色物品配置`、`隔离区` |
|
||||
|
||||
---
|
||||
|
||||
### 2.4 写作类(5 种)
|
||||
|
||||
| # | 名称 | cType | app_token | 字段数 |
|
||||
|---|------|-------|-----------|--------|
|
||||
| 38 | 写作互动 | `core_writing_questionMakeSentence` | `DVkcwVr2giswTckcgD0cpHwNnv2` | 23 |
|
||||
| 39 | 看图组句 | `core_writing_imgMakeSentence` | `BkmtwUBwMiHd5Ak7VS6ccE9SnHd` | 23 |
|
||||
| 40 | 看图撰写 | `core_writing_imgWrite` | `KwPHwnaqdiWlvNkDm5fcFreDnQh` | 24 |
|
||||
| 41 | 邮件组句 | `core_writing_questionMakeSentence` | `M5oTwUP6wiImC4kVJU8cRYnfnyf` | 23 |
|
||||
| 42 | 邮件撰写 | `core_writing_questionWrite` | `Brn0wldKYizsLZkBqK6clp1tnKd` | 23 |
|
||||
| 43 | 看图拼词 | `core_writing_imgMakeWord` | `QDyhwiY7PiSER8kHGZncDsrinde` | 17 |
|
||||
|
||||
**写作类公共字段(38-42):**
|
||||
```
|
||||
ID, dataStatus, taskInfo, textInfo, studyInfo, evalInfo,
|
||||
kpInfo, kpListSentence, kpListVocab, kpStatus,
|
||||
单元 Unit, 关联知识点, 分界线,
|
||||
任务信息, 写作材料, 学习内容, 学习流程配置,
|
||||
教研配置 - 任务信息, 教研配置 - 全文信息,
|
||||
知识, 通过规则, 题目类型
|
||||
```
|
||||
|
||||
**看图拼词字段(43,结构不同):**
|
||||
```
|
||||
ID, dataStatus, taskInfo, imageInfo, questionList, preDialog, studyInfo,
|
||||
kpInfo, kpListSentence, kpListVocab, kpStatus,
|
||||
单元 Unit, 关联知识点, 分界线, 互动描述,
|
||||
学习流程配置,
|
||||
教研配置 - 任务信息, 教研配置-互动配置, 角色配置
|
||||
```
|
||||
|
||||
> ⚠️ 写作互动(38)和邮件组句(41)共用 `core_writing_questionMakeSentence`,通过不同 app_token 区分。
|
||||
|
||||
---
|
||||
|
||||
## 三、数据覆盖情况
|
||||
|
||||
| 分类 | 数量 | 数据状态 |
|
||||
|------|------|---------|
|
||||
| 中互动-对话 | 7 | ✅ 全部有正式数据 |
|
||||
| 中互动-信息 | 6 | ⚠️ 仅测试数据(ID: 0325001) |
|
||||
| 中互动-图片 | 5 | ✅ 全部有正式数据 |
|
||||
| 中互动-其他 | 9 | ✅ 全部有正式数据 |
|
||||
| 核心互动-听力 | 3 | ✅ 全部有正式数据 |
|
||||
| 核心互动-阅读 | 2 | ✅ 全部有正式数据 |
|
||||
| 核心互动-口语 | 6 | ✅ 全部有正式数据 |
|
||||
| 核心互动-写作 | 5 | ✅ 全部有正式数据 |
|
||||
| **合计** | **43** | **37 有正式数据,6 仅测试数据** |
|
||||
|
||||
---
|
||||
|
||||
## 四、关键发现
|
||||
|
||||
1. **双轨数据**:每条记录同时有「教研配置」(人工可读 markdown)和结构化 JSON(`jsonData`/`taskData`/`textData`),内容一致格式不同
|
||||
2. **中互动字段较统一**:14-20 个字段,`jsonData` 为核心结构体
|
||||
3. **核心互动字段高度定制**:17-30 个字段,按类型有 `taskData`、`textData`、`configData`、`learningData` 等多个结构体
|
||||
4. **信息类 6 种未正式投产**:仅有测试数据,字段结构已就绪
|
||||
5. **写作/邮件共用 cType**:写作互动和邮件组句共用 `core_writing_questionMakeSentence`,通过不同 app_token 区分场景
|
||||
6. **发音互动拼写异常**:`kpListVoacb`(应为 Vocab),可能是历史遗留
|
||||
|
||||
---
|
||||
|
||||
## 五、使用建议
|
||||
|
||||
### 作为 LLM 生成规范的 few-shot 源
|
||||
|
||||
1. **按 cType 匹配**:根据目标组件类型,从对应 bitable 取 1-2 条样例
|
||||
2. **优先用 jsonData/taskData**:结构化 JSON 比教研配置更适合 LLM 理解
|
||||
3. **中互动模板化程度高**:字段统一,few-shot 效果好
|
||||
4. **核心互动需按子类处理**:口语/听力/阅读/写作各有不同结构体
|
||||
|
||||
### 读取接口
|
||||
|
||||
```bash
|
||||
# 获取表列表
|
||||
curl -s "https://open.feishu.cn/open-apis/bitable/v1/apps/{app_token}/tables" \
|
||||
-H "Authorization: Bearer {tenant_access_token}"
|
||||
|
||||
# 获取记录(page_size 建议 1-3 条做 few-shot)
|
||||
curl -s "https://open.feishu.cn/open-apis/bitable/v1/apps/{app_token}/tables/{table_id}/records?page_size=3" \
|
||||
-H "Authorization: Bearer {tenant_access_token}"
|
||||
```
|
||||
@ -55,7 +55,8 @@ description: 单元挑战所有题型自动化审校技能。覆盖听力P1-P7
|
||||
|
||||
1. 禁止 Markdown 标记:禁止使用 ** * __ _ 等加粗/斜体标识,也禁止使用 # > - 等块级 Markdown 语法。所有文本纯文本输出。
|
||||
2. 英式拼写优先:单词涉及英美式拼写差异时(如 colour/color、centre/center、travelling/traveling),统一选择英式拼写。
|
||||
3. 标点符号规范:严格区分全角/半角符号。中文内容使用全角标点(,。!?),英文内容使用半角标点(. , ! ?),不得混用。
|
||||
3. 标点符号规范:严格区分全角/半角符号。中文内容使用全角标点(,。!?:),英文内容使用半角标点(. , ! ? :),不得混用。特别注意:英文冒号必须用半角 `:`,不得用全角 `:`。
|
||||
4. 中英文混排空格规范:中文与英文/数字之间加半角空格(如"汇报 Jay 不配合"、"Tom 说 hello"),纯中文或纯英文内容不加额外空格。
|
||||
|
||||
## 审校流程
|
||||
|
||||
|
||||
@ -31,7 +31,8 @@ description: 单元挑战核心层(永久固定,无重大升级不改动)
|
||||
|
||||
1. 禁止 Markdown 标记:禁止使用 `**` `*` `__` `_` 等加粗/斜体标识,也禁止使用 `#` `>` `-` 等块级 Markdown 语法。所有文本纯文本输出。
|
||||
2. 英式拼写优先:单词涉及英美式拼写差异时(如 colour/color、centre/center、travelling/traveling),统一选择英式拼写。
|
||||
3. 标点符号规范:严格区分全角/半角符号。中文内容使用全角标点(,。!?),英文内容使用半角标点(. , ! ?),不得混用。
|
||||
3. 标点符号规范:严格区分全角/半角符号。中文内容使用全角标点(,。!?:),英文内容使用半角标点(. , ! ? :),不得混用。特别注意:英文冒号必须用半角 `:`,不得用全角 `:`。
|
||||
4. 中英文混排空格规范:中文与英文/数字之间加半角空格(如"汇报 Jay 不配合"、"Tom 说 hello"),纯中文或纯英文内容不加额外空格。
|
||||
|
||||
## 改动规则
|
||||
- 非重大规则升级/词库全量更新,禁止修改本层内容
|
||||
|
||||
@ -33,7 +33,8 @@ description: 单元挑战总控调度大脑,统一接收所有单元挑战生
|
||||
5. 文本规范校验(强制):
|
||||
- 禁止 Markdown 标记(`**` `*` `__` `_` `#` `>` `-`),所有文本纯文本输出
|
||||
- 英式拼写优先(colour/centre/travelling 等)
|
||||
- 标点符号规范:中文全角(,。!?),英文半角(. , ! ?),不混用
|
||||
- 标点符号规范:中文全角(,。!?:),英文半角(. , ! ? :),不混用。英文冒号必须用半角 `:`
|
||||
- 中英文混排空格规范:中文与英文/数字之间加半角空格
|
||||
### 步骤5:结果输出
|
||||
按照要求格式输出,支持:
|
||||
- 教研文档格式:带解析、能力项、评分标准
|
||||
|
||||
@ -242,7 +242,8 @@ XXYYZZ
|
||||
3. **文本格式**(强制执行):
|
||||
- 禁止 Markdown 标记(`**` `*` `__` `_` `#` `>` `-` 等),所有文本纯文本输出
|
||||
- 英式拼写优先(colour/center/travelling)
|
||||
- 标点:中文全角(,。!?),英文半角(. , ! ?),禁止混用
|
||||
- 标点:中文全角(,。!?:),英文半角(. , ! ? :),禁止混用。英文冒号必须用半角 `:`
|
||||
- 中英文混排空格:中文与英文/数字之间加半角空格
|
||||
4. **答案分布**:选项题(如 P1 图片选择 A/B/C)答案均匀分布
|
||||
5. **题量规范**:题组1 和 题组2 题量须一致(通常各 5 题)
|
||||
6. **知识点标签**:每道题绑定对应知识点,用于智能出题和错题归因
|
||||
|
||||
14
business_production/组件生产/memory/2026-06-10.md
Normal file
14
business_production/组件生产/memory/2026-06-10.md
Normal file
@ -0,0 +1,14 @@
|
||||
# 组件生产 - 模块记忆
|
||||
|
||||
## 2026-06-10 目录清理
|
||||
- 删除 7 个孤儿 skill(dialogue-xxx-config 系列,无任何引用)
|
||||
- 删除空目录 image_generated/
|
||||
- 15 个历史脚本归档到 backup/scripts/
|
||||
- 保留 2 个核心脚本:produce_components.py + validate_format.py
|
||||
- validate_format.py 接入 produce_components.py pipeline(LLM 生成后校验)
|
||||
- AGENTS.md 补充完整目录结构和子技能引用关系
|
||||
|
||||
## 子技能引用关系
|
||||
- script-component-production → dialogue-interaction-config
|
||||
- task-router → dialogue-selective-reading-config / info-sentence-building-config / info-word-spelling-config
|
||||
- component-design / vala-interactive-components → 独立触发
|
||||
@ -166,7 +166,7 @@ Use exactly this format:
|
||||
|
||||
## KEY RULES
|
||||
1. Titles: NO numbers, NO dash separators, ≤10 characters
|
||||
2. Feedback: ALWAYS character dialogue format "Name: message", NEVER teacher-like instructions
|
||||
2. Feedback: ALWAYS character dialogue format "Name: message", NEVER teacher-like instructions. NO space before colon (e.g. "Tom: Hmm." NOT "Tom : Hmm.")
|
||||
3. Correct feedback: ALWAYS 无
|
||||
4. Fill blanks: use ___ (3 underscores) with spaces
|
||||
5. Dialogue choice/selective: options with inline feedback, NO separate 互动反馈
|
||||
@ -174,7 +174,10 @@ Use exactly this format:
|
||||
7. Dialogue types: 选项1:格式, lowercase start
|
||||
8. 情境引入/后置对话: 无内容时填 无
|
||||
9. Context: use both context_before and context_after
|
||||
10. KP matching: 知识点 must match provided KP"""
|
||||
10. KP matching: 知识点 must match provided KP
|
||||
11. Chinese-English spacing: add half-width space between Chinese and English (e.g. "汇报 Jay 不配合")
|
||||
12. Punctuation: English uses half-width (. , ! ? :), Chinese uses full-width (,。!?:), NEVER mix
|
||||
13. Dialogue fill-in-blanks: the question sentence MUST contain ___ and be in English (NOT a Chinese description)"""
|
||||
|
||||
def llm_generate(prompt):
|
||||
"""Call LLM to generate component config"""
|
||||
@ -270,6 +273,22 @@ def main():
|
||||
content = llm_generate(prompt)
|
||||
print(f" ✅ Generated {len(content)} chars")
|
||||
|
||||
# ── 格式校验 ──
|
||||
from validate_format import validate, Severity
|
||||
violations = validate(content, cr['type'])
|
||||
errors = [v for v in violations if v.severity == Severity.ERROR]
|
||||
warns = [v for v in violations if v.severity == Severity.WARN]
|
||||
if errors:
|
||||
print(f" ❌ Format validation failed ({len(errors)} errors):")
|
||||
for v in errors:
|
||||
print(f" - [{v.rule}] {v.detail}")
|
||||
results.append({"row": sheet_row, "id": cr["id"], "type": cr["type"],
|
||||
"status": "validation_failed", "errors": [v.detail for v in errors]})
|
||||
continue # Skip write-back
|
||||
if warns:
|
||||
for v in warns:
|
||||
print(f" ⚠️ [{v.rule}] {v.detail}")
|
||||
|
||||
# Write back
|
||||
if write_to_sheet(token, sheet_row, content):
|
||||
print(f" ✅ Written to H{sheet_row}")
|
||||
|
||||
807
business_production/组件生产/scripts/validate_format.py
Normal file
807
business_production/组件生产/scripts/validate_format.py
Normal file
@ -0,0 +1,807 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
互动组件配置格式校验脚本
|
||||
覆盖全部 27 种中互动 + 15 种核心互动组件类型
|
||||
校验维度:通用规则 + 题型专属规则 + 拼写检查
|
||||
|
||||
用法:
|
||||
python3 validate_format.py <teaching_config_text> --type <cn_type>
|
||||
python3 validate_format.py --file <path> # 批量校验
|
||||
python3 validate_format.py --sheet <spreadsheet_token> <sheet_id> # 飞书Sheet校验
|
||||
"""
|
||||
|
||||
import re
|
||||
import sys
|
||||
import json
|
||||
import argparse
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List, Dict, Optional, Tuple
|
||||
from enum import Enum
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 第一部分:题型格式特征定义(唯一真相源)
|
||||
# ============================================================
|
||||
|
||||
class ComponentCategory(Enum):
|
||||
MID = "mid" # 中互动
|
||||
CORE = "core" # 核心互动
|
||||
|
||||
|
||||
@dataclass
|
||||
class FormatSpec:
|
||||
"""单个题型的格式规范"""
|
||||
cn_name: str
|
||||
cType: str
|
||||
category: ComponentCategory
|
||||
|
||||
# 题型特征标记
|
||||
has_blank_marker: bool = False # 题干必须有 ___
|
||||
has_options: bool = False # 有选项列表
|
||||
has_answer: bool = False # 有答案
|
||||
has_per_option_feedback: bool = False # 每个选项有独立反馈
|
||||
is_read_type: bool = False # 朗读型
|
||||
is_express_type: bool = False # 表达型
|
||||
is_sentence_build: bool = False # 组句型(选项为碎片,答案为拼接句)
|
||||
is_fillin: bool = False # 挖空/填空型
|
||||
|
||||
# 文本规范
|
||||
question_lang: str = "" # 题干语言要求: "en" / "cn" / ""
|
||||
option_format: str = "" # 选项格式: "word" / "fragment" / "sentence" / "letter" / ""
|
||||
answer_format: str = "" # 答案格式: "word" / "sentence" / "index" / ""
|
||||
|
||||
# 附加说明
|
||||
notes: str = ""
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 中互动组件格式规范(27种)
|
||||
# ============================================================
|
||||
|
||||
MID_FORMAT_SPECS: Dict[str, FormatSpec] = {
|
||||
"对话互动": FormatSpec(
|
||||
cn_name="对话互动", cType="mid_sentence_dialogue",
|
||||
category=ComponentCategory.MID,
|
||||
is_read_type=True,
|
||||
question_lang="en",
|
||||
notes="朗读型,无选项无答案"),
|
||||
"对话朗读": FormatSpec(
|
||||
cn_name="对话朗读", cType="mid_dialog_repeat",
|
||||
category=ComponentCategory.MID,
|
||||
is_read_type=True,
|
||||
question_lang="en",
|
||||
notes="朗读型,无选项无答案"),
|
||||
"对话表达": FormatSpec(
|
||||
cn_name="对话表达", cType="mid_dialog_express",
|
||||
category=ComponentCategory.MID,
|
||||
is_express_type=True,
|
||||
notes="表达型,有示例回答,无选项"),
|
||||
"对话选读": FormatSpec(
|
||||
cn_name="对话选读", cType="mid_dialog_select",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
has_per_option_feedback=True,
|
||||
option_format="sentence",
|
||||
notes="选项为完整句子,每个选项有独立反馈"),
|
||||
"对话选择": FormatSpec(
|
||||
cn_name="对话选择", cType="mid_dialog_choose",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
has_per_option_feedback=True,
|
||||
option_format="sentence",
|
||||
notes="选项为完整回复句,每个选项有独立反馈,选项需标注(音频)"),
|
||||
"对话挖空": FormatSpec(
|
||||
cn_name="对话挖空", cType="mid_dialog_fillin",
|
||||
category=ComponentCategory.MID,
|
||||
has_blank_marker=True,
|
||||
has_options=True,
|
||||
is_fillin=True,
|
||||
question_lang="en",
|
||||
option_format="word",
|
||||
notes="题干必须是带 ___ 的英文句子,选项为填入空位的单词"),
|
||||
"对话组句": FormatSpec(
|
||||
cn_name="对话组句", cType="mid_dialog_sentence",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
has_answer=True,
|
||||
is_sentence_build=True,
|
||||
option_format="fragment",
|
||||
answer_format="sentence",
|
||||
notes="选项为句子片段,答案为拼接后的完整句"),
|
||||
"信息描写": FormatSpec(
|
||||
cn_name="信息描写", cType="mid_message_trace",
|
||||
category=ComponentCategory.MID,
|
||||
has_answer=True,
|
||||
answer_format="word",
|
||||
notes="答案为单词/短语"),
|
||||
"信息拼词": FormatSpec(
|
||||
cn_name="信息拼词", cType="mid_message_spell",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
has_answer=True,
|
||||
option_format="letter",
|
||||
answer_format="word",
|
||||
notes="选项为字母,答案为拼成的单词"),
|
||||
"信息组句": FormatSpec(
|
||||
cn_name="信息组句", cType="mid_message_combine",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
has_answer=True,
|
||||
is_sentence_build=True,
|
||||
option_format="fragment",
|
||||
answer_format="sentence",
|
||||
notes="选项为句子片段,答案为拼接后的完整句"),
|
||||
"信息补词": FormatSpec(
|
||||
cn_name="信息补词", cType="mid_message_fillin",
|
||||
category=ComponentCategory.MID,
|
||||
has_answer=True,
|
||||
answer_format="word",
|
||||
notes="答案为单词"),
|
||||
"信息填词": FormatSpec(
|
||||
cn_name="信息填词", cType="mid_message_word",
|
||||
category=ComponentCategory.MID,
|
||||
has_answer=True,
|
||||
answer_format="word",
|
||||
notes="答案为单词/短语"),
|
||||
"信息填句": FormatSpec(
|
||||
cn_name="信息填句", cType="mid_message_sentence",
|
||||
category=ComponentCategory.MID,
|
||||
has_answer=True,
|
||||
answer_format="sentence",
|
||||
notes="答案为完整句子"),
|
||||
"物品互动": FormatSpec(
|
||||
cn_name="物品互动", cType="mid_vocab_item",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
option_format="word",
|
||||
notes="选项为单词"),
|
||||
"图片互动": FormatSpec(
|
||||
cn_name="图片互动", cType="mid_vocab_image",
|
||||
category=ComponentCategory.MID,
|
||||
has_answer=True,
|
||||
notes="答案为坐标/区域标识"),
|
||||
"图片单选": FormatSpec(
|
||||
cn_name="图片单选", cType="mid_image_choose",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
has_answer=True,
|
||||
answer_format="index",
|
||||
notes="答案为选项索引"),
|
||||
"图片多选": FormatSpec(
|
||||
cn_name="图片多选", cType="mid_image_multiple",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
has_answer=True,
|
||||
answer_format="index",
|
||||
notes="答案为选项索引列表"),
|
||||
"图片有序": FormatSpec(
|
||||
cn_name="图片有序", cType="mid_image_sequence",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
has_answer=True,
|
||||
answer_format="index",
|
||||
notes="答案为排序索引"),
|
||||
"图片拖拽": FormatSpec(
|
||||
cn_name="图片拖拽", cType="mid_image_drag",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
has_answer=True,
|
||||
answer_format="index",
|
||||
notes="答案为拖拽目标索引"),
|
||||
"材料互动": FormatSpec(
|
||||
cn_name="材料互动", cType="mid_sentence_material",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
notes="选项为材料/句子"),
|
||||
"指令互动": FormatSpec(
|
||||
cn_name="指令互动", cType="mid_vocab_instruction",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
notes="选项为指令"),
|
||||
"挖空互动": FormatSpec(
|
||||
cn_name="挖空互动", cType="mid_grammar_cloze",
|
||||
category=ComponentCategory.MID,
|
||||
has_blank_marker=True,
|
||||
has_options=True,
|
||||
has_answer=True,
|
||||
is_fillin=True,
|
||||
question_lang="en",
|
||||
option_format="word",
|
||||
notes="题干必须是带 ___ 的英文句子,选项为填入空位的单词"),
|
||||
"组句互动": FormatSpec(
|
||||
cn_name="组句互动", cType="mid_grammar_sentence",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
has_answer=True,
|
||||
is_sentence_build=True,
|
||||
option_format="fragment",
|
||||
answer_format="sentence",
|
||||
notes="选项为句子片段,答案为拼接后的完整句"),
|
||||
"填词互动": FormatSpec(
|
||||
cn_name="填词互动", cType="mid_vocab_fillBlank",
|
||||
category=ComponentCategory.MID,
|
||||
has_answer=True,
|
||||
answer_format="word",
|
||||
notes="答案为单词"),
|
||||
"语音互动": FormatSpec(
|
||||
cn_name="语音互动", cType="mid_sentence_voice",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
notes="语音类选项"),
|
||||
"造句互动": FormatSpec(
|
||||
cn_name="造句互动", cType="mid_sentence_makeSentence",
|
||||
category=ComponentCategory.MID,
|
||||
is_express_type=True,
|
||||
notes="造句型,自由输出"),
|
||||
"发音互动": FormatSpec(
|
||||
cn_name="发音互动", cType="mid_pron_pron",
|
||||
category=ComponentCategory.MID,
|
||||
is_read_type=True,
|
||||
notes="发音型,朗读输出"),
|
||||
}
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 核心互动组件格式规范(15种)
|
||||
# ============================================================
|
||||
|
||||
CORE_FORMAT_SPECS: Dict[str, FormatSpec] = {
|
||||
"合作阅读": FormatSpec(
|
||||
cn_name="合作阅读", cType="core_reading_order",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"看图选词": FormatSpec(
|
||||
cn_name="看图选词", cType="core_reading_imageDrag",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"口语快答": FormatSpec(
|
||||
cn_name="口语快答", cType="core_speaking_reply",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"口语独白": FormatSpec(
|
||||
cn_name="口语独白", cType="core_speaking_monologue",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"口语妙问": FormatSpec(
|
||||
cn_name="口语妙问", cType="core_speaking_inquiry",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"看图说话": FormatSpec(
|
||||
cn_name="看图说话", cType="core_speaking_image",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"口语探讨": FormatSpec(
|
||||
cn_name="口语探讨", cType="core_speaking_discuss",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"合作听力": FormatSpec(
|
||||
cn_name="合作听力", cType="core_listening_order",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"听力拖拽": FormatSpec(
|
||||
cn_name="听力拖拽", cType="core_listening_drag",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"听力选择": FormatSpec(
|
||||
cn_name="听力选择", cType="core_listening_choose",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"写作互动": FormatSpec(
|
||||
cn_name="写作互动", cType="core_writing_questionMakeSentence",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"看图组句": FormatSpec(
|
||||
cn_name="看图组句", cType="core_writing_imgMakeSentence",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"看图撰写": FormatSpec(
|
||||
cn_name="看图撰写", cType="core_writing_imgWrite",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"邮件组句": FormatSpec(
|
||||
cn_name="邮件组句", cType="core_writing_questionMakeSentence",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"邮件撰写": FormatSpec(
|
||||
cn_name="邮件撰写", cType="core_writing_questionWrite",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
}
|
||||
|
||||
|
||||
# 合并所有格式规范
|
||||
ALL_FORMAT_SPECS = {**MID_FORMAT_SPECS, **CORE_FORMAT_SPECS}
|
||||
|
||||
# 配图后缀变体映射(剥离后缀后查主表)
|
||||
PICTURE_VARIANTS = {
|
||||
"对话朗读-配图": "对话朗读",
|
||||
"对话表达-配图": "对话表达",
|
||||
"对话选读-配图": "对话选读",
|
||||
"对话选择-配图": "对话选择",
|
||||
"对话挖空-配图": "对话挖空",
|
||||
"对话组句-配图": "对话组句",
|
||||
"图片单选-配图": "图片单选",
|
||||
}
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 第二部分:通用校验规则
|
||||
# ============================================================
|
||||
|
||||
class Severity(Enum):
|
||||
ERROR = "🔴" # 必须修复
|
||||
WARN = "🟡" # 建议修复
|
||||
INFO = "⚪" # 提示
|
||||
|
||||
|
||||
@dataclass
|
||||
class Violation:
|
||||
severity: Severity
|
||||
rule: str
|
||||
detail: str
|
||||
location: str = ""
|
||||
|
||||
|
||||
def resolve_type(cn_type: str) -> Tuple[Optional[FormatSpec], str]:
|
||||
"""解析组件类型名,处理配图后缀变体"""
|
||||
cn_type = cn_type.strip()
|
||||
# 精确匹配
|
||||
if cn_type in ALL_FORMAT_SPECS:
|
||||
return ALL_FORMAT_SPECS[cn_type], cn_type
|
||||
# 配图变体
|
||||
if cn_type in PICTURE_VARIANTS:
|
||||
base = PICTURE_VARIANTS[cn_type]
|
||||
return ALL_FORMAT_SPECS.get(base), cn_type
|
||||
# 模糊匹配(去除末尾数字)
|
||||
m = re.match(r'^(.+?)\d*$', cn_type)
|
||||
if m:
|
||||
base = m.group(1).strip()
|
||||
if base in ALL_FORMAT_SPECS:
|
||||
return ALL_FORMAT_SPECS[base], cn_type
|
||||
return None, cn_type
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 通用规则检查
|
||||
# ============================================================
|
||||
|
||||
def check_title_spacing(text: str) -> List[Violation]:
|
||||
"""检查标题中中英文混排空格"""
|
||||
violations = []
|
||||
for line in text.split('\n'):
|
||||
if '【任务标题】' in line:
|
||||
title = line.replace('【任务标题】', '').strip()
|
||||
# 中文字符后紧跟英文字母(缺空格)
|
||||
issues = re.finditer(r'([\u4e00-\u9fff])([A-Za-z])', title)
|
||||
for m in issues:
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
"中英文混排缺空格",
|
||||
f"标题'{title}'中'{m.group(1)}{m.group(2)}'之间应加半角空格",
|
||||
f"【任务标题】"
|
||||
))
|
||||
# 英文字母后紧跟中文字符(缺空格)
|
||||
issues = re.finditer(r'([A-Za-z])([\u4e00-\u9fff])', title)
|
||||
for m in issues:
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
"中英文混排缺空格",
|
||||
f"标题'{title}'中'{m.group(1)}{m.group(2)}'之间应加半角空格",
|
||||
f"【任务标题】"
|
||||
))
|
||||
return violations
|
||||
|
||||
|
||||
def check_feedback_colon(text: str) -> List[Violation]:
|
||||
"""检查反馈中角色名冒号格式:应为 '角色名: 台词',冒号前无空格,冒号为英文半角"""
|
||||
violations = []
|
||||
# 匹配反馈行中的 "角色名 : 台词"(冒号前有空格)
|
||||
pattern_space = re.compile(r'([A-Z][a-zA-Z]*)\s+:\s')
|
||||
for m in pattern_space.finditer(text):
|
||||
name = m.group(1)
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
"反馈冒号前多余空格",
|
||||
f"'{name} :' 应改为 '{name}:'",
|
||||
"【互动反馈】"
|
||||
))
|
||||
# 匹配中文冒号
|
||||
pattern_cn_colon = re.compile(r'([A-Z][a-zA-Z]*)\s*:')
|
||||
for m in pattern_cn_colon.finditer(text):
|
||||
name = m.group(1)
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
"反馈冒号使用了中文冒号",
|
||||
f"'{name}:' 应改为 '{name}:'",
|
||||
"【互动反馈】"
|
||||
))
|
||||
return violations
|
||||
|
||||
|
||||
def check_markdown(text: str) -> List[Violation]:
|
||||
"""检查是否使用了 Markdown 标记"""
|
||||
violations = []
|
||||
# 检查加粗/斜体,排除 ___(挖空标记)
|
||||
# ** 和 __ 是加粗,* 和 _ 是斜体
|
||||
if '**' in text:
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
"禁止使用 Markdown 加粗标记",
|
||||
"发现 '**' 标记",
|
||||
""
|
||||
))
|
||||
# __ 检查:排除 ___(连续三个下划线是挖空标记)
|
||||
# 检查是否有 __ 但不是 ___ 的一部分
|
||||
stripped = text.replace('___', '') # 移除挖空标记
|
||||
if '__' in stripped:
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
"禁止使用 Markdown 加粗标记",
|
||||
"发现 '__' 标记(非挖空标记 ___)",
|
||||
""
|
||||
))
|
||||
# * 检查:排除 **(已单独检查)
|
||||
if re.search(r'(?<!\*)\*(?!\*)', text):
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
"禁止使用 Markdown 斜体标记",
|
||||
"发现 '*' 标记",
|
||||
""
|
||||
))
|
||||
# _ 检查:排除 ___ 和 __
|
||||
single_underscore = re.sub(r'_{2,}', '', text) # 移除连续2个以上的下划线
|
||||
if '_' in single_underscore:
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
"禁止使用 Markdown 斜体标记",
|
||||
"发现 '_' 标记(非挖空标记)",
|
||||
""
|
||||
))
|
||||
return violations
|
||||
|
||||
|
||||
def check_spelling(text: str) -> List[Violation]:
|
||||
"""检查常见拼写错误"""
|
||||
violations = []
|
||||
common_errors = {
|
||||
'shoud': 'should',
|
||||
'becasue': 'because',
|
||||
'thier': 'their',
|
||||
'recieve': 'receive',
|
||||
'teh': 'the',
|
||||
'adn': 'and',
|
||||
'writting': 'writing',
|
||||
'lisence': 'license',
|
||||
'occured': 'occurred',
|
||||
'untill': 'until',
|
||||
}
|
||||
words = re.findall(r'\b\w+\b', text)
|
||||
for word in words:
|
||||
lower = word.lower()
|
||||
if lower in common_errors:
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
"拼写错误",
|
||||
f"'{word}' 应为 '{common_errors[lower]}'",
|
||||
""
|
||||
))
|
||||
return violations
|
||||
|
||||
|
||||
def check_punctuation(text: str) -> List[Violation]:
|
||||
"""检查标点符号规范"""
|
||||
violations = []
|
||||
# 英文内容中的中文标点
|
||||
# 在【互动内容】区域检查
|
||||
content_match = re.search(r'【互动内容】\n(.*?)(?=【|$)', text, re.DOTALL)
|
||||
if content_match:
|
||||
content = content_match.group(1)
|
||||
# 检查英文句子中的中文标点
|
||||
for cn_punct, en_punct in [(',', ','), ('。', '.'), ('!', '!'), ('?', '?'), (':', ':')]:
|
||||
if cn_punct in content:
|
||||
# 只报告在英文语境中的(简单判断:前后有英文字母)
|
||||
for m in re.finditer(rf'[A-Za-z]\s*{re.escape(cn_punct)}\s*[A-Za-z]', content):
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
"英文内容中使用了中文标点",
|
||||
f"'{cn_punct}' 应改为 '{en_punct}'",
|
||||
"【互动内容】"
|
||||
))
|
||||
return violations
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 题型专属规则检查
|
||||
# ============================================================
|
||||
|
||||
def check_blank_marker(text: str, spec: FormatSpec) -> List[Violation]:
|
||||
"""挖空类题型:检查题干是否包含 ___ 标记"""
|
||||
violations = []
|
||||
if not spec.has_blank_marker:
|
||||
return violations
|
||||
|
||||
content_match = re.search(r'【互动内容】\n(.*?)(?=【|$)', text, re.DOTALL)
|
||||
if content_match:
|
||||
content = content_match.group(1)
|
||||
if '___' not in content:
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
f"{spec.cn_name} 题干缺少 ___ 挖空标记",
|
||||
"题干必须包含 '___' 表示需要填空的位置。"
|
||||
"正确格式示例:'He doesn't ___ to tell us!'",
|
||||
"【互动内容】"
|
||||
))
|
||||
return violations
|
||||
|
||||
|
||||
def check_question_language(text: str, spec: FormatSpec) -> List[Violation]:
|
||||
"""检查题干语言是否符合要求"""
|
||||
violations = []
|
||||
if not spec.question_lang:
|
||||
return violations
|
||||
|
||||
content_match = re.search(r'【互动内容】\n(.*?)(?=【|$)', text, re.DOTALL)
|
||||
if not content_match:
|
||||
return violations
|
||||
|
||||
content = content_match.group(1)
|
||||
# 取第一行非空、非"要求:"、非"题目:"的内容作为题干
|
||||
lines = [l.strip() for l in content.split('\n') if l.strip()
|
||||
and not l.strip().startswith('要求')
|
||||
and not l.strip().startswith('题目')
|
||||
and not l.strip().startswith('选项')
|
||||
and not l.strip().startswith('答案')
|
||||
and not l.strip().startswith('辅助')]
|
||||
|
||||
if spec.question_lang == "en" and lines:
|
||||
first_line = lines[0]
|
||||
# 检查是否以中文为主(超过50%中文字符)
|
||||
cn_chars = len(re.findall(r'[\u4e00-\u9fff]', first_line))
|
||||
total_chars = len(first_line.replace(' ', ''))
|
||||
if total_chars > 0 and cn_chars / total_chars > 0.5:
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
f"{spec.cn_name} 题干应为英文",
|
||||
f"当前题干以中文为主: '{first_line[:60]}...'",
|
||||
"【互动内容】"
|
||||
))
|
||||
return violations
|
||||
|
||||
|
||||
def check_options_format(text: str, spec: FormatSpec) -> List[Violation]:
|
||||
"""检查选项格式"""
|
||||
violations = []
|
||||
if not spec.has_options:
|
||||
return violations
|
||||
|
||||
# 提取选项
|
||||
options = re.findall(r'选项\d+[::]\s*(.+)', text)
|
||||
if not options:
|
||||
# 可能是"选项:"后跟列表的格式
|
||||
opt_match = re.search(r'选项[::]\s*\n?(.*?)(?=答案|辅助|【|$)', text, re.DOTALL)
|
||||
if opt_match:
|
||||
options = [o.strip() for o in opt_match.group(1).split('\n') if o.strip()]
|
||||
|
||||
if spec.has_per_option_feedback:
|
||||
# 对话选择/对话选读:每个选项必须有反馈
|
||||
feedback_count = len(re.findall(r'反馈\s*\w+\s*:', text))
|
||||
if feedback_count < len(options):
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
f"{spec.cn_name} 选项缺少逐项反馈",
|
||||
f"有 {len(options)} 个选项但只有 {feedback_count} 条反馈",
|
||||
"【互动内容】"
|
||||
))
|
||||
|
||||
if spec.is_sentence_build:
|
||||
# 组句型:检查是否有"答案"行
|
||||
if '答案' not in text:
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
f"{spec.cn_name} 缺少答案行",
|
||||
"组句型必须有'答案:'行,给出拼接后的完整句子",
|
||||
"【互动内容】"
|
||||
))
|
||||
# 选项应为片段,答案应为完整句
|
||||
answer_match = re.search(r'答案[::]\s*(.+)', text)
|
||||
if answer_match and options:
|
||||
answer = answer_match.group(1).strip()
|
||||
# 简单检查:答案应该比单个选项长
|
||||
max_opt_len = max(len(o) for o in options)
|
||||
if len(answer) <= max_opt_len * 1.5:
|
||||
violations.append(Violation(
|
||||
Severity.WARN,
|
||||
f"{spec.cn_name} 答案可能不是完整拼接句",
|
||||
f"答案'{answer}'长度与选项片段接近",
|
||||
"【互动内容】"
|
||||
))
|
||||
|
||||
return violations
|
||||
|
||||
|
||||
def check_audio_marker(text: str, spec: FormatSpec) -> List[Violation]:
|
||||
"""检查需要音频标记的题型"""
|
||||
violations = []
|
||||
# 对话选择、对话选读、对话挖空、对话组句:选项/题干后应有(音频)
|
||||
audio_types = {"对话选择", "对话选读", "对话挖空", "对话组句"}
|
||||
if spec.cn_name not in audio_types:
|
||||
return violations
|
||||
|
||||
content_match = re.search(r'【互动内容】\n(.*?)(?=【|$)', text, re.DOTALL)
|
||||
if content_match:
|
||||
content = content_match.group(1)
|
||||
# 检查是否有(音频)标记
|
||||
if '(音频)' not in content and '(音频)' not in content:
|
||||
violations.append(Violation(
|
||||
Severity.WARN,
|
||||
f"{spec.cn_name} 缺少(音频)标记",
|
||||
"对话类组件应在选项或题干后标注(音频)",
|
||||
"【互动内容】"
|
||||
))
|
||||
return violations
|
||||
|
||||
|
||||
def check_no_options_when_not_expected(text: str, spec: FormatSpec) -> List[Violation]:
|
||||
"""非选项型组件不应出现选项"""
|
||||
violations = []
|
||||
if spec.has_options:
|
||||
return violations
|
||||
|
||||
if re.search(r'选项\d*[::]', text):
|
||||
violations.append(Violation(
|
||||
Severity.WARN,
|
||||
f"{spec.cn_name} 不应包含选项",
|
||||
f"该题型为{spec.notes},但配置中出现了选项",
|
||||
"【互动内容】"
|
||||
))
|
||||
return violations
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 第三部分:主校验入口
|
||||
# ============================================================
|
||||
|
||||
def validate(teaching_config: str, cn_type: str) -> List[Violation]:
|
||||
"""
|
||||
校验单个组件配置
|
||||
|
||||
Args:
|
||||
teaching_config: 组件配置文本(teaching_config 字段内容)
|
||||
cn_type: 组件中文类型名(如 "对话挖空"、"对话挖空12")
|
||||
|
||||
Returns:
|
||||
违规列表
|
||||
"""
|
||||
spec, resolved_type = resolve_type(cn_type)
|
||||
violations = []
|
||||
|
||||
if spec is None:
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
"未知组件类型",
|
||||
f"'{cn_type}' 不在已知的 27 种中互动或 15 种核心互动类型中",
|
||||
""
|
||||
))
|
||||
return violations
|
||||
|
||||
# ---- 通用规则 ----
|
||||
violations.extend(check_title_spacing(teaching_config))
|
||||
violations.extend(check_feedback_colon(teaching_config))
|
||||
violations.extend(check_markdown(teaching_config))
|
||||
violations.extend(check_spelling(teaching_config))
|
||||
violations.extend(check_punctuation(teaching_config))
|
||||
|
||||
# ---- 题型专属规则 ----
|
||||
violations.extend(check_blank_marker(teaching_config, spec))
|
||||
violations.extend(check_question_language(teaching_config, spec))
|
||||
violations.extend(check_options_format(teaching_config, spec))
|
||||
violations.extend(check_audio_marker(teaching_config, spec))
|
||||
violations.extend(check_no_options_when_not_expected(teaching_config, spec))
|
||||
|
||||
return violations
|
||||
|
||||
|
||||
def format_report(violations: List[Violation], cn_type: str = "") -> str:
|
||||
"""格式化输出校验报告"""
|
||||
if not violations:
|
||||
return "✅ 全部通过"
|
||||
|
||||
errors = [v for v in violations if v.severity == Severity.ERROR]
|
||||
warns = [v for v in violations if v.severity == Severity.WARN]
|
||||
infos = [v for v in violations if v.severity == Severity.INFO]
|
||||
|
||||
lines = []
|
||||
if cn_type:
|
||||
lines.append(f"📋 校验结果: {cn_type}")
|
||||
lines.append(f" 🔴 错误: {len(errors)} 🟡 警告: {len(warns)} ⚪ 提示: {len(infos)}")
|
||||
lines.append("")
|
||||
|
||||
for v in violations:
|
||||
lines.append(f" {v.severity.value} [{v.rule}] {v.detail}")
|
||||
if v.location:
|
||||
lines.append(f" 位置: {v.location}")
|
||||
|
||||
return '\n'.join(lines)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 第四部分:CLI 入口
|
||||
# ============================================================
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="互动组件配置格式校验脚本",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="""
|
||||
示例:
|
||||
# 校验单个组件
|
||||
python3 validate_format.py "【任务标题】汇报Jay不配合\\n..." --type "对话挖空"
|
||||
|
||||
# 从 stdin 读取
|
||||
echo "..." | python3 validate_format.py --type "对话组句" --stdin
|
||||
|
||||
# 列出所有支持的题型
|
||||
python3 validate_format.py --list-types
|
||||
"""
|
||||
)
|
||||
parser.add_argument('config_text', nargs='?', help='组件配置文本')
|
||||
parser.add_argument('--type', '-t', required=False, help='组件中文类型名')
|
||||
parser.add_argument('--stdin', action='store_true', help='从 stdin 读取配置文本')
|
||||
parser.add_argument('--list-types', action='store_true', help='列出所有支持的题型')
|
||||
parser.add_argument('--json', action='store_true', help='以 JSON 格式输出')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.list_types:
|
||||
print("=== 中互动组件(27种)===")
|
||||
for name, spec in MID_FORMAT_SPECS.items():
|
||||
flags = []
|
||||
if spec.has_blank_marker: flags.append("___标记")
|
||||
if spec.has_options: flags.append("选项")
|
||||
if spec.has_answer: flags.append("答案")
|
||||
if spec.has_per_option_feedback: flags.append("逐项反馈")
|
||||
if spec.is_read_type: flags.append("朗读")
|
||||
if spec.is_express_type: flags.append("表达")
|
||||
if spec.is_sentence_build: flags.append("组句")
|
||||
print(f" {name:12s} | {', '.join(flags) if flags else '(无特殊标记)'}")
|
||||
print("\n=== 核心互动组件(15种)===")
|
||||
for name in CORE_FORMAT_SPECS:
|
||||
print(f" {name}")
|
||||
return
|
||||
|
||||
if not args.type:
|
||||
print("❌ 必须指定 --type 参数", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
if args.stdin:
|
||||
config_text = sys.stdin.read()
|
||||
elif args.config_text:
|
||||
config_text = args.config_text
|
||||
else:
|
||||
print("❌ 必须提供配置文本(参数或 --stdin)", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
violations = validate(config_text, args.type)
|
||||
|
||||
if args.json:
|
||||
result = {
|
||||
"type": args.type,
|
||||
"passed": len(violations) == 0,
|
||||
"error_count": len([v for v in violations if v.severity == Severity.ERROR]),
|
||||
"warn_count": len([v for v in violations if v.severity == Severity.WARN]),
|
||||
"violations": [
|
||||
{"severity": v.severity.value, "rule": v.rule, "detail": v.detail, "location": v.location}
|
||||
for v in violations
|
||||
]
|
||||
}
|
||||
print(json.dumps(result, ensure_ascii=False, indent=2))
|
||||
else:
|
||||
print(format_report(violations, args.type))
|
||||
|
||||
# 有错误时返回非零
|
||||
if any(v.severity == Severity.ERROR for v in violations):
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,109 +0,0 @@
|
||||
---
|
||||
name: dialogue-choose-config
|
||||
version: 1.0.0
|
||||
description: 对话选择类互动组件配置标准化规范,用于剧本中对话选择/对话选择-配图类型组件的标准化生成
|
||||
metadata:
|
||||
requires:
|
||||
permissions: ["sheets:spreadsheet"]
|
||||
identity: bot
|
||||
---
|
||||
# 对话选择组件配置规范
|
||||
## 适用场景
|
||||
当【类型】列内容为【对话选择】或【对话选择-配图】时,使用本规范生成组件配置
|
||||
|
||||
|
||||
## 文本输出规范(强制执行)
|
||||
|
||||
所有输出的文本内容(台词、题目、选项、解析、音频文本、阅读文章等)必须遵守以下规则:
|
||||
|
||||
1. 禁止 Markdown 标记:禁止使用 ** * __ _ 等加粗/斜体标识,也禁止使用 # > - 等块级 Markdown 语法。所有文本纯文本输出。
|
||||
2. 英式拼写优先:单词涉及英美式拼写差异时(如 colour/color、centre/center、travelling/traveling),统一选择英式拼写。
|
||||
3. 标点符号规范:严格区分全角/半角符号。中文内容使用全角标点(,。!?),英文内容使用半角标点(. , ! ?),不得混用。
|
||||
|
||||
## 配置格式
|
||||
### 字段要求
|
||||
1. 【任务标题】:
|
||||
- 设计规则:结合剧情上下文,提炼互动核心内容,使用中文口语化表述,符合低龄用户认知
|
||||
- 核心要素:包含互动对象+核心动作/状态,避免笼统的「对话X」编号或使用「-」连接
|
||||
- 约定:如需表达顺序关系,使用中文括号替代「-」,如「与调酒师对峙(一)」而非「与调酒师对峙-1」
|
||||
- ⚠️ 标题含英文单词时,英文单词前后必须留空格
|
||||
2. 【资源配置】:
|
||||
- 类型为「对话选择」时,填写:无
|
||||
- 类型为「对话选择-配图」时,填写:
|
||||
```
|
||||
图片时机:
|
||||
互动内容
|
||||
互动反馈
|
||||
|
||||
音频载体:Pioneer Band
|
||||
```
|
||||
- 资源命名规范:
|
||||
- 图片文件名:`{组件ID}.png`,如 `0216002.png`
|
||||
- 音频文件名:`{组件ID}.mp3`,如 `0216002.mp3`
|
||||
- 音频默认在互动内容、互动反馈期间出现;若配置音频,必须添加【音频载体】
|
||||
- 图片默认在互动内容、互动反馈期间出现;如需调整节点,在【资源配置】处填写【情境引入】或【后置对话】
|
||||
3. 【情境引入】:
|
||||
- 以对话方式呈现,每行一句。格式为「角色名 : 对话内容」
|
||||
- 若无情境引入,填「无」
|
||||
4. 【互动内容】:
|
||||
- 第一行:固定为「要求:选择正确的回复」
|
||||
- 第二行:标注「选项:(音频)」(表示选项有音频支持)
|
||||
- 第三部分:列出所有选项,编号为「选项1」「选项2」... 依次排列
|
||||
- 每个选项后以「- 反馈 角色名 : 对话内容」形式标注反馈,正确选项需额外标注「(正确)」
|
||||
- 正确选项的反馈为未必填项,若没有则填「无」
|
||||
- ⚠️ 反馈角色不可是 User 自己,必须是当前场景中的其他角色
|
||||
- (音频)标记默认不含,若选项需要播放音频则手动填写「(音频)」,使用中文括号
|
||||
5. 【互动反馈】:本类型不单独设置互动反馈字段,反馈内容已整合在互动内容的各选项中
|
||||
6. 【后置对话】:
|
||||
- 以对话方式呈现,每行一句。格式为「角色名 : 对话内容」
|
||||
- 若无后置对话,填「无」
|
||||
## 完整示例
|
||||
### 对话选择-配图类型示例
|
||||
```
|
||||
【任务标题】
|
||||
加入搏斗俱乐部
|
||||
|
||||
【资源配置】
|
||||
图片时机:
|
||||
互动内容
|
||||
互动反馈
|
||||
|
||||
音频载体:Pioneer Band
|
||||
|
||||
【情境引入】
|
||||
User:Thanks for helping me.
|
||||
Johnny: You have received an invitation. What does it say?
|
||||
|
||||
【互动内容】
|
||||
要求:选择正确的回复
|
||||
选项:(音频)
|
||||
选项1:Follow the road straight.
|
||||
- 反馈 Johnny : Oh, I don't understand what you mean.
|
||||
选项2:Turn left after passing security. (正确)
|
||||
- 反馈: 无
|
||||
|
||||
【后置对话】
|
||||
Johnny: Then let's hurry to find her together.
|
||||
```
|
||||
### 对话选择类型示例
|
||||
```
|
||||
【任务标题】
|
||||
告诉妈妈你喜欢手表
|
||||
|
||||
【资源配置】
|
||||
无
|
||||
|
||||
【情境引入】
|
||||
Mum: Are you happy now?
|
||||
|
||||
【互动内容】
|
||||
要求:选择正确的回复
|
||||
选项:(音频)
|
||||
选项1:Yes, I love it! (正确)
|
||||
- 反馈: 无
|
||||
选项2:No, I don't like it!
|
||||
- 反馈 Mum: Oh, no!
|
||||
|
||||
【后置对话】
|
||||
无
|
||||
```
|
||||
@ -1,120 +0,0 @@
|
||||
---
|
||||
name: dialogue-core-navigation-config
|
||||
version: 1.0.0
|
||||
description: 核心互动导览类组件配置标准化规范,用于剧本中核心互动/导览配置类型组件的标准化生成
|
||||
metadata:
|
||||
requires:
|
||||
permissions: ["sheets:spreadsheet"]
|
||||
identity: bot
|
||||
---
|
||||
# 核心互动导览组件配置规范
|
||||
## 适用场景
|
||||
当【类型】列内容为【核心互动】【导览配置】时,使用本规范生成组件配置
|
||||
|
||||
|
||||
## 文本输出规范(强制执行)
|
||||
|
||||
所有输出的文本内容(台词、题目、选项、解析、音频文本、阅读文章等)必须遵守以下规则:
|
||||
|
||||
1. 禁止 Markdown 标记:禁止使用 ** * __ _ 等加粗/斜体标识,也禁止使用 # > - 等块级 Markdown 语法。所有文本纯文本输出。
|
||||
2. 英式拼写优先:单词涉及英美式拼写差异时(如 colour/color、centre/center、travelling/traveling),统一选择英式拼写。
|
||||
3. 标点符号规范:严格区分全角/半角符号。中文内容使用全角标点(,。!?),英文内容使用半角标点(. , ! ?),不得混用。
|
||||
|
||||
## 配置格式
|
||||
### 字段要求
|
||||
1. 【任务标题】:用户看到的任务名,建议字数在10字以内
|
||||
2. 【任务背景】:
|
||||
- 用户在任务开始前看到的背景描述,目的是告诉孩子为什么需要参加这个任务
|
||||
- 建议字数在25字左右,以第二人称书写
|
||||
- 人名、地名均写成英文
|
||||
3. 【任务描述】:
|
||||
- 用户在任务进行时看到的目标,简洁明确,15字左右描述
|
||||
- 以第二人称描述,格式为「你需要…」
|
||||
- 简单题可笼统描述,难题可具象描述
|
||||
4. 【通关知识】:
|
||||
- 用无序列表分类(若无分类可不填)
|
||||
- 每个分类下多个句子结构,与知识点一致,每个句子先写英文后写译文
|
||||
5. 【对话角色】:
|
||||
- 对话的角色名,需要与资源库中的名称完全一致,用于匹配对应的立绘和音色
|
||||
- 如有多个相同名称,可使用「角色名#id」方式锁定明确资源
|
||||
6. 【角色背景】:
|
||||
- NPC参与任务的背景描述,用于给角色扮演的NPC提供明确的情境信息,用户看不到该内容
|
||||
- 以第二人称书写,格式为「你是谁,你做了什么」
|
||||
- 以剧情信息为主,无需增加太多人物性格、语气等生动化描述,可分条罗列
|
||||
7. 【互动问题】:
|
||||
- 包含NPC提问的问题、问题的答案、以及该问答对应的图片编号
|
||||
- 同一个图片对应多个问题时,编号重复
|
||||
- 问题和答案只写最简单版本,示例对话中可适度包装让对话更自然流畅
|
||||
- **图片命名规则**:
|
||||
- 底图:`[编号]_question.png`,示例:`0102003_question.png`
|
||||
- 叠加图:`[编号]_option_[序号].png`,示例:`0102003_option_00.png`
|
||||
- ⚠️ 注意:需要XML格式
|
||||
8. 【回合设定】:每个问题设置1-2个回合
|
||||
9. 【通过规则】:
|
||||
- 对话完成后判断所有问题是否通过,只要有一个没通过则判定为Oops
|
||||
- 列出用户需要说出的所有正确答案内容
|
||||
10. 【示例对话】:
|
||||
- 以NPC进行开场白和结尾句,对话流畅自然,避免无意义回合
|
||||
- 语言难度低,符合1-3年级学生水平
|
||||
- 对用户回答有引导,但不能直接用Yes/No回复
|
||||
- 可增加NPC回应性话术让对话更自然
|
||||
## 完整示例
|
||||
```
|
||||
【任务标题】
|
||||
找同色工具修机器人
|
||||
|
||||
【任务背景】
|
||||
为快速修复破损的机器人,你需要找出合适工具复原工具箱。
|
||||
|
||||
【任务描述】
|
||||
你需要找出成套的工具,复原工具箱
|
||||
|
||||
【通关知识】
|
||||
- It's... 它是……
|
||||
- Yes, I think it's... 是的,我认为它是……
|
||||
- It seems that... 它看起来是……
|
||||
|
||||
【对话角色】
|
||||
SecurityA
|
||||
|
||||
【角色背景】
|
||||
你是机器人SecurityA,你需要修复一个破损的机器人,但需要完整的工具箱,所以你需要让用户帮你找出工具箱中所需要的工具。
|
||||
|
||||
【互动问题】
|
||||
#图片编号:00
|
||||
Q: Let's find tools together. What's the color of the pliers?
|
||||
A: It's blue.
|
||||
|
||||
#图片编号:00
|
||||
Q: What's the color of the ruler?
|
||||
A: It's yellow.
|
||||
|
||||
#图片编号:01
|
||||
Q:What's the color of the hammer?
|
||||
A:And how about the screwdriver?
|
||||
|
||||
#图片编号:02
|
||||
Q: And how about the screwdriver?
|
||||
A: Blue. Yes, I think it's blue.
|
||||
|
||||
【回合设定】
|
||||
每个问题1-2个回合
|
||||
|
||||
【通过规则】
|
||||
用户说出:
|
||||
1. 钳子是蓝色的
|
||||
2. 尺子是黄色的
|
||||
3. 锤子是橙色的
|
||||
4. 螺丝刀是蓝色的
|
||||
|
||||
【示例对话】
|
||||
NPC: Let's find tools together. What's the color of the pliers?
|
||||
User: It's blue.
|
||||
NPC: What's the color of the ruler?
|
||||
User: It's yellow.
|
||||
NPC: What's the color of the hammer?
|
||||
User: It's orange.
|
||||
NPC: And how about the screwdriver?
|
||||
User: Blue. Yes, I think it's blue.
|
||||
NPC: It seems that the pliers and the screwdriver belong to the same set of toolkit. Good job!
|
||||
```
|
||||
@ -1,79 +0,0 @@
|
||||
---
|
||||
name: dialogue-fill-in-blanks-config
|
||||
version: 1.0.0
|
||||
description: 对话挖空类互动组件配置标准化规范,用于剧本中对话挖空类型组件的标准化生成
|
||||
metadata:
|
||||
requires:
|
||||
permissions: ["sheets:spreadsheet"]
|
||||
identity: bot
|
||||
---
|
||||
# 对话挖空组件配置规范
|
||||
## 适用场景
|
||||
当【类型】列内容为【对话挖空】时,使用本规范生成组件配置
|
||||
|
||||
|
||||
## 文本输出规范(强制执行)
|
||||
|
||||
所有输出的文本内容(台词、题目、选项、解析、音频文本、阅读文章等)必须遵守以下规则:
|
||||
|
||||
1. 禁止 Markdown 标记:禁止使用 ** * __ _ 等加粗/斜体标识,也禁止使用 # > - 等块级 Markdown 语法。所有文本纯文本输出。
|
||||
2. 英式拼写优先:单词涉及英美式拼写差异时(如 colour/color、centre/center、travelling/traveling),统一选择英式拼写。
|
||||
3. 标点符号规范:严格区分全角/半角符号。中文内容使用全角标点(,。!?),英文内容使用半角标点(. , ! ?),不得混用。
|
||||
|
||||
## 配置格式
|
||||
### 字段要求
|
||||
1. 【任务标题】:结合剧情上下文设计语义化标题,点明互动核心,例如「介绍照片」
|
||||
- ⚠️ 标题含英文单词时,英文单词前后必须留空格
|
||||
2. 【资源配置】:
|
||||
- 类型为「对话挖空」时,填写:无
|
||||
- 类型为「对话挖空-配图」时,填写:
|
||||
```
|
||||
图片时机:
|
||||
互动内容
|
||||
互动反馈
|
||||
|
||||
音频载体:Pioneer Band
|
||||
```
|
||||
3. 【情境引入】:填写挖空前的对话上下文,格式为「角色名 : 对话内容」
|
||||
4. 【互动内容】:
|
||||
- 包含带挖空(__标记)的句子,末尾标注「(音频)」
|
||||
- 列出选项,正确选项标注「(正确)」,错误选项无需标注
|
||||
- 版本1(单空、单内容组)格式示例:
|
||||
```
|
||||
This is my picture. It's ___, green and orange.(音频)
|
||||
选项1:blue(正确)
|
||||
选项2:black
|
||||
```
|
||||
5. 【互动反馈】:
|
||||
- 反馈台词要求:根据剧情上下文生成符合角色人设、场景逻辑的合适台词
|
||||
- 正确反馈格式:「正确 角色名 : 对话内容」
|
||||
- 错误反馈格式:「错误 角色名 : 对话内容」
|
||||
- ⚠️ 反馈角色不可是 User 自己,必须是当前场景中的其他角色
|
||||
6. 【后置对话】:默认值为「无」
|
||||
## 完整示例
|
||||
```
|
||||
【任务标题】
|
||||
介绍照片
|
||||
|
||||
【资源配置】
|
||||
图片时机:
|
||||
互动内容
|
||||
互动反馈
|
||||
|
||||
音频载体:Pioneer Band
|
||||
|
||||
【情境引入】
|
||||
Johnny : What's That?
|
||||
|
||||
【互动内容】
|
||||
This is my picture. It's ___, green and orange.(音频)
|
||||
选项1:blue(正确)
|
||||
选项2:black
|
||||
|
||||
【互动反馈】
|
||||
正确 Johnny :It looks nice!
|
||||
错误 Johnny :Come on! It's not what you said.
|
||||
|
||||
【后置对话】
|
||||
无
|
||||
```
|
||||
@ -1,122 +0,0 @@
|
||||
---
|
||||
name: dialogue-image-description-config
|
||||
version: 2.0.0
|
||||
description: 看图说话类互动组件配置标准化规范,用于剧本中看图说话/看图说话-配图类型组件的标准化生成
|
||||
metadata:
|
||||
requires:
|
||||
permissions: ["sheets:spreadsheet"]
|
||||
identity: bot
|
||||
---
|
||||
# 看图说话组件配置规范
|
||||
## 适用场景
|
||||
当【类型】列内容为【看图说话】或【看图说话-配图】时,使用本规范生成组件配置
|
||||
|
||||
|
||||
## 文本输出规范(强制执行)
|
||||
|
||||
所有输出的文本内容(台词、题目、选项、解析、音频文本、阅读文章等)必须遵守以下规则:
|
||||
|
||||
1. 禁止 Markdown 标记:禁止使用 ** * __ _ 等加粗/斜体标识,也禁止使用 # > - 等块级 Markdown 语法。所有文本纯文本输出。
|
||||
2. 英式拼写优先:单词涉及英美式拼写差异时(如 colour/color、centre/center、travelling/traveling),统一选择英式拼写。
|
||||
3. 标点符号规范:严格区分全角/半角符号。中文内容使用全角标点(,。!?),英文内容使用半角标点(. , ! ?),不得混用。
|
||||
|
||||
## 配置格式
|
||||
配置分为两部分:导览配置 + 对话配置
|
||||
### 导览配置
|
||||
1. 【任务标题】:结合图片内容和剧情上下文,设计中文语义化标题,点明看图说话的核心任务,例如「从一堆工具中找出颜色相同的工具」
|
||||
2. 【任务背景】:用中文描述为什么需要完成这个任务、任务的目标是什么
|
||||
3. 【任务描述】:用中文简述用户需要做什么(回答谁的问题、完成什么目标)
|
||||
4. 【知识】:列出本组件涉及的核心知识点/句型,每个一行。例如:
|
||||
```
|
||||
It's... 它是……
|
||||
Yes, I think it's... 是的,我认为它是……
|
||||
It seems that... 它看起来是……
|
||||
```
|
||||
### 对话配置
|
||||
1. 【对话角色】:填写 NPC 角色名,如 `SecurityA`、`May`。如有多个角色,用 `, ` 分隔
|
||||
2. 【角色背景】:描述 NPC 的角色背景和当前任务情境。格式:`你是[角色名],[情境描述]……`
|
||||
3. 【互动问题】:按 `#图片编号:XX` 分组,每张图下Q&A依次列出。如果只有一张图,图片编号为 `00`。
|
||||
格式如下:
|
||||
```
|
||||
#图片编号:00
|
||||
Q: NPC的提问内容
|
||||
A: 期望用户回答的正确内容
|
||||
|
||||
#图片编号:01
|
||||
Q: NPC的提问内容
|
||||
A: 期望用户回答的正确内容
|
||||
```
|
||||
同一图片编号下可有多组Q&A。若无配图,省略图片编号标记。
|
||||
4. 【通过规则】:列出用户需要完成的回答条目,用中文序号描述。例如:
|
||||
```
|
||||
用户说出:
|
||||
1. 钳子是蓝色的
|
||||
2. 尺子是黄色的
|
||||
3. 锤子是橙色的
|
||||
4. 螺丝刀是蓝色的
|
||||
```
|
||||
5. 【示例对话】:完整展示 NPC 和 User 的对话流程,每一轮为一行。格式:
|
||||
```
|
||||
NPC: Let's find tools together. What's the color of the pliers?
|
||||
User: It's blue.
|
||||
NPC: What's the color of the ruler?
|
||||
User: It's yellow.
|
||||
...
|
||||
NPC: [最终结束语]
|
||||
```
|
||||
## 完整示例
|
||||
```
|
||||
【任务标题】
|
||||
从一堆工具中找出颜色相同的工具
|
||||
|
||||
【任务背景】
|
||||
为了快速修复破损的机器人,你需要尽快找到合适的工具,来复原工具箱,从而修复机器人。
|
||||
|
||||
【任务描述】
|
||||
回答 Celina 的问题,找出成套的工具,复原工具箱
|
||||
|
||||
【知识】
|
||||
It's... 它是……
|
||||
Yes, I think it's... 是的,我认为它是……
|
||||
It seems that... 它看起来是……
|
||||
|
||||
【对话角色】
|
||||
SecurityA
|
||||
|
||||
【角色背景】
|
||||
你是机器人 SecurityA,用户需要你去修复一个破损的机器人。但你需要完整的工具箱,所以你需要让用户帮你找出工具箱中所需要的工具 ……
|
||||
|
||||
【互动问题】
|
||||
#图片编号:00
|
||||
Q: Let's find tools together. What's the color of the pliers?
|
||||
A: It's blue.
|
||||
|
||||
Q: What's the color of the ruler?
|
||||
A: It's yellow.
|
||||
|
||||
#图片编号:01
|
||||
Q: What's the color of the hammer?
|
||||
A: It's orange.
|
||||
|
||||
#图片编号:02
|
||||
Q: And how about the screwdriver?
|
||||
A: Blue. Yes, I think it's blue.
|
||||
|
||||
【通过规则】
|
||||
用户说出:
|
||||
1. 钳子是蓝色的
|
||||
2. 尺子是黄色的
|
||||
3. 锤子是橙色的
|
||||
4. 螺丝刀是蓝色的
|
||||
|
||||
【示例对话】
|
||||
NPC: Let's find tools together. What's the color of the pliers?
|
||||
User: It's blue.
|
||||
NPC: What's the color of the ruler?
|
||||
User: It's yellow.
|
||||
NPC: What's the color of the hammer?
|
||||
User: It's orange.
|
||||
NPC: And how about the screwdriver?
|
||||
User: Blue. Yes, I think it's blue.
|
||||
NPC: It seems that the pliers and the screwdriver belong to the same set of toolkit. Good job!
|
||||
```
|
||||
@ -1,52 +0,0 @@
|
||||
---
|
||||
name: dialogue-reading-config
|
||||
version: 1.0.0
|
||||
description: 对话朗读类互动组件配置标准化规范,用于剧本中对话朗读/对话朗读-配图类型组件的标准化生成
|
||||
metadata:
|
||||
requires:
|
||||
permissions: ["sheets:spreadsheet"]
|
||||
identity: bot
|
||||
---
|
||||
# 对话朗读组件配置规范
|
||||
## 适用场景
|
||||
当【类型】列内容为【对话朗读】或【对话朗读-配图】时,使用本规范生成组件配置
|
||||
|
||||
|
||||
## 文本输出规范(强制执行)
|
||||
|
||||
所有输出的文本内容(台词、题目、选项、解析、音频文本、阅读文章等)必须遵守以下规则:
|
||||
|
||||
1. 禁止 Markdown 标记:禁止使用 ** * __ _ 等加粗/斜体标识,也禁止使用 # > - 等块级 Markdown 语法。所有文本纯文本输出。
|
||||
2. 英式拼写优先:单词涉及英美式拼写差异时(如 colour/color、centre/center、travelling/traveling),统一选择英式拼写。
|
||||
3. 标点符号规范:严格区分全角/半角符号。中文内容使用全角标点(,。!?),英文内容使用半角标点(. , ! ?),不得混用。
|
||||
|
||||
## 配置格式
|
||||
### 字段要求
|
||||
1. 【任务标题】:
|
||||
- 设计规则:结合剧情上下文,提炼互动核心内容,使用中文口语化表述,符合低龄用户认知
|
||||
- 核心要素:包含互动对象+核心动作/状态,避免笼统的「对话X」编号
|
||||
- ⚠️ 标题含英文单词时,英文单词前后必须留空格。正确:「回应 Wood 家的孩子们」;错误:「回应Wood家的孩子们」
|
||||
- 示例:「机器人的头坏了」「帮机器人拼接头和身体」
|
||||
2. 【资源配置】:
|
||||
- 类型为「对话朗读」时,填写:图片时机:无
|
||||
- 类型为「对话朗读-配图」时,填写:图片时机:互动内容
|
||||
3. 【情景引入】:默认值为「无」
|
||||
4. 【互动内容】:填写带有知识点的朗读句子(与原台词保持一致),句末**必须**加「(朗读)」
|
||||
5. 【后置对话】:默认值为「无」
|
||||
## 示例
|
||||
### 对话朗读-配图类型示例
|
||||
```
|
||||
【任务标题】机器人的头坏了
|
||||
【资源配置】图片时机:互动内容
|
||||
【情景引入】无
|
||||
【互动内容】Its head is broken.
|
||||
【后置对话】无
|
||||
```
|
||||
### 对话朗读类型示例
|
||||
```
|
||||
【任务标题】帮机器人拼接头和身体
|
||||
【资源配置】图片时机:无
|
||||
【情景引入】无
|
||||
【互动内容】Eva, can you put the head and body together?
|
||||
【后置对话】无
|
||||
```
|
||||
@ -1,81 +0,0 @@
|
||||
---
|
||||
name: dialogue-sentence-building-config
|
||||
version: 1.0.0
|
||||
description: 对话组句类互动组件配置标准化规范,用于剧本中对话组句/对话组句-配图类型组件的标准化生成
|
||||
metadata:
|
||||
requires:
|
||||
permissions: ["sheets:spreadsheet"]
|
||||
identity: bot
|
||||
---
|
||||
# 对话组句组件配置规范
|
||||
## 适用场景
|
||||
当【类型】列内容为【对话组句】或【对话组句-配图】时,使用本规范生成组件配置
|
||||
|
||||
|
||||
## 文本输出规范(强制执行)
|
||||
|
||||
所有输出的文本内容(台词、题目、选项、解析、音频文本、阅读文章等)必须遵守以下规则:
|
||||
|
||||
1. 禁止 Markdown 标记:禁止使用 ** * __ _ 等加粗/斜体标识,也禁止使用 # > - 等块级 Markdown 语法。所有文本纯文本输出。
|
||||
2. 英式拼写优先:单词涉及英美式拼写差异时(如 colour/color、centre/center、travelling/traveling),统一选择英式拼写。
|
||||
3. 标点符号规范:严格区分全角/半角符号。中文内容使用全角标点(,。!?),英文内容使用半角标点(. , ! ?),不得混用。
|
||||
|
||||
## 配置格式
|
||||
### 字段要求
|
||||
1. 【任务标题】:结合剧情上下文设计语义化标题,点明组句的核心场景,例如「提醒 Otis 系好安全带」
|
||||
- ⚠️ 标题含英文单词时,英文单词前后必须留空格
|
||||
2. 【资源配置】:
|
||||
- 类型为「对话组句」时,填写:无
|
||||
- 类型为「对话组句-配图」时,填写:
|
||||
```
|
||||
图片时机:
|
||||
互动内容
|
||||
互动反馈
|
||||
|
||||
音频载体:Pioneer Band
|
||||
```
|
||||
3. 【情境引入】:填写组题出现前的对话上下文,格式为「角色名 : 对话内容」
|
||||
4. 【互动内容】:
|
||||
- 第一行:题目中文描述,说明组句的目标场景
|
||||
- 第二行:末尾标注「(音频)」
|
||||
- 第三部分:列出所有可选单词/短语选项,编号为「选项1:XX」「选项2:XX」依次排列
|
||||
- 第四部分:答案,格式为「答案:XX」(填写完整的正确句子)
|
||||
- 第五部分:辅助信息,提供语法提示、句子结构说明等帮助内容
|
||||
5. 【互动反馈】:
|
||||
- 反馈台词要求:根据剧情上下文生成符合角色人设、场景逻辑的合适台词
|
||||
- 正确反馈格式:「正确 角色名 : 对话内容」
|
||||
- 错误反馈格式:「错误 角色名 : 对话内容」
|
||||
- ⚠️ 反馈角色不可是 User 自己,必须是当前场景中的其他角色
|
||||
6. 【后置对话】:默认值为「无」
|
||||
## 完整示例
|
||||
```
|
||||
【任务标题】
|
||||
提醒 Otis 系好安全带
|
||||
|
||||
【资源配置】
|
||||
图片时机:
|
||||
互动内容
|
||||
互动反馈
|
||||
|
||||
音频载体:Pioneer Band
|
||||
|
||||
【情境引入】
|
||||
User: Let me ask Smith if Maeve is really a visitor.
|
||||
|
||||
【互动内容】
|
||||
题目:询问 Smith:Maeve 真的是你邀请的客人吗?
|
||||
(音频)
|
||||
选项1:is
|
||||
选项2:the visitor
|
||||
选项3:you invited
|
||||
选项4:Maeve
|
||||
答案:Is Maeve the visitor you invited?
|
||||
辅助信息:可以用 is 引导的一般疑问句询问;you invited 是 visitor 的后置定语
|
||||
|
||||
【互动反馈】
|
||||
正确 User : Got it!Sent successfully!
|
||||
错误 User : Oh no, this isn't a correct sentence.
|
||||
|
||||
【后置对话】
|
||||
无
|
||||
```
|
||||
@ -1,62 +0,0 @@
|
||||
---
|
||||
name: dialogue-single-choice-image-config
|
||||
version: 1.0.0
|
||||
description: 图片单选类互动组件配置标准化规范,用于剧本中图片单选/图片单选-配图类型组件的标准化生成
|
||||
metadata:
|
||||
requires:
|
||||
permissions: ["sheets:spreadsheet"]
|
||||
identity: bot
|
||||
---
|
||||
# 图片单选组件配置规范
|
||||
## 适用场景
|
||||
当【类型】列内容为【图片单选】或【图片单选-配图】时,使用本规范生成组件配置
|
||||
|
||||
|
||||
## 文本输出规范(强制执行)
|
||||
|
||||
所有输出的文本内容(台词、题目、选项、解析、音频文本、阅读文章等)必须遵守以下规则:
|
||||
|
||||
1. 禁止 Markdown 标记:禁止使用 ** * __ _ 等加粗/斜体标识,也禁止使用 # > - 等块级 Markdown 语法。所有文本纯文本输出。
|
||||
2. 英式拼写优先:单词涉及英美式拼写差异时(如 colour/color、centre/center、travelling/traveling),统一选择英式拼写。
|
||||
3. 标点符号规范:严格区分全角/半角符号。中文内容使用全角标点(,。!?),英文内容使用半角标点(. , ! ?),不得混用。
|
||||
|
||||
## 配置格式
|
||||
### 字段要求
|
||||
1. 【任务标题】:结合剧情上下文设计语义化标题,点明互动核心,例如「查看公告板说明书」
|
||||
2. 【情境引入】:填写题目出现前的对话上下文,格式为「角色名 : 对话内容」
|
||||
3. 【互动内容】:
|
||||
- 第一行:题目描述,末尾标注「(音频)」,目标对象用$符号包裹,例如`Find a $headset$ in the picture. (音频)`
|
||||
- 第二部分:列出选项,编号为「00」「01」「02」... 依次排列
|
||||
- 第三部分:答案,格式为「答案:XX」(填写对应选项编号)
|
||||
- 第四部分:辅助信息,格式为「辅助信息:XX 指“XXX”」,为目标词汇提供中文释义
|
||||
4. 【互动反馈】:
|
||||
- 反馈台词要求:根据剧情上下文生成符合角色人设、场景逻辑的合适台词
|
||||
- 正确反馈格式:「正确 角色名 : 对话内容」
|
||||
- 错误反馈格式:「错误 角色名 : 对话内容」
|
||||
5. 【后置对话】:默认值为「无」
|
||||
## 完整示例
|
||||
```
|
||||
【任务标题】
|
||||
查看公告板说明书
|
||||
|
||||
【情境引入】
|
||||
Sarah: We've got a message from Rebecca.
|
||||
User: Let's take a look.
|
||||
|
||||
【互动内容】
|
||||
Find a $headset$ in the picture. (音频)
|
||||
选项:
|
||||
00
|
||||
01
|
||||
02
|
||||
答案:
|
||||
01
|
||||
辅助信息:headset 指“耳机”。
|
||||
|
||||
【互动反馈】
|
||||
正确 Sarah :What a cool headset!
|
||||
错误 Sarah:That's not a headset.
|
||||
|
||||
【后置对话】
|
||||
无
|
||||
```
|
||||
@ -28,7 +28,8 @@ metadata:
|
||||
所有生成的 JSON 配置中,任何嵌入的文本内容(题目、选项、解析、台词等)必须遵守:
|
||||
1. 禁止 Markdown 标记(`**` `*` `__` `_` `#` `>` `-`),纯文本输出
|
||||
2. 英式拼写优先(colour/centre/travelling 等)
|
||||
3. 标点符号规范:英文半角(. , ! ?),中文全角(,。!?),不混用
|
||||
3. 标点符号规范:英文半角(. , ! ? :),中文全角(,。!?:),不混用。特别注意:英文冒号必须用半角 `:`,不得用全角 `:`
|
||||
4. 中英文混排空格规范:中文与英文/数字之间加半角空格(如"汇报 Jay 不配合"),纯中文或纯英文内容不加额外空格
|
||||
|
||||
## 触发场景
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@ -0,0 +1,807 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
互动组件配置格式校验脚本
|
||||
覆盖全部 27 种中互动 + 15 种核心互动组件类型
|
||||
校验维度:通用规则 + 题型专属规则 + 拼写检查
|
||||
|
||||
用法:
|
||||
python3 validate_format.py <teaching_config_text> --type <cn_type>
|
||||
python3 validate_format.py --file <path> # 批量校验
|
||||
python3 validate_format.py --sheet <spreadsheet_token> <sheet_id> # 飞书Sheet校验
|
||||
"""
|
||||
|
||||
import re
|
||||
import sys
|
||||
import json
|
||||
import argparse
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List, Dict, Optional, Tuple
|
||||
from enum import Enum
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 第一部分:题型格式特征定义(唯一真相源)
|
||||
# ============================================================
|
||||
|
||||
class ComponentCategory(Enum):
|
||||
MID = "mid" # 中互动
|
||||
CORE = "core" # 核心互动
|
||||
|
||||
|
||||
@dataclass
|
||||
class FormatSpec:
|
||||
"""单个题型的格式规范"""
|
||||
cn_name: str
|
||||
cType: str
|
||||
category: ComponentCategory
|
||||
|
||||
# 题型特征标记
|
||||
has_blank_marker: bool = False # 题干必须有 ___
|
||||
has_options: bool = False # 有选项列表
|
||||
has_answer: bool = False # 有答案
|
||||
has_per_option_feedback: bool = False # 每个选项有独立反馈
|
||||
is_read_type: bool = False # 朗读型
|
||||
is_express_type: bool = False # 表达型
|
||||
is_sentence_build: bool = False # 组句型(选项为碎片,答案为拼接句)
|
||||
is_fillin: bool = False # 挖空/填空型
|
||||
|
||||
# 文本规范
|
||||
question_lang: str = "" # 题干语言要求: "en" / "cn" / ""
|
||||
option_format: str = "" # 选项格式: "word" / "fragment" / "sentence" / "letter" / ""
|
||||
answer_format: str = "" # 答案格式: "word" / "sentence" / "index" / ""
|
||||
|
||||
# 附加说明
|
||||
notes: str = ""
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 中互动组件格式规范(27种)
|
||||
# ============================================================
|
||||
|
||||
MID_FORMAT_SPECS: Dict[str, FormatSpec] = {
|
||||
"对话互动": FormatSpec(
|
||||
cn_name="对话互动", cType="mid_sentence_dialogue",
|
||||
category=ComponentCategory.MID,
|
||||
is_read_type=True,
|
||||
question_lang="en",
|
||||
notes="朗读型,无选项无答案"),
|
||||
"对话朗读": FormatSpec(
|
||||
cn_name="对话朗读", cType="mid_dialog_repeat",
|
||||
category=ComponentCategory.MID,
|
||||
is_read_type=True,
|
||||
question_lang="en",
|
||||
notes="朗读型,无选项无答案"),
|
||||
"对话表达": FormatSpec(
|
||||
cn_name="对话表达", cType="mid_dialog_express",
|
||||
category=ComponentCategory.MID,
|
||||
is_express_type=True,
|
||||
notes="表达型,有示例回答,无选项"),
|
||||
"对话选读": FormatSpec(
|
||||
cn_name="对话选读", cType="mid_dialog_select",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
has_per_option_feedback=True,
|
||||
option_format="sentence",
|
||||
notes="选项为完整句子,每个选项有独立反馈"),
|
||||
"对话选择": FormatSpec(
|
||||
cn_name="对话选择", cType="mid_dialog_choose",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
has_per_option_feedback=True,
|
||||
option_format="sentence",
|
||||
notes="选项为完整回复句,每个选项有独立反馈,选项需标注(音频)"),
|
||||
"对话挖空": FormatSpec(
|
||||
cn_name="对话挖空", cType="mid_dialog_fillin",
|
||||
category=ComponentCategory.MID,
|
||||
has_blank_marker=True,
|
||||
has_options=True,
|
||||
is_fillin=True,
|
||||
question_lang="en",
|
||||
option_format="word",
|
||||
notes="题干必须是带 ___ 的英文句子,选项为填入空位的单词"),
|
||||
"对话组句": FormatSpec(
|
||||
cn_name="对话组句", cType="mid_dialog_sentence",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
has_answer=True,
|
||||
is_sentence_build=True,
|
||||
option_format="fragment",
|
||||
answer_format="sentence",
|
||||
notes="选项为句子片段,答案为拼接后的完整句"),
|
||||
"信息描写": FormatSpec(
|
||||
cn_name="信息描写", cType="mid_message_trace",
|
||||
category=ComponentCategory.MID,
|
||||
has_answer=True,
|
||||
answer_format="word",
|
||||
notes="答案为单词/短语"),
|
||||
"信息拼词": FormatSpec(
|
||||
cn_name="信息拼词", cType="mid_message_spell",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
has_answer=True,
|
||||
option_format="letter",
|
||||
answer_format="word",
|
||||
notes="选项为字母,答案为拼成的单词"),
|
||||
"信息组句": FormatSpec(
|
||||
cn_name="信息组句", cType="mid_message_combine",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
has_answer=True,
|
||||
is_sentence_build=True,
|
||||
option_format="fragment",
|
||||
answer_format="sentence",
|
||||
notes="选项为句子片段,答案为拼接后的完整句"),
|
||||
"信息补词": FormatSpec(
|
||||
cn_name="信息补词", cType="mid_message_fillin",
|
||||
category=ComponentCategory.MID,
|
||||
has_answer=True,
|
||||
answer_format="word",
|
||||
notes="答案为单词"),
|
||||
"信息填词": FormatSpec(
|
||||
cn_name="信息填词", cType="mid_message_word",
|
||||
category=ComponentCategory.MID,
|
||||
has_answer=True,
|
||||
answer_format="word",
|
||||
notes="答案为单词/短语"),
|
||||
"信息填句": FormatSpec(
|
||||
cn_name="信息填句", cType="mid_message_sentence",
|
||||
category=ComponentCategory.MID,
|
||||
has_answer=True,
|
||||
answer_format="sentence",
|
||||
notes="答案为完整句子"),
|
||||
"物品互动": FormatSpec(
|
||||
cn_name="物品互动", cType="mid_vocab_item",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
option_format="word",
|
||||
notes="选项为单词"),
|
||||
"图片互动": FormatSpec(
|
||||
cn_name="图片互动", cType="mid_vocab_image",
|
||||
category=ComponentCategory.MID,
|
||||
has_answer=True,
|
||||
notes="答案为坐标/区域标识"),
|
||||
"图片单选": FormatSpec(
|
||||
cn_name="图片单选", cType="mid_image_choose",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
has_answer=True,
|
||||
answer_format="index",
|
||||
notes="答案为选项索引"),
|
||||
"图片多选": FormatSpec(
|
||||
cn_name="图片多选", cType="mid_image_multiple",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
has_answer=True,
|
||||
answer_format="index",
|
||||
notes="答案为选项索引列表"),
|
||||
"图片有序": FormatSpec(
|
||||
cn_name="图片有序", cType="mid_image_sequence",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
has_answer=True,
|
||||
answer_format="index",
|
||||
notes="答案为排序索引"),
|
||||
"图片拖拽": FormatSpec(
|
||||
cn_name="图片拖拽", cType="mid_image_drag",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
has_answer=True,
|
||||
answer_format="index",
|
||||
notes="答案为拖拽目标索引"),
|
||||
"材料互动": FormatSpec(
|
||||
cn_name="材料互动", cType="mid_sentence_material",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
notes="选项为材料/句子"),
|
||||
"指令互动": FormatSpec(
|
||||
cn_name="指令互动", cType="mid_vocab_instruction",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
notes="选项为指令"),
|
||||
"挖空互动": FormatSpec(
|
||||
cn_name="挖空互动", cType="mid_grammar_cloze",
|
||||
category=ComponentCategory.MID,
|
||||
has_blank_marker=True,
|
||||
has_options=True,
|
||||
has_answer=True,
|
||||
is_fillin=True,
|
||||
question_lang="en",
|
||||
option_format="word",
|
||||
notes="题干必须是带 ___ 的英文句子,选项为填入空位的单词"),
|
||||
"组句互动": FormatSpec(
|
||||
cn_name="组句互动", cType="mid_grammar_sentence",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
has_answer=True,
|
||||
is_sentence_build=True,
|
||||
option_format="fragment",
|
||||
answer_format="sentence",
|
||||
notes="选项为句子片段,答案为拼接后的完整句"),
|
||||
"填词互动": FormatSpec(
|
||||
cn_name="填词互动", cType="mid_vocab_fillBlank",
|
||||
category=ComponentCategory.MID,
|
||||
has_answer=True,
|
||||
answer_format="word",
|
||||
notes="答案为单词"),
|
||||
"语音互动": FormatSpec(
|
||||
cn_name="语音互动", cType="mid_sentence_voice",
|
||||
category=ComponentCategory.MID,
|
||||
has_options=True,
|
||||
notes="语音类选项"),
|
||||
"造句互动": FormatSpec(
|
||||
cn_name="造句互动", cType="mid_sentence_makeSentence",
|
||||
category=ComponentCategory.MID,
|
||||
is_express_type=True,
|
||||
notes="造句型,自由输出"),
|
||||
"发音互动": FormatSpec(
|
||||
cn_name="发音互动", cType="mid_pron_pron",
|
||||
category=ComponentCategory.MID,
|
||||
is_read_type=True,
|
||||
notes="发音型,朗读输出"),
|
||||
}
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 核心互动组件格式规范(15种)
|
||||
# ============================================================
|
||||
|
||||
CORE_FORMAT_SPECS: Dict[str, FormatSpec] = {
|
||||
"合作阅读": FormatSpec(
|
||||
cn_name="合作阅读", cType="core_reading_order",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"看图选词": FormatSpec(
|
||||
cn_name="看图选词", cType="core_reading_imageDrag",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"口语快答": FormatSpec(
|
||||
cn_name="口语快答", cType="core_speaking_reply",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"口语独白": FormatSpec(
|
||||
cn_name="口语独白", cType="core_speaking_monologue",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"口语妙问": FormatSpec(
|
||||
cn_name="口语妙问", cType="core_speaking_inquiry",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"看图说话": FormatSpec(
|
||||
cn_name="看图说话", cType="core_speaking_image",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"口语探讨": FormatSpec(
|
||||
cn_name="口语探讨", cType="core_speaking_discuss",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"合作听力": FormatSpec(
|
||||
cn_name="合作听力", cType="core_listening_order",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"听力拖拽": FormatSpec(
|
||||
cn_name="听力拖拽", cType="core_listening_drag",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"听力选择": FormatSpec(
|
||||
cn_name="听力选择", cType="core_listening_choose",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"写作互动": FormatSpec(
|
||||
cn_name="写作互动", cType="core_writing_questionMakeSentence",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"看图组句": FormatSpec(
|
||||
cn_name="看图组句", cType="core_writing_imgMakeSentence",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"看图撰写": FormatSpec(
|
||||
cn_name="看图撰写", cType="core_writing_imgWrite",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"邮件组句": FormatSpec(
|
||||
cn_name="邮件组句", cType="core_writing_questionMakeSentence",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
"邮件撰写": FormatSpec(
|
||||
cn_name="邮件撰写", cType="core_writing_questionWrite",
|
||||
category=ComponentCategory.CORE,
|
||||
notes="核心互动,JSON结构见 core-content-json-standard"),
|
||||
}
|
||||
|
||||
|
||||
# 合并所有格式规范
|
||||
ALL_FORMAT_SPECS = {**MID_FORMAT_SPECS, **CORE_FORMAT_SPECS}
|
||||
|
||||
# 配图后缀变体映射(剥离后缀后查主表)
|
||||
PICTURE_VARIANTS = {
|
||||
"对话朗读-配图": "对话朗读",
|
||||
"对话表达-配图": "对话表达",
|
||||
"对话选读-配图": "对话选读",
|
||||
"对话选择-配图": "对话选择",
|
||||
"对话挖空-配图": "对话挖空",
|
||||
"对话组句-配图": "对话组句",
|
||||
"图片单选-配图": "图片单选",
|
||||
}
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 第二部分:通用校验规则
|
||||
# ============================================================
|
||||
|
||||
class Severity(Enum):
|
||||
ERROR = "🔴" # 必须修复
|
||||
WARN = "🟡" # 建议修复
|
||||
INFO = "⚪" # 提示
|
||||
|
||||
|
||||
@dataclass
|
||||
class Violation:
|
||||
severity: Severity
|
||||
rule: str
|
||||
detail: str
|
||||
location: str = ""
|
||||
|
||||
|
||||
def resolve_type(cn_type: str) -> Tuple[Optional[FormatSpec], str]:
|
||||
"""解析组件类型名,处理配图后缀变体"""
|
||||
cn_type = cn_type.strip()
|
||||
# 精确匹配
|
||||
if cn_type in ALL_FORMAT_SPECS:
|
||||
return ALL_FORMAT_SPECS[cn_type], cn_type
|
||||
# 配图变体
|
||||
if cn_type in PICTURE_VARIANTS:
|
||||
base = PICTURE_VARIANTS[cn_type]
|
||||
return ALL_FORMAT_SPECS.get(base), cn_type
|
||||
# 模糊匹配(去除末尾数字)
|
||||
m = re.match(r'^(.+?)\d*$', cn_type)
|
||||
if m:
|
||||
base = m.group(1).strip()
|
||||
if base in ALL_FORMAT_SPECS:
|
||||
return ALL_FORMAT_SPECS[base], cn_type
|
||||
return None, cn_type
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 通用规则检查
|
||||
# ============================================================
|
||||
|
||||
def check_title_spacing(text: str) -> List[Violation]:
|
||||
"""检查标题中中英文混排空格"""
|
||||
violations = []
|
||||
for line in text.split('\n'):
|
||||
if '【任务标题】' in line:
|
||||
title = line.replace('【任务标题】', '').strip()
|
||||
# 中文字符后紧跟英文字母(缺空格)
|
||||
issues = re.finditer(r'([\u4e00-\u9fff])([A-Za-z])', title)
|
||||
for m in issues:
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
"中英文混排缺空格",
|
||||
f"标题'{title}'中'{m.group(1)}{m.group(2)}'之间应加半角空格",
|
||||
f"【任务标题】"
|
||||
))
|
||||
# 英文字母后紧跟中文字符(缺空格)
|
||||
issues = re.finditer(r'([A-Za-z])([\u4e00-\u9fff])', title)
|
||||
for m in issues:
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
"中英文混排缺空格",
|
||||
f"标题'{title}'中'{m.group(1)}{m.group(2)}'之间应加半角空格",
|
||||
f"【任务标题】"
|
||||
))
|
||||
return violations
|
||||
|
||||
|
||||
def check_feedback_colon(text: str) -> List[Violation]:
|
||||
"""检查反馈中角色名冒号格式:应为 '角色名: 台词',冒号前无空格,冒号为英文半角"""
|
||||
violations = []
|
||||
# 匹配反馈行中的 "角色名 : 台词"(冒号前有空格)
|
||||
pattern_space = re.compile(r'([A-Z][a-zA-Z]*)\s+:\s')
|
||||
for m in pattern_space.finditer(text):
|
||||
name = m.group(1)
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
"反馈冒号前多余空格",
|
||||
f"'{name} :' 应改为 '{name}:'",
|
||||
"【互动反馈】"
|
||||
))
|
||||
# 匹配中文冒号
|
||||
pattern_cn_colon = re.compile(r'([A-Z][a-zA-Z]*)\s*:')
|
||||
for m in pattern_cn_colon.finditer(text):
|
||||
name = m.group(1)
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
"反馈冒号使用了中文冒号",
|
||||
f"'{name}:' 应改为 '{name}:'",
|
||||
"【互动反馈】"
|
||||
))
|
||||
return violations
|
||||
|
||||
|
||||
def check_markdown(text: str) -> List[Violation]:
|
||||
"""检查是否使用了 Markdown 标记"""
|
||||
violations = []
|
||||
# 检查加粗/斜体,排除 ___(挖空标记)
|
||||
# ** 和 __ 是加粗,* 和 _ 是斜体
|
||||
if '**' in text:
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
"禁止使用 Markdown 加粗标记",
|
||||
"发现 '**' 标记",
|
||||
""
|
||||
))
|
||||
# __ 检查:排除 ___(连续三个下划线是挖空标记)
|
||||
# 检查是否有 __ 但不是 ___ 的一部分
|
||||
stripped = text.replace('___', '') # 移除挖空标记
|
||||
if '__' in stripped:
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
"禁止使用 Markdown 加粗标记",
|
||||
"发现 '__' 标记(非挖空标记 ___)",
|
||||
""
|
||||
))
|
||||
# * 检查:排除 **(已单独检查)
|
||||
if re.search(r'(?<!\*)\*(?!\*)', text):
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
"禁止使用 Markdown 斜体标记",
|
||||
"发现 '*' 标记",
|
||||
""
|
||||
))
|
||||
# _ 检查:排除 ___ 和 __
|
||||
single_underscore = re.sub(r'_{2,}', '', text) # 移除连续2个以上的下划线
|
||||
if '_' in single_underscore:
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
"禁止使用 Markdown 斜体标记",
|
||||
"发现 '_' 标记(非挖空标记)",
|
||||
""
|
||||
))
|
||||
return violations
|
||||
|
||||
|
||||
def check_spelling(text: str) -> List[Violation]:
|
||||
"""检查常见拼写错误"""
|
||||
violations = []
|
||||
common_errors = {
|
||||
'shoud': 'should',
|
||||
'becasue': 'because',
|
||||
'thier': 'their',
|
||||
'recieve': 'receive',
|
||||
'teh': 'the',
|
||||
'adn': 'and',
|
||||
'writting': 'writing',
|
||||
'lisence': 'license',
|
||||
'occured': 'occurred',
|
||||
'untill': 'until',
|
||||
}
|
||||
words = re.findall(r'\b\w+\b', text)
|
||||
for word in words:
|
||||
lower = word.lower()
|
||||
if lower in common_errors:
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
"拼写错误",
|
||||
f"'{word}' 应为 '{common_errors[lower]}'",
|
||||
""
|
||||
))
|
||||
return violations
|
||||
|
||||
|
||||
def check_punctuation(text: str) -> List[Violation]:
|
||||
"""检查标点符号规范"""
|
||||
violations = []
|
||||
# 英文内容中的中文标点
|
||||
# 在【互动内容】区域检查
|
||||
content_match = re.search(r'【互动内容】\n(.*?)(?=【|$)', text, re.DOTALL)
|
||||
if content_match:
|
||||
content = content_match.group(1)
|
||||
# 检查英文句子中的中文标点
|
||||
for cn_punct, en_punct in [(',', ','), ('。', '.'), ('!', '!'), ('?', '?'), (':', ':')]:
|
||||
if cn_punct in content:
|
||||
# 只报告在英文语境中的(简单判断:前后有英文字母)
|
||||
for m in re.finditer(rf'[A-Za-z]\s*{re.escape(cn_punct)}\s*[A-Za-z]', content):
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
"英文内容中使用了中文标点",
|
||||
f"'{cn_punct}' 应改为 '{en_punct}'",
|
||||
"【互动内容】"
|
||||
))
|
||||
return violations
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 题型专属规则检查
|
||||
# ============================================================
|
||||
|
||||
def check_blank_marker(text: str, spec: FormatSpec) -> List[Violation]:
|
||||
"""挖空类题型:检查题干是否包含 ___ 标记"""
|
||||
violations = []
|
||||
if not spec.has_blank_marker:
|
||||
return violations
|
||||
|
||||
content_match = re.search(r'【互动内容】\n(.*?)(?=【|$)', text, re.DOTALL)
|
||||
if content_match:
|
||||
content = content_match.group(1)
|
||||
if '___' not in content:
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
f"{spec.cn_name} 题干缺少 ___ 挖空标记",
|
||||
"题干必须包含 '___' 表示需要填空的位置。"
|
||||
"正确格式示例:'He doesn't ___ to tell us!'",
|
||||
"【互动内容】"
|
||||
))
|
||||
return violations
|
||||
|
||||
|
||||
def check_question_language(text: str, spec: FormatSpec) -> List[Violation]:
|
||||
"""检查题干语言是否符合要求"""
|
||||
violations = []
|
||||
if not spec.question_lang:
|
||||
return violations
|
||||
|
||||
content_match = re.search(r'【互动内容】\n(.*?)(?=【|$)', text, re.DOTALL)
|
||||
if not content_match:
|
||||
return violations
|
||||
|
||||
content = content_match.group(1)
|
||||
# 取第一行非空、非"要求:"、非"题目:"的内容作为题干
|
||||
lines = [l.strip() for l in content.split('\n') if l.strip()
|
||||
and not l.strip().startswith('要求')
|
||||
and not l.strip().startswith('题目')
|
||||
and not l.strip().startswith('选项')
|
||||
and not l.strip().startswith('答案')
|
||||
and not l.strip().startswith('辅助')]
|
||||
|
||||
if spec.question_lang == "en" and lines:
|
||||
first_line = lines[0]
|
||||
# 检查是否以中文为主(超过50%中文字符)
|
||||
cn_chars = len(re.findall(r'[\u4e00-\u9fff]', first_line))
|
||||
total_chars = len(first_line.replace(' ', ''))
|
||||
if total_chars > 0 and cn_chars / total_chars > 0.5:
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
f"{spec.cn_name} 题干应为英文",
|
||||
f"当前题干以中文为主: '{first_line[:60]}...'",
|
||||
"【互动内容】"
|
||||
))
|
||||
return violations
|
||||
|
||||
|
||||
def check_options_format(text: str, spec: FormatSpec) -> List[Violation]:
|
||||
"""检查选项格式"""
|
||||
violations = []
|
||||
if not spec.has_options:
|
||||
return violations
|
||||
|
||||
# 提取选项
|
||||
options = re.findall(r'选项\d+[::]\s*(.+)', text)
|
||||
if not options:
|
||||
# 可能是"选项:"后跟列表的格式
|
||||
opt_match = re.search(r'选项[::]\s*\n?(.*?)(?=答案|辅助|【|$)', text, re.DOTALL)
|
||||
if opt_match:
|
||||
options = [o.strip() for o in opt_match.group(1).split('\n') if o.strip()]
|
||||
|
||||
if spec.has_per_option_feedback:
|
||||
# 对话选择/对话选读:每个选项必须有反馈
|
||||
feedback_count = len(re.findall(r'反馈\s*\w+\s*:', text))
|
||||
if feedback_count < len(options):
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
f"{spec.cn_name} 选项缺少逐项反馈",
|
||||
f"有 {len(options)} 个选项但只有 {feedback_count} 条反馈",
|
||||
"【互动内容】"
|
||||
))
|
||||
|
||||
if spec.is_sentence_build:
|
||||
# 组句型:检查是否有"答案"行
|
||||
if '答案' not in text:
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
f"{spec.cn_name} 缺少答案行",
|
||||
"组句型必须有'答案:'行,给出拼接后的完整句子",
|
||||
"【互动内容】"
|
||||
))
|
||||
# 选项应为片段,答案应为完整句
|
||||
answer_match = re.search(r'答案[::]\s*(.+)', text)
|
||||
if answer_match and options:
|
||||
answer = answer_match.group(1).strip()
|
||||
# 简单检查:答案应该比单个选项长
|
||||
max_opt_len = max(len(o) for o in options)
|
||||
if len(answer) <= max_opt_len * 1.5:
|
||||
violations.append(Violation(
|
||||
Severity.WARN,
|
||||
f"{spec.cn_name} 答案可能不是完整拼接句",
|
||||
f"答案'{answer}'长度与选项片段接近",
|
||||
"【互动内容】"
|
||||
))
|
||||
|
||||
return violations
|
||||
|
||||
|
||||
def check_audio_marker(text: str, spec: FormatSpec) -> List[Violation]:
|
||||
"""检查需要音频标记的题型"""
|
||||
violations = []
|
||||
# 对话选择、对话选读、对话挖空、对话组句:选项/题干后应有(音频)
|
||||
audio_types = {"对话选择", "对话选读", "对话挖空", "对话组句"}
|
||||
if spec.cn_name not in audio_types:
|
||||
return violations
|
||||
|
||||
content_match = re.search(r'【互动内容】\n(.*?)(?=【|$)', text, re.DOTALL)
|
||||
if content_match:
|
||||
content = content_match.group(1)
|
||||
# 检查是否有(音频)标记
|
||||
if '(音频)' not in content and '(音频)' not in content:
|
||||
violations.append(Violation(
|
||||
Severity.WARN,
|
||||
f"{spec.cn_name} 缺少(音频)标记",
|
||||
"对话类组件应在选项或题干后标注(音频)",
|
||||
"【互动内容】"
|
||||
))
|
||||
return violations
|
||||
|
||||
|
||||
def check_no_options_when_not_expected(text: str, spec: FormatSpec) -> List[Violation]:
|
||||
"""非选项型组件不应出现选项"""
|
||||
violations = []
|
||||
if spec.has_options:
|
||||
return violations
|
||||
|
||||
if re.search(r'选项\d*[::]', text):
|
||||
violations.append(Violation(
|
||||
Severity.WARN,
|
||||
f"{spec.cn_name} 不应包含选项",
|
||||
f"该题型为{spec.notes},但配置中出现了选项",
|
||||
"【互动内容】"
|
||||
))
|
||||
return violations
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 第三部分:主校验入口
|
||||
# ============================================================
|
||||
|
||||
def validate(teaching_config: str, cn_type: str) -> List[Violation]:
|
||||
"""
|
||||
校验单个组件配置
|
||||
|
||||
Args:
|
||||
teaching_config: 组件配置文本(teaching_config 字段内容)
|
||||
cn_type: 组件中文类型名(如 "对话挖空"、"对话挖空12")
|
||||
|
||||
Returns:
|
||||
违规列表
|
||||
"""
|
||||
spec, resolved_type = resolve_type(cn_type)
|
||||
violations = []
|
||||
|
||||
if spec is None:
|
||||
violations.append(Violation(
|
||||
Severity.ERROR,
|
||||
"未知组件类型",
|
||||
f"'{cn_type}' 不在已知的 27 种中互动或 15 种核心互动类型中",
|
||||
""
|
||||
))
|
||||
return violations
|
||||
|
||||
# ---- 通用规则 ----
|
||||
violations.extend(check_title_spacing(teaching_config))
|
||||
violations.extend(check_feedback_colon(teaching_config))
|
||||
violations.extend(check_markdown(teaching_config))
|
||||
violations.extend(check_spelling(teaching_config))
|
||||
violations.extend(check_punctuation(teaching_config))
|
||||
|
||||
# ---- 题型专属规则 ----
|
||||
violations.extend(check_blank_marker(teaching_config, spec))
|
||||
violations.extend(check_question_language(teaching_config, spec))
|
||||
violations.extend(check_options_format(teaching_config, spec))
|
||||
violations.extend(check_audio_marker(teaching_config, spec))
|
||||
violations.extend(check_no_options_when_not_expected(teaching_config, spec))
|
||||
|
||||
return violations
|
||||
|
||||
|
||||
def format_report(violations: List[Violation], cn_type: str = "") -> str:
|
||||
"""格式化输出校验报告"""
|
||||
if not violations:
|
||||
return "✅ 全部通过"
|
||||
|
||||
errors = [v for v in violations if v.severity == Severity.ERROR]
|
||||
warns = [v for v in violations if v.severity == Severity.WARN]
|
||||
infos = [v for v in violations if v.severity == Severity.INFO]
|
||||
|
||||
lines = []
|
||||
if cn_type:
|
||||
lines.append(f"📋 校验结果: {cn_type}")
|
||||
lines.append(f" 🔴 错误: {len(errors)} 🟡 警告: {len(warns)} ⚪ 提示: {len(infos)}")
|
||||
lines.append("")
|
||||
|
||||
for v in violations:
|
||||
lines.append(f" {v.severity.value} [{v.rule}] {v.detail}")
|
||||
if v.location:
|
||||
lines.append(f" 位置: {v.location}")
|
||||
|
||||
return '\n'.join(lines)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 第四部分:CLI 入口
|
||||
# ============================================================
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="互动组件配置格式校验脚本",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="""
|
||||
示例:
|
||||
# 校验单个组件
|
||||
python3 validate_format.py "【任务标题】汇报Jay不配合\\n..." --type "对话挖空"
|
||||
|
||||
# 从 stdin 读取
|
||||
echo "..." | python3 validate_format.py --type "对话组句" --stdin
|
||||
|
||||
# 列出所有支持的题型
|
||||
python3 validate_format.py --list-types
|
||||
"""
|
||||
)
|
||||
parser.add_argument('config_text', nargs='?', help='组件配置文本')
|
||||
parser.add_argument('--type', '-t', required=False, help='组件中文类型名')
|
||||
parser.add_argument('--stdin', action='store_true', help='从 stdin 读取配置文本')
|
||||
parser.add_argument('--list-types', action='store_true', help='列出所有支持的题型')
|
||||
parser.add_argument('--json', action='store_true', help='以 JSON 格式输出')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.list_types:
|
||||
print("=== 中互动组件(27种)===")
|
||||
for name, spec in MID_FORMAT_SPECS.items():
|
||||
flags = []
|
||||
if spec.has_blank_marker: flags.append("___标记")
|
||||
if spec.has_options: flags.append("选项")
|
||||
if spec.has_answer: flags.append("答案")
|
||||
if spec.has_per_option_feedback: flags.append("逐项反馈")
|
||||
if spec.is_read_type: flags.append("朗读")
|
||||
if spec.is_express_type: flags.append("表达")
|
||||
if spec.is_sentence_build: flags.append("组句")
|
||||
print(f" {name:12s} | {', '.join(flags) if flags else '(无特殊标记)'}")
|
||||
print("\n=== 核心互动组件(15种)===")
|
||||
for name in CORE_FORMAT_SPECS:
|
||||
print(f" {name}")
|
||||
return
|
||||
|
||||
if not args.type:
|
||||
print("❌ 必须指定 --type 参数", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
if args.stdin:
|
||||
config_text = sys.stdin.read()
|
||||
elif args.config_text:
|
||||
config_text = args.config_text
|
||||
else:
|
||||
print("❌ 必须提供配置文本(参数或 --stdin)", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
violations = validate(config_text, args.type)
|
||||
|
||||
if args.json:
|
||||
result = {
|
||||
"type": args.type,
|
||||
"passed": len(violations) == 0,
|
||||
"error_count": len([v for v in violations if v.severity == Severity.ERROR]),
|
||||
"warn_count": len([v for v in violations if v.severity == Severity.WARN]),
|
||||
"violations": [
|
||||
{"severity": v.severity.value, "rule": v.rule, "detail": v.detail, "location": v.location}
|
||||
for v in violations
|
||||
]
|
||||
}
|
||||
print(json.dumps(result, ensure_ascii=False, indent=2))
|
||||
else:
|
||||
print(format_report(violations, args.type))
|
||||
|
||||
# 有错误时返回非零
|
||||
if any(v.severity == Severity.ERROR for v in violations):
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
File diff suppressed because one or more lines are too long
@ -1,71 +0,0 @@
|
||||
|
||||
import pandas as pd
|
||||
|
||||
# 文件路径
|
||||
l2_file = r'/root/.openclaw/workspace-xiaoyan/business_knowledge/L2单词表/L2知识库-三级+A2.xlsx'
|
||||
l1_file = r'/root/.openclaw/workspace-xiaoyan/business_knowledge/L2单词表/L1完整.xlsx'
|
||||
|
||||
# 读取文件
|
||||
l2_df = pd.read_excel(l2_file)
|
||||
l1_df = pd.read_excel(l1_file)
|
||||
|
||||
print("L2文件列名:", l2_df.columns.tolist())
|
||||
print(f"L2行数: {len(l2_df)}")
|
||||
print("\nL1文件列名:", l1_df.columns.tolist())
|
||||
print(f"L1行数: {len(l1_df)}")
|
||||
|
||||
# 创建L1单词查找字典(小写为key)
|
||||
l1_dict = {}
|
||||
for idx, row in l1_df.iterrows():
|
||||
word = str(row.iloc[0]).strip().lower()
|
||||
pos = row.iloc[1] if len(row) > 1 else ""
|
||||
meaning = row.iloc[2] if len(row) > 2 else ""
|
||||
l1_dict[word] = {
|
||||
"row": idx + 2, # Excel从第2行开始
|
||||
"pos": pos,
|
||||
"meaning": meaning
|
||||
}
|
||||
|
||||
# 处理L2表格
|
||||
is_l1 = []
|
||||
l1_rows = []
|
||||
l1_pos = []
|
||||
l1_meaning = []
|
||||
|
||||
for idx, row in l2_df.iterrows():
|
||||
word = str(row.iloc[0]).strip().lower()
|
||||
if word in l1_dict:
|
||||
info = l1_dict[word]
|
||||
is_l1.append("是")
|
||||
l1_rows.append(info["row"])
|
||||
l1_pos.append(info["pos"])
|
||||
l1_meaning.append(info["meaning"])
|
||||
else:
|
||||
is_l1.append("否")
|
||||
l1_rows.append("")
|
||||
l1_pos.append("")
|
||||
l1_meaning.append("")
|
||||
|
||||
# 添加新列
|
||||
l2_df["是否为L1单词"] = is_l1
|
||||
l2_df["在L1中的行数"] = l1_rows
|
||||
l2_df["L1词性"] = l1_pos
|
||||
l2_df["L1词义"] = l1_meaning
|
||||
|
||||
# 保存结果
|
||||
l2_df.to_excel(l2_file, index=False)
|
||||
|
||||
# 统计
|
||||
count_yes = is_l1.count("是")
|
||||
count_no = is_l1.count("否")
|
||||
|
||||
print("\n" + "="*50)
|
||||
print(f"比对完成!")
|
||||
print(f"L1单词总数: {len(l1_df)}")
|
||||
print(f"L2单词总数: {len(l2_df)}")
|
||||
print(f"重复单词数: {count_yes}")
|
||||
print(f"不重复单词数: {count_no}")
|
||||
print(f"重复率: {count_yes/len(l2_df)*100:.2f}%")
|
||||
print("="*50)
|
||||
|
||||
print("\n保存成功!已更新 L2知识库-三级+A2.xlsx")
|
||||
@ -1,31 +0,0 @@
|
||||
|
||||
import pandas as pd
|
||||
|
||||
file_new = r'/root/.openclaw/workspace-xiaoyan/business_knowledge/L2单词表/L2新版_L1重复标记.xlsx'
|
||||
file_old = r'/root/.openclaw/workspace-xiaoyan/business_knowledge/L2单词表/L2知识库-三级+A2.xlsx'
|
||||
|
||||
df_new = pd.read_excel(file_new)
|
||||
df_old = pd.read_excel(file_old)
|
||||
|
||||
old_words = set(str(w).strip().lower() for w in df_old.iloc[:, 0])
|
||||
|
||||
only_in_new = []
|
||||
for idx, row in df_new.iterrows():
|
||||
word = str(row['单词']).strip().lower()
|
||||
if word not in old_words:
|
||||
only_in_new.append(row)
|
||||
|
||||
print(f"L2新版总单词数: {len(df_new)}")
|
||||
print(f"L2知识库总单词数: {len(df_old)}")
|
||||
print(f"\nL2新版中存在但L2知识库中不存在的单词: {len(only_in_new)} 个")
|
||||
|
||||
# 保存到文件
|
||||
with open('/root/.openclaw/workspace-xiaoyan/only_in_new.txt', 'w', encoding='utf-8') as f:
|
||||
f.write(f"L2新版中存在但L2知识库中不存在的单词: {len(only_in_new)} 个\n")
|
||||
f.write("=" * 60 + "\n")
|
||||
f.write(f"{'序号':<5} {'单词':<35} {'词性':<12} {'词义'}\n")
|
||||
f.write("-" * 80 + "\n")
|
||||
for i, row in enumerate(only_in_new, 1):
|
||||
f.write(f"{i:<5} {str(row['单词']):<35} {str(row['词性']):<12} {str(row['词义'])}\n")
|
||||
|
||||
print("\n完整列表已保存到 only_in_new.txt")
|
||||
@ -1,29 +0,0 @@
|
||||
|
||||
import pandas as pd
|
||||
|
||||
file_path = r'/root/.openclaw/workspace-xiaoyan/business_knowledge/L2单词表/L2知识库-三级+A2.xlsx'
|
||||
df = pd.read_excel(file_path)
|
||||
|
||||
music_keywords = ['唱歌', '音乐', '歌曲', '歌', '唱', '乐器', '钢琴', '吉他', '小提琴', '鼓',
|
||||
'演奏', '乐队', '音乐会', '演唱会', '旋律', '节奏', '音符', '录音', '歌手',
|
||||
'sing', 'song', 'music', 'musical', 'piano', 'guitar', 'violin', 'drum',
|
||||
'band', 'concert', 'melody', 'rhythm', 'note', 'record', 'singer', 'musician',
|
||||
'instrument', 'listen', 'sound', 'voice', 'choir', 'opera', 'jazz',
|
||||
'rock', 'pop', 'dance', 'rap', 'tune', 'lyric', 'album', 'audio']
|
||||
|
||||
results = []
|
||||
for idx, row in df.iterrows():
|
||||
word = str(row.iloc[0]).strip().lower()
|
||||
meaning = str(row.iloc[2]).strip().lower() if len(row) > 2 else ''
|
||||
for kw in music_keywords:
|
||||
if kw in word or kw in meaning:
|
||||
results.append(row)
|
||||
break
|
||||
|
||||
print(f"L2知识库总单词数: {len(df)}")
|
||||
print(f"\n🎵 唱歌/音乐相关单词 ({len(results)} 个):")
|
||||
print("-" * 60)
|
||||
print(f"{'单词':<25} {'词性':<10} {'中文释义'}")
|
||||
print("-" * 60)
|
||||
for row in sorted(results, key=lambda x: str(x.iloc[0]).lower()):
|
||||
print(f"{str(row.iloc[0]):<25} {str(row.iloc[1]):<10} {str(row.iloc[2])}")
|
||||
@ -101,3 +101,17 @@
|
||||
{"type":"memory.recall.recorded","timestamp":"2026-06-09T07:22:27.500Z","query":"互动内容库 app_token 多维表格 bitable 配置","resultCount":4,"results":[{"path":"memory/2026-05-12.md","startLine":61,"endLine":80,"score":1},{"path":"memory/2026-05-18.md","startLine":305,"endLine":346,"score":1},{"path":"memory/2026-05-12.md","startLine":101,"endLine":121,"score":1},{"path":"memory/2026-05-18.md","startLine":783,"endLine":810,"score":1}]}
|
||||
{"type":"memory.recall.recorded","timestamp":"2026-06-09T08:37:12.232Z","query":"core_speaking_image bitable app token 多维表格","resultCount":3,"results":[{"path":"memory/2026-05-12.md","startLine":164,"endLine":187,"score":1},{"path":"memory/2026-05-12.md","startLine":214,"endLine":236,"score":1},{"path":"memory/2026-05-12.md","startLine":234,"endLine":254,"score":1}]}
|
||||
{"type":"memory.recall.recorded","timestamp":"2026-06-09T08:37:27.121Z","query":"core_speaking_image bitable_token app_token 多维表格 核心互动","resultCount":3,"results":[{"path":"memory/2026-05-12.md","startLine":164,"endLine":187,"score":1},{"path":"memory/2026-05-12.md","startLine":214,"endLine":236,"score":1},{"path":"memory/2026-05-12.md","startLine":234,"endLine":254,"score":1}]}
|
||||
{"type":"memory.recall.recorded","timestamp":"2026-06-10T02:19:54.974Z","query":"看图拼写 题型 能力标签 字母书写 认写英文字母","resultCount":4,"results":[{"path":"memory/2026-05-25.md","startLine":49,"endLine":64,"score":1},{"path":"memory/2026-05-25.md","startLine":225,"endLine":243,"score":1},{"path":"memory/2026-05-25.md","startLine":214,"endLine":228,"score":1},{"path":"memory/2026-05-07.md","startLine":1,"endLine":20,"score":1}]}
|
||||
{"type":"memory.recall.recorded","timestamp":"2026-06-10T02:20:12.701Z","query":"看图拼写 writing_pic_spell 题型 能力标签 ability","resultCount":4,"results":[{"path":"memory/2026-05-25.md","startLine":49,"endLine":64,"score":1},{"path":"memory/2026-05-25.md","startLine":225,"endLine":243,"score":1},{"path":"memory/2026-05-25.md","startLine":214,"endLine":228,"score":1},{"path":"memory/2026-05-07.md","startLine":1,"endLine":20,"score":1}]}
|
||||
{"type":"memory.recall.recorded","timestamp":"2026-06-10T02:20:12.701Z","query":"字母书写 认写英文字母 能力标签 单元挑战","resultCount":8,"results":[{"path":"memory/2026-05-25.md","startLine":49,"endLine":64,"score":1},{"path":"memory/2026-05-25.md","startLine":225,"endLine":243,"score":1},{"path":"memory/2026-05-25.md","startLine":214,"endLine":228,"score":1},{"path":"memory/2026-05-18.md","startLine":783,"endLine":810,"score":1},{"path":"memory/2026-05-08.md","startLine":33,"endLine":55,"score":1},{"path":"memory/2026-05-08.md","startLine":18,"endLine":38,"score":1},{"path":"memory/2026-05-18.md","startLine":702,"endLine":726,"score":1},{"path":"memory/2026-05-18.md","startLine":672,"endLine":707,"score":1}]}
|
||||
{"type":"memory.recall.recorded","timestamp":"2026-06-10T02:20:22.634Z","query":"词义分类 反义选择 同义选择 L2单词 B级难度 排序","resultCount":4,"results":[{"path":"memory/2026-05-28.md","startLine":46,"endLine":62,"score":1},{"path":"memory/2026-05-28.md","startLine":60,"endLine":66,"score":1},{"path":"memory/2026-05-29.md","startLine":1,"endLine":14,"score":1},{"path":"memory/2026-05-28.md","startLine":35,"endLine":49,"score":1}]}
|
||||
{"type":"memory.recall.recorded","timestamp":"2026-06-10T02:20:22.635Z","query":"L2 单词题型 难度排序 认知步骤 检索 规则 生成","resultCount":6,"results":[{"path":"memory/2026-05-25.md","startLine":283,"endLine":302,"score":1},{"path":"memory/2026-05-25.md","startLine":118,"endLine":137,"score":1},{"path":"memory/2026-05-28.md","startLine":60,"endLine":66,"score":1},{"path":"memory/2026-05-28.md","startLine":46,"endLine":62,"score":1},{"path":"memory/2026-05-25.md","startLine":74,"endLine":91,"score":1},{"path":"memory/2026-05-25.md","startLine":240,"endLine":256,"score":1}]}
|
||||
{"type":"memory.recall.recorded","timestamp":"2026-06-10T02:20:27.209Z","query":"看图拼词 writing_pic_spell SKILL 能力标签 ability 词汇拼写","resultCount":7,"results":[{"path":"memory/2026-05-28.md","startLine":46,"endLine":62,"score":1},{"path":"memory/2026-05-28.md","startLine":60,"endLine":66,"score":1},{"path":"memory/2026-05-29.md","startLine":1,"endLine":14,"score":1},{"path":"memory/2026-05-28.md","startLine":35,"endLine":49,"score":1},{"path":"memory/2026-05-07.md","startLine":1,"endLine":20,"score":1},{"path":"memory/2026-05-07.md","startLine":215,"endLine":235,"score":1},{"path":"memory/2026-05-08.md","startLine":33,"endLine":55,"score":1}]}
|
||||
{"type":"memory.recall.recorded","timestamp":"2026-06-10T02:20:27.209Z","query":"能力标签 字母书写 认写英文字母 写作 标签映射 单元挑战能力标签","resultCount":7,"results":[{"path":"memory/2026-05-18.md","startLine":702,"endLine":726,"score":1},{"path":"memory/2026-05-18.md","startLine":672,"endLine":707,"score":1},{"path":"memory/2026-05-26.md","startLine":218,"endLine":226,"score":1},{"path":"memory/2026-05-12.md","startLine":164,"endLine":187,"score":1},{"path":"memory/2026-05-07.md","startLine":337,"endLine":356,"score":1},{"path":"memory/2026-05-26.md","startLine":198,"endLine":223,"score":1},{"path":"memory/2026-05-12.md","startLine":34,"endLine":50,"score":1}]}
|
||||
{"type":"memory.recall.recorded","timestamp":"2026-06-10T02:20:40.073Z","query":"词义分类 反义选择 同义选择 题型定义 认知步骤","resultCount":4,"results":[{"path":"memory/2026-05-28.md","startLine":46,"endLine":62,"score":1},{"path":"memory/2026-05-28.md","startLine":60,"endLine":66,"score":1},{"path":"memory/2026-05-29.md","startLine":1,"endLine":14,"score":1},{"path":"memory/2026-05-28.md","startLine":35,"endLine":49,"score":1}]}
|
||||
{"type":"memory.recall.recorded","timestamp":"2026-06-10T03:52:02.147Z","query":"深度复核 组件 component review","resultCount":2,"results":[{"path":"memory/2026-05-07.md","startLine":354,"endLine":368,"score":1},{"path":"memory/2026-04-22.md","startLine":1,"endLine":8,"score":1}]}
|
||||
{"type":"memory.recall.recorded","timestamp":"2026-06-10T03:52:02.147Z","query":"core_speaking_image 组件 复核","resultCount":3,"results":[{"path":"memory/2026-05-12.md","startLine":164,"endLine":187,"score":1},{"path":"memory/2026-05-12.md","startLine":214,"endLine":236,"score":1},{"path":"memory/2026-05-12.md","startLine":234,"endLine":254,"score":1}]}
|
||||
{"type":"memory.recall.recorded","timestamp":"2026-06-10T03:52:13.443Z","query":"深度复核 core_speaking_image 口语看图","resultCount":3,"results":[{"path":"memory/2026-05-12.md","startLine":164,"endLine":187,"score":1},{"path":"memory/2026-05-12.md","startLine":214,"endLine":236,"score":1},{"path":"memory/2026-05-12.md","startLine":234,"endLine":254,"score":1}]}
|
||||
{"type":"memory.recall.recorded","timestamp":"2026-06-10T03:52:13.443Z","query":"Perfect Oops 数据 复核 审校 组件","resultCount":1,"results":[{"path":"memory/2026-05-28.md","startLine":19,"endLine":37,"score":1}]}
|
||||
{"type":"memory.recall.recorded","timestamp":"2026-06-10T03:52:28.180Z","query":"深度复核 流程 步骤 component review audit","resultCount":4,"results":[{"path":"memory/2026-05-20.md","startLine":40,"endLine":59,"score":1},{"path":"memory/2026-05-20.md","startLine":55,"endLine":65,"score":1},{"path":"memory/2026-05-12.md","startLine":234,"endLine":254,"score":1},{"path":"memory/2026-06-08.md","startLine":17,"endLine":27,"score":1}]}
|
||||
{"type":"memory.recall.recorded","timestamp":"2026-06-10T03:52:28.181Z","query":"core_speaking_image JSON 结构 口语看图","resultCount":3,"results":[{"path":"memory/2026-05-12.md","startLine":164,"endLine":187,"score":1},{"path":"memory/2026-05-12.md","startLine":214,"endLine":236,"score":1},{"path":"memory/2026-05-12.md","startLine":234,"endLine":254,"score":1}]}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"version": 1,
|
||||
"updatedAt": "2026-06-09T08:37:27.121Z",
|
||||
"updatedAt": "2026-06-10T03:52:28.181Z",
|
||||
"entries": {
|
||||
"memory:memory/2026-05-07.md:57:74": {
|
||||
"key": "memory:memory/2026-05-07.md:57:74",
|
||||
@ -44,24 +44,26 @@
|
||||
"endLine": 235,
|
||||
"source": "memory",
|
||||
"snippet": "3. He is (4) Japan. → from(男孩穿和服,背景富士山) 4. She is a (7). → student(女孩背书包进校门) - **JSON 结构:** questionSetID=020102, category=writing, type=writing_pic_qa - **关键教训:** - 初版设计错误:让学手写 Anna/China 等非知识点词,被用户纠正 - 初版 questionDesc \"She is a (7) girl.\" 不自然,修正为 \"She is a (7).\" - writing_pic_qa 题型核心考察点:知识点词本身(am/from),而非题干已知信息 - 挖空字母数标记(如(4))必须与答案单词字母数一致 - **词库缺口发现:** L1和L2词库均缺失人称代词(I/you/he/she)、be动词(am/is/are)、介词(from)、国家名等基础功能词,写题时先绕过词汇校验硬性约束 ### 刘彦江 (ou_5af74c1fb96042e33cc0f16b5ca02cf4) — 单元挑战新增3个题型(已完结) - 详见上文 11:19-11:28 记录 ### 刘彦江 (ou_5af74c1fb96042e33cc0f16b5ca02cf4) — 写作看图回答题 \"I am ready / Thank you\" 样题生产 - **时间:** 15:53 ~ 15:55 - **需求:** 使用知识点 \"I am ready! / Thank you for...\" 再生产一套",
|
||||
"recallCount": 4,
|
||||
"recallCount": 5,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 4,
|
||||
"totalScore": 5,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-05-08T01:18:18.412Z",
|
||||
"lastRecalledAt": "2026-05-26T01:58:13.120Z",
|
||||
"lastRecalledAt": "2026-06-10T02:20:27.209Z",
|
||||
"queryHashes": [
|
||||
"390d35f8d143",
|
||||
"be437071312f",
|
||||
"12653110bb68",
|
||||
"ab90b7e9cde8"
|
||||
"ab90b7e9cde8",
|
||||
"3ac726b21876"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-05-08",
|
||||
"2026-05-11",
|
||||
"2026-05-25",
|
||||
"2026-05-26"
|
||||
"2026-05-26",
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"writing-pic-qa",
|
||||
@ -119,13 +121,13 @@
|
||||
"endLine": 20,
|
||||
"source": "memory",
|
||||
"snippet": "# 2026-05-07 工作日志 ## 会话记录 ### 刘彦江 (ou_5af74c1fb96042e33cc0f16b5ca02cf4) — 单元挑战新增3个题型 - **时间:** 11:19 ~ 11:28 - **需求:** 单元挑战新增3个题型:阅读看图回答题(reading_pic_qa)、阅读看图判断题(reading_pic_judge)、写作看图回答题(writing_pic_qa) - **状态:** ✅ 已完成题型规范落地 - **交付内容:** 1. 创建3个题型SKILL.md: - `reading/common/reading_pic_qa/SKILL.md` — 阅读看图回答题(共享大图+多题Yes/No判断) - `reading/common/reading_pic_judge/SKILL.md` — 阅读看图判断题(每题独立配图+Yes/No判断) - `writing/common/writing_pic_qa/SKILL.md` — 写作看图回答题(看图+提示答案开头+填空) 2. 更新 `MEMORY.md` 全题型阶段归属规则 3. 明确题型JSON结构、难度等级(A/B/C/D四级)、能力标签、校验规则 - **关键决策:** 3个题型均为 L1&L2 共用,通过难度参数区分阶段;reading_pic_qa 共享大图,reading_pic_judge 每题独立配图 ### 李应瑛 (ou_1bd7317ae2ccfeb57e1132028847279e) — 单词表对比请求",
|
||||
"recallCount": 12,
|
||||
"recallCount": 15,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 12,
|
||||
"totalScore": 15,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-05-08T01:18:18.412Z",
|
||||
"lastRecalledAt": "2026-05-29T00:23:17.392Z",
|
||||
"lastRecalledAt": "2026-06-10T02:20:27.209Z",
|
||||
"queryHashes": [
|
||||
"390d35f8d143",
|
||||
"fd4c9b7de37b",
|
||||
@ -138,7 +140,10 @@
|
||||
"5f858a7d5e0b",
|
||||
"ab90b7e9cde8",
|
||||
"fbf96ac9320e",
|
||||
"bd790c7e2a35"
|
||||
"bd790c7e2a35",
|
||||
"7de89d94cd21",
|
||||
"e679709051aa",
|
||||
"3ac726b21876"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-05-08",
|
||||
@ -149,7 +154,8 @@
|
||||
"2026-05-17",
|
||||
"2026-05-26",
|
||||
"2026-05-28",
|
||||
"2026-05-29"
|
||||
"2026-05-29",
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"reading-pic-qa",
|
||||
@ -200,13 +206,13 @@
|
||||
"endLine": 55,
|
||||
"source": "memory",
|
||||
"snippet": "**图片资源新规:** - 每个题组共享一张图(非每题独立配图) - 产出 JSON 同时输出图片描述 prompt(英文,卡通简线条风格) - prompt 写入 bitable `图片描述` 列,格式 `{\"first\": \"...\", \"second\": \"...\"}` **通用化写入流程:** - 单元挑战全题型适用:定位 bitable 表 → 创建/更新记录 → 写入 `题目集合 ID` + `jsonData` + `图片描述` - 各题型仅 jsonData 结构不同,写入流程统一 **重写文件:** - `business_production/单元挑战/skills/unit_challenge/questions/writing/common/writing_pic_qa/SKILL.md`(11节完整规范) - `business_production/单元挑战/skills/unit_challenge/questions/writing/writing_pic_qa/SKILL.md`(简化为快速入口) **bitable 更新:** 已将新 JSON(每题组1图2题)+ 图片描述写入 `recviZlAxxXlAb` ### 刘彦江 (ou_5af74c1fb96042e33cc0f16b5ca02cf4) — 图片描述格式修正 - **时间:** 09:46 ~ 09:51 - **修正:** 用户给出中文样例格式,要求图片描述从英文 prompt 改为纯中文结构化列表 - **新格式:** 编号 `1.` / `2.` 自上而下,每段",
|
||||
"recallCount": 12,
|
||||
"recallCount": 14,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 12,
|
||||
"totalScore": 14,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-05-11T02:19:37.985Z",
|
||||
"lastRecalledAt": "2026-06-02T01:49:17.841Z",
|
||||
"lastRecalledAt": "2026-06-10T02:20:27.209Z",
|
||||
"queryHashes": [
|
||||
"6f88450e9f9b",
|
||||
"be437071312f",
|
||||
@ -219,7 +225,9 @@
|
||||
"14d903a64d04",
|
||||
"ab90b7e9cde8",
|
||||
"240a6a5dca41",
|
||||
"7e6aa000abdb"
|
||||
"7e6aa000abdb",
|
||||
"9018e8896dcd",
|
||||
"3ac726b21876"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-05-11",
|
||||
@ -228,7 +236,8 @@
|
||||
"2026-05-20",
|
||||
"2026-05-25",
|
||||
"2026-05-26",
|
||||
"2026-06-02"
|
||||
"2026-06-02",
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"创建/更新记录",
|
||||
@ -878,13 +887,13 @@
|
||||
"endLine": 368,
|
||||
"source": "memory",
|
||||
"snippet": "- **需求:** 将 020102(I am...)和 020103(I am ready / Thank you)两套题合并为一个 `{first:..., second:...}` JSON,统一 questionSetID=0000001 - **状态:** ✅ 已完成 - **核心考点分析(用户强调):** 需分析每个句型的核心考点(孩子最容易犯错的地方),挖空对准核心考点 - I am/from 组:am(系动词第一人称)、from(介词选择)、student(a+名词结构) - Thank you for 组:for(介词选择,非 you)、helping(for+动名词,非 help/to help) - **输出文件:** `output/writing_pic_qa_combined.json` ### 刘彦江 — 组件配置-json 请求(L1-S2-U13-L4 沙漠之花) - **时间:** 16:45 ~ 17:51 - **文档:** `https://makee-interactive.feishu.cn/wiki/K5E1wzwk7it9t7kXvcbc6Xugnhc` - **状态:** ⚠️ 未完成 — pipeline 识别到 0 组件 - **根因:** 剧本文档的13个组件数据存储在 markdown 内联表格中(lark-table,5列×36行),而非内嵌 Sheet。当前 pipeline 的 parse_script 只从内嵌 Sheet 读取组件数据,不支持 markdown 表格组件解析 - **已识别组件(ma",
|
||||
"recallCount": 16,
|
||||
"recallCount": 17,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 16,
|
||||
"totalScore": 17,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-05-15T07:13:08.147Z",
|
||||
"lastRecalledAt": "2026-06-09T07:14:02.277Z",
|
||||
"lastRecalledAt": "2026-06-10T03:52:02.147Z",
|
||||
"queryHashes": [
|
||||
"08364c8746ab",
|
||||
"4f08741ab4fd",
|
||||
@ -901,7 +910,8 @@
|
||||
"5d025e291984",
|
||||
"472b243ec77c",
|
||||
"fd4c8aca2cb6",
|
||||
"5319f16d7a0d"
|
||||
"5319f16d7a0d",
|
||||
"bab77e938a4a"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-05-15",
|
||||
@ -912,7 +922,8 @@
|
||||
"2026-05-28",
|
||||
"2026-06-01",
|
||||
"2026-06-04",
|
||||
"2026-06-09"
|
||||
"2026-06-09",
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"am/from",
|
||||
@ -932,13 +943,13 @@
|
||||
"endLine": 8,
|
||||
"source": "memory",
|
||||
"snippet": "[李应瑛 2026-04-22 提出要求] 所有需要包含对话的内容(如剧本、互动组件等)必须要有【后置对话】字段,无后置对话时填写“无”。 [李应瑛 2026-04-22 确认规则] 剧本内嵌表格组件填写位置规则:仅当表格第一列(A列)明确标注为对话类类型(对话朗读/对话挖空/对话选读/对话组句等)时,才在同一行的H列(【组件】列)填写对应的组件内容,其他类型行(TL/场景/角色/图片/非对话类等)无需填写。 [李应瑛 2026-04-22 确认格式规则] 对话类组件字段换行规则:每个结构单独占一行,格式为: 【任务标题】xxx 【情境引入】xxx 【互动内容】xxx 【后置对话】xxx 单元格内使用\\n作为换行符实现,后续所有组件均遵循此格式。",
|
||||
"recallCount": 14,
|
||||
"recallCount": 15,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 14,
|
||||
"totalScore": 15,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-05-15T07:13:08.147Z",
|
||||
"lastRecalledAt": "2026-06-09T07:14:02.277Z",
|
||||
"lastRecalledAt": "2026-06-10T03:52:02.147Z",
|
||||
"queryHashes": [
|
||||
"08364c8746ab",
|
||||
"4f08741ab4fd",
|
||||
@ -953,7 +964,8 @@
|
||||
"5d025e291984",
|
||||
"472b243ec77c",
|
||||
"fd4c8aca2cb6",
|
||||
"5319f16d7a0d"
|
||||
"5319f16d7a0d",
|
||||
"bab77e938a4a"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-05-15",
|
||||
@ -964,7 +976,8 @@
|
||||
"2026-05-28",
|
||||
"2026-06-01",
|
||||
"2026-06-04",
|
||||
"2026-06-09"
|
||||
"2026-06-09",
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"对话朗读/对话挖空/对话选读/对话组句等",
|
||||
@ -1410,21 +1423,24 @@
|
||||
"endLine": 726,
|
||||
"source": "memory",
|
||||
"snippet": "- 颜色题: \"What colour is it?\",物体题: \"What's this?\" - ability: 图文匹配 - explanation: 含回答要点、图片内容、能力、评估标准、回答指导 ### 审校结果 - ✅ 全部27题 jsonData 结构完整、explanation 全中文、题目格式正确 - ✅ 题目集合ID一致、图片编号连续(00-10/00-11/00-09) - ✅ 题目配置(人类可读)格式规范 - ⚠️ 口语-P4表无「审校结果」列,无法标记审校状态 - ℹ️ 110101题组2 \"colour\"出现2次(调色盘+彩虹)— 按规格生成 - ℹ️ 110201 \"mice\"(复数) 使用 \"What are these?\" 区分于 \"mouse\"(单数) 使用 \"What's this?\" - ℹ️ 以下词汇未在L1词库中检索到(词库仅160词/声称980词,疑似文件不完整):jacket, T-shirt, hair, monster, colour, bread, cake, candy, chocolate, ice cream, mice, mouse — 按用户指定词汇生产,未做替换 ### Bitable信息 - App Token: CMHSbUUjka3TrUsaxxEc297ongf - Table ID: tblsD2dxaRpLmkXD - 操作方式: Python subprocess + curl(避免shell转义) ## [李应瑛] L1-S2-U17-L3 紧急拜访 组件配置(2026-05-18 20:5",
|
||||
"recallCount": 3,
|
||||
"recallCount": 5,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 3,
|
||||
"totalScore": 5,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-05-19T03:08:27.099Z",
|
||||
"lastRecalledAt": "2026-06-04T03:43:35.423Z",
|
||||
"lastRecalledAt": "2026-06-10T02:20:27.209Z",
|
||||
"queryHashes": [
|
||||
"34bf2e5fbdee",
|
||||
"3f9471df9e50",
|
||||
"19f5f93f3465"
|
||||
"19f5f93f3465",
|
||||
"9018e8896dcd",
|
||||
"113e8be33943"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-05-19",
|
||||
"2026-06-04"
|
||||
"2026-06-04",
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"00-10/00-11/00-09",
|
||||
@ -1444,21 +1460,24 @@
|
||||
"endLine": 707,
|
||||
"source": "memory",
|
||||
"snippet": "- `/tmp/unit_challenge_ability_doc.md` — 对外分享版(已发送文件 + 飞书文档) --- ## L1-S2-U18-L5 双龙会 台词润色审校([王璐辰]) ### 审校结果 - 语法/拼写硬错误:5处(Rows 41, 55, 126, 153, 178) - 表达优化建议:4处(Rows 77, 84, 63, 207) - 一致性遗漏:4行无润色 + dragon/Loong 混用不统一 - D列知识点:6个知识点,共20次 ### 交互模式收获 - 用户(王璐辰)偏好直接在 bitable 中写入统计表格 → 后续同类需求优先写入原表 ## [刘彦江] 口语-P4-看图识物 内容生产(2026-05-18 19:34) ### 生产范围(3条记录,全部双题组,全部回填验证通过 ✅) | ID | record_id | 题组1 | 题组2 | 状态 | |----|-----------|-------|-------|------| | 100001 | recvjYhcXkYXIM | 6题(颜色) | 5题(衣物) | ✅ | | 110101 | recvjYhdvUxDgs | 6题(身体) | 6题(颜色) | ✅ | | 110201 | recvjYhe4opOGm | 6题(食物) | 4题(动物) | ✅ | ### 题型结构 **口语-P4 (speaking_pic_recognize)**: - textTitle: \"Look and answer.\" - 每词1题,配1图(白底中央展",
|
||||
"recallCount": 3,
|
||||
"recallCount": 5,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 3,
|
||||
"totalScore": 5,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-05-19T03:08:27.099Z",
|
||||
"lastRecalledAt": "2026-06-04T03:43:35.423Z",
|
||||
"lastRecalledAt": "2026-06-10T02:20:27.209Z",
|
||||
"queryHashes": [
|
||||
"34bf2e5fbdee",
|
||||
"3f9471df9e50",
|
||||
"19f5f93f3465"
|
||||
"19f5f93f3465",
|
||||
"9018e8896dcd",
|
||||
"113e8be33943"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-05-19",
|
||||
"2026-06-04"
|
||||
"2026-06-04",
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"l1-s2-u18-l5",
|
||||
@ -1478,20 +1497,22 @@
|
||||
"endLine": 356,
|
||||
"source": "memory",
|
||||
"snippet": "| 对话挖空 | 1213314 | 画面左右各半:左边猴子站草地上生气 + 右边猴子在树林中开心 | | 对话朗读 | 1213315 | 画面左右各半:左边蜥蜴站草地上生气 + 右边蜥蜴在沙子里开心 | | 对话朗读 | 1213316 | 画面左右各半:左边斑马站沙子上生气 + 右边斑马在草地上开心 | | 对话朗读 | 1213317 | 河马/熊/猴子/蜥蜴/山羊/鸭子都很高兴的合照 | --- ## 经验教训(跨会话通用) ### replace_range 使用规范 - **必须精确定位单个 `<lark-td>` 标签**,不能用跨多行的范围定位 - **定位字符串应包含行ID标记**(如 `对话朗读1213401`)以确保唯一性 - **每次替换前先 fetch 确认当前文档结构**,避免基于缓存数据操作 - **替换后立即验证**表格结构完整性(行数、各列是否对齐) - 如果意外损坏表格,可用缓存的原始 fetch 数据重建 ### 刘彦江 — writing_pic_qa 两套题拼接合并 - **时间:** 16:08 ~ 16:30 - **需求:** 将 020102(I am...)和 020103(I am ready / Thank you)两套题合并为一个 `{first:..., second:...}` JSON,统一 questionSetID=0000001 - **状态:** ✅ 已完成 - **核心考点分析(用户强调):** 需分析每个句型的核心考点(孩子最容易犯错的地方),挖空对准核心考点",
|
||||
"recallCount": 2,
|
||||
"recallCount": 3,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 2,
|
||||
"totalScore": 3,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-05-19T03:08:27.099Z",
|
||||
"lastRecalledAt": "2026-05-26T01:58:13.119Z",
|
||||
"lastRecalledAt": "2026-06-10T02:20:27.209Z",
|
||||
"queryHashes": [
|
||||
"34bf2e5fbdee",
|
||||
"4010d52c12f3"
|
||||
"4010d52c12f3",
|
||||
"113e8be33943"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-05-19",
|
||||
"2026-05-26"
|
||||
"2026-05-26",
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"河马/熊/猴子/蜥蜴/山羊/鸭子都很高兴的合照",
|
||||
@ -1551,13 +1572,13 @@
|
||||
"endLine": 38,
|
||||
"source": "memory",
|
||||
"snippet": "4. question与questionDesc人称必须一致(统一改为 What does [角色] say? → 第一人称直接引语) - **JSON wrapper格式:** `{\"first\": 题组1完整JSON, \"second\": 题组2完整JSON}` - **输出文件:** `output/writing_pic_qa_000001_sample.json` ### 刘彦江 (ou_5af74c1fb96042e33cc0f16b5ca02cf4) — writing_pic_qa 生产流程标准化 + SKILL 重写 - **时间:** 09:34 ~ 09:46 - **需求:** 将完整生产流程补充到 SKILL.md,强化核心规则 - **状态:** ✅ 已完成 **核心规则强化(用户明确):** 1. **挖空 = 考察句型结构本身**,不是复述图片信息(如 Thank you for → 挖 for 而非 you) 2. **考察多样化**:同句型覆盖多种搭配(for + 名词 / for + 动名词、be + 身份 / be + 状态词等) 3. **语言难度匹配欧标 A1-A2**(Starters/Movers) 4. **题干不千篇一律**:question 随语境微调(如 \"What does she say about herself?\" / \"Where does she say she is going?\" / \"What does she say to her friend?\") **图片资源新规:** - 每个题组共享一",
|
||||
"recallCount": 8,
|
||||
"recallCount": 9,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 8,
|
||||
"totalScore": 9,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-05-20T06:31:39.981Z",
|
||||
"lastRecalledAt": "2026-05-28T10:04:34.024Z",
|
||||
"lastRecalledAt": "2026-06-10T02:20:12.701Z",
|
||||
"queryHashes": [
|
||||
"688d2dceca9d",
|
||||
"e637236fe74b",
|
||||
@ -1566,13 +1587,15 @@
|
||||
"a455c766229c",
|
||||
"ff8454ebcc30",
|
||||
"9c790f74fc5b",
|
||||
"71e44ea68b09"
|
||||
"71e44ea68b09",
|
||||
"9018e8896dcd"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-05-20",
|
||||
"2026-05-25",
|
||||
"2026-05-26",
|
||||
"2026-05-28"
|
||||
"2026-05-28",
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"writing-pic-qa",
|
||||
@ -1798,20 +1821,22 @@
|
||||
"endLine": 65,
|
||||
"source": "memory",
|
||||
"snippet": "- **结果**:16个组件中 15成功 / 0失败 / 1跳过(看图拼词 1217413 未注册) ### Bug修复:parse_script.py cId提取fallback - **现象**:pipeline 识别到 0 个组件行 - **根因**:本文档的 cId(如 1217408)嵌入在 B 列(配置信息)而非 A 列(类型)。`extract_component_id` 只从类型列提取 cId,找不到就返回 None - **修复**:在 `parse_component_rows` 中新增 fallback — 当 comp_info 为 None 时,从 config_info 列(B列)提取 cId - **修改文件**:`business_production/组件配置/interactive-component-json/scripts/parse_script.py` ### 待处理 - 「看图拼词」类型需注册到 `match_component.py` 后才能生成 JSON",
|
||||
"recallCount": 2,
|
||||
"recallCount": 3,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 2,
|
||||
"totalScore": 3,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-05-21T02:47:59.335Z",
|
||||
"lastRecalledAt": "2026-05-26T06:08:47.532Z",
|
||||
"lastRecalledAt": "2026-06-10T03:52:28.180Z",
|
||||
"queryHashes": [
|
||||
"09344f87b646",
|
||||
"92e62f6b8e3a"
|
||||
"92e62f6b8e3a",
|
||||
"0924e1755b1c"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-05-21",
|
||||
"2026-05-26"
|
||||
"2026-05-26",
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"parse-script.py",
|
||||
@ -1897,22 +1922,24 @@
|
||||
"endLine": 59,
|
||||
"source": "memory",
|
||||
"snippet": "3. **后置对话禁止重复下行台词**:如下行是 User 的后续台词,后置对话不能复制,统一用「无」 4. **组件配置权威文档**:`WD6LwyWNtip8M8k0RWxcbJDcnxe`(飞书知识库 - 教研生产配置、修改规范) ## [李应瑛] 组件配置正确流程纠正 - **纠正**:不应手动往 wiki 文档 C 列写文本格式配置,正确做法是用 pipeline 脚本 - **正确流程**: ``` cd /root/.openclaw/workspace-xiaoyan/business_production/组件配置/interactive-component-json && \\ python3 scripts/pipeline.py \"<wiki_url>\" --send-to gc9f72ff ``` - **Pipeline 6 步**:读取飞书文档 → 解析剧本sheet → 匹配组件类型 → LLM生成jsonData/kpInfo → 写入本地SQLite → 生成HTML报告发送给童瑶 - **Skill 目录**:`business_production/组件配置/interactive-component-json/` ## [李应瑛] L1-S2-U17-L4 门关啦 — Pipeline 组件配置生产 - **文档**: SAadwW8YaiObl8k4op3c6vs8nqb | **Spreadsheet**: It4AsFkC7hXHc4te9yUcyLHRnOe - **结果**:16个组件中 15成功 / 0失败",
|
||||
"recallCount": 3,
|
||||
"recallCount": 4,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 3,
|
||||
"totalScore": 4,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-05-21T02:47:59.335Z",
|
||||
"lastRecalledAt": "2026-06-02T07:02:08.195Z",
|
||||
"lastRecalledAt": "2026-06-10T03:52:28.180Z",
|
||||
"queryHashes": [
|
||||
"09344f87b646",
|
||||
"92e62f6b8e3a",
|
||||
"d70b515b4a03"
|
||||
"d70b515b4a03",
|
||||
"0924e1755b1c"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-05-21",
|
||||
"2026-05-26",
|
||||
"2026-06-02"
|
||||
"2026-06-02",
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"scripts/pipeline.py",
|
||||
@ -2691,23 +2718,28 @@
|
||||
"endLine": 62,
|
||||
"source": "memory",
|
||||
"snippet": "- B级规则:听力句子 5-8 词(均 7 词),每组 3 张同类物品不同属性图片 - 能力标签:显性事实理解|关键词识别 ×2 + 基础语境理解|场景/物品/动作识别 ## 梁辰(user_id: ou_28f02dcada1193913cfbb6310f8daf07)— HTML 诊断页面教研规则 JS 文件 - 用户有一个 L1 关卡诊断工作台 HTML 页面(部署在腾讯云空间),当前只做数量级统计,缺少教研规则校验 - 需求:提供可嵌入 HTML 的前端 JS 校验规则文件,使诊断有据可依 - 输出:`output/l1_pedagogy_rules.js`(42KB),包含 8 个校验维度: 1. 词汇超纲检测(基于 L1/L2 词库) 2. 英式拼写检测(color→colour 等 115 组映射) 3. Markdown 标记检测(`**`/`#`/`>` 等) 4. 标点规范检测(全角混入、`~`、`!!!`) 5. 题型-阶段匹配校验(20 种题型对应的 L1/L2 阶段映射) 6. 台词质量分析(句子长度、负面评价) 7. 知识点曝光度 8. 句型合规检测 - 接入方式:`<script src=\"l1_pedagogy_rules.js\"></script>` + 调用 `PedagogyRules.validate(summary, level)` - 数据源:L1 词库 147 词(过滤 enabled=true)、L2 词库 52 词、L1 句型 8 个、L2 句型(从 437MB bitable 导出中提取唯一结",
|
||||
"recallCount": 4,
|
||||
"recallCount": 8,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 4,
|
||||
"totalScore": 8,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-05-29T00:23:17.391Z",
|
||||
"lastRecalledAt": "2026-06-02T01:49:17.841Z",
|
||||
"lastRecalledAt": "2026-06-10T02:20:40.073Z",
|
||||
"queryHashes": [
|
||||
"c1d4076205e1",
|
||||
"4aa0ef719160",
|
||||
"e30c130b9d1d",
|
||||
"7e6aa000abdb"
|
||||
"7e6aa000abdb",
|
||||
"094bfb865b29",
|
||||
"6568231ab2d7",
|
||||
"3ac726b21876",
|
||||
"867f7264cd0e"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-05-29",
|
||||
"2026-06-01",
|
||||
"2026-06-02"
|
||||
"2026-06-02",
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"5-8",
|
||||
@ -2820,21 +2852,23 @@
|
||||
"endLine": 302,
|
||||
"source": "memory",
|
||||
"snippet": "- 14 阶段 4 科目全部重写,目标文档: `W5Vjw2fLiiCqfck0Mfzc0xkrnte` - L2 阶段1-2 阅读/写作从\"无\"补为实际技能点(刘彦江确认\"L2 阶段1-2 阅读和写作都是有题型的\") - L1 阶段1 阅读/写作也从\"无\"补为实际技能点 - 0 个\"无\",全量覆盖 - 生成脚本: `tmp/build_skill_points.py` ## 生产覆盖范围修正 [刘彦江] - L1 生产到 **U16**(非 U33) - L2 生产到 **U29**(非 U16) - 已同步更新 `business_knowledge/单元挑战全貌.md` ## 单元挑战全貌文档 [刘彦江] - 创建 `business_knowledge/单元挑战全貌.md` - 覆盖九大板块:业务定位、阶段划分、题型体系(18种)、能力标签(45个)、生产流程(ID规则/标准/写入陷阱)、审校体系(7+4项检查)、生产覆盖现状、模块关联、快速链接 ## L1/L2 难度等级映射 [刘彦江] ✅已确认 - L1-A: Starters入门+基础 (U1-U16) | L1-B: Starters达标 (U17-U24) | L1-C: Movers入门+基础 (U25-U40) | L1-D: Movers达标 (U41-U48) - L2-A: Flyers入门+基础 (U1-U12) | L2-B: Flyers达标 (U13-U18) | L2-C: KET入门+基础 (U19-U30) | L2-D: KET强化+高位+达标 (U31-U48) - 已写入",
|
||||
"recallCount": 3,
|
||||
"recallCount": 4,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 3,
|
||||
"totalScore": 4,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-05-29T02:33:30.526Z",
|
||||
"lastRecalledAt": "2026-06-08T02:24:43.647Z",
|
||||
"lastRecalledAt": "2026-06-10T02:20:22.635Z",
|
||||
"queryHashes": [
|
||||
"4aa0ef719160",
|
||||
"20f6c2d072df",
|
||||
"068db47fdc05"
|
||||
"068db47fdc05",
|
||||
"6568231ab2d7"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-05-29",
|
||||
"2026-06-08"
|
||||
"2026-06-08",
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"阶段1-2",
|
||||
@ -2854,21 +2888,23 @@
|
||||
"endLine": 137,
|
||||
"source": "memory",
|
||||
"snippet": "- 生成脚本: `tmp/build_skill_points.py` ## 生产覆盖范围修正 [刘彦江] - L1 生产到 **U16**(非 U33) - L2 生产到 **U29**(非 U16) - 已同步更新 `business_knowledge/单元挑战全貌.md` ## 单元挑战全貌文档 [刘彦江] - 创建 `business_knowledge/单元挑战全貌.md` - 覆盖九大板块:业务定位、阶段划分、题型体系(18种)、能力标签(45个)、生产流程(ID规则/标准/写入陷阱)、审校体系(7+4项检查)、生产覆盖现状、模块关联、快速链接 ## L1/L2 难度等级映射 [刘彦江] ✅已确认 - L1-A: Starters入门+基础 (U1-U16) | L1-B: Starters达标 (U17-U24) | L1-C: Movers入门+基础 (U25-U40) | L1-D: Movers达标 (U41-U48) - L2-A: Flyers入门+基础 (U1-U12) | L2-B: Flyers达标 (U13-U18) | L2-C: KET入门+基础 (U19-U30) | L2-D: KET强化+高位+达标 (U31-U48) - 已写入 `business_knowledge/单元挑战全貌.md` §5.3 # 2026-05-25 工作日志 ## 组件配置 pipeline:单独重试 cId=1217214 - [童瑶] 请求单独重试 pipeline 中的失败组件 cId=1217214(听力拖拽 / core_listenin",
|
||||
"recallCount": 3,
|
||||
"recallCount": 4,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 3,
|
||||
"totalScore": 4,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-05-29T02:33:30.526Z",
|
||||
"lastRecalledAt": "2026-06-08T02:24:43.647Z",
|
||||
"lastRecalledAt": "2026-06-10T02:20:22.635Z",
|
||||
"queryHashes": [
|
||||
"4aa0ef719160",
|
||||
"20f6c2d072df",
|
||||
"068db47fdc05"
|
||||
"068db47fdc05",
|
||||
"6568231ab2d7"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-05-29",
|
||||
"2026-06-08"
|
||||
"2026-06-08",
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"tmp/build-skill-points.py",
|
||||
@ -2888,22 +2924,27 @@
|
||||
"endLine": 66,
|
||||
"source": "memory",
|
||||
"snippet": "8. 句型合规检测 - 接入方式:`<script src=\"l1_pedagogy_rules.js\"></script>` + 调用 `PedagogyRules.validate(summary, level)` - 数据源:L1 词库 147 词(过滤 enabled=true)、L2 词库 52 词、L1 句型 8 个、L2 句型(从 437MB bitable 导出中提取唯一结构) - 技术注意:L2_pattern_list.json 体积 437MB(1,082,450 条记录),直接嵌入前端不可行,已提取唯一句型结构后嵌入 - 所有 6 个测试用例通过 - 用户后续想尝试其他对接方式(API 模式 / 飞书 Bot 联动 / CI 集成)",
|
||||
"recallCount": 3,
|
||||
"recallCount": 7,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 3,
|
||||
"totalScore": 7,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-05-29T02:33:30.526Z",
|
||||
"lastRecalledAt": "2026-06-02T01:49:17.841Z",
|
||||
"lastRecalledAt": "2026-06-10T02:20:40.073Z",
|
||||
"queryHashes": [
|
||||
"4aa0ef719160",
|
||||
"e30c130b9d1d",
|
||||
"7e6aa000abdb"
|
||||
"7e6aa000abdb",
|
||||
"094bfb865b29",
|
||||
"6568231ab2d7",
|
||||
"3ac726b21876",
|
||||
"867f7264cd0e"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-05-29",
|
||||
"2026-06-01",
|
||||
"2026-06-02"
|
||||
"2026-06-02",
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"l1-pedagogy-rules.js",
|
||||
@ -2923,18 +2964,22 @@
|
||||
"endLine": 14,
|
||||
"source": "memory",
|
||||
"snippet": "## [梁晨] L1 Pedagogy Rules v4.0.0 交付 - 在 v3 基础上新增 5 个校验维度(来自 16 个教研 skill 规则提取): 6. 组件合规性(12 种题型规则,来自 11 个 dialogue/info config skills) 7. 字段完整性(7 项自动检查,来自 audit_l1_config) 8. 掌握度预测(W_i×M_i 加权公式,来自 knowledge-mastery-calculator) 9. 格式规范(标题/Markdown/标点/英式拼写/价值观,来自全量文本规范) 10. 语法检测(三单/主谓一致/双重否定,来自 audit_l1_config) - 输出:`output/l1_pedagogy_rules_v4.js`(59KB) - 数据:L1 147 词、L2 52 词、L1 8 句型、L2 1 句型、89 组英式拼写映射、12 种题型规则 - 已通过飞书 Bot 发送给梁晨 - API 兼容 v3:不加 options 参数即为原行为;加 component/componentExposures 启用新维度 - 能力边界:内容质量诊断(第一层筛选),不是全链路归因(看不到 UX/服务端/学生侧因素)",
|
||||
"recallCount": 1,
|
||||
"recallCount": 4,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 1,
|
||||
"totalScore": 4,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-06-02T01:49:17.841Z",
|
||||
"lastRecalledAt": "2026-06-02T01:49:17.841Z",
|
||||
"lastRecalledAt": "2026-06-10T02:20:40.073Z",
|
||||
"queryHashes": [
|
||||
"7e6aa000abdb"
|
||||
"7e6aa000abdb",
|
||||
"094bfb865b29",
|
||||
"3ac726b21876",
|
||||
"867f7264cd0e"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-06-02"
|
||||
"2026-06-02",
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"v4.0.0",
|
||||
@ -2954,18 +2999,22 @@
|
||||
"endLine": 49,
|
||||
"source": "memory",
|
||||
"snippet": "- 答案设为[2](英语的),与申报 adj. 英文的不符,应为[0] - 🟡 rubber (1218116):释义题例句\"an eraser made of rubber\"解释的是橡胶材料,非橡皮擦工具 - 🟡 Chinese(n.) (1218113):例句\"Chinese food\"中 Chinese 是形容词非名词,与题目义项\"中文\"不符 - 🟢 fun (1218119):解析末尾多余一个 `\"` - 🟢 eraser (1218111):`\"an eraser表示\"` 缺少空格 ## 武钰涵 — 听力-P1-图片选择题生产 - 题目集合 ID: 121601,难度 B级(L1 第3-4阶段,Starters 3) - 知识点验证:10个词中仅 run(v.) 在 L1 词库,feet(foot 的复数)可视为已有,其余 8 个(bus, taxi, trousers, shorts, winter, snow, cold, bee)不在 L1/L2 词库 - 用户指示直接生产,已按 SKILL 规范生成 2 个题组(各5题),含听力文本、图片描述、正确答案、能力标签 - 已按 bitable 配置格式输出完整 jsonData + 题目完整配置 + 图片描述 - B级规则:听力句子 5-8 词(均 7 词),每组 3 张同类物品不同属性图片 - 能力标签:显性事实理解|关键词识别 ×2 + 基础语境理解|场景/物品/动作识别 ## 梁辰(user_id: ou_28f02dcada1193913cfbb6310f8daf07)— HTML 诊断页面",
|
||||
"recallCount": 1,
|
||||
"recallCount": 4,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 1,
|
||||
"totalScore": 4,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-06-02T01:49:17.841Z",
|
||||
"lastRecalledAt": "2026-06-02T01:49:17.841Z",
|
||||
"lastRecalledAt": "2026-06-10T02:20:40.073Z",
|
||||
"queryHashes": [
|
||||
"7e6aa000abdb"
|
||||
"7e6aa000abdb",
|
||||
"094bfb865b29",
|
||||
"3ac726b21876",
|
||||
"867f7264cd0e"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-06-02"
|
||||
"2026-06-02",
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"听力-p1-图片选择题生产",
|
||||
@ -3239,19 +3288,21 @@
|
||||
"endLine": 810,
|
||||
"source": "memory",
|
||||
"snippet": "--- ## [李应瑛] L1-S2-U17-L5 笨蛋坏蛋?英文生产(2026-05-18 21:15) ### 背景 李应瑛发送知识库文档 `U1zEwHZaaie07TkjmOOchurgnIh`(L1-S2-U17-L5 笨蛋坏蛋?),要求\"英文生产\"。 ### 文档结构(与L3/L4不同) - Wiki token: `U1zEwHZaaie07TkjmOOchurgnIh` - Spreadsheet token: `DCcKsLbrmhfXgrtB7N2c9GA4ntf` - Script sheet: `wMQVyV`(186行×9列) - Knowledge points sheet: `DCcKsLbrmhfXgrtB7N2c9GA4ntf_NtIcXt` - 列结构:A=类型, D=剧情描述, E=角色名, F=编剧台词(English已填好), **G=组件配置** - 知识点:point, talk, understand, a lot of + `talk to...` / `I can/can't understand...` ### 交互模式差异 - L5 文档 B列/C列 为空,无详细组件类型标签(仅 A=互动/核心互动-口语) - 编剧台词F列已全部填写(英文) - 互动行的 User 台词含红色标注知识点词 ### 完成事项 - 24个互动行全部生成G列配置(组件类型推断:听力挖空、朗读台词、口语表达) - 写入方式:同上 Sheets v2 API - 24/24 全部回读验证通过 ### 脚本 `scripts/write_",
|
||||
"recallCount": 2,
|
||||
"recallCount": 3,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 2,
|
||||
"totalScore": 3,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-06-09T07:21:33.704Z",
|
||||
"lastRecalledAt": "2026-06-09T07:22:27.500Z",
|
||||
"lastRecalledAt": "2026-06-10T02:20:12.701Z",
|
||||
"queryHashes": [
|
||||
"ff0d0637f255",
|
||||
"f525b14a0c5b"
|
||||
"f525b14a0c5b",
|
||||
"9018e8896dcd"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-06-09"
|
||||
"2026-06-09",
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"l1-s2-u17-l5",
|
||||
@ -3271,19 +3322,24 @@
|
||||
"endLine": 187,
|
||||
"source": "memory",
|
||||
"snippet": "- **五大分类:** 📖阅读(2) / 🎧听力(3) / 🗣口语(4) / ✏️写作(5) / 未完成(1) - **通用字段提取:** ID/dataStatus/kpStatus/kpInfo/taskData 是所有题型共用的基础结构 #### 覆盖率 - 14 种题型已录入 ✅(1 种无数据:口语探讨) - 4 个一级板块:通用结构 / 题型专区 / 审校规则 / 扩展指南 - 每个题型:cType + bitable 定位 + JSON 字段表 + 结构特点 + 与同类题型的差异说明 #### 发现 - 写作互动和邮件组句 cType 相同(`core_writing_questionMakeSentence`),通过 textInfo 区分素材 - 口语快答/妙问 JSON 结构几乎相同,差异在 prompt 配置和对话样例内容 - 合作阅读和合作听力的核心差异:`textData.text[]` ↔ `textData.audio[]` - meaning 标签(合作阅读)为开放型自由文本,非受控词表 #### 产出文件 - `business_production/_shared/bitable-reader/SKILL.md` — 通用 bitable 读取技能(164行) - `business_knowledge/skills/core-content-json-standard/SKILL.md` — 全题型 JSON 标准 v2.0(393行) - `scripts/audit_core_reading_S0.py` — 合作阅读 S0",
|
||||
"recallCount": 2,
|
||||
"recallCount": 6,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 2,
|
||||
"totalScore": 6,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-06-09T08:37:12.232Z",
|
||||
"lastRecalledAt": "2026-06-09T08:37:27.121Z",
|
||||
"lastRecalledAt": "2026-06-10T03:52:28.181Z",
|
||||
"queryHashes": [
|
||||
"91bf4d50e5a2",
|
||||
"b8853a0aafcc"
|
||||
"b8853a0aafcc",
|
||||
"113e8be33943",
|
||||
"9573fdf60768",
|
||||
"70a3284bc0c5",
|
||||
"78420d02cc4d"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-06-09"
|
||||
"2026-06-09",
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"口语快答/妙问",
|
||||
@ -3303,19 +3359,23 @@
|
||||
"endLine": 236,
|
||||
"source": "memory",
|
||||
"snippet": "- **产出 Skill 2:** `business_knowledge/skills/core-content-json-standard/SKILL.md` v2.0 — 全题型 JSON 标准(393行) - **架构:** 通用字段在前(ID/kpInfo/taskData)+ 5大题型分类(📖阅读2 🎧听力3 🗣口语4 ✏️写作5)+ 审校规则 + 扩展指南 - **覆盖率:** 14/15 种题型(口语探讨 S0 无数据) - **产出脚本:** `scripts/audit_core_reading_S0.py` — 合作阅读 S0 审校 ## 经验教训 ### bitable 写入需严格流程管控(2026-05-12) - 批量更新 JSON:写入前完整提取 → 写入后逐字段 diff → 异常立即回滚 - 首次修复多题 JSON 导致 Q2 丢失 → 先单条试跑验证再批量 ### sentenceMeaningMeaning 引号规范(2026-05-12) - explanation 中 ASCII `\"` 与中文引号混用导致 JSON 解析失败 - 建议:生产侧统一用中文引号 `\"\"`(U+201C/D),或写入前做引号归一化 ### 写作互动 / 邮件组句 cType 相同(2026-05-12) - 两者 cType 均为 `core_writing_questionMakeSentence`,通过 textInfo.textList[].type 区分素材 ### 刘彦江 — 中互动全题型录入(18:00 ~ 18:25) ###",
|
||||
"recallCount": 2,
|
||||
"recallCount": 5,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 2,
|
||||
"totalScore": 5,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-06-09T08:37:12.232Z",
|
||||
"lastRecalledAt": "2026-06-09T08:37:27.121Z",
|
||||
"lastRecalledAt": "2026-06-10T03:52:28.181Z",
|
||||
"queryHashes": [
|
||||
"91bf4d50e5a2",
|
||||
"b8853a0aafcc"
|
||||
"b8853a0aafcc",
|
||||
"9573fdf60768",
|
||||
"70a3284bc0c5",
|
||||
"78420d02cc4d"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-06-09"
|
||||
"2026-06-09",
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"v2.0",
|
||||
@ -3335,19 +3395,24 @@
|
||||
"endLine": 254,
|
||||
"source": "memory",
|
||||
"snippet": "#### 发现 - **中互动结构高度统一:** 全部 27 类都用 `jsonData`(主配置)+ `kpInfo`(知识点绑定),没有核心互动那种多字段分散结构 - **6 大分类:** 🗨对话(7) / 📋信息(6) / 📦词汇(2) / 🖼图片选择(4) / 📝语法(3) / 🔧其他(5) - **对话类公共字段:** cType, cId, title, resourceMapping, preDialog, imgShowTimingList - 写作互动和邮件组句 cType 相同(`core_writing_questionMakeSentence`) #### 产出文件 - `skills/interactive-component-json/references/json_structure_guide.md` — 27 种中互动 jsonData 字段结构(8736 bytes) - `skills/interactive-component-json/references/component_registry.md` — 核心互动部分从🔲更新为完整注册表(含 cType+bitable_token) - 与 `business_knowledge/skills/core-content-json-standard/SKILL.md` 双向关联 #### 覆盖率 - 核心互动:15/15 ✅(口语探讨 S0 无数据已标注) - 中互动:27/27 ✅ - 关联文件:3 个(core-content-json-standard + com",
|
||||
"recallCount": 2,
|
||||
"recallCount": 6,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 2,
|
||||
"totalScore": 6,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-06-09T08:37:12.232Z",
|
||||
"lastRecalledAt": "2026-06-09T08:37:27.121Z",
|
||||
"lastRecalledAt": "2026-06-10T03:52:28.181Z",
|
||||
"queryHashes": [
|
||||
"91bf4d50e5a2",
|
||||
"b8853a0aafcc"
|
||||
"b8853a0aafcc",
|
||||
"9573fdf60768",
|
||||
"70a3284bc0c5",
|
||||
"0924e1755b1c",
|
||||
"78420d02cc4d"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-06-09"
|
||||
"2026-06-09",
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"bitable-token",
|
||||
@ -3359,6 +3424,322 @@
|
||||
"结构",
|
||||
"高度"
|
||||
]
|
||||
},
|
||||
"memory:memory/2026-05-25.md:49:64": {
|
||||
"key": "memory:memory/2026-05-25.md:49:64",
|
||||
"path": "memory/2026-05-25.md",
|
||||
"startLine": 49,
|
||||
"endLine": 64,
|
||||
"source": "memory",
|
||||
"snippet": "- [刘彦江] 要求将写作P1 021301~032901共16条ID的explanation简化 - 标准:先称呼→按写作要求匹配正文→最后署名,格式类似\"先称呼Dear Lucy,再按三个要求匹配正文:相册失踪对应...在哪丢的对应...请求帮忙找对应...最后署名\" - 已逐条输出15条解析(021301按样例略过),列表:021401, 021501, 021701, 021801, 021901, 022001, 022101, 022201, 022301, 022401, 032501, 032601, 032701, 032801, 032901 - 022101特殊:按故事逻辑排列(非写作要求匹配),因该题无编号要求而是按叙事顺序排列句子 ## L1/L2 能力图谱梳理 [刘彦江] ⏳待确认 - [刘彦江] 分享了wiki文档 https://makee-interactive.feishu.cn/wiki/TFB9wJm4IilkCekyFdzcc42on6d - 要求:梳理L1 6阶段+L2 8阶段听说读写tag类型和考点,在@刘彦江的位置输出方案 - 已输出四部分方案框架(见对话),用户尚未确认: 1. 各阶段听/说/读/写能力分布表格(汇总表 + 14阶段×4科目tag) 2. 单项目卡描述(≤100字,4条分别覆盖听/说/读/写) 3. 能力考察项(小标题≤12字,每条≤70字,总≤280字,以听力Movers为例) 4. 单能力项描述(≤210字,以\"单句信息点抓取\"为例) - 待用户确认格式和内容方向后,再写入文档 ## 能力",
|
||||
"recallCount": 3,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 3,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-06-10T02:19:54.974Z",
|
||||
"lastRecalledAt": "2026-06-10T02:20:12.701Z",
|
||||
"queryHashes": [
|
||||
"7de89d94cd21",
|
||||
"e679709051aa",
|
||||
"9018e8896dcd"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"l1/l2",
|
||||
"各阶段听/说/读/写能力分布表格",
|
||||
"4条分别覆盖听/说/读/写",
|
||||
"彦江",
|
||||
"要求",
|
||||
"写作",
|
||||
"explanation",
|
||||
"简化"
|
||||
]
|
||||
},
|
||||
"memory:memory/2026-05-25.md:225:243": {
|
||||
"key": "memory:memory/2026-05-25.md:225:243",
|
||||
"path": "memory/2026-05-25.md",
|
||||
"startLine": 225,
|
||||
"endLine": 243,
|
||||
"source": "memory",
|
||||
"snippet": "- 要求:梳理L1 6阶段+L2 8阶段听说读写tag类型和考点,在@刘彦江的位置输出方案 - 已输出四部分方案框架(见对话),用户尚未确认: 1. 各阶段听/说/读/写能力分布表格(汇总表 + 14阶段×4科目tag) 2. 单项目卡描述(≤100字,4条分别覆盖听/说/读/写) 3. 能力考察项(小标题≤12字,每条≤70字,总≤280字,以听力Movers为例) 4. 单能力项描述(≤210字,以\"单句信息点抓取\"为例) - 待用户确认格式和内容方向后,再写入文档 ## 能力图谱固定文案回填完成 [刘彦江] - 文档: https://makee-interactive.feishu.cn/wiki/W5Vjw2fLiiCqfck0Mfzc0xkrnte - 严格按照L1/L2阶段分配文档的\"阶段目标\"描述 - 回填内容: - L1: 阶段1听口 / 阶段2听口阅 / 阶段3-6听口阅写 - L2: 阶段1-8听口阅写 - 各阶段描述均对齐文档设定的阶段目标(如L1阶段1:基础字母识别关键词抓取, 阶段3:数字/时间细节抓取同义替换识别等) - 格式: 每阶段下听力/口语/阅读/写作各一段≤210字描述 ## 能力图谱考察项文档写入完成 [刘彦江] ✅已完成 - 文档: https://makee-interactive.feishu.cn/wiki/W5Vjw2fLiiCqfck0Mfzc0xkrnte (考察项描述目录) - 14 阶段 14 张表全部填充:L1 阶段1-6 + L2 阶段1-8",
|
||||
"recallCount": 3,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 3,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-06-10T02:19:54.974Z",
|
||||
"lastRecalledAt": "2026-06-10T02:20:12.701Z",
|
||||
"queryHashes": [
|
||||
"7de89d94cd21",
|
||||
"e679709051aa",
|
||||
"9018e8896dcd"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"各阶段听/说/读/写能力分布表格",
|
||||
"4条分别覆盖听/说/读/写",
|
||||
"严格按照l1/l2阶段分配文档的",
|
||||
"阶段3-6听口阅写",
|
||||
"阶段1-8听口阅写",
|
||||
"数字/时间细节抓取同义替换识别等",
|
||||
"每阶段下听力/口语/阅读/写作各一段",
|
||||
"阶段1-6"
|
||||
]
|
||||
},
|
||||
"memory:memory/2026-05-25.md:214:228": {
|
||||
"key": "memory:memory/2026-05-25.md:214:228",
|
||||
"path": "memory/2026-05-25.md",
|
||||
"startLine": 214,
|
||||
"endLine": 228,
|
||||
"source": "memory",
|
||||
"snippet": "- 替代方案:用飞书 Drive API `DELETE /open-apis/drive/v1/files/{doc_token}?type=docx` 删除文件(不归入回收站) - 验证:删除后再次查询 node → 131005 \"not found\",确认已移除 ## 写作P1 16条解析简化输出 [刘彦江] - [刘彦江] 要求将写作P1 021301~032901共16条ID的explanation简化 - 标准:先称呼→按写作要求匹配正文→最后署名,格式类似\"先称呼Dear Lucy,再按三个要求匹配正文:相册失踪对应...在哪丢的对应...请求帮忙找对应...最后署名\" - 已逐条输出15条解析(021301按样例略过),列表:021401, 021501, 021701, 021801, 021901, 022001, 022101, 022201, 022301, 022401, 032501, 032601, 032701, 032801, 032901 - 022101特殊:按故事逻辑排列(非写作要求匹配),因该题无编号要求而是按叙事顺序排列句子 ## L1/L2 能力图谱梳理 [刘彦江] ⏳待确认 - [刘彦江] 分享了wiki文档 https://makee-interactive.feishu.cn/wiki/TFB9wJm4IilkCekyFdzcc42on6d - 要求:梳理L1 6阶段+L2 8阶段听说读写tag类型和考点,在@刘彦江的位置输出方案 - 已输出四部分方案框架(见对话),用户尚未确认: 1. 各阶段听/说/读/写能力分布",
|
||||
"recallCount": 3,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 3,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-06-10T02:19:54.974Z",
|
||||
"lastRecalledAt": "2026-06-10T02:20:12.701Z",
|
||||
"queryHashes": [
|
||||
"7de89d94cd21",
|
||||
"e679709051aa",
|
||||
"9018e8896dcd"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"open-apis/drive/v1/files",
|
||||
"doc-token",
|
||||
"l1/l2",
|
||||
"各阶段听/说/读/写能力分布",
|
||||
"替代",
|
||||
"方案",
|
||||
"drive",
|
||||
"api"
|
||||
]
|
||||
},
|
||||
"memory:memory/2026-05-25.md:74:91": {
|
||||
"key": "memory:memory/2026-05-25.md:74:91",
|
||||
"path": "memory/2026-05-25.md",
|
||||
"startLine": 74,
|
||||
"endLine": 91,
|
||||
"source": "memory",
|
||||
"snippet": "- 14 阶段 14 张表全部填充:L1 阶段1-6 + L2 阶段1-8 - 考察项格式:考察项名称 + 描述,不标注题型来源(括号内Part编号等) - 表格格式:3列(单项 / 考察项 / 考察项描述),单项列使用rowspan合并 ### 生产数据 vs 设计文档的差异 - **设计文档不可信**:L1/L2 阶段分配文档(Jjd8wghbeidXt2kDFaPcU09wnzc / D9EFwVC9Gi9nCAk4heec2qYCnwe)与实际生产不一致 - 实际生产数据来源:生产文档「单元挑战旧题目解析待补充 ID 整理」(CS8Ww2XaSiFwhakQenycRU5ZnYf) - Part→题型映射来源于多维表格 (App Token: CMHSbUUjka3TrUsaxxEc297ongf) - 关键差异:L1阶段1实际有阅读(P7)和写作(P3),不是设计文档声称的「仅听力+口语」 - 生产数据覆盖范围有限:L1 仅到 ~U33 (032901),L2 仅到 ~U16 (121601) - 无生产数据的阶段(L1阶段5-6, L2阶段4-8)使用设计文档 + 题型递进规律推算 ### 飞书 lark-table 写入注意事项 - rowspan 在飞书 markdown 回写时会被自动剥离 - 表格写入后单项列会逐行重复显示而非合并单元格(飞书原生限制) - 写入前需 extract 原始文档的 S1 表格,再与生成的新表格拼接后 overwrite ### Part→题型映射速查(来自多维表格 CMHSbUUjka3TrUsaxxEc297ongf)",
|
||||
"recallCount": 1,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 1,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-06-10T02:20:22.635Z",
|
||||
"lastRecalledAt": "2026-06-10T02:20:22.635Z",
|
||||
"queryHashes": [
|
||||
"6568231ab2d7"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"阶段1-6",
|
||||
"阶段1-8",
|
||||
"l1/l2",
|
||||
"l1阶段5-6",
|
||||
"l2阶段4-8",
|
||||
"lark-table",
|
||||
"阶段",
|
||||
"全部"
|
||||
]
|
||||
},
|
||||
"memory:memory/2026-05-25.md:240:256": {
|
||||
"key": "memory:memory/2026-05-25.md:240:256",
|
||||
"path": "memory/2026-05-25.md",
|
||||
"startLine": 240,
|
||||
"endLine": 256,
|
||||
"source": "memory",
|
||||
"snippet": "- 格式: 每阶段下听力/口语/阅读/写作各一段≤210字描述 ## 能力图谱考察项文档写入完成 [刘彦江] ✅已完成 - 文档: https://makee-interactive.feishu.cn/wiki/W5Vjw2fLiiCqfck0Mfzc0xkrnte (考察项描述目录) - 14 阶段 14 张表全部填充:L1 阶段1-6 + L2 阶段1-8 - 考察项格式:考察项名称 + 描述,不标注题型来源(括号内Part编号等) - 表格格式:3列(单项 / 考察项 / 考察项描述),单项列使用rowspan合并 ### 生产数据 vs 设计文档的差异 - **设计文档不可信**:L1/L2 阶段分配文档(Jjd8wghbeidXt2kDFaPcU09wnzc / D9EFwVC9Gi9nCAk4heec2qYCnwe)与实际生产不一致 - 实际生产数据来源:生产文档「单元挑战旧题目解析待补充 ID 整理」(CS8Ww2XaSiFwhakQenycRU5ZnYf) - Part→题型映射来源于多维表格 (App Token: CMHSbUUjka3TrUsaxxEc297ongf) - 关键差异:L1阶段1实际有阅读(P7)和写作(P3),不是设计文档声称的「仅听力+口语」 - 生产数据覆盖范围有限:L1 仅到 ~U33 (032901),L2 仅到 ~U16 (121601) - 无生产数据的阶段(L1阶段5-6, L2阶段4-8)使用设计文档 + 题型递进规律推算 ### 飞书 lark-table 写入注意事项 - rowspan 在飞书 markdown",
|
||||
"recallCount": 1,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 1,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-06-10T02:20:22.635Z",
|
||||
"lastRecalledAt": "2026-06-10T02:20:22.635Z",
|
||||
"queryHashes": [
|
||||
"6568231ab2d7"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"每阶段下听力/口语/阅读/写作各一段",
|
||||
"阶段1-6",
|
||||
"阶段1-8",
|
||||
"l1/l2",
|
||||
"l1阶段5-6",
|
||||
"l2阶段4-8",
|
||||
"lark-table",
|
||||
"格式"
|
||||
]
|
||||
},
|
||||
"memory:memory/2026-05-26.md:218:226": {
|
||||
"key": "memory:memory/2026-05-26.md:218:226",
|
||||
"path": "memory/2026-05-26.md",
|
||||
"startLine": 218,
|
||||
"endLine": 226,
|
||||
"source": "memory",
|
||||
"snippet": "| 139 | 1219215 | 对话朗读 | 朗读job相关台词 | | 157 | 1219216 | 对话朗读 | 朗读句式相关台词 | | 169 | 1219217 | 对话表达 | 展示团队成就 | ### 技术备忘 - **lark-cli docs +fetch markdown** 可检测到内嵌 Sheet 标签(`<sheet token=\"...\"/>`),比 RAW content API 更可靠 - U19-L2 文档的RAW content未显示sheet标签,但lark-cli markdown输出中包含两个内嵌sheet - 组件生产(结构化文本)vs 组件配置-json(JSON管线)是两个不同流程,需根据用户指令区分",
|
||||
"recallCount": 1,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 1,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-06-10T02:20:27.209Z",
|
||||
"lastRecalledAt": "2026-06-10T02:20:27.209Z",
|
||||
"queryHashes": [
|
||||
"113e8be33943"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"lark-cli",
|
||||
"u19-l2",
|
||||
"但lark-cli",
|
||||
"组件配置-json",
|
||||
"对话",
|
||||
"朗读",
|
||||
"job",
|
||||
"相关"
|
||||
]
|
||||
},
|
||||
"memory:memory/2026-05-26.md:198:223": {
|
||||
"key": "memory:memory/2026-05-26.md:198:223",
|
||||
"path": "memory/2026-05-26.md",
|
||||
"startLine": 198,
|
||||
"endLine": 223,
|
||||
"source": "memory",
|
||||
"snippet": "- **Spreadsheet token:** `Mt4rsAj8ehtA1ztetACc0HGWnMb` | Sheet `wMQVyV` - **知识点:** astronaut / job / great / also / I have a/an... / We also need... - **17/17 全部写入 H 列 ✅** | Row | ID | 类型 | 任务标题 | |-----|-----|------|----------| | 14 | 1219201 | 图片多选 | 宇航员套装识别 | | 27 | 1219202 | 对话朗读 | 朗读job相关台词 | | 37 | 1219203 | 图片单选 | 识别宇航员服 | | 43 | 1219204 | 对话朗读 | 朗读also相关台词 | | 61 | 1219205 | 对话挖空 | 询问Dad的工作 | | 65 | 1219206 | 对话朗读 | 朗读job相关台词 | | 78 | 1219207 | 对话挖空 | User自豪地介绍自己 | | 83 | 1219208 | 对话朗读 | 朗读great相关台词 | | 91 | 1219209 | 对话组句 | User发现自己也有工作 | | 103 | 1219210 | 看图拼词 | 拼写任务卡片 | | 114 | 1219211 | 对话朗读 | 朗读句式相关台词 | | 118 | 1219212 | 对话组句 | 向爸妈展示计划 | | 123 | 1219213 | 对话组句 | 提议进行演习 | | 135",
|
||||
"recallCount": 1,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 1,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-06-10T02:20:27.209Z",
|
||||
"lastRecalledAt": "2026-06-10T02:20:27.209Z",
|
||||
"queryHashes": [
|
||||
"113e8be33943"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"a/an",
|
||||
"17/17",
|
||||
"spreadsheet",
|
||||
"token",
|
||||
"mt4rsaj8ehta1ztetacc0hgwnmb",
|
||||
"sheet",
|
||||
"wmqvyv",
|
||||
"知识"
|
||||
]
|
||||
},
|
||||
"memory:memory/2026-05-12.md:34:50": {
|
||||
"key": "memory:memory/2026-05-12.md:34:50",
|
||||
"path": "memory/2026-05-12.md",
|
||||
"startLine": 34,
|
||||
"endLine": 50,
|
||||
"source": "memory",
|
||||
"snippet": "- **问题:** 021301-021801 信息匹配题的图片描述缺少 `【Notice Type】` 标签,格式不符合参考规范 - **处理:** 1. 查询 bitable 获取6条记录当前图片描述(tblCgfYDnnqwLfgH) 2. 按每道题的上下文匹配对应的标识/通知类型标签(如 Show Poster、Wanted Notice、School Notice 等) 3. 批量更新6条记录的图片描述字段,全部10个 `【Type】` 标签验证通过 4. 脚本:`scripts/fix_matchInfo_0213_0218_desc.py` - **技能更新:** 将图片描述规范(格式要求、核心规则、参考示例、常用类型标签参考表)更新到 `business_production/单元挑战/skills/unit_challenge/questions/reading/reading_info_match/SKILL.md` - **规范要点:** - 每张图片 → `图片材料文本:\\n【Type】\\nActual text` - 图片必须是真实标识/通知(非标签式) - L2 B级及以上图片文字需为完整陈述句(3-5词+) ### 刘彦江 — L1 配置表审校 + 技能沉淀(11:50 ~ 12:10) - **数据源:** 飞书多维表格「互动知识点 - 句子」→「Level 1 配置表」(`Nq3Zb258aae7SRs2QfXcqsQYnxJ` / `tblTxGpf6GQ5c7DZ`) - **ID 编码规则:** 7位 = 前",
|
||||
"recallCount": 1,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 1,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-06-10T02:20:27.209Z",
|
||||
"lastRecalledAt": "2026-06-10T02:20:27.209Z",
|
||||
"queryHashes": [
|
||||
"113e8be33943"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"021301-021801",
|
||||
"按每道题的上下文匹配对应的标识/通知类型标签",
|
||||
"图片必须是真实标识/通知",
|
||||
"3-5词",
|
||||
"问题",
|
||||
"信息",
|
||||
"匹配",
|
||||
"图片"
|
||||
]
|
||||
},
|
||||
"memory:memory/2026-05-28.md:19:37": {
|
||||
"key": "memory:memory/2026-05-28.md:19:37",
|
||||
"path": "memory/2026-05-28.md",
|
||||
"startLine": 19,
|
||||
"endLine": 37,
|
||||
"source": "memory",
|
||||
"snippet": "- 用户提交第二批 20 个 L1 词汇知识点审校 - 校验结果:16个超纲(仅 read/ruler/write/pencil 4个在库) - 内容问题: - 🔴 10个词条格式不统一(``` 包裹 + 中英文无空格):read, line, Chinese(adj.), perfect, eraser, Chinese(n.), write, rubber, playground, English(adj.) - 🔴 Chinese(n.) 例句语法错误:\"My neighbour is Chinese who cooks\" → 应改为 \"My neighbour is Chinese and cooks\" - 🔴 China 例句冗余:\"Chinese food from China\" - 🔴 read 释义与词库不一致:申报\"阅读,读懂\",词库仅\"阅读\" - 🟡 eraser/rubber 双重申报,内容几乎一致,建议二选一 ## 武钰涵 — 词汇巩固题审校(批次1: 20词×3题=60题) - 仅发现1个错误:home (1217116) 释义题答案设为[2](家庭),应为[0](回家,在家),与用户申报的词性 adv. 一致 - 其余59题通过 ## 武钰涵 — 词汇巩固题审校(批次2: 20词×3题=60题) - 🔴 English (1218118): - 释义题解析为 LLM 兜底拒答占位文本:\"请你提供具体的题目和对应正确答案内容...\" - 答案设为[2](英语的),与申报 adj. 英文的不符,应为[0] -",
|
||||
"recallCount": 1,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 1,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-06-10T03:52:13.443Z",
|
||||
"lastRecalledAt": "2026-06-10T03:52:13.443Z",
|
||||
"queryHashes": [
|
||||
"92034bab1861"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"read/ruler/write/pencil",
|
||||
"eraser/rubber",
|
||||
"用户",
|
||||
"提交",
|
||||
"第二",
|
||||
"词汇",
|
||||
"知识",
|
||||
"结果"
|
||||
]
|
||||
},
|
||||
"memory:memory/2026-06-08.md:17:27": {
|
||||
"key": "memory:memory/2026-06-08.md:17:27",
|
||||
"path": "memory/2026-06-08.md",
|
||||
"startLine": 17,
|
||||
"endLine": 27,
|
||||
"source": "memory",
|
||||
"snippet": "- 图片时机根据有实际内容(非「无」)的 section 动态列出(如「互动内容」「情境引入 互动内容 互动反馈」) - 图片时机和音频载体禁止同时存在 ### 已更新文件 - `business_production/组件生产/skills/component-design/SKILL.md` → v1.3.0 - `business_production/组件生产/skills/script-component-production/SKILL.md` → v1.2.0 ### 已执行操作 - L1-S2-U21-L2 运输小队:全量修正(辅助信息、资源配置、互动反馈、情境引入/后置对话去重、配图资源配置) - L1-S2-U21-L1 寻人启事:组件配置流水线 16/16 成功",
|
||||
"recallCount": 1,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 1,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-06-10T03:52:28.180Z",
|
||||
"lastRecalledAt": "2026-06-10T03:52:28.180Z",
|
||||
"queryHashes": [
|
||||
"0924e1755b1c"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-06-10"
|
||||
],
|
||||
"conceptTags": [
|
||||
"v1.3.0",
|
||||
"v1.2.0",
|
||||
"l1-s2-u21-l2",
|
||||
"情境引入/后置对话去重",
|
||||
"l1-s2-u21-l1",
|
||||
"16/16",
|
||||
"图片",
|
||||
"时机"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
24
memory/2026-06-10.md
Normal file
24
memory/2026-06-10.md
Normal file
@ -0,0 +1,24 @@
|
||||
# 2026-06-10 工作日志
|
||||
|
||||
## 规则更新:文本输出格式规范
|
||||
|
||||
[刘彦江确认] 以下三条规则已同步更新到 MEMORY.md、unit_challenge_core、audit_unit_challenge、unit_challenge_master、interactive-component-json、单元挑战全貌.md:
|
||||
|
||||
### 1. 中英文混排空格规范(新增)
|
||||
- 中文与英文/数字之间加半角空格(如"汇报 Jay 不配合"、"Tom 说 hello")
|
||||
- 纯中文或纯英文内容不加额外空格
|
||||
|
||||
### 2. 标点符号规范(补充)
|
||||
- 英文冒号必须用半角 `:`,不得用全角 `:`
|
||||
- 中文内容使用全角标点(,。!?:)
|
||||
- 英文内容使用半角标点(. , ! ? :)
|
||||
|
||||
### 3. 英式拼写优先(已有,无变更)
|
||||
|
||||
## 待处理问题
|
||||
|
||||
[王璐辰反馈] 以下问题待提供文档链接后修复:
|
||||
- 组句选项内容错误(具体记录待定位)
|
||||
- 对话挖空做成了对话组句(题型错配)
|
||||
- 对话选择/选读句子后面需加"(音频)"标记
|
||||
- 反馈中角色名冒号应为英文冒号
|
||||
Loading…
Reference in New Issue
Block a user