🌐 English version: ARCHITECTURE.en.md
🧭 导航 · 🏠 首页 · PROJECT_STRUCTURE 目录结构 · 成本与限制 · 可观测性
🏷️ 类型:架构参考 · 时长:约 20 分钟 · 前置:完成教程 01~06
写给"想从全局理解项目"的读者。读完后你应该能用一张图画清本项目的模块关系。
| 目标 | 说明 |
|---|---|
| 学习驱动 | 每个概念都对应一个 examples/0x_*.py,所见即所学 |
| 工程化 | 提供 CI、测试、Makefile,安全(无 eval)、可复现(requirements.lock) |
| 渐进式 | 章节 01~06 由浅入深,每章建立在前一章之上 |
| 可扩展 | 公共能力放 _common.py,新增章节只需新增一个脚本 |
┌────────────────────────────────────────────────────────────┐
│ 用户 (User) │
└──────┬──────────────────────────────────┬──────────────────┘
│ 文档 │ 代码
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ docs/ │ │ examples/ │
│ 学习文档 │ │ 可运行脚本 │
│ (9 篇) │ │ (00~06 + common)│
└────────┬────────┘ └────────┬────────┘
│ │
│ 互为索引 │ import
└────────────┐ ┌───────────┘
▼ ▼
┌─────────────────────────┐
│ LangChain / 第三方库 │
│ - langchain 1.x │
│ - langchain-classic 0.x │
│ - openai / chroma ... │
└────────────┬────────────┘
│ 调用
▼
┌─────────────────────────┐
│ LLM Provider │
│ OpenAI / 第三方 / 本地 │
└─────────────────────────┘
辅助系统:
tests/ → pytest 离线 smoke 测试
.github/ → CI / Issue / PR / Release
data/ → 示例文档 + Chroma 持久化
notebooks/→ 交互式实验
用户问题
│
▼
[Retriever] ←————— Chroma 向量库(data/chroma/)
│ top-k chunks
▼
[format_docs] ←————— examples/_common.py::format_docs
│ "\n\n" 拼接
▼
[ChatPromptTemplate] ←————— RAG 提示词模板
│ {context} + {question}
▼
[ChatOpenAI] ←————— .env OPENAI_API_KEY / MODEL
│ AIMessage
▼
[StrOutputParser] ←————— 提取 content
│
▼
用户可见回答
7 个示例脚本共享 check_api_key / get_llm / get_embeddings / data_path / format_docs / _safe_eval,避免样板代码重复。
tests/ 下的 16 个测试覆盖:
- ChatPromptTemplate 拼装(纯字符串)
- format_docs 拼接(纯逻辑)
- 安全计算器(纯 AST 解析)
CI 用 OPENAI_API_KEY=dummy 占位即能跑通。
requirements.txt:宽松(>=)便于学习requirements.lock:严格(==)用于 CI / 复现
05_agents.py不用eval,用 AST 白名单.env已在.gitignore- SECURITY.md 给出"密钥泄露 → 轮换"流程
| 想加什么 | 改哪里 |
|---|---|
| 新示例 | examples/0x_xxx.py,按需复用 _common |
| 新笔记本 | notebooks/0x_xxx.ipynb |
| 新文档章节 | docs/0x-xxx.md + 在 README.md 目录树加入 |
| 新工具 | 在 _common.py 加 helper |
| 新 CI 任务 | .github/workflows/*.yml |
| 新测试 | tests/test_xxx.py |
- Ollama / 通义千问分支示例(
examples/07_ollama_local.py、examples/08_qwen.py) mkdocs文档站点(Material 主题 + GitHub Pages 自动部署)- Dockerfile 多阶段镜像
- LangGraph 替代
RunnableWithMessageHistory(见改进计划 P29) - RAG 评估与可观测性增强(见 P37 / P38)
uv替换pip、多向量库后端(见 P50 / P51)
完整文档:WEB_FRONTEND.md
web/ 是一个独立的 React 单页应用(SPA),与仓库的 LangChain 课程内容解耦但主题对齐。
它的职责是把课程数据(src/data/)以现代化交互呈现给用户,并把学习行为沉淀为本地状态。
┌────────────────────────────────────────────────────────────┐
│ 浏览器 (React SPA) │
└───────┬───────────────────────────┬──────────┬──────────────┘
│ 路由 (react-router) │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────────┐
│ 页面 Pages │ │ 布局 Layout │ │ 路由守卫 Guard │
│ 首页/课程/ │◄──消费────►│ Header/Footer│ │ RequireAuth │
│ 学习/账户/ │ └──────────────┘ └──────────────────┘
└──────┬───────┘
│ 组合
▼
┌────────────────────────────────────────────────────────────┐
│ 状态层 (src/store,Context + Hooks) │
│ ThemeContext ── 浅/深色主题 │
│ AuthContext ── 当前用户 / 登录注册 │
│ ProgressContext ── 学习进度(按 userId 分桶,持久化) │
└──────┬───────────────────────────────────┬─────────────────┘
│ │ 持久化
▼ ▼
┌──────────────┐ ┌──────────────────┐
│ UI 组件 / 播放器│ │ localStorage │
│ course/player │ │ (主题/账户/进度) │
└──────────────┘ └──────────────────┘
用户点击课时
│
▼
[LearnPage] 读取 URL ?l= 与 ProgressContext 当前课时
│ setCurrentLesson(courseId, lessonId)
▼
[VideoPlayer] <video> 加载;loadedmetadata 时跳到上次观看秒数
│ onTimeUpdate(每 ~3s)
▼
[updateWatchSeconds] 仅增不减地写入 ProgressContext
│ persist → localStorage(按 userId 分桶)
▼
[markComplete] 视频结束后标记完成 → 课程完成度重算 → 首页/进度页刷新
- 组件化 + 规范状态管理:全局状态收口到 3 个 Context,组件只通过
useXxx()消费,杜绝 prop drilling。 - 进度按用户隔离:
ProgressContext以userId为存储键分桶,登录/登出自动切换各自进度。 - URL 即状态:课程筛选(关键词/分类)与当前课时写入 URL(
searchParams),可分享、可后退。 - 零运行时 UI 依赖:样式用原生 CSS + 变量,图标自建 SVG,构建产物仅约 74KB(gzip)。
- 可扩展:新增课程只需在
src/data/courses.ts追加数据;新增页面只需在App.tsx注册路由。