# RDAIReaderView 架构设计 **文档状态:** Draft 0.1 **最后更新:** 2026-07-25 **目标版本:** RDAIReaderView 1.0 ## 1. 架构目标 RDAIReaderView 必须满足四个架构目标: 1. 不改变 RDPDFReaderView、RDEpubReaderView 和 RDSpeechReaderView 的核心职责。 2. iOS 15 用户继续获得稳定阅读、基础 NLP 和 TTS;Foundation 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. 存储设计 建议使用 SQLite,Schema 初稿: ```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-002:UTF-16 作为跨模块文本范围。 - ADR-003:本地 SQLite 和增量资源哈希。 - ADR-004:检索先行、生成后置、引用强校验。 - ADR-005:Foundation Models 可选依赖和运行时降级。 - ADR-006:已读范围作为默认安全边界。 ## 16. 已知技术风险 | 风险 | 影响 | 缓解 | |------|------|------| | 中文小说实体识别不足 | 人物漏识别或误合并 | 规则候选 + 结构化模型提取 + 证据与置信度 | | OCR 阅读顺序错误 | 摘要和引用错误 | 保留 readingOrder、双栏测试、允许宿主提供文本 | | PDF OCR 请求被页面导航取消 | 后台索引不完整 | AI 使用独立调度队列与缓存 | | EPUB 重排后范围变化 | 引用跳转漂移 | CFI/rangeCFI 优先,文本哈希校验 | | 系统模型更新 | Prompt 质量回归 | Prompt 版本化、模型版本分层评测 | | 上下文不足 | 回答遗漏 | 检索压缩、分层摘要、新会话 | | 同名人物 | 错误关系合并 | 不自动合并低置信候选,保留冲突 |