Skip to content

Commit bfe93b0

Browse files
committed
docs: align runtime and about-page architecture
1 parent 2b6873e commit bfe93b0

7 files changed

Lines changed: 296 additions & 84 deletions

File tree

README.md

Lines changed: 58 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
- 🔍 **跨学科搜索** — 搜索一个概念,按学科分组展示不同教材中的内容
1414
- 💡 **自动关联提示** — 检测到概念横跨多学科时,自动提示跨学科联系
1515
-**AI 跨学科解读** — 一键调用 Gemini,综合多学科教材内容生成带出处的解读
16-
- 🗺️ **知识图谱** — D3.js 力导向交互式图谱,可视化 784 个学术概念在 9 学科间的关联网络,支持缩放/拖拽/悬停高亮
17-
- 📊 **数据洞察**720 个精选学术术语的词频分析、学科关联热力图、考试覆盖分析、概念广度排名
16+
- 🗺️ **知识图谱** — D3.js 力导向交互式图谱,可视化 788 个学术概念在 9 学科间的关联网络,支持缩放/拖拽/悬停高亮
17+
- 📊 **数据洞察**726 个精选学术术语的词频分析、学科关联热力图、考试覆盖分析、概念广度排名
1818
- 📚 **教材下载** — 全部 316 本高中教材 PDF 可从 [jks.bdfz.net](https://jks.bdfz.net/) 下载
1919

2020
### 高级检索
@@ -30,15 +30,17 @@
3030

3131
| 指标 | 数值 |
3232
|------|------|
33-
| 教材总数 | **316 本**(人教版高中全科) |
33+
| 在线索引教材 | **63 本**(当前线上已入库教材语料) |
34+
| PDF 下载库 | **316 本**(独立教材下载区) |
3435
| 学科覆盖 | **9 科**:语文、数学、英语、物理、化学、生物学、历史、地理、思想政治 |
35-
| 结构化语料 | **70,007** chunks (包含 65,978 条教材知识 + **4,029 道高考真题**) |
36-
| 高考真题 | **4,029 道** (2010-2024 全国/地方卷 + gk.bdfz.net 北京卷语文,含 904 张多模态题图) |
37-
| 学术概念图谱 | **784**有效概念,1,714 条学科映射,83 个跨学科聚类 |
38-
| 精选术语 | **720**精选学术术语,2,825 条频次统计 |
36+
| 结构化语料 | **20,553**(教材 **16,524** + 高考真题 **4,029** |
37+
| 高考真题 | **4,029 道**`2002-2025`,其中 **651** 道含图题) |
38+
| 学术概念图谱 | **788**概念,1,723 条学科映射,83 条跨学科聚合记录 |
39+
| 精选术语 | **726**精选学术术语 |
3940
| 教材插图 | **87,156 张**(3.4 GB,由 R2 CDN 全球分发) |
40-
| FTS 索引大小 | **142 MB**(SQLite FTS5) |
41-
| Docker 镜像 | **467 MB**(仅代码 + 索引,图片走 CDN) |
41+
| FTS 索引大小 | **110 MB**(SQLite FTS5 运行库) |
42+
| FAISS 索引大小 | **65 MB**`BAAI/bge-m3`,16,524 向量) |
43+
| Docker 运行镜像 | **2.07 GB**(CPU-only,运行时数据和缓存走宿主机挂载) |
4244

4345
### 概念图谱各学科分布
4446

@@ -91,11 +93,12 @@
9193
│ └── Docker: textbook-knowledge
9294
│ ├── FastAPI 后端 (Python 3.13)
9395
│ ├── NLP/ML 引擎
94-
│ │ ├── BAAI/bge-small-zh-v1.5 ── 中文语义向量 (512D)
95-
│ │ ├── FAISS ── 65,978 向量稠密检索
96+
│ │ ├── BAAI/bge-m3 ── 多语言语义向量 (1024D)
97+
│ │ ├── FAISS ── 16,524 条教材向量稠密检索
9698
│ │ └── Jieba ── 中文分词 + 词性标注
9799
│ ├── 前端 (HTML/CSS/JS + D3.js + KaTeX)
98-
│ └── SQLite FTS5 索引 + 概念图谱 (142MB)
100+
│ ├── SQLite FTS5 检索库 (110MB)
101+
│ └── 宿主机挂载 data/index + state/cache
99102
100103
├── HTTPS → img.rdfzer.com (Cloudflare R2 CDN)
101104
│ └── 87,156 张教材原图(3.4GB,全球加速,免费出站)
@@ -110,19 +113,22 @@
110113
- `ai.bdfz.net` 是 Cloudflare Worker custom domain,实际绑定到 service `apis` / `production`
111114
- 在 Cloudflare Dashboard 里看到的 `apis` 是服务名,不是这个项目应优先暴露给用户的 canonical 域名
112115
- 详细说明见 [docs/ai_gateway_rule.md](docs/ai_gateway_rule.md)
116+
- 运行时与运维总览见 [docs/runtime_operations_overview.md](docs/runtime_operations_overview.md)
113117

114118
### Docker 内容
115119

116120
```
117-
/app/
121+
/app/ # 镜像内代码
118122
├── backend/main.py # FastAPI 应用
119123
├── frontend/
120124
│ ├── index.html # 主页(搜索/真题/图谱/数据/关于)
121125
│ └── assets/
122-
│ ├── style.css # 暗色主题 + 响应式(640px/380px)
123-
│ └── app.js # D3.js 图谱 + 高级搜索 + AI 解读
126+
│ ├── style.css
127+
│ └── app.js
128+
├── requirements.runtime.txt # 运行时 Python 依赖
129+
└── scripts/deploy_vps.sh # 生产发布脚本
124130
125-
/data/index/ # 宿主机挂载的运行时数据
131+
/data/index/ # 宿主机挂载的运行时检索资产
126132
├── textbook_mineru_fts.db # FTS5 索引 + 概念图谱
127133
├── textbook_chunks.index # FAISS 向量索引
128134
└── textbook_chunks.manifest.json
@@ -190,7 +196,11 @@ CREATE TABLE chunks (
190196
CREATE VIRTUAL TABLE chunks_fts USING fts5(text, content=chunks, content_rowid=id);
191197
```
192198

193-
**产物**`data/index/textbook_mineru_fts.db`**142 MB**
199+
**产物**
200+
201+
- `data/index/textbook_mineru_fts.db`**110 MB**
202+
- `data/index/textbook_chunks.index`**65 MB**
203+
- `data/index/textbook_chunks.manifest.json` → 运行时向量校验清单
194204

195205
### Phase 4: 概念图谱构建
196206

@@ -222,13 +232,9 @@ rclone sync data/images/ r2:textbook-images/orig/ --transfers 16 --progress
222232
### Phase 6: 部署
223233

224234
```bash
225-
# 构建 Docker 镜像(仅含代码 + FTS 索引,不含图片)
226-
docker build -t textbook-knowledge .
227-
228-
# 部署
229-
docker run -d --name textbook-knowledge \
230-
--restart unless-stopped \
231-
-p 8080:8080 textbook-knowledge
235+
# 生产推荐:运行带健康闸门和回滚的发布脚本
236+
chmod +x scripts/deploy_vps.sh
237+
RUNTIME_ROOT=/root/cross-subject-knowledge ./scripts/deploy_vps.sh
232238
```
233239

234240
---
@@ -242,13 +248,13 @@ docker run -d --name textbook-knowledge \
242248
| `data/raw_pdf/` | **31 GB** | 316 本原始 PDF | ❌ 需重新下载 |
243249
| `data/mineru_output/` | **101 GB** | MinerU OCR 产物 | ✅ 从 PDF 重新生成(~20h) |
244250
| `data/images/` | **3.4 GB** | 87K 张提取的教材图片 | ✅ 从 MinerU 产物提取 |
245-
| `data/index/` | **308 MB** | FTS 索引 + chunks JSONL | ✅ 从 MinerU 产物重建 |
251+
| `data/index/` | **175 MB** | 运行时 FTS + FAISS 索引 + manifest | ✅ 从 MinerU 产物重建 |
246252

247253
### 云端
248254

249255
| 服务 | 内容 | 大小 |
250256
|------|------|------|
251-
| VPS | Docker 镜像 + 容器(代码,运行时数据走挂载|1-2 GB |
257+
| VPS | Docker 镜像 + 容器(代码) |2.1 GB |
252258
| Cloudflare R2 (`img.rdfzer.com`) | 87,156 张跨学科教材原图及页面图 | 4.2 GB |
253259
| GitHub | 源代码 | < 1 MB |
254260

@@ -284,7 +290,8 @@ docker run -d --name textbook-knowledge \
284290
### 1. 资源存储隔离
285291
* **源代码 (GitHub)**:前端页面、后端 API、Dockerfile、各种配置。**绝对不含**庞大的数据库和图片。
286292
* **图片资源 (R2 CDN)**:所有的教材原图、单页截图等,托管在 Cloudflare R2 (`img.rdfzer.com`),全球加速分发,不消耗部署服务器 (VPS) 的带宽。
287-
* **检索数据库 (VPS 本地)**`textbook_mineru_fts.db` (全文检索) 和 `textbook_chunks.index` (向量索引),加起来 <500MB,存放于 VPS 本地 `data/` 目录,通过 Docker 挂载提供服务。
293+
* **检索数据库 (VPS 本地)**`textbook_mineru_fts.db``textbook_chunks.index` 和 manifest,存放于 VPS 本地 `data/index/`,通过 Docker 挂载提供服务。
294+
* **模型缓存 (VPS 本地)**:Hugging Face / sentence-transformers 缓存保存在 VPS 本地 `state/cache/`,不再烘进镜像。
288295

289296
### 2. 自动化部署 (GitHub Actions)
290297
项目利用 GitHub Actions 实现了完全自动化的持续部署:
@@ -311,7 +318,8 @@ docker run -d --name textbook-knowledge \
311318
### 本地运行
312319

313320
```bash
314-
pip install fastapi uvicorn sentence-transformers faiss-cpu jieba
321+
pip install -r requirements.runtime.txt
322+
pip install --index-url https://download.pytorch.org/whl/cpu "torch==2.10.0+cpu"
315323

316324
# 将 textbook_mineru_fts.db 和 textbook_chunks.index 放到 data/index/ 目录
317325
uvicorn backend.main:app --host 0.0.0.0 --port 8080
@@ -362,40 +370,45 @@ rclone sync data/images/ r2:textbook-images/orig/ --transfers 16
362370
python scripts/17_process_beijing_gaokao.py
363371

364372
# 8. 部署
365-
docker build -t textbook-knowledge .
366-
docker run -d -p 8080:8080 --restart unless-stopped textbook-knowledge
373+
chmod +x scripts/deploy_vps.sh
374+
RUNTIME_ROOT=/root/cross-subject-knowledge ./scripts/deploy_vps.sh
367375
```
368376

369377
---
370378

371379
## 🔄 VPS 迁移指南
372380

373-
### 最低配置
381+
### 运行规格
374382

375383
| 参数 | 最低 | 推荐 |
376384
|---|---|---|
377385
| CPU | 2 核 | 4 核 |
378-
| 内存 | 2 GB | 4 GB |
379-
| 磁盘 | 5 GB | 10 GB |
386+
| 内存 | 4 GB | 8 GB |
387+
| 磁盘 | 25 GB | 60 GB |
380388
| OS | Ubuntu 22.04+ | Ubuntu 24.04 |
381389
| Docker | 必须 ||
382390

391+
> 如果同机还需要执行 `docker build`、承载别的服务,或希望给模型缓存和回滚镜像留余量,建议直接用 **4 vCPU / 8 GB RAM / 80 GB SSD**
392+
383393
### 迁移步骤
384394

385395
```bash
386396
# 1. 克隆仓库
387397
git clone https://github.com/ieduer/cross-subject-knowledge.git
388398
cd cross-subject-knowledge
389399

390-
# 2. 获取 FTS 数据库(从旧容器或本机复制)
391-
docker cp textbook-knowledge:/app/data/index/textbook_mineru_fts.db data/
400+
# 2. 获取运行时目录
401+
mkdir -p /root/cross-subject-knowledge/data/index /root/cross-subject-knowledge/state/cache
392402

393-
# 3. 获取 FAISS 向量索引
394-
docker cp textbook-knowledge:/app/data/index/textbook_chunks.index data/
403+
# 3. 复制运行时检索资产
404+
cp /old-host/data/index/textbook_mineru_fts.db /root/cross-subject-knowledge/data/index/
405+
cp /old-host/data/index/textbook_chunks.index /root/cross-subject-knowledge/data/index/
406+
cp /old-host/data/index/textbook_chunks.manifest.json /root/cross-subject-knowledge/data/index/
395407

396-
# 4. 构建并运行
397-
docker build -t textbook-knowledge .
398-
docker run -d --name textbook-knowledge --restart unless-stopped -p 8080:8080 textbook-knowledge
408+
# 4. 运行发布脚本
409+
cd cross-subject-knowledge
410+
chmod +x scripts/deploy_vps.sh
411+
RUNTIME_ROOT=/root/cross-subject-knowledge ./scripts/deploy_vps.sh
399412

400413
# 5. 可选:nginx + SSL
401414
apt install -y nginx certbot python3-certbot-nginx
@@ -415,19 +428,19 @@ certbot --nginx -d your-domain.com
415428
| 公式渲染 | KaTeX | LaTeX 数学公式 |
416429
| 图片 CDN | Cloudflare R2 | `img.rdfzer.com` |
417430
| AI 解读 | Gemini (via Cloudflare Worker service `apis` / `production`) | `ai.bdfz.net`(custom domain) |
418-
| 容器 | Docker | 单文件部署 |
431+
| 容器 | Docker | CPU-only 运行镜像,运行时数据/缓存走宿主机挂载 |
419432
| 数据备份 | rclone → Google Drive / R2 | |
420433

421434
### 后端及发掘技术栈
422435

423436
| 组件 | 技术 | 说明 |
424437
|------|------|------|
425438
| 中文向量模型 | `BAAI/bge-m3` | 1024D 多语言/长文本嵌入,2.2GB,全面提升语义理解度 |
426-
| 向量检索 | `faiss-cpu` | 15,652 向量 IndexIDMap,61MB |
439+
| 向量检索 | `faiss-cpu` | 16,524 向量 IndexIDMap,65MB |
427440
| API 缓存 | `cachetools` | TTLCache (5min, maxsize=64) 加速读密集型高频 API |
428-
| 中文分词 | `jieba` + POS tagging | 启动时自动加载 `curated_keywords`720 个学术术语为高权重用户词典,精准切词 |
429-
| 自动部署 | GitHub Actions | 提交触发 CI/CD 自动连入 VPS 拉取并在 Docker 重建 |
430-
| 概念图谱 | SQLite `concept_map` | 784 个学术概念,跨学科自动发现 |
441+
| 中文分词 | `jieba` + POS tagging | 启动时自动加载 `curated_keywords`726 个学术术语为高权重用户词典,精准切词 |
442+
| 自动部署 | GitHub Actions + `deploy_vps.sh` | 干净 release checkout 构建、健康检查、失败回滚 |
443+
| 概念图谱 | SQLite `concept_map` | 788 个学术概念,跨学科自动发现 |
431444
| 全文检索 | SQLite FTS5 | Porter 分词器,OR 组合查询 |
432445
| 评分算法 | 自定义 `_score_result` | IDF 加权词项匹配 + 概念命中 + 同学科加分,阈值 ≥15 |
433446

backend/main.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1347,6 +1347,13 @@ def stats():
13471347
gaokao_by_subject = con.execute(
13481348
"SELECT subject, COUNT(*) as cnt FROM chunks WHERE source='gaokao' GROUP BY subject ORDER BY cnt DESC"
13491349
).fetchall()
1350+
ai_table_counts = {
1351+
"explanations": con.execute("SELECT COUNT(*) FROM ai_explanations").fetchone()[0],
1352+
"synonyms": con.execute("SELECT COUNT(*) FROM ai_synonyms").fetchone()[0],
1353+
"relations": con.execute("SELECT COUNT(*) FROM ai_relations").fetchone()[0],
1354+
"summaries": con.execute("SELECT COUNT(*) FROM ai_summaries").fetchone()[0],
1355+
"gaokao_links": con.execute("SELECT COUNT(*) FROM ai_gaokao_links").fetchone()[0],
1356+
}
13501357

13511358
result = {
13521359
"total_chunks": total,
@@ -1356,6 +1363,7 @@ def stats():
13561363
"gaokao_multimodal": gaokao_multimodal,
13571364
"subjects_count": len(dist),
13581365
"ai_model": AI_SERVICE_LABEL,
1366+
"ai_tables": ai_table_counts,
13591367
"faiss_enabled": faiss_index is not None,
13601368
"faiss_vectors": faiss_index.ntotal if faiss_index else 0,
13611369
"gaokao_year_range": [gaokao_years["min_y"], gaokao_years["max_y"]] if gaokao_years and gaokao_years["min_y"] else None,
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Runtime And Operations Overview
2+
3+
This document records the current runtime, data, and deployment boundaries of the textbook project.
4+
5+
## Machine roles
6+
7+
- Local development machine: code editing, data inspection, lightweight validation
8+
- Offline processing/build machine: OCR, FAISS rebuild, batch backfill, and large model downloads
9+
- Production VPS: serves search, graph, gaokao linkage, and AI chat APIs; does not run OCR or FAISS rebuild
10+
- Cloudflare R2: image and page asset delivery
11+
- Cloudflare Worker custom domain `ai.bdfz.net`: external AI gateway bound to Worker service `apis` / `production`
12+
13+
## Runtime assets
14+
15+
Production runtime depends on host-mounted directories instead of baking data into the image:
16+
17+
- `/root/cross-subject-knowledge/data/index/textbook_mineru_fts.db`
18+
- `/root/cross-subject-knowledge/data/index/textbook_chunks.index`
19+
- `/root/cross-subject-knowledge/data/index/textbook_chunks.manifest.json`
20+
- `/root/cross-subject-knowledge/state/cache/huggingface`
21+
- `/root/cross-subject-knowledge/state/cache/sentence_transformers`
22+
- `/root/cross-subject-knowledge/state/logs`
23+
- `/root/cross-subject-knowledge/state/batch`
24+
25+
## Current runtime profile
26+
27+
As of 2026-03-06:
28+
29+
- DB chunks: `20553`
30+
- Textbook chunks: `16524`
31+
- Gaokao chunks: `4029`
32+
- FAISS vectors: `16524`
33+
- Embedder: `BAAI/bge-m3`
34+
- Production image size: about `2.07 GB`
35+
- Host-side model cache: about `8.6 GB`
36+
- Steady-state container memory: about `1.2 GiB`
37+
38+
## Resource guidance
39+
40+
Recommended separation:
41+
42+
- OCR, MinerU, FAISS rebuild, and large batch enrichment stay on offline machines
43+
- Production VPS only handles runtime retrieval and API serving
44+
45+
VPS sizing:
46+
47+
- Minimum usable: `2 vCPU / 4 GB RAM / 25 GB SSD`
48+
- Recommended production: `4 vCPU / 8 GB RAM / 60 GB SSD`
49+
- If the same host also performs Docker builds for deployment or runs other services: `4 vCPU / 8 GB RAM / 80 GB SSD`
50+
51+
## Deployment flow
52+
53+
Current production deploy is:
54+
55+
1. Push to GitHub `main`
56+
2. GitHub Actions creates a clean temporary checkout on the VPS
57+
3. `scripts/deploy_vps.sh` builds a new CPU-only image
58+
4. Host model cache is reused or warmed before cutover
59+
5. Old container is replaced only after image build succeeds
60+
6. `/api/health` must pass or the script rolls back to the previous image
61+
7. Dangling images are pruned; only recent rollback tags are retained
62+
63+
## Operational watchpoints
64+
65+
- Disk pressure now mainly comes from host-side model cache and rollback images, not from the SQLite/FAISS runtime assets
66+
- Production should not be used for FAISS rebuild or MinerU OCR
67+
- The runtime DB and FAISS manifest must stay aligned; dense retrieval should remain gated if manifest validation fails
68+
- The production repo can contain hotfix history or manual changes, so deployment should always build from a clean release checkout rather than `git pull` into the runtime directory

0 commit comments

Comments
 (0)