Skip to content

教师工作台 Phase A:教学大纲 → 授课计划 → 课件生成 - #2

Open
codesoldier99 wants to merge 3 commits into
mainfrom
worktree-teacher-workbench
Open

教师工作台 Phase A:教学大纲 → 授课计划 → 课件生成#2
codesoldier99 wants to merge 3 commits into
mainfrom
worktree-teacher-workbench

Conversation

@codesoldier99

Copy link
Copy Markdown
Owner

做了什么

落地 DEVELOPMENT_PLAN.md 1.1 节"基础文档生成"的前三项,打通用户最看重的
那条链路:"授课计划出来后,系统可以生成授课的课件"。

  • packages/courseware/(新包):syllabus.py / teaching_plan.py / deck.py
    沿用 packages/agentsplan()/express() 二段式——章节怎么分、覆盖哪些知识点
    全部由确定性查询决定(复用 graph.algo.topological_sorttask.compute_gap 同款排序
    逻辑),大模型只负责把已经定好边界的内容说成人话。
  • 课件渲染两级降级:优先调用 OfficeCLI
    (外部 .NET 自包含二进制,纯确定性 OOXML 引擎,不含 LLM、不需要 API Key),
    不可用/调用失败时自动降级到 packages/courseware/pptx_writer.py——从
    scripts/make_deck.py 抽出的纯 stdlib 引擎,make_deck.py 现在也改为依赖它
    (避免同一段 OOXML 拼装逻辑存在两份)。教师任何时候都能拿到一份能打开的 pptx。
  • DeckPlan.kp_coverage():机器可验证"这份课件是否覆盖了授课计划要求的全部
    知识点",这是"质量高于纯 LLM 直接生成"的具体、可判定的落点。
  • apps/web/teacher/(新增独立页面):侧边栏三栏布局,7 个功能入口先上线
    教学大纲/授课计划/课件生成 3 个,其余标注"即将上线";复用现有 X-Auth-Token
    鉴权与 CSS 变量系统。主界面右上角新增入口(仅教师角色可见)。

架构守护

  • tests/test_layering.py 新增三条:courseware 的大模型 SDK 引入检查、
    掌握度直写检查、subprocess 收敛到 officecli_render.py 一处的检查。
  • 评卷等真正涉及学生状态的写入是 Phase B 的工作,本期 courseware 不建掌握度表、
    不碰 mastery_state
    ——已用静态检查兜底。
  • apps/api/microapi.py 新增 FileResponse(课件文件下载用),不影响现有 JSON 路由。
  • 新表(syllabus/teaching_plan/courseware_deckmigrations/003_courseware.sql
    按"教师可修订的教学设计文档"设计(version + superseded_by 版本链),不套用
    002_append_only.sql 的强制只追加触发器——那是给"不可篡改证据流"用的。

验证

  • make check / make test(112 用例,新增 11 个)/ make lint 全绿。
  • 真实 HTTP 全链路手测:POST syllabus → teaching-plan → deck → 文件下载
    产出的 pptx 通过 zipfile 校验、可正常打开、知识点全覆盖。
  • scripts/make_deck.py 重构后重新生成汇报 PPT,页数(12 页)与产物结构不变。

尚未做的(后续 PR)

试卷生成、评卷、成绩分析、达成度评价、课堂练习——前端已留好入口占位,
后端按 Phase B/C 的既定设计逐步补上。

🤖 Generated with Claude Code

新增 packages/courseware/(syllabus/teaching_plan/deck,沿用 agents 的
plan()/express() 二段式,复用 graph.algo.topological_sort 与 task.compute_gap
同款确定性排序)。课件渲染分两级:优先调用 OfficeCLI(外部 .NET 自包含二进制,
纯确定性 OOXML 引擎,不含 LLM、不需要 API Key),不可用时自动降级到
packages/courseware/pptx_writer.py——从 scripts/make_deck.py 抽出的 stdlib
引擎,make_deck.py 现在也依赖它,避免同一段 OOXML 拼装逻辑存在两份。
DeckPlan.kp_coverage() 提供机器可验证的知识点覆盖率校验。

新增 apps/web/teacher/ 独立教师工作台页面(侧边栏导航,复用 X-Auth-Token
鉴权与现有 CSS 变量系统,新增侧边栏专属变量),3/7 个功能入口已接后端,
其余标注"即将上线"。主界面 index.html 新增入口链接(仅教师角色可见)。

架构守护:
- tests/test_layering.py 新增 courseware 的 SDK 引入检查、掌握度直写检查、
  subprocess 收敛检查(三条防线均通过)
- 评卷等学生状态写入(Phase B)将只经 packages.state.tracker,本期
  courseware 不建掌握度表、不碰 mastery_state
- apps/api/microapi.py 新增 FileResponse 支持课件文件下载,不影响现有 JSON 路由

验证:
- make check / make test(112 用例)/ make lint 全绿
- 真实 HTTP 全链路验证:POST syllabus → teaching-plan → deck → 文件下载,
  产出的 pptx 通过 zipfile 校验且可正常打开
- scripts/make_deck.py 重构后重新生成汇报 PPT,页数与产物结构不变

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8a1bf2abb2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

"""整体替换某版大纲下的授课计划(重新生成即覆盖,不追加历史——
这是"计划"不是"证据流",教师改主意时不需要保留旧的每周安排)。"""
db = get_db()
db.execute("DELETE FROM teaching_plan WHERE syllabus_id=?", (syllabus_id,))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve deck references when replacing plans

When a teacher regenerates a teaching plan after creating a deck, this delete tries to remove teaching_plan rows that are still referenced by courseware_deck.teaching_plan_id from migrations/003_courseware.sql; with PRAGMA foreign_keys=ON, the request fails with FOREIGN KEY constraint failed before the new plan is inserted. This breaks the advertised “生成 / 更新授课计划” flow for any syllabus that already has generated courseware, so either cascade/archive the dependent deck rows or avoid deleting referenced sessions.

Useful? React with 👍 / 👎.

return plan, degraded

def render(self, plan: DeckPlan) -> AgentOutput:
out_path = DECK_OUT_DIR / f"deck_tp{plan.teaching_plan_id}" / "deck.pptx"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use unique files for repeated deck renders

Each render for the same teaching-plan item writes to the same deck.pptx, but every courseware_deck row stores that path and remains downloadable by deck_id. If a teacher regenerates a session deck, the new PPTX overwrites the file behind all earlier deck records, so old download links and their stored metadata no longer match the artifact. Make the output path unique per saved deck/generation, or save first and include the deck id in the filename.

Useful? React with 👍 / 👎.

codesoldier99 and others added 2 commits August 9, 2026 13:47
Bug 修复:授课计划页此前依赖"教师先访问过教学大纲页"才能拿到 syllabus_id,
刷新页面或直接点「授课计划」时会误判为"还没生成过大纲"。改为每个 view 进入时
独立、幂等地向后端拉取自己需要的数据(ensureSyllabus/ensureSessions/
ensureDeckDetail),不再依赖导航顺序。

对话式修订(新功能):大纲章节说明 / 授课计划环节说明 / 课件要点文字,
教师现在都能用一句自然语言指令让大模型改写,预览草稿后点「采纳并保存」才真正
落库——沿用 review.py"AI 建议、教师确认"的既有闸门模式。聊天只改"怎么说",
不改"有哪些知识点/哪几章/哪几页"这类结构事实,结构永远只能由各自的 plan()
重新生成(packages/courseware/chat.py 的模块docstring明确写了这条边界,
并有单测断言结构字段在聊天修订前后完全不变)。课件要点修订后可点「按当前文字
重新渲染文件」,走 DeckAgent.rerender(),只重渲染不重新规划结构。

顺带修了一个真实 bug:离线降级模式下修订课件要点时,把免责声明文字和原要点
拼在一起重新切分,导致最后一条被从中间截断——现在离线模式直接原样返回原
bullets,不再二次切分。

可点击流程条:① 教学大纲 → ② 授课计划 → ③ 课件生成 现在是可点击的按钮、
带箭头连接,点击直接跳转对应阶段;完成状态(done/now)根据真实数据算出,
不是写死的。

新增 apps/api/routes/courseware.py 三个接口:POST /chat(生成修订草稿)、
POST /chat/save(教师确认后落库)、POST /deck/{id}/rerender、
GET /deck/by-session/{teaching_plan_id}(切到已生成过课件的次课时直接看到内容,
不用重新点生成)。

验证:新增 4 个单测(含"离线模式不再切碎免责声明"的回归测试),
make test 116 用例全绿,make check 架构铁律通过;本地起服务用 curl 完整走了一遍
大纲→计划→课件→对话修订→保存→重渲染→下载文件的全链路,pptx 产出内容核对无误。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
问题:生产环境从未装过 OfficeCLI,课件生成一直走最简陋的降级路径
(纯标题+3~5条要点,零图表零层次),跟 Claude/DeepSeek/豆包直接生成的 PPT
比明显不够看。这次不等 OfficeCLI,先把我们完全能控制的确定性渲染引擎做扎实:

内容更深(LLM 更多介入,但仍然只管"怎么说"):
  - 每个知识点一页,一次 express() 调用要求模型按「一句话类比 / 讲解要点 /
    应用例子 / 易错点建议」四个字段回复(新增 packages/core/textfmt.py,
    复用 `- 字段:值` 这个系统里已有的接口约定去解析结构化回复,
    不引入 JSON mode——不是所有底座都稳定支持,也不需要)
  - "常见误区"优先取真实错误模式库数据(packages.errors.typical_errors_for),
    没有真实数据才用模型建议兜底,且 pitfalls_grounded 字段诚实标注来源,
    前端与渲染都要把两者区分开显示——这是"有深度"具体落在哪:
    不是编的例子,是往届学生真实错过的地方

真的有图:
  - 每份课件固定带一页"知识点难度分布"条形图,数据来自知识图谱标注,
    不依赖 LLM、不依赖学生数据,任何时候都能生成——原生 OOXML 矩形拼接画的
    真图表,不是拿表格假装图表

版式更专业:
  - 新增 pptx_writer.py 的 concept 布局(图标标题 + 类比高亮条 + 要点 +
    例子/易错点双色卡片)与 barchart 布局,都是新增分支,
    不影响 cover/twobig/section/常规页这些已有布局(含汇报 PPT 复用的那些)

验证:新增 4 个单测(含"离线模式下也要能渲得出合法 pptx"),
make test 119 用例全绿,make check 通过;逐页抽取真实生成的 pptx 文本内容
核对无误,且用了带真实错误模式的知识点验证了 pitfalls_grounded 正确区分
"真实数据"与"AI 建议"两种情况。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant