27 KiB
系统架构
状态: Draft
读者: 项目核心开发者、负责本地文档库和服务端实现的开发者
范围: 本地文档库、server、worker、数据库、文件处理、配置和生命周期
非目标: API 字段级定义;CLI 参数完整手册
来源: 由根目录旧技术设计底稿迁移整理而来,当前 mineru/doclib 代码已核对
DocVortex 引擎边界
通用文档引擎已抽为独立依赖 docvortex。MinerU 保留应用、推理和任务管理,原生解析、PDF 分类与基础访问、文档类型、确定性后处理、素材和 renderer 由 DocVortex 唯一维护。
MinerU Flash TXT ──→ DocVortex 原生分析 ──→ ModelJson
MinerU OCR/VLM/Hybrid ─────────────────→ ModelJson
↓
DocVortex 确定性后处理
↓
MinerU 可选 LLM 增强
↓
DocVortex Render
PDF 只有 auto 模式调用共享 classify;显式 txt 不分类,显式 ocr 保留已有推理路线。原生分析只由 Flash 分支调用。DocVortex 不反向依赖 MinerU。
DocVortex 内存对象和 JSON 使用中性 producer/extensions;MinerU 对外继续输出 schema 2.0,由兼容 codec 恢复产品元数据。所有持久化边界应使用 ParseResult 或明确的 MinerU codec,而不是直接写出 DocVortex 对象的原生封装。
1. 系统上下文
Next MinerU 的本地能力中心由 mineru doclib 和可选的 local parse-server 组成。
mineru CLI / MCP Server / MinerU.app
-> mineru doclib
- FastAPI + uvicorn
- Routes -> Services -> Core
- Background workers
- SQLite + FTS5
-> local parse-server
- 独立进程
- basic / standard / advanced tier
- HTTP API
doclib 是默认常驻的本地文档库服务,负责文件入库、SHA256 去重、解析任务调度、缓存、搜索、配置和本地 API。local parse-server 是可选独立进程,负责加载较重模型并执行 basic / standard / advanced 等质量 tier 解析。
Tier 的产品语义以 解析 Tier 为准;本文只描述它们在 doclib 和 ParseWorker 中的执行路径。
核心边界:
| 边界 | 选择 | 目的 |
|---|---|---|
| CLI/MCP/桌面端 -> doclib | HTTP + JSON over UDS or TCP loopback | UDS 优先;Windows Python 无 UDS 时自动 fallback 到 TCP |
| doclib -> local parse-server | HTTP + JSON over TCP loopback | 进程隔离,允许 GPU 模型崩溃不拖垮 doclib |
| doclib 存储 | SQLite WAL + FTS5 | 零运维、单文件、支持全文检索 |
| 任务队列 | DB rows + timestamp lock | 无外部依赖,崩溃后可恢复 |
| CPU 密集操作 | asyncio.to_thread() |
避免阻塞 async worker |
默认通道:
| 通道 | 地址 | 用途 |
|---|---|---|
| UDS | $MINERU_HOME/doclib.sock |
CLI、MCP、桌面端访问 doclib,UDS 可用时默认启用 |
| TCP | 127.0.0.1:15980 |
UDS 不可用时访问 doclib 的本地 fallback |
| endpoint discovery | $MINERU_HOME/doclib.endpoint.json |
CLI / SDK 发现 doclib 实际可用 transport |
| TCP | 127.0.0.1:16580 |
doclib 调用 local parse-server |
| TCP 随机端口 | 127.0.0.1:<random> |
P1 Web UI |
2. 模块分层
doclib 内部采用三层结构:
Routes
-> Services
-> Core
| 层级 | 职责 | 约束 |
|---|---|---|
| Routes | HTTP 路由、参数校验、响应格式化 | 不直接承载业务状态 |
| Services | 业务逻辑、状态管理、跨模块协调 | 组织 parse/search/config/cleanup 流程 |
| Core | SQLite、FTS、文件 IO、metadata 提取 | 不感知 CLI/API 产品语义 |
主要 service:
| Service | 职责 |
|---|---|
ParseService |
接收解析请求、同步入库、查缓存、创建解析任务 |
SearchService |
文件名和内容搜索 |
ConfigService |
KV 配置、watch 目录、parsing-rules、exclude 规则 |
CleanupService |
孤儿文档、删除文件和解析缓存清理 |
当前 doclib HTTP API 统一挂在 /api/v1 前缀下。对外稳定边界以 doclib public models 和 SDK client route 为准,主要资源包括 /server/status、/parses、/invalidate、/forget、/scans、/files、/docs、/search、/find、/configs、/watches、/exclude-rules、/parsing-rules、/cleanup/* 和 /telemetry/*。
后台组件:
| 组件 | 并发 | 职责 |
|---|---|---|
WatchLoop |
1 | 监听文件系统变化 |
IngestWorker |
2 | 计算 SHA256、提取 metadata、写 files/docs、触发默认 parse |
ParseWorker |
2 | 执行解析任务并写入产物 |
ParseServerHealthCheck |
1 | 探测 local/remote parse-server 健康状态 |
DeviceMonitor |
1 | 检测可插拔 watch 路径 |
Compaction |
1 | 合并已完成 parse 批次 |
ScanWorkerPool |
1 | 执行排队的文件系统 scan 任务 |
TelemetryFlushLoop |
1 | 按固定间隔批量上报 telemetry |
所有后台组件都是 asyncio task,随 server 启停。
3. 数据模型
doclib 的核心数据模型围绕三张表展开:
| 表 | 粒度 | 作用 |
|---|---|---|
files |
文件路径实例 | 记录路径、文件状态、watch 来源和对应 sha256 |
docs |
文档内容 | 以 SHA256 去重,记录文档级 metadata |
parses |
一次解析请求 | 记录 tier、page_range、privacy、状态和错误 |
3.1 files
files 表表示本机看到的文件实例。同一份内容可能有多个路径,因此 files.sha256 指向 docs.sha256。
关键字段:
| 字段 | 含义 |
|---|---|
path |
本地文件绝对路径,唯一 |
filename / ext / size_bytes / mtime_ms |
文件基础信息 |
sha256 |
入库后关联到 docs |
watch_id |
来源 watch 目录 |
status |
active / deleted / unreachable |
locked_at |
IngestWorker 抢占锁 |
error_code / error_msg |
文件级错误 |
status 表达路径可达性,而不是 doc 生命周期:
| 状态 | 含义 | 默认搜索可见 | 是否保护 doc |
|---|---|---|---|
active |
路径当前存在且可访问 | 是 | 是 |
unreachable |
所属 removable watch 当前不可达 | 否 | 是 |
deleted |
路径已确认不存在,且不是设备整体不可达导致 | 否 | 是 |
只有当某个 doc 没有任何 file row 关联时,才算 orphan。deleted file row 在被清理前仍保留 sha256 并保护 doc。完整规则见 ADR-0007。
普通文档列表只展示 active docs,即至少被一个 status=active file row 引用的 doc。被 deleted / unreachable file row 保护的 doc 不算 orphan,但也不进入 GET /docs / mineru list docs 的默认结果。
3.2 docs
docs 表表示按内容去重后的文档。
关键字段:
| 字段 | 含义 |
|---|---|
sha256 |
文档内容主键 |
file_type / page_count |
入库阶段尽量提取;file_type 是短类型名,例如 pdf / docx |
title / author / subject / keywords |
文档 metadata,做保护性截断 |
is_image_based |
文档是否以页面图片为主,缺少可用文字层 |
meta_tier |
当前 metadata 来源 tier |
error_code / error_msg |
内容身份级错误,例如加密、损坏、metadata 失败 |
metadata 更新规则:入库阶段写基础 metadata;解析完成后,只有当新结果的 tier 不低于当前 meta_tier 时才覆盖。
3.3 parses
parses 表表示解析任务和缓存记录。同一 sha256 + tier 可以有多行,用于增量页码解析和 force 重解析。
关键字段:
| 字段 | 含义 |
|---|---|
sha256 |
指向文档内容 |
tier |
实体 tier:flash / basic / standard / advanced;未指定 tier 应在入队前或执行前解析为实体 tier |
page_range |
正值页码范围字符串,如 1-5,46-50 |
status |
pending / parsing / done / failed / superseded |
priority |
Agent 同步请求高于 watch 后台任务 |
privacy |
用户请求偏好:local / remote |
via |
实际执行路径:local / remote |
error_code / error_msg |
解析级错误 |
缓存键为 (sha256, tier),不区分 privacy 和 via。同一内容、同一 tier 的本地与远端产物应视为等价缓存。
3.4 辅助表
| 表 | 作用 |
|---|---|
fts_contents |
内容全文搜索;解析内容保留最高 tier 文本,text 源内容的 tier 为 null |
fts_filenames |
文件名搜索 |
watches |
监控目录、可插拔设备状态 |
exclude_rules |
exclude 路径规则 |
parsing_rules |
parsing-rule 路径规则 |
scans |
scan 任务表与轻量 scan log |
telemetry_state |
telemetry 上报状态(consent、上次 flush 等) |
telemetry_aggregates |
待上报 telemetry 聚合数据 |
config |
SQLite KV 配置 |
_migrations |
schema 版本追踪 |
SQLite 运行在 WAL 模式,使用 FTS5 提供搜索能力。每次 DB 操作打开独立 aiosqlite 连接,提交后关闭,避免跨 worker 游标冲突。WAL mode 只在初始化时设置;运行期连接配置显式 busy timeout。单 doclib 进程内的写操作通过共享写锁串行化,普通读取保持并发;SQLITE_BUSY / SQLITE_LOCKED 使用有上限的指数退避重试,耗尽后对外返回可重试的 server_busy。
4. 数据流
4.1 两阶段模型
所有内容提取都归入 parse 概念,但内部拆成两个阶段:
阶段 1: 入库
-> 计算 SHA256
-> 提取基础 metadata
-> 写入 files/docs
-> 写入 fts_filenames
-> 根据 watch 默认 tier 或 parsing-rules 创建 parses 任务
阶段 2: 解析
-> flash: 本地轻量解析
-> 默认选择: 通过 parse-server 能力发现解析为质量 tier
-> basic/standard/advanced: local 或 remote parse-server
-> 写 parsed artifacts
-> 更新 fts_contents
-> 更新 parses/docs 状态
这样用户无需理解“索引”和“解析”两个概念;不同 tier 只是解析深度和执行路径不同。
注意:flash 是 watch 自动发现和搜索索引的低成本 tier,不应作为 PDF/image 主动阅读时的默认最终质量。PDF/image 主动阅读未指定 tier 时应使用默认选择策略;有能力发现上下文时按 standard -> basic 解析。OFD/EPUB/Office/HTML/MHTML/CSV/TSV 的归一规则见 ADR-0024、ADR-0028 与 ADR-0032;其它 text 只入库和索引,直接读取源文件。
4.2 文件发现到入库
文件可以来自 watch,也可以来自显式 mineru parse <path>、mineru show file <path>、GET /docs/by-path?path=... 或 invalidate(path=...)。
所有 source file path 入口在使用 files.sha256 前,都必须先执行统一文件发现/刷新步骤:
- 按扩展名白名单和 exclude 规则过滤。
- 对 path 执行轻量 stat,读取
size_bytes和mtime_ms。 - 如果 path 不存在于 active
files,插入记录并设置sha256=NULL。 - 如果 path 已存在且
mtime_ms、size_bytes均未变化,不做重新入库。 - 如果 path 已存在但
mtime_ms或size_bytes变化,更新文件 stat,清空files.sha256、锁和错误字段。 IngestWorker通过原子 SQL 抢占status=active AND sha256 IS NULL的文件。
birthtime_ms 暂不进入 P0。文件创建时间在不同平台上的语义和可用性不一致,目前还没有明确的产品或 Agent 行为依赖它;P0 不记录该字段,也不使用它参与文件变化判定。
7. 计算 SHA256,提取 metadata。
8. INSERT OR IGNORE 到 docs。
9. 更新 files.sha256,释放锁。
10. 更新文件名索引,并根据文件类型、watch 默认策略或 parsing-rules 创建 parses 任务。
必须执行文件变化检查的用户 path 操作:
| 操作 | 入口 |
|---|---|
| 主动解析 | POST /parses / SDK ensure_parse() / mineru parse <path> |
| 文件信息 | GET /files/by-path?path=... / SDK get_file_by_path() / mineru show file <path> |
| 按路径取文档 | GET /docs/by-path?path=... / SDK get_doc_by_path(path) |
| 按路径失效解析 | POST /invalidate { path } / SDK invalidate(path=...) / mineru invalidate <path> |
watch 流程也调用同一发现/刷新步骤:
WatchLoop收到文件事件或执行初始扫描。- 按扩展名白名单和 exclude 规则过滤。
- 调用统一文件发现/刷新步骤。
删除和不可达检测同样属于统一发现/刷新:
- watch file event、所有 scan 操作和上述 4 个同步 path 操作,都必须检查 path 当前是否存在。
- 如果 path 不存在,且所属 removable watch root 不可达,则标记为
unreachable。 - 如果 path 不存在,且不是设备整体不可达导致,则标记为
deleted,写入deleted_at,保留sha256。 - 标记
deleted或unreachable时不清理 FTS;find 默认只返回 active file。search JSON 返回全部 file aliases 及状态,非 JSON CLI 才使用 active 优先展示。
失败时按错误绑定对象写入对应层级:
- 路径实例当前不可读、权限不足、stat / SHA256 读取失败: 写入
files.error_code/files.error_msg。 - 已经计算出 SHA256,但内容本身无法完成基础 metadata 识别、加密或损坏: 写入
docs.error_code/docs.error_msg。 - 某次 parse batch 执行失败: 写入
parses.error_code/parses.error_msg。
4.3 解析请求到任务
显式解析请求流程:
- CLI 或 SDK 调用 doclib
POST /parses。 ParseService先执行文件发现/刷新,确认 path 当前状态。- 如文件需要重新入库,则等待或同步完成入库,获得当前
sha256。 - 查询
(sha256, tier)下已完成批次;PDF 判断 page_range 覆盖,非 PDF 只接受完整整文件 batch。 - 缓存命中则返回
cache_hit=true和空wait_parse_ids。 - 已有 active parse 覆盖的页复用并提升
priority。 - 未覆盖页插入新的
parses记录,Agent 请求使用更高priority。 ParseWorker抢占任务并执行。
--force 对本次请求不复用 done 缓存,但可以复用已存在的 active parse。它不删除、不作废旧的 done 记录。增量页码解析和 force 重解析都通过多行 parses 表示。读取时只合并有效 done 批次;同一页出现多次时,按 done_at 选择最新有效页面。
POST /invalidate 是独立的缓存生命周期动作。第一版要求 target="parses"。被 invalidate 的记录不参与缓存覆盖判断、读取合并、搜索索引刷新和 compaction;对应 JSON 文件的物理删除由 cleanup 或 Compaction 后台完成。
4.4 ParseWorker 路由
ParseWorker 按 tier、privacy 和 parse-server 健康状态路由:
| 条件 | 执行路径 |
|---|---|
| 未指定 tier | PDF/image 通过当前目标 parse-server 能力发现,按 standard -> basic 解析;OFD/EPUB/Office/HTML/MHTML/CSV/TSV 归一为 flash;其它 text 直接读取 |
tier=flash |
直接本地调用轻量 parser,via=local |
tier=basic/standard/advanced 且 privacy=remote |
优先调用 config 中的远端地址,默认使用 https://mineru.net/api |
| remote 不可用 | 尝试 fallback 到 local parse-server |
privacy=local 且 local parse-server disabled |
返回 no_engine |
| local parse-server 配置但探活失败 | 返回可重试错误 |
| parse-server 不支持请求 tier | 返回 tier_mismatch |
关键约束:
- 用户显式
--remote才允许上传文档。 - PDF/image 未指定 tier 使用默认选择策略,但永远不会降级到
flash。 - 远端解析失败且属于文件损坏、加密等非网络错误时,不 fallback 到本地。
- 重试时保持原始
privacy不变。 via只在解析完成后写入,避免失败记录误导。
5. 产物与搜索
解析产物按 sha256、实际使用的 tier 和解析页码批次隔离存储。doclib 的 parsed/ 目录持久化 Middle JSON 批次文件,并可保存解析结果引用到的图片 sidecar:
~/.mineru/
config.yaml
doclib.endpoint.json
doclib.sock
doclib.db
logs/
doclib.log
doclib.access.log
doclib.stdout.log
doclib.stderr.log
doclib/
temp/
parsed/
ab/
ab3f...7e2d/
flash/
1-5_1710000000000.json
98-102_1710000123000.json
basic/
1-10_1710001234000.json
11-20_1710002234000.json
images/ # 仅在解析结果包含必要 sidecar 时存在
standard/
1-20_1710003234000.json
advanced/
1-20_1710004234000.json
每个 JSON 文件表示一次解析批次,文件名由页码范围和完成时间组成。每个 tier 独立目录,互不覆盖。remote 解析完成后也写入同一结构,供 CLI、SDK、搜索和缓存统一读取。
doclib 不在 parsed/ 中保存 Markdown、Content List 或 HTML。它们都从 Middle JSON 读取时转换得到;搜索索引可以使用临时渲染出的 Markdown 文本,但不把这份 Markdown 保存为产物文件。PDF 和 image 通常不保存 block 图片,读取时从源页面按 bbox 裁剪;Office 等后端只有在解析结果包含图片时才保存 images/ sidecar。
搜索策略:
fts_filenames用于文件名搜索。fts_contents用于正文、标题和作者搜索,同一文档只保留一份内容,不存储或匹配 filename。解析内容记录实际 tier,直接索引的 text 源内容记录tier=null。- 内容超过 30K 字符时,保留 head + tail,完整内容仍从解析产物读取。
- 中文分词采用 jieba + FTS5
unicode61的组合方案。
6. Server 生命周期
6.1 启动
启动顺序:
- 获取
$MINERU_HOME/doclib.lock,独占当前 home。 - 清理 stale endpoint 和 UDS socket。
- 原子写入包含当前 PID、
server_id和空 transports 的 endpoint,供启动阶段诊断。 - 启动本地 HTTP transport,并用实际 transports 原子更新 endpoint。
- 创建
data_dir。 - 初始化 SQLite schema、migration 和种子配置。
- 清理 stale ingest 锁。
- 将崩溃前
parsing状态任务标记为failed并释放锁。 - 创建 services。
- managed 模式下启动 local parse-server。
- 启动后台 asyncio tasks。
6.2 关闭
关闭顺序:
- 通知后台任务停止,等待当前任务收尾。
- managed 模式下终止 local parse-server。
- 关闭数据库资源。
- 在仍持有
doclib.lock时尝试清理 socket 和 endpoint discovery 文件。 - 释放
doclib.lock;lock 文件本身是否保留属于平台实现细节。
CLI 的 stop/restart 同时等待 endpoint 不可连接和 ownership lock 可重新获取,并在临时持有该锁时兜底清理 discovery 文件; 不能只用 endpoint 消失判断 shutdown 完成。
6.3 崩溃恢复
server 启动时执行恢复:
| 恢复动作 | 目的 |
|---|---|
清空 files.locked_at |
释放未完成 ingest 锁 |
parsing -> failed |
避免解析任务永久卡住 |
| 检查已入库文件是否仍存在 | 标记 deleted 或 unreachable |
| 检查 managed parse-server | 不存在则自动拉起,连续失败降级 disabled |
7. 配置管理
doclib 启动期配置由 YAML / 环境变量管理,运行期策略配置由 SQLite config 表和 mineru config 管理。
基础配置:
| key | 默认值 | 说明 |
|---|---|---|
data_dir |
~/.mineru/doclib |
数据目录 |
scan_interval_sec |
300 |
watch 全量扫描间隔 |
ingest_lock_timeout_sec |
60 |
ingest 锁超时 |
parse_lock_timeout_sec |
1800 |
parse 锁超时 |
parse-server 配置:
| key | 默认值 | 说明 |
|---|---|---|
parse_server.local.mode |
disabled |
disabled / managed / self_hosted |
parse_server.local.managed_tier |
standard |
managed 模式的启动能力上限;只允许 basic / standard,Standard 同时提供 Advanced 请求能力 |
parse_server.local.self_hosted_url |
无 | self-hosted 地址 |
parse_server.remote.url |
https://mineru.net/api |
默认远端地址 |
parse_server.remote.api_key |
无 | 远端 API Key |
API Key 优先级:config 表中的 API Key 高于环境变量 MINERU_API_KEY;环境变量仅作为未配置 API Key 时的默认值。
除 API Key 等运行时凭证另有说明外,配置优先级统一为:CLI 参数 > 环境变量 > 文件配置 / SQLite 配置 > 内置默认值。启动前文件配置和 SQLite 配置不应定义同一配置项;需要在 doclib server 启动前确定的配置使用文件配置,运行时可变配置使用 SQLite。
Watch、parsing-rules 和 exclude 规则也由 CLI 写入 SQLite。Parsing-rules 不得导致静默上传:只有规则显式允许 remote 时,才可以走远端解析。
8. 文件类型与处理策略
当前代码中的 watch discoverable 文件类型包括:pdf、ofd、epub、doc、docx、ppt、pptx、xls、xlsx、rtf、odt、ods、odp、html、htm、shtml、mhtml、mht、csv、tsv、md、markdown、rst、tex、txt。图片不在 watch 白名单中,但可以通过显式 mineru parse image.png 触发。Apple 文档、其它电子书和邮件格式暂不在当前 discoverable 白名单内。
处理路径:
| 类型 | 策略 |
|---|---|
| 纯文本 | 直接读取,无需模型解析 |
| Image | 按 tier 路由到默认选择 / flash / basic / standard / advanced,但整文件解析并拒绝显式 page_range |
| OFD / EPUB / Office / HTML / MHTML / CSV / TSV | 本地 CPU Flash 整本解析;显式 page_range 拒绝 |
| 按 tier 路由,并支持增量 page_range 解析和缓存 |
9. 错误与恢复
9.1 可插拔设备恢复
DeviceMonitor 只对 removable=1 的 watch target 做设备可达性判断。
设备不可达时:
- watch target 标记为
unreachable。 - 该 watch 下
activefiles 标记为unreachable。 - 不删除 file row、doc、parse cache 或 FTS。
设备恢复时:
- watch target 标记为
active。 - 该 watch 下
unreachablefiles 标记为active。 - 立即对该 watch 执行一次 scan: 文件仍不存在则标记
deleted;文件 stat 变化则清空sha256等待 ingest;文件未变化则保持当前绑定。
9.2 Cleanup 边界
deleted file cleanup 与 orphan doc cleanup 是两个独立动作。
- deleted file cleanup 只删除
status='deleted'的 file row,并清理对应fts_filenames。 - 手动 cleanup deleted 立即删除所有 deleted file rows。
- 后台 cleanup deleted 固定保留 7 天后删除。
- deleted cleanup 不自动删除 docs、parses、parsed JSON 或
fts_contents。 - orphan doc cleanup 只处理完全没有任何 file row 关联的 docs;执行时才删除 docs、parses、
fts_contents和 parsed JSON。
fts_filenames 生命周期跟随 files row;fts_contents 生命周期跟随 docs row。
9.3 Forget Path
forget 是显式移除 doclib path 记录的维护动作。
forget删除匹配的filesrow,并清理对应fts_filenames。forget不删除真实磁盘文件。forget不删除docs、parses、parsed JSON 或fts_contents。- 如果最后一个 file row 被 forget,对应 doc 会成为 orphan,由
cleanup orphan-docs后续处理。 - 如果 path 是目录,P0 永远递归匹配该目录树下的 file rows,不提供
recursive参数。 - 如果 path 是已配置 watch root,默认拒绝;应先执行 watch remove。
- 如果 path 位于 active watch root 下,允许 forget,但后续 scan 可能重新发现。
forget不是 ignore rule,也不是 invalidate。
完整规则见 ADR-0008。
9.4 Scan Task
scan 是 doclib server 侧后台任务。
核心边界:
- CLI / SDK / HTTP 只创建 scan task 和查询状态,不直接执行扫描。
- watch initial scan、watch rescan、设备恢复后的 watch scan 都复用
ScanService + ScanWorker。 scans表同时作为任务表和轻量 scan log。- scan 不同步执行 ingest;新文件或变化文件通过
files.sha256=NULL进入 ingest worker。 - scan status 为
pending/running/done/failed,P0 不做 cancelled。 - scan kind 为
manual/watch。 - source 是 best-effort 记录字段,P0 不作为行为依据。
P0 API:
POST /scansGET /scansGET /scans/{scan_id}
完整规则见 ADR-0009。
9.5 错误分类
错误按层级存储和恢复:
| 层级 | 示例 | 存储位置 | 恢复策略 |
|---|---|---|---|
| File | 路径不存在、权限不足、文件被锁、SHA256 读取失败 | files.error_code |
清除锁后可重试 |
| Doc | 文件损坏、加密、metadata 读取失败、内容不可识别 | docs.error_code |
不自动重试,除非文件内容变化或用户显式重试 |
| Parse | 引擎崩溃、超时、OOM | parses.error_code |
标记 failed,可由用户或策略重试 |
| Parse-server | 探活失败、服务不可用 | parses.error_code |
可重试,保留 privacy |
错误归属按对象划分,而不是按代码调用栈划分:
files.error_*: 这个 path 实例当前有问题。docs.error_*: 这个sha256内容身份本身有问题。parses.error_*: 这一次 tier/page_range parse batch 有问题。
如果 ParseWorker 根据 sha256 找不到任何 active file,当前 parse batch 应写 parses.error_code=no_accessible_file。如果它找到了 file row 但 path 已不可读,还应同步更新 file 的可达性或 file 级错误。
parse-server 相关错误:
| code | 含义 | 可重试 |
|---|---|---|
quality_tier_unavailable |
PDF/image 主动阅读需要质量 tier,但只有 flash 可用 |
否 |
no_engine |
本地请求质量 tier,但 local parse-server disabled | 否 |
engine_unavailable |
local parse-server 已配置但探活失败 | 是 |
parse_server_unavailable |
remote 不可用且 local fallback 不可用 | 是 |
tier_mismatch |
parse-server 不支持请求 tier | 否 |
parse_failed |
文档损坏、加密等解析失败 | 否 |
internal_error |
parse-server 500 | 否 |
完整错误模型、retryable 和 user_action 见 错误码体系。重试次数、退避算法和触发方仍需后续定稿。
10. 依赖边界
新增或重点依赖:
| 包 | 用途 |
|---|---|
typer |
CLI |
httpx |
Product SDK HTTP 客户端,支持 UDS |
uvicorn / fastapi |
doclib 和 parse-server HTTP |
aiosqlite |
异步 SQLite |
watchfiles |
文件系统监控 |
jieba |
中文分词 |
pypdfium2 |
PDF metadata 和 flash 解析辅助 |
对外 API 层应遵守惰性加载原则,避免导入 SDK 或 CLI 时触发 GPU、torch、transformers 等重依赖。
与其他文档的关系
- 产品优先级见 产品路线图。
- CLI 如何触发本地能力见 CLI 规格。
- API 如何暴露解析任务见 Unified API。
- SDK 分层见 SDK 设计。
- 解析 tier 语义见 解析 Tier。
- middle_json 结构见 Middle JSON。
- 错误分类见 错误码体系。
- 配置项收敛见 配置体系。
- 未决问题集中维护在 开放问题清单。