From 60dcd4edf1137a6d26dd6d783e12d47f2f777846 Mon Sep 17 00:00:00 2001 From: ai_member_only Date: Wed, 24 Jun 2026 08:10:01 +0800 Subject: [PATCH] auto backup: 2026-06-24 08:10:01 --- AGENTS.md | 2 + USER.md | 3 +- .../L2/L2 剧本教研规范 .md | 110 + .../_shared/feishu-embedded-sheet/SKILL.md | 116 +- .../_shared/l2-script-review/SKILL.md | 298 + .../db/components.db | Bin 10072064 -> 10113024 bytes ...20-L5 足球接力赛_20260623_172548.html | 5397 +++++++++++++++++ .../kids-english-script-production/SKILL.md | 14 +- memory/.dreams/events.jsonl | 8 + memory/.dreams/short-term-recall.json | 124 +- memory/2026-06-23-1639.md | 87 + scripts/knowledge_coverage_analyzer.py | 447 ++ 12 files changed, 6535 insertions(+), 71 deletions(-) create mode 100644 business_knowledge/L2/L2 剧本教研规范 .md create mode 100644 business_production/_shared/l2-script-review/SKILL.md create mode 100644 business_production/组件配置/interactive-component-json/outputs/L1-S2-U20-L5 足球接力赛_20260623_172548.html create mode 100644 memory/2026-06-23-1639.md create mode 100644 scripts/knowledge_coverage_analyzer.py diff --git a/AGENTS.md b/AGENTS.md index a1e7560..c840ef8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -192,6 +192,7 @@ Skills 按四层架构组织: | 身份识别 | `lark-identify-sender` | `./skills/lark-identify-sender/SKILL.md` | — | | 多维表格结构读取 | `bitable-reader` | `./business_production/_shared/bitable-reader/SKILL.md` | Bot | | L1配置审校 | `audit_l1_config` | `./business_production/_shared/audit_l1_config/SKILL.md` | — | +| L2剧本审校 | `l2-script-review` | `./business_production/_shared/l2-script-review/SKILL.md` | — | | 知识点掌握度计算 | `knowledge-mastery-calculator` | `./business_production/_shared/knowledge-mastery-calculator/SKILL.md` | — | ### 教研资源速查(业务知识库) @@ -232,6 +233,7 @@ Skills 按四层架构组织: | `/英文台词`、`英文台词生产` | `kids-english-script-production` | `business_production/英文台词/skills/kids-english-script-production/SKILL.md` | | 飞书文档表格读写(通用I/O层) | `feishu-doc-io` | `business_production/英文台词/skills/feishu-table-translate-fill/SKILL.md` | | `剧本复核`、`/剧本复核` | `script-post-check` | `business_production/英文台词/skills/script-post-check/SKILL.md` | +| `L2审校`、`剧本审校`、`L2剧本审校` | `l2-script-review` | `business_production/_shared/l2-script-review/SKILL.md` | > **示例:** 用户发来飞书 wiki 链接说「英文台词生产」→ 调用 `kids-english-script-production`,用 `--feishu-url` 模式读 F 列编剧台词 → 英语思维重构 → 写回 G 列 > **示例:** 用户说「剧本复核 <链接>」→ 调用 `script-post-check`,对 F 列执行长句拆分 + 标点检查等代码规则复核 diff --git a/USER.md b/USER.md index 1286f86..9da8885 100644 --- a/USER.md +++ b/USER.md @@ -37,8 +37,7 @@ | 姓名 | 飞书 user_id | |------|-------------| -| (姓名) | `xxxx` | -| (姓名) | `xxxx` | +| 张幸莹 | `4535af71` | ### 第二级:受限权限用户 diff --git a/business_knowledge/L2/L2 剧本教研规范 .md b/business_knowledge/L2/L2 剧本教研规范 .md new file mode 100644 index 0000000..5dc9fb7 --- /dev/null +++ b/business_knowledge/L2/L2 剧本教研规范 .md @@ -0,0 +1,110 @@ +# L2 剧本教研规范 + +### **台词字数** + +L2 每课台词范围:**1500\-2000 个中文字** + +重剧情关卡:不超过**2200 个中文字** + +如果超过 2300 字,学生在 20\-25 分钟体验中会明显变成“听故事为主”,互动和练习空间会被压缩。 + + + +> 参考依据:Cambridge A2 Key / KET Listening 是 **30 分钟、5 个部分、25 题**,要求学生能理解“语速较慢”的口语材料;Speaking 是 **8\-10 分钟**,重点是回答和提问简单问题。官方格式见 [Cambridge A2 Key exam format](https://www.cambridgeenglish.org/exams-and-tests/qualifications/key/format/)。 +> +> KET Listening 30 分钟对应 25 题,约等于 **1\.2 分钟/题**。L2 一节课 22\-26 个互动,互动密度已经接近 KET Listening,但 L2 是教学产品,不是纯测试,所以需要更多停顿和反馈。 +> +> 因此,真正能承载剧情对白的空间大约是 **8\-10 分钟有效听读量**。按 A2/KET“较慢、清晰”的语言输入估算,英文台词约 **1000\-1300 词**。换成中文,约等于**1500\-2000 个中文。** +> +> + + + +单句词数建议 + +一般对白: 8\-14 + +互动句子:6\-12 + +阅读理解句子:10\-20 + +听力句子:6\-12 + + + +### 台词难度 + +1\.语言准确,**语法正确**,符合英语**母语表达习惯**,符合上下文逻辑; +2\.所有单词**英式拼写**; + +3\.**大小写和标点**:符合英式英语正式书面文本使用标准; +4\.**词句难度**剑桥A1\-A2水平,不要超过A2 + +### **互动规则** + +L2 每课知识点为: + +- 单词 6 个; + +- 句型 3 个; + +- 每个知识点 2\-3 次互动练习; + +- 总互动量 **22\-26 个(包含核心互动)**。 + +- 核心互动: S3/S4\-1个lesson 2个核心互动 读3: 说3: 听2 写2 + + + +### 互动选择参考 + +#### 中互动 + +物品互动 + +图片单选 + +图片多选 + +图片有序 + +对话朗读 + +对话挖空 + +对话组句 + +对话表达 + +对话选读 + +对话选择 + +信息拼词 + +信息补词 + +信息组句 + +信息填词 + +信息填句 + +#### 核心互动 + + + + + + + + + + + + + + + + + diff --git a/business_production/_shared/feishu-embedded-sheet/SKILL.md b/business_production/_shared/feishu-embedded-sheet/SKILL.md index 9644f8d..bb0dddd 100644 --- a/business_production/_shared/feishu-embedded-sheet/SKILL.md +++ b/business_production/_shared/feishu-embedded-sheet/SKILL.md @@ -132,7 +132,54 @@ curl -s -X GET \ ### 第四步:写入数据 -#### 写入/更新指定行 +#### ⚠️ 步骤 4.0:行号连续性强制校验(写入前必须执行,不可跳过) + +**问题:** 飞书 Sheets API 的 range 写入按连续区域覆盖。如果 range 指定 `F4:F67`,API 会把数据依次写入 Row 4, 5, 6, ..., 67,**不管这些行是否对应正确的数据行**。 + +**典型事故:** 剧本表格中,E 列有角色名的行号不连续(Row 4 有台词、Row 5 是剧情描述空行、Row 6 又有台词),如果按连续 range 批量写入,Row 6 的英文台词会写到 Row 5 上,造成全列偏移。 + +**强制规则(不可跳过):** + +```python +def validate_and_write(spreadsheet_token, sheet_id, column_letter, data: dict, token): + """ + 写入前强制校验行号连续性,不连续时自动切换逐行写入。 + + Args: + data: {行号: "内容"} 字典,如 {118: "They are like kids.", 120: "Enough!", ...} + """ + rows = sorted(data.keys()) + + # 检查连续性 + is_continuous = all(rows[i+1] - rows[i] == 1 for i in range(len(rows)-1)) + + if is_continuous: + # ✅ 行号连续 → 批量 range 写入(高效) + values = [[data[r]] for r in rows] + range_str = f"{sheet_id}!{column_letter}{rows[0]}:{column_letter}{rows[-1]}" + write_range(spreadsheet_token, range_str, values, token) + print(f"✅ 批量写入: {range_str} ({len(rows)} 行,行号连续)") + else: + # ⚠️ 行号不连续 → 必须逐行写入(安全) + print(f"⚠️ 行号不连续,切换逐行写入(共 {len(rows)} 行)") + gaps = [rows[i+1] - rows[i] for i in range(len(rows)-1) if rows[i+1] - rows[i] > 1] + print(f" 跳空位置: {[(rows[i], rows[i+1]) for i in range(len(rows)-1) if rows[i+1] - rows[i] > 1]}") + + for row in rows: + range_str = f"{sheet_id}!{column_letter}{row}:{column_letter}{row}" + write_range(spreadsheet_token, range_str, [[data[row]]], token) + time.sleep(0.15) # 逐行写入间隔,避免频率限制 + + # 写入后立即执行 E-F 对齐校验(步骤 4.3) + verify_ef_alignment(spreadsheet_token, sheet_id, rows, token) +``` + +**禁止行为:** +- ❌ 直接构造连续 range(如 `F118:F142`)而不检查行号是否真的连续 +- ❌ 假设行号连续、跳过校验 +- ❌ 写入后不回读验证 + +#### 步骤 4.1:写入/更新指定行 ```bash curl -s -X PUT \ @@ -149,9 +196,10 @@ curl -s -X PUT \ }' ``` -#### 批量写入多行 +#### 步骤 4.2:批量写入多行(仅行号连续时使用) ```bash +# ⚠️ 仅当行号连续时可用!写入前必须先执行步骤 4.0 校验 curl -s -X PUT \ "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/${SPREADSHEET_TOKEN}/values" \ -H "Authorization: Bearer $TOKEN" \ @@ -168,6 +216,45 @@ curl -s -X PUT \ }' ``` +#### 步骤 4.3:写入后 E-F 对齐验证(强制执行) + +写入完成后,必须回读 E 列和 F 列,逐行验证对齐: + +```python +def verify_ef_alignment(spreadsheet_token, sheet_id, written_rows, token): + """ + 写入后验证:E 列有角色名的行,F 列必须有对应台词; + E 列为空的行(剧情描述行),F 列必须为空。 + """ + min_row = min(written_rows) + max_row = max(written_rows) + + # 回读 E 列和 F 列 + range_str = f"{sheet_id}!E{min_row}:F{max_row}" + values = read_range(spreadsheet_token, range_str, token) + + errors = [] + for i, row_data in enumerate(values): + actual_row = min_row + i + e_val = row_data[0] if len(row_data) > 0 else None # E列:角色名 + f_val = row_data[1] if len(row_data) > 1 else None # F列:英文台词 + + if e_val and not f_val: + # E 列有角色名但 F 列为空 → 台词缺失 + errors.append(f"行{actual_row}: E列有角色[{e_val}]但F列为空,台词缺失") + elif not e_val and f_val: + # E 列为空但 F 列有内容 → 位移!台词写到了剧情描述行 + errors.append(f"行{actual_row}: E列为空但F列有内容[{f_val[:30]}...],台词位移到非台词行!") + + if errors: + print("❌ E-F 对齐校验失败:") + for e in errors: + print(f" {e}") + raise RuntimeError("写入后对齐校验失败,数据可能错位,请检查并修复") + else: + print(f"✅ E-F 对齐校验通过({len(written_rows)} 行)") +``` + #### 更新指定单元格 ```bash @@ -188,7 +275,7 @@ curl -s -X PUT \ 写入空字符串 `""` 即可清空单元格内容。 -### 第五步:写入后验证 +### 第五步:写入后回读验证 **必须回读验证**,确保写入内容与预期一致: @@ -208,30 +295,7 @@ curl -s -X GET \ 6. **数据类型**:写入时,数字直接用 number 类型,文本用 string,空值用 null 7. **换行符**:需要在单元格内换行时,在字符串中使用 `\n` -### ⚠️ 批量写入前必须验证行号连续性(强制执行) -**问题:** 飞书 Sheets API 的 range 写入是按连续区域覆盖的。如果 range 指定 `F4:F67`,API 会把数据依次写入 Row 4, 5, 6, ..., 67,**不管这些行是否对应正确的数据行**。 - -**场景:** 剧本表格中,E 列有内容的行号不连续(Row 4 有台词、Row 5 是剧情描述空行、Row 6 又有台词),如果按连续 range 批量写入,会导致 Row 6 的英文台词写到 Row 5 上,造成全列偏移。 - -**强制规则:** -1. 写入前,先统计目标行号列表,检查是否连续(`rows[i+1] - rows[i] == 1`) -2. **行号连续** → 可以用 range 批量写入(如 `F4:F67`) -3. **行号不连续** → 必须逐行写入(每个行号单独一个 range,如 `F4:F4`, `F6:F6`, ...),或先清空整列再逐行写入 -4. 写入后必须抽样验证 E/F 列行号对齐(至少抽查前 5 行、中间 5 行、末尾 5 行) - -```python -# 示例:检查行号连续性 -rows = sorted(data.keys()) -is_continuous = all(rows[i+1] - rows[i] == 1 for i in range(len(rows)-1)) -if is_continuous: - # 安全:批量 range 写入 - write_range(f"F{rows[0]}:F{rows[-1]}", values) -else: - # 不安全:逐行写入 - for row in rows: - write_range(f"F{row}:F{row}", [data[row]]) -``` ## 读取后错行/乱行校验(强制执行) diff --git a/business_production/_shared/l2-script-review/SKILL.md b/business_production/_shared/l2-script-review/SKILL.md new file mode 100644 index 0000000..fdfd182 --- /dev/null +++ b/business_production/_shared/l2-script-review/SKILL.md @@ -0,0 +1,298 @@ +--- +name: l2-script-review +version: 1.0.0 +description: "L2剧本教研审校技能。对L2级别剧本执行9维度逐项审校,输出结构化审校报告。触发方式:消息包含'L2审校'或'剧本审校'或'L2剧本审校'。" +--- + +# L2 剧本教研审校(l2-script-review) + +## 定位 + +L2 剧本的**全维度教研审校**。基于 `L2 剧本教研规范` 对剧本执行 9 个维度的逐项检查,输出结构化审校报告。审校结果需经人工确认后再执行修改。 + +## 触发词 + +| 触发词 | 效果 | +|--------|------| +| `L2审校` + 飞书链接 | 对指定文档执行全部 9 维度审校 | +| `剧本审校` + 飞书链接 | 同上 | +| `L2剧本审校` + 飞书链接 | 同上 | + +## 审校流程(9 维度) + +### 一、台词字数 + +**规范来源:** `business_knowledge/L2/L2 剧本教研规范 .md` + +| 指标 | 规范值 | 重剧情上限 | 超标阈值 | +|------|--------|-----------|----------| +| 中文台词字数 | 1500–2000 字 | ≤2200 字 | >2300 字 | +| 英文台词词数 | 1000–1300 词 | — | — | + +**检查方法:** +1. 统计剧本表中「中文对白」列的总中文字数 +2. 统计「翻译」列的总英文词数 +3. 与规范值对比,标注超标幅度 + +**单句词数检查(逐行):** + +| 场景 | 建议范围 | 上限 | +|------|----------|------| +| 一般对白 | 8–14 词 | 18 词 | +| 互动句子 | 6–12 词 | 15 词 | +| 阅读理解句子 | 10–20 词 | 22 词 | +| 听力句子 | 6–12 词 | 15 词 | + +### 二、互动量 + +**规范来源:** `business_knowledge/L2/L2 剧本教研规范 .md` + +| 指标 | 规范值 | +|------|--------| +| 总互动量 | 22–26 个(含核心互动) | +| 核心互动数 | 2 个/lesson(S3/S4) | + +**检查方法:** +1. 统计剧本表中所有互动行(非 TL 行) +2. 统计核心互动数量 +3. 与规范值对比 + +### 三、知识点覆盖 + +**规范来源:** `business_knowledge/L2/L2 剧本教研规范 .md` + +| 指标 | 规范值 | +|------|--------| +| 单词数 | 6 个 | +| 句型数 | 3 个 | +| 每个知识点互动次数 | 2–3 次 | + +**检查方法:** +1. 从教研知识区提取单词和句型列表 +2. 在剧本表中统计每个知识点的互动出现次数 +3. 标注超标(>3 次)或不足(<2 次)的知识点 + +**词库校验:** +- 单词必须在 `business_knowledge/L2_word_list.json` 范围内 +- 句型必须在 `business_knowledge/L2_pattern_list.json` 范围内 + +### 四、核心互动 + +**规范来源:** `business_knowledge/L2/L2 剧本教研规范 .md` + +| 指标 | 规范值 | +|------|--------| +| 每 lesson 核心互动数 | 2 个 | +| 全 Unit 类型比例 | 读3 : 说3 : 听2 : 写2 | + +**检查方法:** +1. 从教研知识区提取核心互动列表 +2. 检查每 lesson 是否超过 2 个核心互动 +3. 统计全 Unit 核心互动类型分布(读/说/听/写) +4. 与规范比例对比,标注偏差 + +**核心互动类型映射:** +- 阅读理解 → 读 +- 任务对话 / 口语妙问 / 口语独白 → 说 +- 合作听力 → 听 +- 邮件撰写 / 写作回复 → 写 + +### 五、拼写/语法 + +**检查项:** + +| 检查项 | 规则 | 修正方式 | +|--------|------|----------| +| 常见拼写错误 | 扫描 `recieve` `seperate` `occured` 等高频错误 | 标注正确拼写 | +| 重复词 | 连续出现两次相同单词 | 标注位置 | +| its/it's 混淆 | `its` 后接形容词/副词 | 标注修正 | +| 主谓一致 | 第三人称单数遗漏 `-s` | 标注修正 | +| 时态一致性 | 同一段落时态跳跃 | 标注修正 | +| 冠词缺失 | 单数可数名词前缺 `a/an/the` | 标注修正 | + +**检查方法:** +1. 逐行扫描翻译列英文文本 +2. 对每个检查项执行正则匹配 +3. 标注位置、原文、修正建议 + +### 六、词汇难度 + +**规范来源:** `business_knowledge/L2/L2 剧本教研规范 .md` — 剑桥 A1–A2 水平,不超过 A2 + +**检查方法:** +1. 提取翻译列所有英文词汇 +2. 对照 CEFR 等级表,标记 B1 及以上词汇 +3. 逐词判断:剧情核心词可保留(标注 🟡),非必要超纲词建议替换(标注 🔴) + +**分级判定:** + +| CEFR | 判定 | 处理 | +|------|------|------| +| A1–A2 | ✅ 合规 | 无需处理 | +| B1(剧情核心词) | 🟡 可保留 | 标注但建议确认 | +| B1(非核心词) | 🔴 建议替换 | 给出 A2 替代词 | +| B2+ | 🔴 必改 | 给出 A2 替代词 | + +**常见 B2+ 超纲词及替换建议:** + +| 超纲词 | CEFR | 建议替换 | +|--------|------|----------| +| unforgivable | B2 | very wrong / cannot be forgiven | +| arrogance | B2 | too much pride | +| corrupts | B2 | changes / makes people bad | +| electromagnetic | B2+ | laser | +| bargain (v.) | B2 | argue / discuss | +| negotiate | B2 | talk about / discuss | +| convince | B1 | make someone believe | + +### 七、标点符号与价值观 + +#### 7.1 标点符号 + +| 检查项 | 规则 | 修正 | +|--------|------|------| +| 波浪号 `~` | 中文对白中出现 | 改为 `。` 或 `!` | +| 双叹号 `!!` | 英文翻译中出现 | 归一为单个 `!` | +| Markdown 标记 `**` | 翻译列中出现 | 清除 | +| 中文混用半角标点 | 中文对白中出现 `!` `?` | 改为全角 `!` `?` | +| 英文混用全角标点 | 翻译列中出现 `!` `?` `,` | 改为半角 `!` `?` `,` | +| 中英文混排空格 | 中文与英文/数字之间缺空格 | 添加半角空格 | + +#### 7.2 价值观/用语 + +| 检查项 | 规则 | 修正 | +|--------|------|------| +| 侮辱性词汇 | `白痴` `人渣` `废物`(贬义用法) | 替换为中性表达 | +| 暴力隐喻 | `吃人不吐骨` `死得很惨` `只能活一个` | 替换为温和表达 | +| 歧视性比喻 | `猴子们`(贬义) | 替换为 `you guys` | +| 威胁性语言 | `你会后悔的` `让你好看` | 替换为正向表达 | + +### 八、结构性问题 + +**检查项:** + +| 检查项 | 说明 | +|--------|------| +| 教研与剧本同步 | 教研知识区的知识点/核心互动是否与剧本表一致 | +| 删除线残留 | 剧本表中 `~~删除线~~` 内容是否已清理 | +| 场景衔接 | 场景切换是否流畅,有无逻辑跳跃 | +| 角色出场合理性 | 角色出场是否符合剧情逻辑 | +| 组件配置完整性 | 互动行的组件配置列是否已填写 | +| 配置信息完整性 | 互动行的配置信息列是否已填写 | +| 知识点标注准确性 | 剧本表中知识点列标注是否与教研知识区一致 | + +### 九、总结评分 + +对前 8 个维度汇总评分: + +| 维度 | 状态 | 等级 | +|------|------|------| +| 台词字数 | 超标/偏多/合规 | 🔴/🟡/✅ | +| 互动量 | 超标/合规 | 🔴/✅ | +| 知识点覆盖 | 过量/不足/合规 | 🔴/🟡/✅ | +| 核心互动 | 超标/不一致/合规 | 🔴/🟡/✅ | +| 拼写/语法 | 硬伤数 | 🔴/🟡/✅ | +| 词汇难度 | 超纲数 | 🔴/🟡/✅ | +| 标点/价值观 | 问题数 | 🔴/🟡/✅ | +| 结构性问题 | 问题数 | 🔴/🟡/✅ | + +**整体判定:** +- 🔴 不合格(需大修):≥3 个维度为 🔴 +- 🟡 需修改:1–2 个维度为 🔴 +- ✅ 合格:无 🔴 维度 + +## 执行流程 + +``` +用户发送 "L2审校 <飞书链接>" + │ + ├── 1. 读取 L2 剧本教研规范 + │ `business_knowledge/L2/L2 剧本教研规范 .md` + ├── 2. 解析飞书链接 → 获取文档 + │ 使用 `lark_wiki_operate_as_bot` 技能 + ├── 3. 读取文档完整内容 + │ 使用 `lark-cli docs +fetch --as bot` + ├── 4. 按 9 维度逐项审校 + │ ├── 一、台词字数 + │ ├── 二、互动量 + │ ├── 三、知识点覆盖 + │ ├── 四、核心互动 + │ ├── 五、拼写/语法 + │ ├── 六、词汇难度 + │ ├── 七、标点符号与价值观 + │ ├── 八、结构性问题 + │ └── 九、总结评分 + ├── 5. 输出结构化审校报告 + └── 6. 等待人工确认后再执行修改 +``` + +## 输出格式 + +``` +📝 L2 剧本审校报告 — <文档标题> + +### 一、台词字数 +| 指标 | 规范值 | 实际 | 判定 | +... + +### 二、互动量 +... + +### 三、知识点覆盖 +... + +### 四、核心互动 +... + +### 五、拼写/语法 +| # | 类型 | 原文 | 位置 | 修正 | +... + +### 六、词汇难度 +| # | 原文 | CEFR | 位置 | 建议替换 | 严重度 | +... + +### 七、标点符号与价值观 +| # | 类型 | 原文 | 位置 | 建议 | 严重度 | +... + +### 八、结构性问题 +| # | 问题 | 位置 | 建议 | +... + +### 九、总结评分 +| 维度 | 状态 | 等级 | +... + +**整体判定:** <结论> +``` + +## 修改执行 + +审校报告经人工确认后,使用 `lark_docx_update_as_bot` 技能逐条执行修改: + +```bash +LARKSUITE_CLI_CONFIG_DIR=/root/.openclaw/credentials/xiaoyan \ + lark-cli docs +update --api-version v2 --doc "" --as bot \ + --command str_replace \ + --pattern "原文" \ + --content "修正后文本" +``` + +**修改原则:** +1. 每次修改后回读验证 +2. 优先修改 🔴 必改项 +3. 🟡 建议改项需人工逐条确认 +4. 修改完成后输出修改清单 + +## 依赖 + +- `lark_wiki_operate_as_bot`:读取飞书知识库文档 +- `lark_docx_update_as_bot`:修改文档正文 +- `business_knowledge/L2/L2 剧本教研规范 .md`:审校规范依据 +- `business_knowledge/L2_word_list.json`:L2 词库 +- `business_knowledge/L2_pattern_list.json`:L2 句型库 + +## 权限要求 + +Bot 应用需对目标文档有编辑权限。 diff --git a/business_production/组件配置/interactive-component-json/db/components.db b/business_production/组件配置/interactive-component-json/db/components.db index 4eefee9e3be66534afbb1dbff5e59c0f4f3925d3..e1910e2d7e39adb3927c1648f34575b5d18fa4ed 100644 GIT binary patch delta 17169 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 + + + + +L1-S2-U20-L5 足球接力赛 — 组件JSON报告 + + + + + +
+ + + + +
+
+
就绪
+
+
+ 成功: 0 + 失败: 0 +
+
+ +
+
+

L1-S2-U20-L5 足球接力赛

+
+ 生成时间: 2026-06-23 17:25:48 + 模型: doubao-seed-2.0-pro + Wiki: VEGwwoVdTiFu00koNoOc1MGhnec +
+
+ +
+
+
1
核心互动
+
16
中互动
+
+
17
总组件
+
17
成功
+
0
失败
+ +
+ + +
+
+ 1 + 图片单选 + cId: 1220501 + mid_image_choose + + + + + + 已保存 + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
cType
cId
title
meaning
resourceMapping
question
imageInfo
optionList
answer
preDialog
tip
corFeedback
errFeedback
postDialog
cDesc
+
+ +
+ +
+ +
+ + + + + + + + + + + + + + + +
pushType
cType
cId
kpInfo
+
+ +
+
+ + + +
+
+ +
+
+ 2 + 对话朗读 + cId: 1220502 + mid_dialog_repeat + + + + + + 已保存 + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
cType
cId
title
resourceMapping
preDialog
imgShowTimingList
question
postDialog
+
+ +
+ +
+ +
+ + + + + + + + + + + + + + + +
pushType
cType
cId
kpInfo
+
+ +
+
+ + + +
+
+ +
+
+ 3 + 对话选择 + cId: 1220503 + mid_dialog_choose + + + + + + 已保存 + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
cType
cId
title
resourceMapping
preDialog
imgShowTimingList
optionList
answer
corFeedback
errFeedback
postDialog
+
+ +
+ +
+ +
+ + + + + + + + + + + + + + + +
pushType
cType
cId
kpInfo
+
+ +
+
+ + + +
+
+ +
+
+ 4 + 对话挖空 + cId: 1220504 + mid_dialog_fillin + + + + + + 已保存 + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
cType
cId
title
resourceMapping
preDialog
imgShowTimingList
img
question
optionGroupList
corFeedback
errFeedback
postDialog
+
+ +
+ +
+ +
+ + + + + + + + + + + + + + + +
pushType
cType
cId
kpInfo
+
+ +
+
+ + + +
+
+ +
+
+ 5 + 对话选择 + cId: 1220505 + mid_dialog_choose + + + + + + 已保存 + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
cType
cId
title
resourceMapping
preDialog
imgShowTimingList
img
optionList
answer
corFeedback
errFeedback
postDialog
+
+ +
+ +
+ +
+ + + + + + + + + + + + + + + +
pushType
cType
cId
kpInfo
+
+ +
+
+ + + +
+
+ +
+
+ 6 + 对话组句 + cId: 1220506 + mid_dialog_sentence + + + + + + 已保存 + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
cType
cId
title
resourceMapping
preDialog
imgShowTimingList
question
optionList
answer
tip
corFeedback
errFeedback
postDialog
+
+ +
+ +
+ +
+ + + + + + + + + + + + + + + +
pushType
cType
cId
kpInfo
+
+ +
+
+ + + +
+
+ +
+
+ 7 + 对话挖空 + cId: 1220507 + mid_dialog_fillin + + + + + + 已保存 + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
cType
cId
title
resourceMapping
preDialog
imgShowTimingList
question
optionGroupList
corFeedback
errFeedback
postDialog
+
+ +
+ +
+ +
+ + + + + + + + + + + + + + + +
pushType
cType
cId
kpInfo
+
+ +
+
+ + + +
+
+ +
+
+ 8 + 对话朗读 + cId: 1220508 + mid_dialog_repeat + + + + + + 已保存 + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
cType
cId
title
resourceMapping
preDialog
imgShowTimingList
img
question
postDialog
+
+ +
+ +
+ +
+ + + + + + + + + + + + + + + +
pushType
cType
cId
kpInfo
+
+ +
+
+ + + +
+
+ +
+
+ 9 + 对话选择 + cId: 1220509 + mid_dialog_choose + + + + + + 已保存 + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
cType
cId
title
resourceMapping
preDialog
imgShowTimingList
img
optionList
answer
corFeedback
errFeedback
postDialog
+
+ +
+ +
+ +
+ + + + + + + + + + + + + + + +
pushType
cType
cId
kpInfo
+
+ +
+
+ + + +
+
+ +
+
+ 10 + 对话朗读 + cId: 1220510 + mid_dialog_repeat + + + + + + 已保存 + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
cType
cId
title
resourceMapping
preDialog
imgShowTimingList
img
question
postDialog
+
+ +
+ +
+ +
+ + + + + + + + + + + + + + + +
pushType
cType
cId
kpInfo
+
+ +
+
+ + + +
+
+ +
+
+ 11 + 对话挖空 + cId: 1220511 + mid_dialog_fillin + + + + + + 已保存 + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
cType
cId
title
resourceMapping
preDialog
imgShowTimingList
question
optionGroupList
corFeedback
errFeedback
postDialog
+
+ +
+ +
+ +
+ + + + + + + + + + + + + + + +
pushType
cType
cId
kpInfo
+
+ +
+
+ + + +
+
+ +
+
+ 12 + 对话朗读 + cId: 1220512 + mid_dialog_repeat + + + + + + 已保存 + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
cType
cId
title
resourceMapping
preDialog
imgShowTimingList
img
question
postDialog
+
+ +
+ +
+ +
+ + + + + + + + + + + + + + + +
pushType
cType
cId
kpInfo
+
+ +
+
+ + + +
+
+ +
+
+ 13 + 对话挖空 + cId: 1220513 + mid_dialog_fillin + + + + + + 已保存 + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
cType
cId
title
resourceMapping
preDialog
imgShowTimingList
img
question
optionGroupList
corFeedback
errFeedback
postDialog
+
+ +
+ +
+ +
+ + + + + + + + + + + + + + + +
pushType
cType
cId
kpInfo
+
+ +
+
+ + + +
+
+ +
+
+ 14 + 对话组句 + cId: 1220514 + mid_dialog_sentence + + + + + + 已保存 + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
cType
cId
title
resourceMapping
preDialog
imgShowTimingList
img
question
optionList
answer
tip
corFeedback
errFeedback
postDialog
+
+ +
+ +
+ +
+ + + + + + + + + + + + + + + +
pushType
cType
cId
kpInfo
+
+ +
+
+ + + +
+
+ +
+
+ 15 + 核心看图说话 + cId: 1220515 + core_speaking_image + + + + + + 已保存 + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
cType
cId
title
taskDesc
sceneDesc
key
resourceMapping
cDesc
+
+ +
+ +
+ +
+ + + +
config
+
+ +
+ +
+ +
+ + + + + + + +
learningPart
closing
+
+ +
+ +
+ +
+ + + +
questionImg
+
+ +
+ +
+ +
+
1234567891011121314151617181920212223
+ +
+
+ +
+ +
+
1234567891011
+ +
+
+ +
+ +
+ + + + + + + + + + + + + + + +
pushType
cType
cId
kpInfo
+
+ +
+ +
+ +
```
+# 中间回合1
+Logi: What is the game about? The soccer ball or the basketball?
+Brainy: 裁判Logi询问你这场比赛的用球是足球还是篮球,你需要根据实际比赛情况回答他的问题。
+用户选项:
+(选项 A)The soccer ball. [正确]
+  Brainy: 太棒了!你正确说出了比赛用球是足球。请大声朗读这句话!
+(选项 B)The basketball.
+  Brainy: 这句话的意思是篮球,但你们进行的是足球比赛,和当前的比赛情境不相符。请仔细回想比赛经历,告诉Logi正确的比赛用球。
+(选项 C)One hour.
+  Brainy: 这句话的意思是一个小时,但Logi现在问的是比赛用球是什么,不是比赛时长。请仔细听清问题,回答Logi关于比赛用球的问题。
+
+# 中间回合2
+Logi: How long is the game? 
+Brainy: Logi现在询问你这场比赛的总时长是多少,你需要告诉他对应的时长信息。
+用户选项:
+(选项 A)Only five minutes!
+  Brainy: 这句话的意思是只剩五分钟了,但Logi问的是比赛的总时长,不是剩余时间。请仔细听清问题,告诉Logi比赛的总时长。
+(选项 B)The soccer ball.
+  Brainy: 这句话的意思是足球,但Logi现在问的是比赛时长,不是比赛用球。请仔细听清问题,回答Logi关于比赛总时长的问题。
+(选项 C)One hour. [正确]
+  Brainy: 太棒了!你正确说出了比赛总时长是一个小时。请大声朗读这句话!
+
+# 中间回合3
+Logi: How much time do you have now?
+Brainy: Logi现在询问你目前比赛还剩下多长时间,你需要告诉他对应的剩余时长。
+用户选项:
+(选项 A)The soccer ball.
+  Brainy: 这句话的意思是足球,但Logi现在问的是比赛剩余时长,不是比赛用球。请仔细听清问题,回答Logi关于剩余时间的问题。
+(选项 B)Only five minutes! [正确]
+  Brainy: 太棒了!你正确说出了比赛只剩五分钟了。请大声朗读这句话!
+(选项 C)One hour.
+  Brainy: 这句话的意思是一个小时,这是比赛的总时长,不是现在剩余的时间,和当前情境不符。请仔细回想比赛的剩余时间,再回答Logi的问题。
+
+# 结尾回合
+Brainy: 你已经正确回答了Logi的所有规则问题,成功证明你们了解比赛规则,争取到了继续比赛的机会,任务完成!
+```
+
+ +
+ +
soccer,ball,hour,minute,minutes left
+
+
+ + + +
+
+ +
+
+ 16 + 对话挖空 + cId: 1220516 + mid_dialog_fillin + + + + + + 已保存 + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
cType
cId
title
resourceMapping
preDialog
imgShowTimingList
img
question
optionGroupList
corFeedback
errFeedback
postDialog
+
+ +
+ +
+ +
+ + + + + + + + + + + + + + + +
pushType
cType
cId
kpInfo
+
+ +
+
+ + + +
+
+ +
+
+ 17 + 对话表达 + cId: 1220517 + mid_dialog_express + + + + + + 已保存 + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
cType
cId
title
asrPrompt
resourceMapping
preDialog
imgShowTimingList
tip
corFeedback
errFeedback
question
example
postDialog
+
+ +
+ +
+ +
+ + + + + + + + + + + + + + + +
pushType
cType
cId
kpInfo
+
+ +
+
+ + + +
+
+ + +
+ + + + + + + \ No newline at end of file diff --git a/business_production/英文台词/skills/kids-english-script-production/SKILL.md b/business_production/英文台词/skills/kids-english-script-production/SKILL.md index 8c957be..6d6414a 100644 --- a/business_production/英文台词/skills/kids-english-script-production/SKILL.md +++ b/business_production/英文台词/skills/kids-english-script-production/SKILL.md @@ -79,17 +79,17 @@ description: 用英语母语儿童思维生成自然地道的分级英文台词 3. 如果目录下有多个 docx 文档 → 列出标题和 obj_token,让用户指定目标 4. 禁止在有多份文档时自行猜测选择 -### 1. 写入前必须验证行号连续性 +### 1. 写入前必须执行行号连续性强制校验(不可跳过) **问题:** 飞书 Sheets API 的 range 写入按连续区域覆盖,不关心行号是否对应。剧本表格中 E 列有内容的行号通常不连续(中间有剧情描述空行),连续 range 写入会导致全列偏移。 -**规则:** -- 写入前统计目标行号列表,检查连续性 -- 行号连续 → 可用 range 批量写入 -- 行号不连续 → 必须逐行写入(每个行号单独 range) -- 写入后抽样验证 E/F 列行号对齐(前5行+中间5行+末尾5行) +**规则(已固化为代码级强制校验):** +- 写入前必须调用 `feishu-embedded-sheet` 技能中的 **步骤 4.0 `validate_and_write()`** 函数 +- 该函数自动检测行号连续性:连续 → 批量写入,不连续 → 逐行写入 +- 写入后自动执行 **步骤 4.3 E-F 对齐验证**,发现错位立即报错 +- 禁止跳过步骤 4.0 直接构造连续 range 写入 -详见 `feishu-embedded-sheet` 技能中的「批量写入前必须验证行号连续性」章节。 +详见 `feishu-embedded-sheet` 技能中的「步骤 4.0:行号连续性强制校验」章节。 ### 2. 完成后必须输出结果统计与变更明细(强制执行) diff --git a/memory/.dreams/events.jsonl b/memory/.dreams/events.jsonl index 878fef0..88d604f 100644 --- a/memory/.dreams/events.jsonl +++ b/memory/.dreams/events.jsonl @@ -138,3 +138,11 @@ {"type":"memory.recall.recorded","timestamp":"2026-06-18T04:36:16.755Z","query":"L1 每单元 lesson 5课 L1-L5 结构","resultCount":5,"results":[{"path":"memory/2026-05-26.md","startLine":130,"endLine":166,"score":1},{"path":"memory/2026-05-28.md","startLine":46,"endLine":62,"score":1},{"path":"memory/2026-05-25.md","startLine":283,"endLine":302,"score":1},{"path":"memory/2026-05-29.md","startLine":1,"endLine":14,"score":1},{"path":"memory/2026-05-25.md","startLine":118,"endLine":137,"score":1}]} {"type":"memory.recall.recorded","timestamp":"2026-06-18T08:09:19.223Z","query":"L1 句子 结构 第三级 知识维度 句型结构 看图组句 句子补全","resultCount":2,"results":[{"path":"memory/2026-05-26.md","startLine":130,"endLine":166,"score":1},{"path":"memory/2026-05-28.md","startLine":46,"endLine":62,"score":1}]} {"type":"memory.recall.recorded","timestamp":"2026-06-22T02:56:35.364Z","query":"L1 知识巩固 题型 词义 单词题","resultCount":5,"results":[{"path":"memory/2026-05-26.md","startLine":130,"endLine":166,"score":1},{"path":"memory/2026-05-28.md","startLine":46,"endLine":62,"score":1},{"path":"memory/2026-05-25.md","startLine":283,"endLine":302,"score":1},{"path":"memory/2026-05-29.md","startLine":1,"endLine":14,"score":1},{"path":"memory/2026-05-25.md","startLine":118,"endLine":137,"score":1}]} +{"type":"memory.recall.recorded","timestamp":"2026-06-23T02:16:16.280Z","query":"巩固题 单词朗读 无音频 L1 L2 题型规则","resultCount":2,"results":[{"path":"memory/2026-05-12.md","startLine":141,"endLine":155,"score":1},{"path":"memory/2026-05-12.md","startLine":132,"endLine":143,"score":1}]} +{"type":"memory.recall.recorded","timestamp":"2026-06-23T02:16:32.659Z","query":"巩固题 单词朗读 题型 口语 L1 无音频","resultCount":2,"results":[{"path":"memory/2026-05-12.md","startLine":141,"endLine":155,"score":1},{"path":"memory/2026-05-12.md","startLine":132,"endLine":143,"score":1}]} +{"type":"memory.recall.recorded","timestamp":"2026-06-23T02:16:32.659Z","query":"单词知识巩固 word consolidation 朗读 read aloud","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-23T02:16:57.690Z","query":"巩固题 单词朗读 read aloud 口语 题型 L1 阶段","resultCount":2,"results":[{"path":"memory/2026-05-12.md","startLine":141,"endLine":155,"score":1},{"path":"memory/2026-05-12.md","startLine":132,"endLine":143,"score":1}]} +{"type":"memory.recall.recorded","timestamp":"2026-06-23T02:16:57.691Z","query":"word consolidation 巩固 题型列表 朗读 发音","resultCount":1,"results":[{"path":"memory/2026-05-07.md","startLine":29,"endLine":48,"score":1}]} +{"type":"memory.recall.recorded","timestamp":"2026-06-23T02:17:17.970Z","query":"巩固题 题型 单词 口语 朗读 read aloud 无音频 发音评测","resultCount":2,"results":[{"path":"memory/2026-05-12.md","startLine":141,"endLine":155,"score":1},{"path":"memory/2026-05-12.md","startLine":132,"endLine":143,"score":1}]} +{"type":"memory.recall.recorded","timestamp":"2026-06-23T02:51:54.388Z","query":"L2剧本教研规范","resultCount":1,"results":[{"path":"memory/2026-04-30.md","startLine":1,"endLine":27,"score":1}]} +{"type":"memory.recall.recorded","timestamp":"2026-06-23T02:51:54.388Z","query":"L2剧本 教研规范 knowledge","resultCount":1,"results":[{"path":"memory/2026-04-30.md","startLine":1,"endLine":27,"score":1}]} diff --git a/memory/.dreams/short-term-recall.json b/memory/.dreams/short-term-recall.json index d44cb97..1adcbab 100644 --- a/memory/.dreams/short-term-recall.json +++ b/memory/.dreams/short-term-recall.json @@ -1,6 +1,6 @@ { "version": 1, - "updatedAt": "2026-06-22T02:56:35.364Z", + "updatedAt": "2026-06-23T02:51:54.388Z", "entries": { "memory:memory/2026-05-07.md:57:74": { "key": "memory:memory/2026-05-07.md:57:74", @@ -1010,18 +1010,21 @@ "endLine": 27, "source": "memory", "snippet": "# 2026-04-30 工作日志 ## 李应瑛 — L1-S2-U15-L5 剧本组件配置生产 ### 文档信息 - **剧本**: 另一个BoBo 副本 - **Wiki**: https://makee-interactive.feishu.cn/wiki/HSSRwUqxSi8p51k6FtIcA7UAn8y - **Spreadsheet Token**: SD3Fs2zv8hM5evtHA5Nc7UjQncd - **Sheet ID**: wMQVyV - **Sheet 列结构**(注意:中间新增了\"配置信息\"列C,组件配置列从F移至G): - A: 类型, B: ID, C: 配置信息, D: 剧情描述, E: 角色名, F: 英文台词, G: 组件配置, H: 知识点, I: 编剧台词 ### 已完成组件配置 #### 1. 对话朗读 (6条) — 规则: dialogue-reading-config | ID | 类型 | 任务标题 | 互动内容 | |---|------|---------|---------| | 1 | 对话朗读-配图 | 给May看照片 | I have a photo. | | 2 | 对话朗读-配图 | 指认照片中的房子 | Look at this one. | | 3 | 对话朗读-配图 | 告诉May这是我的房子 | This house is mine. | | 4 | 对话朗读 | 赞叹May有一个农场 | You have a farm! | | 7 | 对话朗读 | 夸May刷漆刷得好 | You", - "recallCount": 1, + "recallCount": 3, "dailyCount": 0, "groundedCount": 0, - "totalScore": 1, + "totalScore": 3, "maxScore": 1, "firstRecalledAt": "2026-05-17T05:52:07.611Z", - "lastRecalledAt": "2026-05-17T05:52:07.611Z", + "lastRecalledAt": "2026-06-23T02:51:54.388Z", "queryHashes": [ - "65b539c56ec3" + "65b539c56ec3", + "77cfbe459e1d", + "63eeac46a47c" ], "recallDays": [ - "2026-05-17" + "2026-05-17", + "2026-06-23" ], "conceptTags": [ "l1-s2-u15-l5", @@ -2752,13 +2755,13 @@ "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. 句型合规检测 - 接入方式:`` + 调用 `PedagogyRules.validate(summary, level)` - 数据源:L1 词库 147 词(过滤 enabled=true)、L2 词库 52 词、L1 句型 8 个、L2 句型(从 437MB bitable 导出中提取唯一结", - "recallCount": 16, + "recallCount": 17, "dailyCount": 0, "groundedCount": 0, - "totalScore": 16, + "totalScore": 17, "maxScore": 1, "firstRecalledAt": "2026-05-29T00:23:17.391Z", - "lastRecalledAt": "2026-06-22T02:56:35.364Z", + "lastRecalledAt": "2026-06-23T02:16:32.659Z", "queryHashes": [ "c1d4076205e1", "4aa0ef719160", @@ -2775,7 +2778,8 @@ "533765637e65", "367cd3303e1d", "fc0ce35c5668", - "fecfc20c077f" + "fecfc20c077f", + "8d35216cc8bc" ], "recallDays": [ "2026-05-29", @@ -2784,7 +2788,8 @@ "2026-06-10", "2026-06-17", "2026-06-18", - "2026-06-22" + "2026-06-22", + "2026-06-23" ], "conceptTags": [ "5-8", @@ -2993,13 +2998,13 @@ "endLine": 66, "source": "memory", "snippet": "8. 句型合规检测 - 接入方式:`` + 调用 `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": 10, + "recallCount": 11, "dailyCount": 0, "groundedCount": 0, - "totalScore": 10, + "totalScore": 11, "maxScore": 1, "firstRecalledAt": "2026-05-29T02:33:30.526Z", - "lastRecalledAt": "2026-06-18T04:36:05.631Z", + "lastRecalledAt": "2026-06-23T02:16:32.659Z", "queryHashes": [ "4aa0ef719160", "e30c130b9d1d", @@ -3010,7 +3015,8 @@ "867f7264cd0e", "5f16a7426a41", "7c761b49b948", - "533765637e65" + "533765637e65", + "8d35216cc8bc" ], "recallDays": [ "2026-05-29", @@ -3018,7 +3024,8 @@ "2026-06-02", "2026-06-10", "2026-06-17", - "2026-06-18" + "2026-06-18", + "2026-06-23" ], "conceptTags": [ "l1-pedagogy-rules.js", @@ -3038,13 +3045,13 @@ "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": 11, + "recallCount": 12, "dailyCount": 0, "groundedCount": 0, - "totalScore": 11, + "totalScore": 12, "maxScore": 1, "firstRecalledAt": "2026-06-02T01:49:17.841Z", - "lastRecalledAt": "2026-06-22T02:56:35.364Z", + "lastRecalledAt": "2026-06-23T02:16:32.659Z", "queryHashes": [ "7e6aa000abdb", "094bfb865b29", @@ -3056,14 +3063,16 @@ "341edb569d53", "533765637e65", "367cd3303e1d", - "fecfc20c077f" + "fecfc20c077f", + "8d35216cc8bc" ], "recallDays": [ "2026-06-02", "2026-06-10", "2026-06-17", "2026-06-18", - "2026-06-22" + "2026-06-22", + "2026-06-23" ], "conceptTags": [ "v4.0.0", @@ -3083,13 +3092,13 @@ "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": 7, + "recallCount": 8, "dailyCount": 0, "groundedCount": 0, - "totalScore": 7, + "totalScore": 8, "maxScore": 1, "firstRecalledAt": "2026-06-02T01:49:17.841Z", - "lastRecalledAt": "2026-06-18T04:36:05.631Z", + "lastRecalledAt": "2026-06-23T02:16:32.659Z", "queryHashes": [ "7e6aa000abdb", "094bfb865b29", @@ -3097,13 +3106,15 @@ "867f7264cd0e", "5f16a7426a41", "7c761b49b948", - "533765637e65" + "533765637e65", + "8d35216cc8bc" ], "recallDays": [ "2026-06-02", "2026-06-10", "2026-06-17", - "2026-06-18" + "2026-06-18", + "2026-06-23" ], "conceptTags": [ "听力-p1-图片选择题生产", @@ -3154,22 +3165,27 @@ "endLine": 155, "source": "memory", "snippet": "- **最终结果:10/10 条记录 sentenceMeaningMeaning 均可 json.loads 正确解析,每条含 2 题,无残留垃圾数据** - **受影响记录:** 1213004, 1213006, 1213010, 1214008, 1215005, 1216001, 1216004, 1216007, 1216008, 1216010 - **审校结果同步更新:** 移除所有 10 条的 `❌ JSON 解析失败` 标记 - **注意:** Q1 explanation 在重建时词表述可能微调(内容含义一致),如需精确原始 wording 可从中文列恢复后人工微调 ## 经验教训 ### bitable 写入需严格流程管控(2026-05-12) - 批量更新 JSON 字段时必须:写入前完整提取原始数据 → 写入后逐字段 diff 验证 → 发现异常立即回滚 - 本次 JSON 修复中首次写入不完整导致 Q2 丢失,原因:修复脚本未正确处理多题 JSON 结构 - **教训:** 任何涉及 JSON 重建/修复的批量操作,先单条试运行验证通过后再批量执行,不可并行甩出多条 ### sentenceMeaningMeaning 的 explanation 引号规范(2026-05-12) - explanation 字段中的中文双引号极易被误用为 ASCII `\"` (U+0022) - 建议生产侧统一使用中文引号 `\"` (U+201C) 和 `\"` (U+201D),或在 explanation 写入前做引号归一化预处理", - "recallCount": 4, + "recallCount": 8, "dailyCount": 0, "groundedCount": 0, - "totalScore": 4, + "totalScore": 8, "maxScore": 1, "firstRecalledAt": "2026-06-04T03:23:22.968Z", - "lastRecalledAt": "2026-06-17T02:46:25.801Z", + "lastRecalledAt": "2026-06-23T02:17:17.970Z", "queryHashes": [ "defa0daee9d7", "92343053bee2", "302eafc578a7", - "666912b77eb8" + "666912b77eb8", + "8b8c93a101f0", + "a051b817dda7", + "0ae754ed0ea5", + "ec8098bc9476" ], "recallDays": [ "2026-06-04", - "2026-06-17" + "2026-06-17", + "2026-06-23" ], "conceptTags": [ "10/10", @@ -3189,22 +3205,27 @@ "endLine": 143, "source": "memory", "snippet": "- 检查题型:句意选择题 ×30、句子补全题、听句作答题、场景选择题、看图选择题 - 验证方法:提取 explanation 中的英文引句 vs question 中的英文句子、正则提取\"空处应填X\" vs options[answer] - 结果:✅ **0 条实质性不对应** - **10 条 sentenceMeaningMeaning JSON 修复:** - **根因:** explanation 文本中的 ASCII `\"` (U+0022) 被当作中文双引号使用,JSON 解析器将其视为字符串终止符 - **修复策略:** 从「句意选择题」中文列提取英文原句和选项 → json.dumps 重建标准 JSON(只修格式,不修内容) - **1216007 特殊处理:** 原始 JSON 损坏严重,需从中文列完全重建 - **二次修复(Q2 丢失问题):** 首次不完全修复导致 9 条记录的 Q2 被覆盖丢失,且 Q1 被 JSON 垃圾污染 → 从中文列全面重建 Q1+Q2 - **最终结果:10/10 条记录 sentenceMeaningMeaning 均可 json.loads 正确解析,每条含 2 题,无残留垃圾数据** - **受影响记录:** 1213004, 1213006, 1213010, 1214008, 1215005, 1216001, 1216004, 1216007, 1216008, 1216010 - **审校结果同步更新:** 移除所有 10 条的 `❌ JSON 解析失败` 标记", - "recallCount": 4, + "recallCount": 8, "dailyCount": 0, "groundedCount": 0, - "totalScore": 4, + "totalScore": 8, "maxScore": 1, "firstRecalledAt": "2026-06-04T03:23:22.968Z", - "lastRecalledAt": "2026-06-17T02:46:25.801Z", + "lastRecalledAt": "2026-06-23T02:17:17.970Z", "queryHashes": [ "defa0daee9d7", "92343053bee2", "302eafc578a7", - "666912b77eb8" + "666912b77eb8", + "8b8c93a101f0", + "a051b817dda7", + "0ae754ed0ea5", + "ec8098bc9476" ], "recallDays": [ "2026-06-04", - "2026-06-17" + "2026-06-17", + "2026-06-23" ], "conceptTags": [ "json.dumps", @@ -4077,6 +4098,37 @@ "dialogue-fill-in-blanks-config", "对话挖空-配图" ] + }, + "memory:memory/2026-05-07.md:29:48": { + "key": "memory:memory/2026-05-07.md:29:48", + "path": "memory/2026-05-07.md", + "startLine": 29, + "endLine": 48, + "source": "memory", + "snippet": "- **时间:** 10:39 ~ 10:49 - **需求:** 对比两份单词表的区别,找出\"表1有但表2没有\"的单词逐个列出。 - **状态:** 已完成对比,结果已交付用户。 - **文件:** - 表1:.doc 文件(分类主题单词表,14个大类,~970个单词) - 表2:.xlsx 文件(LV2词表,~1326个单词) - **对比结果:** - 两表共有:459个单词 - 表1有但表2没有:502个单词(基础生活词汇为主,L1级别高频词) - 表2有但表1没有:867个单词(LV2进阶/学术词汇为主) - **输出文件:** `/root/.openclaw/workspace-xiaoyan/output/word_comparison_result.xlsx` - **关键发现:** 表1包含大量L1级别基础生活词汇(家庭成员、日期、颜色、食物等),表2偏重LV2级别学术词汇,两者覆盖范围差异大。表1的502个独有词主要是小学阶段高频基础词。 - **备注:** 李应瑛不在负责人配置中,不在完整权限用户列表中。当前请求属于教研内容分析,已先接单处理,后续如有敏感数据查询需求需按权限规则处理。 # 2026-05-07 工作日志 ## 会话记录 ### 李应瑛 (ou_1bd7317ae2ccfeb57e1132028847279e) — 单词表对比请求(三轮对比) - **时间:** 10:39 ~ 11:18 - **需求:** 对比三份单词表,找出\"表1有但表2和表3都没有\"的单词。", + "recallCount": 1, + "dailyCount": 0, + "groundedCount": 0, + "totalScore": 1, + "maxScore": 1, + "firstRecalledAt": "2026-06-23T02:16:57.691Z", + "lastRecalledAt": "2026-06-23T02:16:57.691Z", + "queryHashes": [ + "01b80ce79584" + ], + "recallDays": [ + "2026-06-23" + ], + "conceptTags": [ + "lv2进阶/学术词汇为主", + "时间", + "需求", + "对比", + "单词", + "区别", + "找出", + "没有" + ] } } } diff --git a/memory/2026-06-23-1639.md b/memory/2026-06-23-1639.md new file mode 100644 index 0000000..20a584d --- /dev/null +++ b/memory/2026-06-23-1639.md @@ -0,0 +1,87 @@ +# Session: 2026-06-23 16:39:31 GMT+8 + +- **Session Key**: agent:xiaoyan:feishu:direct:ou_d17da6d91277b56710bf8dc45846fb7b +- **Session ID**: 24ef878c-6940-424e-8bd6-3919414fac79 +- **Source**: feishu + +## Conversation Summary + +assistant: "他们是为了获奖的" 可以翻译为: + +**They're in it for the prize.** + +或者更直译一些: + +**They are doing it to win the prize.** + +如果结合你之前的语境(那些东西是用来兑奖/获奖的),更自然的说法是: + +**They're trying to win the prize.** +user: [message_id: om_x100b6c94379954a4b1128b65a7e462e] +张幸莹: He ate some fruit.His face goes red from kiwi or pineapple.合并成一句话 +assistant: 合并后: + +**He ate some fruit, and his face went red from the kiwi or pineapple.** + +(注意:原句 "goes" 改为过去式 "went",与前面的 "ate" 时态保持一致。) + +如果想强调"过敏反应"的转折感,也可以用: + +**He ate some fruit, but his face went red from the kiwi or pineapple.** +user: [message_id: om_x100b6c97a746bcacb207929207e245f] +张幸莹: https://makee-interactive.feishu.cn/wiki/GvXTwO7V5iulQtkDOqPcM8o4nBe?from=from_copylink,组件生成 +assistant: 开始执行组件生产流程。先读取文档。 + + +assistant: 当前Bot无访问该知识空间权限。这个链接属于 `makee-interactive` 租户的知识库,而Bot应用(App ID: `cli_a931175d41799cc7`)注册在 Vala 租户下,无法跨租户访问。 + +需要确认:这个文档是否在 Vala 租户下有副本?或者能否将文档迁移到 Vala 租户下 Bot 可访问的知识空间(如 AI_member、Content Universe 等)? +user: [message_id: om_x100b6c97b4da28acb4c8abb79261422] +张幸莹: 怎么样能获得权限呢 +assistant: 跨租户访问的限制,有几种解决方式: + +**方案一(推荐):把文档迁移到 Vala 租户** +将文档复制/移动到 Vala 租户下 Bot 可访问的知识空间。目前 Bot 可访问的空间包括: +- **AI_member** — 技术负责人群组空间 +- **Content Universe** — 内容宇宙 +- **VALA Academy** — 教研学院 + +你可以在飞书里把文档复制到以上任一空间,然后给我新链接即可。 + +**方案二:在 makee-interactive 租户安装 Bot 应用** +需要在 makee-interactive 飞书后台安装小研 Bot(App ID: `cli_a931175d41799cc7`),但涉及跨租户部署,流程较复杂,建议联系技术负责人李若松处理。 + +**方案三:手动搬运** +你把文档内容粘贴到 Vala 租户下的新知识库文档中,我来继续处理。 + +建议先用方案一,最快。你把文档复制到 AI_member 或 Content Universe 空间后把新链接发我就行。 +user: [message_id: om_x100b6c907b2284b0b1431824c2a3fd9] +张幸莹: https://makee-interactive.feishu.cn/wiki/GvXTwO7V5iulQtkDOqPcM8o4nBe?from=from_copylink,组件生成 +assistant: 还是同一个链接,情况没变——这个文档在 `makee-interactive` 租户下,小研 Bot 注册在 Vala 租户,跨租户无法访问。 + +最快的办法:在飞书里把这个文档**复制到 Vala 租户下的知识空间**(比如 **AI_member** 或 **Content Universe**),然后把新链接发给我,我立刻开始处理。 +user: [message_id: om_x100b6c907641d8bcb1ff0d133814f5a] +张幸莹: https://makee-interactive.feishu.cn/wiki/GvXTwO7V5iulQtkDOqPcM8o4nBe?from=from_copylink,组件生成 +assistant: 链接还是同一个,问题没变——这个文档在 `makee-interactive` 租户,小研 Bot 跨不了租户。 + +**操作步骤:** + +1. 在飞书打开这个文档 +2. 右上角 `...` → **复制到** → 选择 **AI_member** 或 **Content Universe** 空间 +3. 把复制后的新链接发给我 + +就这三步,新链接到手我立刻开工。 +user: [message_id: om_x100b6c900bec68b4b48c5232fccce09] +张幸莹: https://makee-interactive.feishu.cn/wiki/GvXTwO7V5iulQtkDOqPcM8o4nBe?from=from_copylink 组件生产 +assistant: 我再试一种不同的方式访问。 + + +assistant: 试了两种 API 路径(wiki + docx),都返回 `not found`。结论不变:Bot 无法跨租户访问 `makee-interactive` 的文档。 + +**没有别的办法,只能复制文档。** 在飞书里: + +1. 打开这个文档 +2. 右上角 `...` → **复制到** → 选 **AI_member** 空间 +3. 把新链接发我 + +三秒的事,比反复发同一个链接快 😄 diff --git a/scripts/knowledge_coverage_analyzer.py b/scripts/knowledge_coverage_analyzer.py new file mode 100644 index 0000000..1df45a0 --- /dev/null +++ b/scripts/knowledge_coverage_analyzer.py @@ -0,0 +1,447 @@ +#!/usr/bin/env python3 +""" +知识点覆盖率分析 + 回填脚本 +用法: python3 knowledge_coverage_analyzer.py <飞书文档ID或URL> + +功能: +1. 解析剧本主表,区分 TL 行(输入)与组件行(输出) +2. 读取「知识点现状」表格中的单词和句型 +3. 统计每个知识点在输入/输出中的出现次数 +4. 回填到「知识点现状」表格 +5. 输出用法质量检查报告 + +依赖: lark-cli(用于读取文档 markdown),Python3(用于 API 回填) +""" + +import json +import re +import subprocess +import sys +import time +import urllib.request +from pathlib import Path + +# ── 配置 ────────────────────────────────────────────── +CONFIG_PATH = Path("/root/.openclaw/credentials/xiaoyan/config.json") +LARK_CLI_ENV = { + "LARKSUITE_CLI_CONFIG_DIR": "/root/.openclaw/credentials/xiaoyan", + "PATH": "/root/.nvm/versions/node/v24.14.0/bin:" + "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", +} + + +# ── 工具函数 ────────────────────────────────────────── + +def parse_doc_id(url_or_id): + """从 URL 或直接 ID 中提取文档 ID""" + m = re.search(r"docx/([A-Za-z0-9]+)", url_or_id) + if m: + return m.group(1) + return url_or_id.strip() + + +def fetch_markdown(doc_id): + """用 lark-cli 获取文档 markdown""" + result = subprocess.run( + ["/root/.nvm/versions/node/v24.14.0/bin/lark-cli", "docs", "+fetch", "--doc", doc_id, "--as", "bot"], + capture_output=True, text=True, env=LARK_CLI_ENV, timeout=30, + ) + data = json.loads(result.stdout) + return data["data"]["markdown"] + + +def get_token(): + """获取 tenant_access_token""" + with open(CONFIG_PATH) as f: + cfg = json.load(f) + app = cfg["apps"][0] + body = json.dumps({"app_id": app["appId"], "app_secret": app["appSecret"]}).encode() + req = urllib.request.Request( + "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal", + data=body, + headers={"Content-Type": "application/json"}, + ) + resp = json.loads(urllib.request.urlopen(req).read()) + return resp["tenant_access_token"] + + +def api_get(token, path): + """GET 请求飞书 API""" + req = urllib.request.Request( + f"https://open.feishu.cn/open-apis{path}", + headers={"Authorization": f"Bearer {token}"}, + ) + return json.loads(urllib.request.urlopen(req).read()) + + +def api_patch(token, path, body): + """PATCH 请求飞书 API""" + data = json.dumps(body).encode() + req = urllib.request.Request( + f"https://open.feishu.cn/open-apis{path}", + data=data, + headers={"Authorization": f"Bearer {token}", "Content-Type": "application/json"}, + method="PATCH", + ) + return json.loads(urllib.request.urlopen(req).read()) + + +def api_get_all_children(token, doc_id, block_id): + """分页获取 block 的所有子块""" + all_items = [] + page_token = None + while True: + path = f"/docx/v1/documents/{doc_id}/blocks/{block_id}/children?page_size=50" + if page_token: + path += f"&page_token={page_token}" + resp = api_get(token, path) + items = resp.get("data", {}).get("items", []) + all_items.extend(items) + if not resp.get("data", {}).get("has_more"): + break + page_token = resp["data"]["page_token"] + return all_items + + +# ── Markdown 解析 ───────────────────────────────────── + +def parse_markdown_table(md, heading_text): + """找到标题下方的 lark-table,返回二维数组 [row][col]""" + idx = md.find(heading_text) + if idx == -1: + return None + + table_match = re.search(r"", md[idx:], re.DOTALL) + if not table_match: + return None + + table_md = table_match.group(0) + rows = re.findall(r"(.*?)", table_md, re.DOTALL) + + result = [] + for row in rows: + cells = re.findall(r"]*>(.*?)", row, re.DOTALL) + clean_cells = [] + for c in cells: + # 去掉所有 HTML 标签,提取纯文本 + text = re.sub(r"<[^>]+>|\*\*|\{[^}]*\}", "", c).strip() + clean_cells.append(text) + result.append(clean_cells) + + return result + + +def find_table_by_first_cell_md(md, first_cell_text): + """在 markdown 中找到第一列第一行为指定文本的表格""" + tables = re.findall(r"", md, re.DOTALL) + for table_md in tables: + rows = re.findall(r"(.*?)", table_md, re.DOTALL) + if not rows: + continue + cells = re.findall(r"]*>(.*?)", rows[0], re.DOTALL) + if cells: + text = re.sub(r"<[^>]+>|\*\*|\{[^}]*\}", "", cells[0]).strip() + if text == first_cell_text: + return parse_markdown_table_from_string(table_md) + return None + + +def parse_markdown_table_from_string(table_md): + """从 lark-table markdown 字符串解析为二维数组""" + rows = re.findall(r"(.*?)", table_md, re.DOTALL) + result = [] + for row in rows: + cells = re.findall(r"]*>(.*?)", row, re.DOTALL) + clean_cells = [re.sub(r"<[^>]+>|\*\*|\{[^}]*\}", "", c).strip() for c in cells] + result.append(clean_cells) + return result + + +# ── 统计逻辑 ────────────────────────────────────────── + +def count_occurrences(word, texts): + """统计单词在文本列表中的出现次数(不区分大小写,整词匹配)""" + if not word: + return 0 + count = 0 + pattern = re.compile(r"\b" + re.escape(word) + r"\b", re.IGNORECASE) + for t in texts: + count += len(pattern.findall(t)) + return count + + +def count_pattern_occurrences(pattern_text, texts): + """统计句型在文本列表中的出现次数(子串匹配,不区分大小写)""" + if not pattern_text: + return 0 + key = pattern_text.strip().rstrip(".").rstrip("!").rstrip("?") + key_lower = key.lower() + count = 0 + for t in texts: + count += t.lower().count(key_lower) + return count + + +# ── 回填逻辑(使用 Block API)───────────────────────── + +def find_table_block_id(token, doc_id, heading_text): + """找到标题下方的第一个表格 block_id""" + blocks = api_get(token, f"/docx/v1/documents/{doc_id}/blocks?page_size=500") + items = blocks.get("data", {}).get("items", []) + + heading_index = -1 + for i, b in enumerate(items): + text = "" + for e in b.get("text", {}).get("elements", []): + text += e.get("text_run", {}).get("content", "") + if text == heading_text: + heading_index = i + break + + if heading_index == -1: + return None + + for b in items[heading_index + 1:]: + if b.get("block_type") == 31: + return b["block_id"] + + return None + + +def get_cell_block_ids(token, doc_id, table_block_id): + """ + 获取表格中所有单元格的 block_id,返回二维数组 [row][col] + 飞书表格结构:table > row > cell,每个 row 只有一个 cell + 需要按列数分组。 + """ + rows = api_get_all_children(token, doc_id, table_block_id) + + all_cells = [] + for row in rows: + try: + cell_items = api_get_all_children(token, doc_id, row["block_id"]) + except Exception: + continue + if cell_items: + all_cells.append(cell_items[0]["block_id"]) + + return all_cells + + +def fill_cells(token, doc_id, cell_ids, col_count, knowledge_items, tl_rows, comp_rows): + """回填统计结果到表格""" + ok = 0 + fail = 0 + + for item_idx, item in enumerate(knowledge_items): + word = item.get("word", "") + pattern = item.get("pattern", "") + + # 计算该行在 cell_ids 中的起始位置 + # 跳过表头行 + row_start = (item_idx + 1) * col_count + + if word: + word_only = word.split()[0] if word else "" + w_in = count_occurrences(word_only, tl_rows) + w_out = count_occurrences(word_only, comp_rows) + + # col 1 = 输入(单词) + if row_start + 1 < len(cell_ids): + ok += patch_cell(token, doc_id, cell_ids[row_start + 1], str(w_in)) + time.sleep(0.3) + else: + fail += 1 + # col 2 = 输出(单词) + if row_start + 2 < len(cell_ids): + ok += patch_cell(token, doc_id, cell_ids[row_start + 2], str(w_out)) + time.sleep(0.3) + else: + fail += 1 + + if pattern: + p_in = count_pattern_occurrences(pattern, tl_rows) + p_out = count_pattern_occurrences(pattern, comp_rows) + + # col 4 = 输入(句型) + if row_start + 4 < len(cell_ids): + ok += patch_cell(token, doc_id, cell_ids[row_start + 4], str(p_in)) + time.sleep(0.3) + else: + fail += 1 + # col 5 = 输出(句型) + if row_start + 5 < len(cell_ids): + ok += patch_cell(token, doc_id, cell_ids[row_start + 5], str(p_out)) + time.sleep(0.3) + else: + fail += 1 + + print(f" 回填完成: {ok} 成功, {fail} 失败") + return ok, fail + + +def patch_cell(token, doc_id, block_id, content): + """更新单个文本块的内容""" + body = { + "update_text_elements": { + "elements": [{"text_run": {"content": content}}] + } + } + try: + resp = api_patch(token, f"/docx/v1/documents/{doc_id}/blocks/{block_id}", body) + return resp.get("code") == 0 + except Exception as e: + print(f" ❌ 回填失败 {block_id}: {e}") + return False + + +# ── 报告 ────────────────────────────────────────────── + +def print_report(knowledge_items, tl_rows, comp_rows): + """打印统计报告""" + print("\n" + "=" * 60) + print("📊 知识点覆盖率统计") + print("=" * 60) + + print(f"\nTL 行(输入): {len(tl_rows)} 行") + print(f"组件行(输出): {len(comp_rows)} 行") + + print(f"\n{'知识点':<30} {'输入':>4} {'输出':>4}") + print("-" * 42) + + for item in knowledge_items: + word = item.get("word", "") + pattern = item.get("pattern", "") + + if word: + word_only = word.split()[0] + w_in = count_occurrences(word_only, tl_rows) + w_out = count_occurrences(word_only, comp_rows) + print(f"{word:<30} {w_in:>4} {w_out:>4}") + + if pattern: + p_in = count_pattern_occurrences(pattern, tl_rows) + p_out = count_pattern_occurrences(pattern, comp_rows) + label = pattern[:28] + ".." if len(pattern) > 30 else pattern + print(f" {label:<28} {p_in:>4} {p_out:>4}") + + # 质量检查 + print("\n" + "=" * 60) + print("🔍 用法质量快速检查") + print("=" * 60) + + for item in knowledge_items: + word = item.get("word", "") + if not word: + continue + word_only = word.split()[0] + w_out = count_occurrences(word_only, comp_rows) + w_total = count_occurrences(word_only, tl_rows) + w_out + + if w_total < 2: + print(f"\n⚠️ {word} — 仅出现 {w_total} 次,建议增加曝光") + elif w_total > 8: + print(f"\n💡 {word} — 出现 {w_total} 次,可适当精简") + + +# ── 主入口 ──────────────────────────────────────────── + +def main(): + if len(sys.argv) < 2: + print("用法: python3 knowledge_coverage_analyzer.py <飞书文档ID或URL>") + sys.exit(1) + + doc_id = parse_doc_id(sys.argv[1]) + print(f"📄 文档 ID: {doc_id}") + + # Step 1: 用 lark-cli 获取 markdown + print("📥 获取文档内容...") + md = fetch_markdown(doc_id) + + # Step 2: 解析知识点现状表格 + print("📋 解析「知识点现状」表格...") + knowledge_data = parse_markdown_table(md, "知识点现状") + if not knowledge_data: + print("❌ 未找到「知识点现状」表格") + sys.exit(1) + + # 表头: 单词, 输入, 输出, 句型, 输入, 输出 + knowledge_items = [] + for row in knowledge_data[1:]: # 跳过表头 + if len(row) < 6: + continue + word = row[0] + # 清理 markdown 格式:去掉列表符号 + word = re.sub(r'^[-*+]\s+', '', word).strip() + pattern = row[3].strip() + if not word and not pattern: + continue + knowledge_items.append({"word": word, "pattern": pattern}) + + print(f" 知识点: {len(knowledge_items)} 条") + for item in knowledge_items: + w = item["word"] or "(无)" + p = item["pattern"] or "(无)" + print(f" - {w} | {p}") + + # Step 3: 解析剧本主表 + print("\n📋 解析剧本主表...") + script_data = find_table_by_first_cell_md(md, "类型") + if not script_data: + print("❌ 未找到剧本主表(第一列第一行为「类型」)") + sys.exit(1) + + tl_rows = [] + comp_rows = [] + last_was_tl = True + for row in script_data[1:]: # 跳过表头 + if not row: + continue + type_text = row[0].strip() + # 排除「知识点」列(第6列,index 5)避免单词自计数 + row_text = " ".join(row[1:5] + row[6:] if len(row) > 6 else row[1:5]) + # 分类:类型列明确标记为 TL → 输入; + # 类型列包含交互关键词 → 输出; + # 空类型 → 继承上一行 + if type_text.startswith("TL"): + tl_rows.append(row_text) + last_was_tl = True + elif not type_text: + if last_was_tl: + tl_rows.append(row_text) + else: + comp_rows.append(row_text) + elif any(kw in type_text for kw in ("对话朗读", "对话挖空", "剧情任务", "对话", "挖空", "互动")): + comp_rows.append(row_text) + last_was_tl = False + else: + # 其他(场景描述等)归为 TL + tl_rows.append(row_text) + last_was_tl = True + + print(f" TL 行: {len(tl_rows)}, 组件行: {len(comp_rows)}") + + # Step 4: 获取 token + 回填 + print("\n🔑 获取 API Token...") + token = get_token() + + print("📝 查找表格 block ID...") + knowledge_table_id = find_table_block_id(token, doc_id, "知识点现状") + if not knowledge_table_id: + print("❌ 未找到「知识点现状」表格 block") + sys.exit(1) + + cell_ids = get_cell_block_ids(token, doc_id, knowledge_table_id) + col_count = 6 # 知识点现状表格固定6列 + print(f" 表格 block: {knowledge_table_id}, 共 {len(cell_ids)} 个单元格") + + print("\n📝 回填统计结果...") + fill_cells(token, doc_id, cell_ids, col_count, knowledge_items, tl_rows, comp_rows) + + # Step 5: 打印报告 + print_report(knowledge_items, tl_rows, comp_rows) + + print("\n✅ 完成!") + + +if __name__ == "__main__": + main()