# 《WaLiAPI - 本地 LLM API 网关》第3-3节:知识库数据模型与文档解析
作者:小傅哥
博客:https://bugstack.cn (opens new window)
沉淀、分享、成长,让自己和他人都能有所收获!😄
大家好,我是技术UP主小傅哥。
从这一节开始,我们进入知识库的核心——数据存储和文档解析。知识库不是简单的文本搜索,而是 文档 → 解析 → 分块 → 向量化 → 索引 → 检索 的完整流水线。这一节覆盖前半段:数据模型和文档解析。
# 一、本章诉求
- 设计知识库的数据库表结构(4个migration)
- 实现 Rust 数据模型(models.rs)
- 实现文档解析(parser.rs — 支持 txt/md/pdf/docx/代码文件)
- 实现文本分块(splitter.rs — 普通文本 + Markdown按标题分块 + 代码按符号分块)
- 实现 tree-sitter 符号感知代码解析(code_parser.rs)
- 实现数据库 CRUD(repository.rs)
# 二、数据库表结构设计
# 2.1 Migration 008 — 核心四表
知识库的核心是四张表,形成 知识库 → 文档 → 切片 的层级关系:
kb_knowledge_bases (知识库)
│ 1:N
kb_documents (文档)
│ 1:N
kb_chunks (切片 + 向量)
kb_tasks (处理任务)
1
2
3
4
5
6
7
2
3
4
5
6
7
008_knowledge_base.sql:
-- 知识库:一个知识库对应一个主题/项目
CREATE TABLE IF NOT EXISTS kb_knowledge_bases (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
description TEXT,
status INTEGER NOT NULL DEFAULT 1, -- 1=active, 0=disabled
doc_count INTEGER NOT NULL DEFAULT 0,
chunk_count INTEGER NOT NULL DEFAULT 0,
total_tokens INTEGER NOT NULL DEFAULT 0,
embedding_model TEXT, -- 向量模型名
embedding_channel_id TEXT, -- 向量渠道 ID
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
-- 文档:上传的每个文件是一条记录
CREATE TABLE IF NOT EXISTS kb_documents (
id TEXT PRIMARY KEY,
kb_id TEXT NOT NULL,
filename TEXT NOT NULL,
file_path TEXT, -- 本地文件路径(如果是导入)
file_type TEXT NOT NULL, -- pdf/txt/md/docx/code...
file_size INTEGER NOT NULL DEFAULT 0,
content_hash TEXT NOT NULL, -- SHA256,防止重复上传
chunk_count INTEGER NOT NULL DEFAULT 0,
token_count INTEGER NOT NULL DEFAULT 0,
status TEXT NOT NULL DEFAULT 'pending', -- pending/processing/ready/failed
error_message TEXT,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL,
FOREIGN KEY (kb_id) REFERENCES kb_knowledge_bases(id) ON DELETE CASCADE
);
-- 切片:文档被分块后的最小检索单元
CREATE TABLE IF NOT EXISTS kb_chunks (
id TEXT PRIMARY KEY,
doc_id TEXT NOT NULL,
kb_id TEXT NOT NULL,
chunk_index INTEGER NOT NULL, -- 分块序号
content TEXT NOT NULL, -- 分块文本内容
token_count INTEGER NOT NULL DEFAULT 0,
embedding BLOB, -- 向量数据(二进制)
embedding_dim INTEGER NOT NULL DEFAULT 0, -- 向量维度
metadata TEXT NOT NULL DEFAULT '{}', -- JSON元数据
created_at TEXT NOT NULL,
FOREIGN KEY (doc_id) REFERENCES kb_documents(id) ON DELETE CASCADE,
FOREIGN KEY (kb_id) REFERENCES kb_knowledge_bases(id) ON DELETE CASCADE
);
-- 处理任务:记录异步处理进度
CREATE TABLE IF NOT EXISTS kb_tasks (
id TEXT PRIMARY KEY,
kb_id TEXT NOT NULL,
doc_id TEXT,
task_type TEXT NOT NULL, -- embed/index/import
status TEXT NOT NULL DEFAULT 'pending',
progress INTEGER NOT NULL DEFAULT 0,
total_items INTEGER NOT NULL DEFAULT 0,
done_items INTEGER NOT NULL DEFAULT 0,
error_message TEXT,
created_at TEXT NOT NULL,
completed_at TEXT,
FOREIGN KEY (kb_id) REFERENCES kb_knowledge_bases(id) ON DELETE CASCADE
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
设计决策:
| 决策点 | 选择 | 原因 |
|---|---|---|
| 主键类型 | TEXT (UUID) | 避免自增ID暴露顺序信息,支持分布式场景 |
| embedding 存储 | BLOB | 向量是 f32 数组,用 bincode 序列化为二进制,比 JSON 存储节省 50% 空间 |
| 外键 | CASCADE | 删除知识库时自动删除关联文档和切片,避免孤儿数据 |
| content_hash | SHA256 | 防止重复上传同一文档,hash 相同则跳过 |
| status 字段 | pending→processing→ready→failed | 文档处理是异步的,需要状态追踪 |

