更新阅读器功能与示例

This commit is contained in:
shen
2026-07-27 21:43:13 +08:00
parent 68d9363f0a
commit 9392027106
78 changed files with 8780 additions and 2084 deletions
@@ -0,0 +1,431 @@
# RDAIReaderView 架构设计
**文档状态:** Draft 0.1
**最后更新:** 2026-07-25
**目标版本:** RDAIReaderView 1.0
## 1. 架构目标
RDAIReaderView 必须满足四个架构目标:
1. 不改变 RDPDFReaderView、RDEpubReaderView 和 RDSpeechReaderView 的核心职责。
2. iOS 15 用户继续获得稳定阅读、基础 NLP 和 TTSFoundation Models 仅作为可选增强。
3. 所有生成结果都能追溯到稳定原文位置。
4. AI Provider、索引实现和 UI 可替换,公共数据模型保持稳定。
## 2. 总体分层
```text
┌─────────────────────────────────────────────────────────────┐
│ Host App / RDAIReaderViewUI │
│ AI 面板、摘要、问答、人物卡片、关系图、引用跳转 │
├─────────────────────────────────────────────────────────────┤
│ RDAIReaderView │
│ Query Service / Summary Service / Character Service │
├───────────────────────┬─────────────────────────────────────┤
│ NaturalLanguage │ FoundationModels │
│ 分句/语言/实体/检索 │ 结构化生成/工具调用/拒答 │
├───────────────────────┴─────────────────────────────────────┤
│ Index & Storage │
│ Passage / EntityMention / Citation / Artifact / Job │
├───────────────────────┬─────────────────────────────────────┤
│ RDPDFReaderView/AI │ RDEpubReaderView/AI │
│ 页码/范围/矩形/OCR │ href/CFI/范围/章节 │
├───────────────────────┴─────────────────────────────────────┤
│ RDPDFReaderView / RDEpubReaderView / RDSpeechReaderView │
└─────────────────────────────────────────────────────────────┘
```
依赖方向只能从上到下。阅读器核心不能反向依赖 RDAIReaderView。
## 3. CocoaPods 模块设计
建议新增:
```ruby
pod 'RDAIReaderView/Core'
pod 'RDAIReaderView/NaturalLanguage'
pod 'RDAIReaderView/FoundationModels'
pod 'RDAIReaderView/UI'
pod 'RDPDFReaderView/AI'
pod 'RDEpubReaderView/AI'
```
### 3.1 Core
- 最低 iOS 15。
- 只依赖 Foundation、SQLite3/CryptoKit 等系统能力。
- 包含公共协议、数据模型、索引调度、存储和查询编排。
- 不导入 UIKit、PDFKit、DTCoreText 或 FoundationModels。
### 3.2 NaturalLanguage
- 最低 iOS 15。
- 依赖 Core 和 NaturalLanguage。
- 提供语言识别、分句、实体候选、关键词和语义评分。
- iOS 17+ 可选使用 `NLContextualEmbedding`;资源不可用时降级。
### 3.3 FoundationModels
- 源码使用 `@available(iOS 26.0, *)` 隔离。
- 依赖 Core 和系统 FoundationModels。
- 需要支持 Foundation Models 的 Xcode 工具链。
- 不被基础 Pod 默认引入,避免旧工具链客户无法编译。
### 3.4 UI
- 最低 iOS 15。
- 依赖 Core,可选识别 FoundationModels 可用性。
- UI 不直接构造 Prompt,也不直接访问数据库。
### 3.5 Reader Adapters
- `RDPDFReaderView/AI` 依赖 RDAIReaderView/Core。
- `RDEpubReaderView/AI` 依赖 RDAIReaderView/Core。
- Adapter 只负责内容快照、定位转换、跳转和高亮。
## 4. 建议目录
```text
Sources/RDAIReaderView/
├── RDAIReaderView.podspec
├── Core/
│ ├── Contracts/
│ ├── Models/
│ ├── Indexing/
│ ├── Retrieval/
│ ├── Storage/
│ └── Services/
├── NaturalLanguage/
│ ├── Analysis/
│ ├── Embeddings/
│ └── Retrieval/
├── FoundationModels/
│ ├── Availability/
│ ├── Generation/
│ ├── Prompts/
│ ├── Schemas/
│ └── Tools/
├── UI/
│ ├── Assistant/
│ ├── Citations/
│ └── Characters/
└── Tests/
Sources/RDPDFReaderView/AI/
Sources/RDEpubReaderView/AI/
```
## 5. 核心数据流
### 5.1 建立索引
```text
ContentProvider
↓ 读取资源快照
Text Snapshot + Stable Locator
Language Detection
Paragraph/Sentence Chunking
Entity Mentions + Keywords + Embeddings
Transactional Storage
Index Checkpoint
```
每次数据库事务只提交一个资源或一组有界片段。应用退出时,最多重做当前事务,不重做整本书。
### 5.2 问答
```text
User Question
Language / Intent / Spoiler Scope
Hybrid Retrieval
Access + Read-Progress Filter
Context Budget Builder
Foundation Models Structured Generation
Citation Validator
Answer or Evidence-Insufficient Refusal
```
检索由代码执行。首版不让模型自由遍历整本数据库,只有需要多轮查找时才使用受限 Tool Calling。
### 5.3 人物关系
```text
Entity Mentions
Alias Candidate Grouping
Chunk-level Structured Extraction
Evidence Validation
Relationship Merge
confirmed / possible / conflicting
```
代码只能自动合并完全相同的标准化名称和明确别名。代词消解、同名人物合并和隐含关系必须保持低置信度,等待更多证据或用户确认。
## 6. 稳定定位模型
### 6.1 通用定位
`RDAILocator` 包含:
- `documentIdentifier`
- `resourceIdentifier`
- `utf16Range`
- `sourceHash`
- 格式专属 Anchor
文本范围统一使用 UTF-16,与现有 RDSpeechReaderView、NSString 和 EPUB 搜索范围保持一致。
### 6.2 PDF Anchor
```text
pageIndex
normalizedRects
textSource: native / ocr
readingOrder
```
PDF Adapter 从现有 `RDPDFReaderTextRun` 构建连续页文本和 UTF-16 范围。每个 Passage 必须保留与 run 的映射,不能在 AI 层重新拼接后丢失矩形。
扫描 PDF 使用现有 `speechTextRuns(at:)`/OCR 能力,但商用实现应增加独立的 AI OCR 调度入口,避免页面导航取消请求时同时取消后台索引。
### 6.3 EPUB Anchor
```text
normalizedHref
cfi
rangeCFI
rangeAnchor
progressionFallback
```
优先级:
1. `rangeCFI`
2. `cfi + UTF-16 range`
3. `rangeAnchor`
4. `href + progression`
屏幕页码只用于展示,不能作为持久化引用主键。
## 7. 文本快照与分块
### 7.1 不修改原文
索引保存两份文本信息:
- `sourceText`:原始文本,用于引用与范围映射。
- `searchText`:规范化副本,用于检索。
禁止使用规范化文本范围直接驱动阅读器高亮。
### 7.2 分块策略
- 先按资源和章节边界划分。
- 再按段落划分。
- 超长段落使用 `NLTokenizer(unit: .sentence)`
- 中文目标 600-900 字;英文目标 300-600 词。
- 片段之间保留 1-2 句重叠。
- 表格、代码、脚注和标题保留语义类型,避免与正文无差别拼接。
### 7.3 内容哈希
建议使用 SHA-256
```text
documentHash = hash(ordered resource identifiers + resource hashes)
resourceHash = hash(source text + format-specific stable metadata)
passageHash = hash(resource hash + UTF-16 range + source text)
```
书籍更新时按资源哈希增量失效。
## 8. 检索架构
首版采用 Hybrid Retrieval
```text
finalScore =
0.45 * lexicalScore +
0.40 * semanticScore +
0.10 * proximityScore +
0.05 * headingBoost
```
权重是初始值,必须通过评测集调优,不作为永久常量。
检索步骤:
1. 规范化查询并识别语言。
2. 关键词倒排召回 Top 30。
3. 语义相似度重排。
4. 合并高度重叠 Passage。
5. 按已读范围、文档授权和最大上下文过滤。
6. 返回 Top 3-4,并保留评分解释。
若语义模型资源不可用,使用纯词法检索,不阻塞问答入口;UI 可提示结果质量可能降低。
## 9. Foundation Models 编排
### 9.1 Provider 抽象
Core 只依赖 `RDAIGenerativeProvider`。Apple 实现位于 FoundationModels 子模块,未来可增加 Core ML、MLX 或经用户授权的云端实现。
### 9.2 会话策略
- 摘要、问答、人物关系使用不同 instructions 和独立会话。
- 同一会话只处理一个并发请求。
- 用户切换书籍、变更阅读范围或取消时终止任务。
- 达到上下文阈值前主动新建会话,不等待系统抛错。
- 记录 Prompt 版本、模型可用性分类、耗时和 token 数,不记录原文。
### 9.3 上下文预算
默认预算建议:
| 项目 | Token 预算 |
|------|------------|
| Instructions + Schema | 500 |
| 用户问题 | 200 |
| 检索上下文 | 2400 |
| 模型输出 | 700 |
| 安全余量 | 296 |
实际使用 `contextSize``tokenCount(for:)` 动态计算,不写死为 4096。
### 9.4 引用验证
生成后执行确定性校验:
1. Citation ID 必须存在于本次上下文。
2. Citation 必须属于当前文档和允许阅读范围。
3. 引用文本必须能在 Passage 原文中匹配。
4. 每个事实项至少有一个有效引用。
5. 删除无效项后答案为空,则返回 evidence insufficient。
## 10. 存储设计
建议使用 SQLiteSchema 初稿:
```text
documents
resources
passages
passage_fts
embeddings
entity_mentions
entities
entity_aliases
relationships
relationship_evidence
artifacts
index_jobs
schema_metadata
```
关键原则:
- FTS 和关系表通过 Passage ID 关联原文。
- 向量数据按模型标识符、revision 和语言分区。
- 生成结果不覆盖人工编辑内容。
- 每个 Artifact 保存 Prompt/模型/输入哈希。
- 索引表支持按文档级联删除。
## 11. 并发与生命周期
建议采用 Swift Concurrency
- `RDAIIndexCoordinator`actor,管理索引队列和 checkpoint。
- `RDAIStore`actor,串行化数据库写入。
- `RDAIRetriever`:Sendable 服务,可并发读取快照。
- Reader Adapter`@MainActor`,仅提取 UI/阅读器状态和执行跳转。
- Foundation Models Session:由单请求 actor 或服务隔离。
优先级:
1. 用户当前问答所需 Passage。
2. 当前章节。
3. 相邻章节。
4. 已读范围。
5. 其余获准内容。
发生内存警告时:
- 取消低优先级 embedding 任务。
- 卸载 contextual embedding。
- 清理内存 Passage/向量缓存。
- 保留已提交数据库和当前用户请求。
## 12. 可用性与降级
```text
Foundation Models available
├─ 是 → 完整生成能力
└─ 否
├─ Natural Language available → 索引、实体、基础检索
└─ 语言/资源不支持 → 关键词检索与基础分段
```
降级状态是公共 API 的一部分,UI 不根据 Error 字符串猜测原因。
## 13. 安全与隐私
- 默认 Provider 为设备端 Provider。
- Core 不包含网络代码。
- 云端 Provider 若未来增加,必须是单独 Pod,并要求宿主显式配置。
- 日志只记录文档匿名哈希、阶段、耗时、错误类别和计数。
- 禁止记录 Prompt、Passage、用户问题和模型回答全文。
- 导出诊断包前再次脱敏。
- 删除书籍时由宿主调用 `removeDocument`,同时删除索引、关系和生成缓存。
## 14. 可观测性
本地指标:
- 索引耗时、资源数、片段数、失败类别。
- 检索 P50/P95、召回数量和降级模式。
- 生成耗时、取消率、错误类别和引用校验失败率。
- Foundation Models availability 分布。
- 缓存命中率和数据库大小。
商用版本默认只汇总数值。任何远程遥测必须由宿主决定,并遵守其隐私政策。
## 15. 架构决策记录
实施时至少补充以下 ADR
- ADR-001:独立 RDAIReaderView 而非嵌入阅读器核心。
- ADR-002UTF-16 作为跨模块文本范围。
- ADR-003:本地 SQLite 和增量资源哈希。
- ADR-004:检索先行、生成后置、引用强校验。
- ADR-005Foundation Models 可选依赖和运行时降级。
- ADR-006:已读范围作为默认安全边界。
## 16. 已知技术风险
| 风险 | 影响 | 缓解 |
|------|------|------|
| 中文小说实体识别不足 | 人物漏识别或误合并 | 规则候选 + 结构化模型提取 + 证据与置信度 |
| OCR 阅读顺序错误 | 摘要和引用错误 | 保留 readingOrder、双栏测试、允许宿主提供文本 |
| PDF OCR 请求被页面导航取消 | 后台索引不完整 | AI 使用独立调度队列与缓存 |
| EPUB 重排后范围变化 | 引用跳转漂移 | CFI/rangeCFI 优先,文本哈希校验 |
| 系统模型更新 | Prompt 质量回归 | Prompt 版本化、模型版本分层评测 |
| 上下文不足 | 回答遗漏 | 检索压缩、分层摘要、新会话 |
| 同名人物 | 错误关系合并 | 不自动合并低置信候选,保留冲突 |