AI 驱动的编程学习平台,用于清华大学第三届"智理杯"智能体大赛。
核心愿景:让学习者"按部就班做完就能学到 80 分,不需要额外努力"——通过伴随编程让知识"做中学"、随时可问 AI、系统化引导,即使课堂教学质量不高也能自学自救。
- 👤 登录 / 多用户:注册、登录(scrypt 密码哈希 + bearer token),课程/聊天按用户隔离,旧数据自动迁移给首个注册账号
- 🤖 Agentic 课程生成:输入想学的主题(如 "C++ 指针"),AI 智能体按 Skill 工作流生成课程
- DSH 原生 skill:模型调用
skill工具加载generate-course工作流,按主题复杂度决定讲次/Part 组合(多讲次、结构灵活、不套模板) - 结构灵活:简单主题少 Part,复杂主题拆多讲;每讲 ≥1 课件 + ≥1 检验类
- 工具内联校验:
create_part/edit_part写库前校验格式/字段/真实 g++ 编译,不合格 422 不落库,错误喂回 agent 修复重试(工具失败红色显示) - Part 类型校验:仅
courseware/quiz/accompanied/independent四类,未注册类型(臆造的lecture等)被拒,新增类型可在_PART_VALIDATORS注册 - 课程级终检:
validate_course检查每讲结构(课件+检验类、Part 数) - 质量对比:skill 路径逐步对齐/替代确定性管线(
generate_course保留为快速兜底)
- DSH 原生 skill:模型调用
- 📖 课件:PPT 式分页展示,方向键/按钮翻页,圆点导航
- 📊 课件示意图(AI 画图):agent 用
render_course_diagram为课件生成结构化 SVG(box_arrow框+箭头 /graph加权图含 Dijkstra 状态配色),多帧序列讲流程/算法演变,后端确定性渲染 + 资源服务 + 前端自动渲染;cairosvg 可用时用read_image视觉自检 - ❓ 选择题:交互式测验,即时判分(兼容字母/文本答案);答完后显示 AI 写的解析
- 💻 伴随编程:CodeMirror + 编译运行 + 终端 + 分步引导(含代码提示)
- 🏆 独立编程挑战:完整编程题,支持编写和运行测试
- ⚖️ OJ 判题:独立编程题「✅ 提交判题」——服务端隐藏测试用例评测,返回 AC/WA/TLE/RE/CE 总结果 + 逐 case 状态与耗时;样例 case 可展开看输入/期望/实际输出,隐藏 case 只显示状态;遇致命错误停止后续测试点;用例由 AI 生成(输入 + 参考解答实跑得期望输出),存服务端不下发
- 🕸️ 知识依赖 DAG:把课程概念/知识点做成一张有向无环图,保证不跳过前置知识点(生成侧蓝本 + 生成后校验)
- 三层校验:
validate_dag(抽象图结构:环/自环/悬空引用/拓扑序,确定性算法)/review_dag_completeness(前置是否列全,LLM 软校验,独立 LLM)/check_course_against_dag(课程是否符合 DAG:哪些概念没被覆盖=缺前置、顺序是否符合拓扑序) - skill:
build-course-dag(建 DAG)/complex-course(复杂课程:先建蓝图再生成课件穿插题目),generate-course引导"若复杂建议先建 DAG" - 前端可视化:课程详情页标题旁"DAG知识图谱"按钮 →
#/kg/课程id,力导向图渲染(G6 组件KG.mount:节点按类型着色、缺失前置红色高亮、点击节点中心高亮+关联边发散、图谱/树形双视图、搜索缩放、诊断问题面板点击定位;另有独立演示页kg.html双击即开);契约GET /api/courses/{id}/knowledge-graph返回nodes/edges/issues
- 三层校验:
- 💬 AI 助教:侧边栏常驻聊天(DeepSeek Harness 驱动)
- 流式输出:回复逐字流出(打字机效果 + 光标),代码块语法高亮(语言标签 + 复制)
- 工具调用活动流:实时显示 agent 调用的工具(
🔧卡片 + 耗时 + 回合统计),失败红色❌/成功绿色✅;可折叠:关掉开关只保留"进行中"的那条,减少杂乱 - 对话上传文档:📎 上传 PDF/Word/PPT/Excel/图片 → 存用户工作区(内容去重 / 相对路径脱敏 / 提图清单)→ agent 用 python/pdftotext/
read_image读取 - 知晓当前页面:
get_current_page工具让 agent 知道你在看哪(课程列表/详情/讲次,含标题),答疑更精准 - 停止按钮:生成中可中断,agent 真的停(不再后台偷偷建课)
- 历史服务端化:聊天历史以 DSH 会话为唯一事实源(稳定会话 id,dsh web 重启不丢),刷新/换设备都能恢复;localStorage 降级回退
- 🎨 主题:全站深色/浅色切换(默认深色),记忆偏好,代码块颜色随主题
- 🛡️ 代码沙箱:Linux/WSL 上运行任意代码时隔离(禁外网 + 降权 sandbox 用户 + 资源限制),防恶意代码影响宿主
- Python 3.10+
- g++(C++ 编译,MinGW 或 GCC)
- Node.js + npm(运行 DSH 桥接;本地用
DSH_NPM_DIR指向 dsh 安装目录) - pip
cd code
cp .env.example .env # 填入 DeepSeek API Key
pip install -r requirements.txt
export DSH_NPM_DIR=<你装 dsh 的目录> # Windows 本地示例:E:\...\dsh-npm-test
python -m backend.main打开浏览器访问 http://localhost:8000 → 注册/登录 → 生成课程、做题、用侧边栏 AI 助教。
macOS 本地运行请用
RUNNER_ISOLATION=off python -m backend.main(macOS 没有unshare,会被误判为 Linux 启用沙箱;Linux/WSL/Windows 不受影响)。
在 code/.env 中:
DEEPSEEK_API_KEY=sk-xxxx
DEEPSEEK_MODEL=deepseek-v4-flash
DSH 相关:DSH_NPM_DIR(bridge 默认 code/dsh/runtime,本地用环境变量覆盖);skill 文件在 ~/.dsh/skills/generate-course/(仓库源 code/dsh/skills/)。
/api/agent-dsh 和课程生成走 DSH(它负责 agent 循环、会话、事件流、调 DeepSeek)。只装 Python 依赖、不把 DSH 配好,AI 助教会报 network error(因为后端连不上 dsh web / 调不通 DeepSeek)。
第一步(必须,一次性):跑 DSH 初始化脚本——它负责把 DSH 本体、course-tools 插件、web profile 补丁、skills 一并装好:
- Windows:在
code/dsh下执行setup.bat(需 Node ≥ 20、npm、pnpm、以及环境变量DEEPSEEK_API_KEY)。它会:① 把@deepseek-ai/dsh装进code/dsh/runtime;② 装插件依赖;③dsh plugin --profile web add挂上 course-tools;④ 写~/.dsh/profiles/web/cordis.patch.yml(开 web 搜索 + 加载插件)。 - Ubuntu/云:
code/deploy/deploy.sh(同上 + 写~/.dsh/settings.yaml+ 复制 skills 到~/.dsh/skills/)。
之后设置 DSH_NPM_DIR 指向装好 dsh 的目录(即 code/dsh/runtime):
set DSH_NPM_DIR="<项目>/code/dsh/runtime" # Windows
# export DSH_NPM_DIR=<项目>/code/dsh/runtime # Linux/macOS运行时自动拉起:python -m backend.main 时 bridge 会用 DSH_NPM_DIR/node_modules/.bin/dsh web 自动启动 DSH(并继承环境变量里的 DEEPSEEK_API_KEY,.env 已被 load_dotenv 加载)。所以只需把初始化脚本跑对 + 设好 DSH_NPM_DIR。
常见坑(会导致 network error):
- 没跑
setup.bat/deploy.sh→code/dsh/runtime里没有dsh→dsh web起不来 → 3080 没监听; DSH_NPM_DIR指到一个没装@deepseek-ai/dsh的目录;- 首次起不来可手动在 DSH_NPM_DIR 里跑
dsh web看报错。
验证:浏览器开 http://localhost:3080 能看到 DSH web UI → DSH 正常;再进应用点 AI 助教能回复 → 全链路通。
后端无热重载,改后端代码需重启(python -m backend.main);前端代码通过 index.html 的 ?v= 版本号缓存,改前端后要 bump 版本号并强刷。
code/
├── start.sh # 一键启动
├── requirements.txt
├── .env.example
├── data/ # 运行时数据(gitignored):users/<uid>/{courses,lessons,parts}
├── backend/
│ ├── main.py # FastAPI 入口
│ ├── config.py # 环境变量
│ ├── auth.py # 登录/注册/token(scrypt)
│ ├── models.py # Pydantic 模型
│ ├── storage.py # 按用户隔离的 JSON 持久化
│ ├── validation.py # Part 级 + 课程级校验(内联 + validate_course)
│ ├── dag.py # 知识依赖 DAG 三层校验(validate/review/check + 可视化契约)
│ ├── generator.py # 确定性生成管线(4 件套快速通道)
│ ├── runner.py # 代码编译运行 + Tier 1 沙箱隔离(Linux/WSL)
│ ├── judge/ # OJ 判题(runner 编译一次逐case跑 + comparator 归一化比对 + service 汇总 + cases_store 用例生成)
│ ├── dsh_bridge.py # DeepSeek Harness 桥接(会话/事件流/history)
│ ├── llm.py # DeepSeek client 封装
│ ├── skills/ # Skill 机制(手搓 agent 路径用)
│ ├── tools/ # 工具注册表
│ └── routes/ # REST API 路由(含 auth/agent/generation/run/courses/dag)
├── dsh/
│ ├── course-tools-plugin/ # DSH 插件(course 工具 + DAG 工具,按会话 token 鉴权)
│ └── skills/ # skill 源:generate-course / zero-basics / read-document / build-course-dag / complex-course(复制到 ~/.dsh/skills/)
├── deploy/ # 云部署包(deploy.sh + README)
└── frontend/
├── index.html # App 外壳(hash 路由 + 聊天侧边栏 + 主题切换)
├── kg.html # 知识图谱可视化独立演示页(无需后端/登录)
├── kg-demo-data.json # 知识图谱演示数据(含缺失前置/顺序问题)
├── kg-README.md # 知识图谱前端说明(选库理由/接入方式)
├── css/styles.css
├── css/kg.css # 知识图谱组件样式
└── js/ # api/router/views/editor/chat/judge/kg-graph(G6)/markdown/state/main 等
另有 demo_v0/(早期 demo,保留)和 docs/(设计文档)。
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /api/register /api/login |
注册/登录(返回 token) |
| GET | /api/me |
当前用户 |
| GET/POST | /api/courses |
课程列表/创建 |
| GET/PUT/DELETE | /api/courses/{id} |
课程信息 |
| GET | /api/courses/{id}/structure |
嵌套结构(课程+讲次+Parts) |
| GET | /api/courses/{id}/knowledge-graph |
知识图谱可视化契约(nodes/edges/issues,供前端渲染) |
| POST | /api/courses/{id}/validate |
课程级结构终检(只读) |
| POST | /api/lessons / /api/parts |
创建讲次/Part(写前内联校验,422 不落库) |
| GET/PUT/DELETE | /api/lessons/{id} /api/parts/{id} |
讲次/Part 管理 |
| POST/GET/DELETE | /api/courses/{id}/dag |
DAG 创建/读取/删除(course 级成员,独立 JSON) |
| POST | /api/dag/node /api/dag/edge |
DAG 新增/更新概念节点、前置依赖边 |
| POST | /api/dag/node-delete /api/dag/edge-delete |
DAG 删除节点/边 |
| POST | /api/courses/{id}/dag/validate |
DAG 图结构自检(环/自环/悬空/拓扑序,确定性) |
| POST | /api/courses/{id}/dag/review-completeness |
DAG 前置列全(LLM 软校验,建议) |
| POST | /api/courses/{id}/check-against-dag |
课程是否符合 DAG(覆盖/顺序) |
| POST | /api/parts/{id}/link-dag |
回填"Part 覆盖了哪个概念"(covers) |
| POST | /api/generate-course |
确定性管线生成(4 件套兜底) |
| POST | /api/agent-dsh |
DSH agent(SSE 事件流:delta/tool/tool_result/reply) |
| POST | /api/agent-cancel |
停止当前回合 |
| GET | /api/agent-history |
该用户 DSH 会话历史事件(服务端事实源) |
| POST | /api/run-code |
编译运行代码(隔离/校验) |
| POST | /api/judge |
OJ 判题:提交代码,隐藏用例评测(AC/WA/TLE/RE/CE + 逐 case 结果,隐藏点脱敏) |
| POST | /api/parts/{id}/generate-cases |
为 independent Part 生成判题用例(AI 出输入+参考解答实跑) |
| GET | /api/parts/{id}/has-cases |
查询该 Part 是否已有判题用例 |
| GET | /api/courses/{id}/knowledge-graph |
课程知识图谱 JSON(nodes/edges/issues;后端团队负责,前端已就绪) |
docs/next_steps_plan.md— 技术路线图(Phase 1-5 状态)docs/phase3_detailed_plan.md— Phase 3 详案(沙箱 + 云部署 + WSL)docs/dsh_skill_course_design.md— DSH 原生 skill + 工具内联校验设计docs/chat_ui_redesign_notes.md— 聊天 UI 参考 DSH 的复刻清单docs/chat_history_server_side_design.md— 聊天历史服务端化设计docs/dsh_architecture_decisions.md— DSH 迁移架构决策docs/云服务器部署与使用说明.md— 云服务器部署说明docs/course_knowledge_graph_plan.md— 知识依赖 DAG 总纲(想法 + EduKG 调研 + 契约定义)docs/knowledge_dependency_generation_plan.md— 生成侧 DAG 详设(蓝本、skill、工具调用、校验分层)docs/knowledge_graph_frontend_spec.md— 知识图谱可视化前端分包需求docs/vision_and_material_translation.md、docs/skill_mechanism_design.md等
- 后端:Python FastAPI + uvicorn;scrypt 密码哈希;websocket-client(DSH 桥接)
- AI:DeepSeek(
deepseek-v4-flash),DSH(DeepSeek Harness)承载 agent 循环/会话/事件流/web 搜索 - 前端:原生 HTML/CSS/JS(hash 路由)+ CodeMirror 5 + marked.js + highlight.js
- 代码执行:g++(C++17)/ Python3(subprocess + Tier 1 沙箱隔离)
- 流式:SSE(Server-Sent Events)