更新阅读器功能与示例
This commit is contained in:
@@ -0,0 +1,411 @@
|
||||
# RDAIReaderView AI 系统设计合同
|
||||
|
||||
**文档状态:** Draft 0.1
|
||||
**最后更新:** 2026-07-25
|
||||
**目标版本:** RDAIReaderView 1.0
|
||||
|
||||
## 1. 系统分类
|
||||
|
||||
RDAIReaderView 是一个本地优先的 Retrieval-Augmented Generation 阅读系统,包含:
|
||||
|
||||
- 确定性 NLP:语言识别、分句、实体候选、词法检索。
|
||||
- 本地语义检索:Natural Language embeddings。
|
||||
- 生成式任务:摘要、书内问答、人物卡片和人物关系。
|
||||
- 引用约束:生成内容必须映射到 PDF/EPUB 原文。
|
||||
|
||||
系统不是通用聊天机器人,也不把模型自身知识作为书籍事实来源。
|
||||
|
||||
## 2. 框架选择
|
||||
|
||||
### 2.1 主框架
|
||||
|
||||
- Apple Natural Language:iOS 15+ 基础分析和检索。
|
||||
- Apple Foundation Models:支持设备上的生成式增强。
|
||||
- Vision:扫描 PDF OCR,继续复用 RDPDFReaderView 现有能力。
|
||||
|
||||
### 2.2 选择理由
|
||||
|
||||
- 与当前纯 Swift/UIKit/CocoaPods 架构一致。
|
||||
- 默认设备端处理,不需要新增服务端和书籍上传链路。
|
||||
- Natural Language 可覆盖不支持 Apple Intelligence 的设备。
|
||||
- Foundation Models 支持 structured generation 和 tool calling。
|
||||
- 系统 API 可与现有 PDF/EPUB 定位直接结合。
|
||||
|
||||
### 2.3 未选择的首版方案
|
||||
|
||||
| 方案 | 首版不采用原因 |
|
||||
|------|----------------|
|
||||
| LangChain/LlamaIndex | 主要面向 Python/服务端,增加不必要基础设施 |
|
||||
| 云端 LLM | 引入内容上传、成本、隐私、版权和网络可用性问题 |
|
||||
| ONNX Runtime 自带模型 | 需要自行选择、量化、分发和维护语言模型 |
|
||||
| 自训练 Foundation Models Adapter | 模型版本绑定和 entitlement 增加发布复杂度 |
|
||||
|
||||
Core 保留 `RDAIGenerativeProvider`,以后可以增加其他 Provider,不把 Apple 实现写死在公共业务层。
|
||||
|
||||
## 3. 模型可用性合同
|
||||
|
||||
调用 Foundation Models 前必须检查:
|
||||
|
||||
1. API 在当前系统可用。
|
||||
2. `SystemLanguageModel.default.availability` 为 available。
|
||||
3. 当前 Locale 被支持。
|
||||
4. 当前请求未超过并发限制。
|
||||
5. 当前任务的上下文预算可满足。
|
||||
|
||||
不可用原因映射:
|
||||
|
||||
| Apple 状态 | RDAI 状态 | UI 行为 |
|
||||
|------------|-----------|---------|
|
||||
| deviceNotEligible | `.deviceNotEligible` | 隐藏生成操作,保留基础分析 |
|
||||
| appleIntelligenceNotEnabled | `.appleIntelligenceNotEnabled` | 说明可在系统设置中开启 |
|
||||
| modelNotReady | `.modelNotReady` | 展示模型准备中,可稍后重试 |
|
||||
| unsupported locale | `.languageUnsupported` | 保留检索,关闭生成 |
|
||||
| unknown | `.unknown` | 通用不可用状态,允许重试 |
|
||||
|
||||
禁止通过静态设备型号列表推断可用性,运行时状态是唯一依据。
|
||||
|
||||
参考:
|
||||
|
||||
- [Foundation Models](https://developer.apple.com/documentation/FoundationModels)
|
||||
- [SystemLanguageModel](https://developer.apple.com/documentation/FoundationModels/SystemLanguageModel)
|
||||
- [语言与 Locale 支持](https://developer.apple.com/documentation/foundationmodels/supporting-languages-and-locales-with-foundation-models)
|
||||
|
||||
## 4. 输入与上下文策略
|
||||
|
||||
### 4.1 唯一事实来源
|
||||
|
||||
模型可以使用:
|
||||
|
||||
- 本次请求提供的 Passage。
|
||||
- Passage 的章节标题、页码/资源信息。
|
||||
- 用户当前问题。
|
||||
- 非内容性规则,例如输出语言和防剧透范围。
|
||||
|
||||
模型不得把训练知识、其他书籍、互联网知识或先前书籍会话作为当前书籍事实来源。
|
||||
|
||||
### 4.2 上下文预算
|
||||
|
||||
运行时读取模型 `contextSize`,并使用 `tokenCount(for:)` 估算。
|
||||
|
||||
初始预算比例:
|
||||
|
||||
- 12%:instructions 和 schema。
|
||||
- 5%:用户问题。
|
||||
- 60%:检索 Passage。
|
||||
- 17%:输出。
|
||||
- 6%:安全余量。
|
||||
|
||||
若预算不足,按以下顺序处理:
|
||||
|
||||
1. 删除低分 Passage。
|
||||
2. 缩短 Passage 到完整句子边界。
|
||||
3. 使用预计算的有引用片段摘要。
|
||||
4. 创建新会话。
|
||||
5. 仍不足则返回 `contextLimitExceeded`。
|
||||
|
||||
不得静默截断引用或生成半个结构化对象。
|
||||
|
||||
参考:[Managing the context window](https://developer.apple.com/documentation/foundationmodels/managing-the-context-window)
|
||||
|
||||
## 5. Prompt 资产管理
|
||||
|
||||
Prompt 作为版本化代码资产保存:
|
||||
|
||||
```text
|
||||
FoundationModels/Prompts/
|
||||
├── summary_v1.swift
|
||||
├── answer_v1.swift
|
||||
├── characters_v1.swift
|
||||
└── relationships_v1.swift
|
||||
```
|
||||
|
||||
每个 Prompt 定义:
|
||||
|
||||
- `identifier`
|
||||
- `version`
|
||||
- `minimumModelProfile`
|
||||
- `instructions`
|
||||
- 输入构造器
|
||||
- 输出 schema
|
||||
- 评测集标签
|
||||
|
||||
修改 Prompt 必须:
|
||||
|
||||
1. 增加版本号。
|
||||
2. 跑完整离线评测集。
|
||||
3. 与上一版本对比准确率、拒答、引用和延迟。
|
||||
4. 更新缓存失效策略。
|
||||
|
||||
## 6. 通用 Instructions
|
||||
|
||||
所有任务共享以下不可省略规则:
|
||||
|
||||
```text
|
||||
你是书内阅读助手。
|
||||
只使用提供的原文片段,不使用外部知识补充书中事实。
|
||||
每个事实性结论必须引用一个或多个有效片段 ID。
|
||||
证据不足时返回 insufficientEvidence,不猜测。
|
||||
不得引用允许阅读范围之外的内容。
|
||||
区分原文明确事实与可能推断。
|
||||
使用用户当前语言回答。
|
||||
```
|
||||
|
||||
实际实现使用简洁英文或经评测验证的目标语言 instructions;以上文字表达语义合同,不要求逐字使用。
|
||||
|
||||
## 7. 结构化输出
|
||||
|
||||
### 7.1 摘要 Schema
|
||||
|
||||
```swift
|
||||
@Generable
|
||||
struct GeneratedSummary {
|
||||
var overview: String
|
||||
|
||||
@Guide(.maximumCount(6))
|
||||
var points: [GeneratedStatement]
|
||||
}
|
||||
|
||||
@Generable
|
||||
struct GeneratedStatement {
|
||||
var text: String
|
||||
|
||||
@Guide(.minimumCount(1), .maximumCount(3))
|
||||
var passageIDs: [String]
|
||||
}
|
||||
```
|
||||
|
||||
规则:
|
||||
|
||||
- `overview` 只能概括已提供 Passage。
|
||||
- 每个 point 必须有 Passage ID。
|
||||
- brief 最多 3 点,standard 最多 6 点。
|
||||
|
||||
### 7.2 问答 Schema
|
||||
|
||||
```swift
|
||||
@Generable
|
||||
enum GeneratedAnswerStatus {
|
||||
case answered
|
||||
case insufficientEvidence
|
||||
}
|
||||
|
||||
@Generable
|
||||
struct GeneratedAnswer {
|
||||
var status: GeneratedAnswerStatus
|
||||
var answer: String
|
||||
|
||||
@Guide(.maximumCount(6))
|
||||
var statements: [GeneratedStatement]
|
||||
}
|
||||
```
|
||||
|
||||
若 `status == insufficientEvidence`:
|
||||
|
||||
- `statements` 必须为空。
|
||||
- `answer` 只说明当前已读内容没有足够依据。
|
||||
- 不推荐用户从互联网获取答案,除非宿主未来明确增加该产品能力。
|
||||
|
||||
### 7.3 人物 Schema
|
||||
|
||||
```swift
|
||||
@Generable
|
||||
struct GeneratedCharacter {
|
||||
var displayName: String
|
||||
|
||||
@Guide(.maximumCount(6))
|
||||
var aliases: [String]
|
||||
|
||||
var description: String
|
||||
|
||||
@Guide(.minimumCount(1), .maximumCount(6))
|
||||
var evidencePassageIDs: [String]
|
||||
}
|
||||
```
|
||||
|
||||
人物必须在 Passage 中有明确名称或可验证别名。纯代词不能单独创建人物。
|
||||
|
||||
### 7.4 关系 Schema
|
||||
|
||||
```swift
|
||||
@Generable
|
||||
enum GeneratedRelationshipStatus {
|
||||
case confirmed
|
||||
case possible
|
||||
case conflicting
|
||||
}
|
||||
|
||||
@Generable
|
||||
struct GeneratedRelationship {
|
||||
var sourceName: String
|
||||
var targetName: String
|
||||
var label: String
|
||||
var status: GeneratedRelationshipStatus
|
||||
|
||||
@Guide(.minimumCount(1), .maximumCount(5))
|
||||
var evidencePassageIDs: [String]
|
||||
}
|
||||
```
|
||||
|
||||
关系标签应简短,例如“师徒”“同事”“敌对”“亲属”。描述性事件放在人物事件中,不无限创建关系类型。
|
||||
|
||||
## 8. 任务设计
|
||||
|
||||
### 8.1 章节摘要
|
||||
|
||||
输入:
|
||||
|
||||
- 当前章节 Passage,或已读范围内的章节片段摘要。
|
||||
- 目标长度。
|
||||
- 用户 Locale。
|
||||
|
||||
流程:
|
||||
|
||||
1. 章节能放入上下文时直接生成。
|
||||
2. 超长章节分块生成带引用局部摘要。
|
||||
3. 聚合局部摘要时保留原 Passage ID。
|
||||
4. 运行引用验证。
|
||||
|
||||
禁止只把局部摘要文本作为最终事实来源而丢失原始 Passage ID。
|
||||
|
||||
### 8.2 书内问答
|
||||
|
||||
流程:
|
||||
|
||||
1. 识别问题语言和实体词。
|
||||
2. Hybrid Retrieval 召回 30 个候选。
|
||||
3. 重排并过滤到 3-4 个 Passage。
|
||||
4. 直接把 Passage 放入 Prompt。
|
||||
5. 生成结构化答案。
|
||||
6. 验证引用和阅读范围。
|
||||
7. 无有效事实项时拒答。
|
||||
|
||||
首版优先使用代码检索,不默认使用 Tool Calling,这样召回过程更确定、可测试、节省 token。
|
||||
|
||||
### 8.3 人物卡片
|
||||
|
||||
流程:
|
||||
|
||||
1. Natural Language 提供人物候选及出现位置。
|
||||
2. 按名称和明确别名聚合候选。
|
||||
3. 检索候选周边 Passage。
|
||||
4. Foundation Models 生成结构化人物信息。
|
||||
5. 代码校验所有别名和证据。
|
||||
6. 低置信别名保持独立候选。
|
||||
|
||||
### 8.4 人物关系
|
||||
|
||||
采用两阶段:
|
||||
|
||||
1. Chunk-level extraction:从局部 Passage 提取关系候选。
|
||||
2. Document-level merge:按人物 ID、关系标签和时间顺序合并。
|
||||
|
||||
合并规则:
|
||||
|
||||
- 相同关系 + 相同方向:合并证据。
|
||||
- 对称关系可由受控词典决定是否双向展示。
|
||||
- 新证据否定旧关系:状态变为 conflicting。
|
||||
- 隐含动机、情感和立场默认 possible。
|
||||
- 任何关系没有有效证据时不入库。
|
||||
|
||||
## 9. Tool Calling
|
||||
|
||||
仅在单次检索无法回答、且评测证明多轮查找有明显收益时启用。最多提供三个工具:
|
||||
|
||||
```text
|
||||
searchBook(query, scope, limit)
|
||||
getPassages(ids)
|
||||
getCharacterEvidence(name, scope, limit)
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- 工具只读。
|
||||
- 工具强制应用文档和已读范围过滤。
|
||||
- 参数有严格长度和数量上限。
|
||||
- 返回内容有 token 上限。
|
||||
- 每个请求最大 Tool 调用次数为 3。
|
||||
- 检测重复参数调用并终止循环。
|
||||
- 工具调用和结果 ID进入本地 trace,但不记录原文。
|
||||
|
||||
不提供跳页、删除、购买、网络请求等副作用工具。
|
||||
|
||||
参考:[Expanding generation with tool calling](https://developer.apple.com/documentation/foundationmodels/expanding-generation-with-tool-calling)
|
||||
|
||||
## 10. 确定性后处理
|
||||
|
||||
模型输出必须经过:
|
||||
|
||||
1. Schema 解码。
|
||||
2. Passage ID 存在性校验。
|
||||
3. 阅读范围校验。
|
||||
4. Quote/Locator 构造。
|
||||
5. 重复 statement 合并。
|
||||
6. 空文本和长度校验。
|
||||
7. 敏感内容与系统错误映射。
|
||||
8. Artifact 元数据补齐。
|
||||
|
||||
模型不能直接构造页码、CFI、CGRect 或数据库 ID;这些字段全部由代码通过 Passage ID解析。
|
||||
|
||||
## 11. 安全与产品规则
|
||||
|
||||
- 不将 AI 输出表示为作者原话。
|
||||
- UI 明确标记“AI 生成”。
|
||||
- possible/conflicting 关系必须视觉区分。
|
||||
- 用户问题涉及未读内容时,默认拒绝并提示防剧透设置。
|
||||
- 原文包含违法或敏感内容时,遵循系统模型 guardrails;不能绕过。
|
||||
- 输入和输出触发系统安全限制时,返回稳定、非技术性的不可生成状态。
|
||||
- 不要求模型提供医学、法律或金融建议;如果书中包含相关内容,只能解释“书中写了什么”。
|
||||
|
||||
发布前必须复核 Apple Foundation Models acceptable use requirements 和最新 App Review Guidelines。
|
||||
|
||||
## 12. 关键失败模式
|
||||
|
||||
| 失败模式 | 检测 | 处理 |
|
||||
|----------|------|------|
|
||||
| 模型编造人物或关系 | Passage ID/名称验证 | 删除无效项,无结果则拒答 |
|
||||
| 引用存在但不支持结论 | 人工评测 + LLM judge | Prompt 调整,低分结果进入回归集 |
|
||||
| 同名人物合并 | 别名证据检查 | 保持独立,标记待确认 |
|
||||
| 未读内容泄漏 | Scope validator | 阻断输出并记录安全计数 |
|
||||
| OCR 错字导致错误事实 | OCR source 标记和置信策略 | 降低置信度,展示 OCR 来源 |
|
||||
| Prompt 在系统更新后退化 | 模型版本分桶评测 | 版本化 Prompt 和缓存 |
|
||||
| 上下文溢出 | tokenCount/contextSize | 重建上下文或分层摘要 |
|
||||
| Tool 循环 | 调用次数和参数去重 | 终止并降级为现有证据回答 |
|
||||
| 用户快速重复请求 | request actor + cancellation | 取消旧任务或排队 |
|
||||
|
||||
## 13. 评测维度
|
||||
|
||||
| 维度 | 定义 | 1.0 门槛 |
|
||||
|------|------|----------|
|
||||
| Citation validity | 引用能否恢复到原文 | ≥ 99% |
|
||||
| Context faithfulness | 事实是否由引用支持 | ≥ 98% |
|
||||
| Refusal accuracy | 无证据时是否拒答 | ≥ 95% |
|
||||
| Spoiler safety | 是否只使用允许范围 | 100% |
|
||||
| Schema validity | 结构化输出是否通过校验 | ≥ 99.5% |
|
||||
| Character precision | 人物是否真实出现 | ≥ 97% |
|
||||
| Relationship evidence | 关系是否至少有一条证据 | 100% |
|
||||
| Alias precision | 自动合并别名是否正确 | ≥ 98% |
|
||||
| Retrieval recall@5 | 正确证据是否在 Top 5 | ≥ 90% |
|
||||
| Answer usefulness | 人工 1-5 分平均值 | ≥ 4.0 |
|
||||
|
||||
## 14. 评测方法
|
||||
|
||||
- 代码指标:Schema、引用 ID、范围、阅读权限、延迟和拒答格式。
|
||||
- 人工标注:人物、别名、关系、引用支持度、剧透边界。
|
||||
- LLM judge:只用于语气、完整性和引用支持度的辅助评估;必须先与人工评分校准。
|
||||
- 生产抽样:只上传宿主允许的匿名数值和用户显式反馈;不上传书籍原文。
|
||||
|
||||
评测集和完整方法见 [RDAIReaderView-TEST-PLAN.md](RDAIReaderView-TEST-PLAN.md)。
|
||||
|
||||
## 15. 发布检查清单
|
||||
|
||||
- [ ] 所有 Prompt 有 identifier 和 version。
|
||||
- [ ] 每个生成任务使用 `@Generable`。
|
||||
- [ ] 每个事实输出经过 Citation Validator。
|
||||
- [ ] 防剧透 Scope 在检索前和生成后各检查一次。
|
||||
- [ ] Foundation Models 不可用路径已真机验证。
|
||||
- [ ] 上下文预算使用运行时 API 计算。
|
||||
- [ ] 模型版本变化不会复用旧缓存。
|
||||
- [ ] 评测集达到所有 1.0 门槛。
|
||||
- [ ] 日志不包含原文、问题或完整回答。
|
||||
- [ ] Apple 最新 acceptable use 与审核要求已复核。
|
||||
|
||||
@@ -0,0 +1,604 @@
|
||||
# RDAIReaderView 公共 API 设计
|
||||
|
||||
**文档状态:** Proposal 0.1
|
||||
**最后更新:** 2026-07-25
|
||||
**目标版本:** RDAIReaderView 1.0
|
||||
|
||||
## 1. API 设计原则
|
||||
|
||||
- Core 最低支持 iOS 15,不直接依赖 UIKit、PDFKit、DTCoreText 或 FoundationModels。
|
||||
- 公共模型优先使用值类型,并遵循 `Codable`、`Sendable`、`Equatable`。
|
||||
- 文本范围统一使用 UTF-16 偏移,与现有 PDF、EPUB、NSString 和 TTS 范围保持一致。
|
||||
- Reader Adapter 负责格式转换,Core 不识别 PDF 页视图或 EPUB 排版对象。
|
||||
- Foundation Models 通过 Provider 协议接入,不能泄漏到基础 API。
|
||||
- 公开 API 在 1.0 后遵循语义化版本;新增字段必须有解码默认值。
|
||||
|
||||
本文中的 Swift 定义是实现合同,允许在不改变语义的前提下调整文件组织和内部实现。
|
||||
|
||||
## 2. 标识符与基础范围
|
||||
|
||||
```swift
|
||||
import Foundation
|
||||
|
||||
public struct RDAIDocumentIdentifier: RawRepresentable, Codable, Hashable, Sendable {
|
||||
public let rawValue: String
|
||||
|
||||
public init(rawValue: String) {
|
||||
self.rawValue = rawValue
|
||||
}
|
||||
}
|
||||
|
||||
public struct RDAIResourceIdentifier: RawRepresentable, Codable, Hashable, Sendable {
|
||||
public let rawValue: String
|
||||
|
||||
public init(rawValue: String) {
|
||||
self.rawValue = rawValue
|
||||
}
|
||||
}
|
||||
|
||||
public struct RDAITextRange: Codable, Hashable, Sendable {
|
||||
public var location: Int
|
||||
public var length: Int
|
||||
|
||||
public init(location: Int, length: Int) {
|
||||
self.location = max(0, location)
|
||||
self.length = max(0, length)
|
||||
}
|
||||
|
||||
public var upperBound: Int { location + length }
|
||||
}
|
||||
```
|
||||
|
||||
约束:
|
||||
|
||||
- `RDAIDocumentIdentifier` 必须与宿主书籍 ID 一致并保持稳定。
|
||||
- `RDAIResourceIdentifier` 在 PDF 中使用页索引字符串,在 EPUB 中使用规范化 `href`。
|
||||
- 所有文本范围均针对资源原始文本,不针对规范化搜索文本。
|
||||
|
||||
## 3. 定位与引用
|
||||
|
||||
### 3.1 归一化矩形
|
||||
|
||||
Core 使用自定义矩形,避免公共存储格式依赖 UIKit:
|
||||
|
||||
```swift
|
||||
public struct RDAINormalizedRect: Codable, Hashable, Sendable {
|
||||
public var x: Double
|
||||
public var y: Double
|
||||
public var width: Double
|
||||
public var height: Double
|
||||
|
||||
public init(x: Double, y: Double, width: Double, height: Double) {
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.width = width
|
||||
self.height = height
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
所有值应限制在 `0...1`。Reader Adapter 负责与 `CGRect` 转换。
|
||||
|
||||
### 3.2 格式 Anchor
|
||||
|
||||
```swift
|
||||
public struct RDAIPDFAnchor: Codable, Hashable, Sendable {
|
||||
public enum TextSource: String, Codable, Sendable {
|
||||
case native
|
||||
case ocr
|
||||
}
|
||||
|
||||
public var pageIndex: Int
|
||||
public var rects: [RDAINormalizedRect]
|
||||
public var textSource: TextSource
|
||||
public var readingOrder: Int?
|
||||
}
|
||||
|
||||
public struct RDAIEPUBAnchor: Codable, Hashable, Sendable {
|
||||
public var href: String
|
||||
public var cfi: String?
|
||||
public var rangeCFI: String?
|
||||
public var progression: Double?
|
||||
}
|
||||
|
||||
public enum RDAIAnchor: Codable, Hashable, Sendable {
|
||||
case pdf(RDAIPDFAnchor)
|
||||
case epub(RDAIEPUBAnchor)
|
||||
}
|
||||
```
|
||||
|
||||
`RDAIAnchor` 必须实现显式 Codable discriminator,例如 `type: "pdf"`,未知类型解码为明确错误,不能误当成其他格式。
|
||||
|
||||
### 3.3 通用定位
|
||||
|
||||
```swift
|
||||
public struct RDAILocator: Codable, Hashable, Sendable {
|
||||
public var documentIdentifier: RDAIDocumentIdentifier
|
||||
public var resourceIdentifier: RDAIResourceIdentifier
|
||||
public var textRange: RDAITextRange
|
||||
public var anchor: RDAIAnchor
|
||||
public var sourceHash: String
|
||||
}
|
||||
|
||||
public struct RDAICitation: Codable, Hashable, Sendable, Identifiable {
|
||||
public let id: String
|
||||
public let passageIdentifier: String
|
||||
public let quote: String
|
||||
public let locator: RDAILocator
|
||||
}
|
||||
```
|
||||
|
||||
引用恢复流程:
|
||||
|
||||
1. 校验文档和资源存在。
|
||||
2. 校验 `sourceHash`。
|
||||
3. 优先按格式 Anchor 恢复。
|
||||
4. Anchor 失败时使用文本范围和 quote 搜索。
|
||||
5. 仍失败则返回 `staleCitation`,不得跳转到近似但未验证的位置。
|
||||
|
||||
## 4. 文档与资源
|
||||
|
||||
```swift
|
||||
public enum RDAIDocumentFormat: String, Codable, Sendable {
|
||||
case pdf
|
||||
case epub
|
||||
}
|
||||
|
||||
public struct RDAIDocumentDescriptor: Codable, Equatable, Sendable {
|
||||
public let identifier: RDAIDocumentIdentifier
|
||||
public let title: String
|
||||
public let format: RDAIDocumentFormat
|
||||
public let contentRevision: String
|
||||
}
|
||||
|
||||
public struct RDAIResourceDescriptor: Codable, Equatable, Sendable {
|
||||
public let identifier: RDAIResourceIdentifier
|
||||
public let title: String?
|
||||
public let order: Int
|
||||
public let estimatedUTF16Length: Int?
|
||||
}
|
||||
|
||||
public struct RDAIResourceSnapshot: Sendable {
|
||||
public let descriptor: RDAIResourceDescriptor
|
||||
public let sourceText: String
|
||||
public let sourceHash: String
|
||||
public let locatorRuns: [RDAILocatorRun]
|
||||
}
|
||||
|
||||
public struct RDAILocatorRun: Sendable {
|
||||
public let textRange: RDAITextRange
|
||||
public let anchor: RDAIAnchor
|
||||
}
|
||||
```
|
||||
|
||||
`contentRevision` 由宿主提供;若宿主没有版本号,Adapter 使用资源哈希汇总生成。
|
||||
|
||||
## 5. 内容提供协议
|
||||
|
||||
```swift
|
||||
@MainActor
|
||||
public protocol RDAIContentProvider: AnyObject {
|
||||
func aiDocumentDescriptor() -> RDAIDocumentDescriptor
|
||||
func aiResources() async throws -> [RDAIResourceDescriptor]
|
||||
func aiResourceSnapshot(
|
||||
for identifier: RDAIResourceIdentifier
|
||||
) async throws -> RDAIResourceSnapshot
|
||||
func aiNavigate(to locator: RDAILocator, animated: Bool) async throws
|
||||
func aiShowCitationHighlight(_ citation: RDAICitation) async throws
|
||||
func aiClearCitationHighlight()
|
||||
}
|
||||
```
|
||||
|
||||
协议标记为 `@MainActor`,因为现有 Reader Controller 和页面缓存均由主线程管理。实现必须只在主线程获取快照引用和 UI 状态;OCR、分块、分析和数据库写入移交后台 actor。
|
||||
|
||||
可选读取范围协议:
|
||||
|
||||
```swift
|
||||
public struct RDAIReadScope: Codable, Equatable, Sendable {
|
||||
public let upperBound: RDAILocator?
|
||||
public let includesWholeDocument: Bool
|
||||
}
|
||||
|
||||
@MainActor
|
||||
public protocol RDAIReadScopeProviding: AnyObject {
|
||||
func aiCurrentReadScope() -> RDAIReadScope
|
||||
}
|
||||
```
|
||||
|
||||
未实现时,默认只允许当前资源及之前的资源,不能默认整本书。
|
||||
|
||||
## 6. Passage 与分析结果
|
||||
|
||||
```swift
|
||||
public enum RDAIPassageKind: String, Codable, Sendable {
|
||||
case title
|
||||
case paragraph
|
||||
case list
|
||||
case table
|
||||
case code
|
||||
case footnote
|
||||
case unknown
|
||||
}
|
||||
|
||||
public struct RDAIPassage: Codable, Equatable, Sendable, Identifiable {
|
||||
public let id: String
|
||||
public let documentIdentifier: RDAIDocumentIdentifier
|
||||
public let resourceIdentifier: RDAIResourceIdentifier
|
||||
public let text: String
|
||||
public let languageCode: String?
|
||||
public let kind: RDAIPassageKind
|
||||
public let locator: RDAILocator
|
||||
public let contentHash: String
|
||||
public let order: Int
|
||||
}
|
||||
|
||||
public enum RDAIEntityKind: String, Codable, Sendable {
|
||||
case person
|
||||
case place
|
||||
case organization
|
||||
case other
|
||||
}
|
||||
|
||||
public struct RDAIEntityMention: Codable, Equatable, Sendable, Identifiable {
|
||||
public let id: String
|
||||
public let normalizedName: String
|
||||
public let surfaceText: String
|
||||
public let kind: RDAIEntityKind
|
||||
public let confidence: Double
|
||||
public let locator: RDAILocator
|
||||
}
|
||||
```
|
||||
|
||||
Natural Language 的标签不是最终人物事实,只是 `RDAIEntityMention` 候选。
|
||||
|
||||
## 7. 索引 API
|
||||
|
||||
```swift
|
||||
public enum RDAIIndexState: Equatable, Sendable {
|
||||
case notStarted
|
||||
case indexing(completedResources: Int, totalResources: Int)
|
||||
case paused
|
||||
case ready
|
||||
case failed(RDAIError)
|
||||
}
|
||||
|
||||
public struct RDAIIndexOptions: Sendable {
|
||||
public var scope: RDAIReadScope
|
||||
public var priorityResource: RDAIResourceIdentifier?
|
||||
public var allowsEmbeddingAssetDownload: Bool
|
||||
}
|
||||
|
||||
public protocol RDAIIndexing: AnyObject, Sendable {
|
||||
func prepareIndex(options: RDAIIndexOptions) async throws
|
||||
func pauseIndexing() async
|
||||
func resumeIndexing() async
|
||||
func indexState() async -> RDAIIndexState
|
||||
func stateUpdates() async -> AsyncStream<RDAIIndexState>
|
||||
func removeIndex() async throws
|
||||
}
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- `prepareIndex` 幂等。
|
||||
- 重复调用只能扩大范围或提高优先级,不能创建重复 Job。
|
||||
- `removeIndex` 删除索引、实体和生成缓存,但不删除原书或用户笔记。
|
||||
|
||||
## 8. 能力与可用性
|
||||
|
||||
```swift
|
||||
public enum RDAICapability: String, Codable, Sendable {
|
||||
case languageAnalysis
|
||||
case entityExtraction
|
||||
case lexicalSearch
|
||||
case semanticSearch
|
||||
case summarization
|
||||
case questionAnswering
|
||||
case characterRelationships
|
||||
}
|
||||
|
||||
public enum RDAIUnavailableReason: Equatable, Sendable {
|
||||
case operatingSystemUnsupported
|
||||
case deviceNotEligible
|
||||
case appleIntelligenceNotEnabled
|
||||
case modelNotReady
|
||||
case languageUnsupported(String?)
|
||||
case embeddingAssetsUnavailable
|
||||
case providerNotInstalled
|
||||
case unknown(String)
|
||||
}
|
||||
|
||||
public enum RDAICapabilityAvailability: Equatable, Sendable {
|
||||
case available
|
||||
case degraded(reason: RDAIUnavailableReason)
|
||||
case unavailable(reason: RDAIUnavailableReason)
|
||||
}
|
||||
|
||||
public protocol RDAICapabilityProviding: Sendable {
|
||||
func availability(
|
||||
for capability: RDAICapability,
|
||||
locale: Locale?
|
||||
) async -> RDAICapabilityAvailability
|
||||
}
|
||||
```
|
||||
|
||||
UI 只能根据枚举状态展示文案,不能匹配本地化 Error 字符串。
|
||||
|
||||
## 9. 检索 API
|
||||
|
||||
```swift
|
||||
public struct RDAIRetrievalOptions: Sendable {
|
||||
public var maximumResults: Int
|
||||
public var scope: RDAIReadScope
|
||||
public var minimumScore: Double
|
||||
}
|
||||
|
||||
public struct RDAIRetrievalMatch: Sendable, Identifiable {
|
||||
public let id: String
|
||||
public let passage: RDAIPassage
|
||||
public let score: Double
|
||||
public let lexicalScore: Double?
|
||||
public let semanticScore: Double?
|
||||
}
|
||||
|
||||
public protocol RDAIRetrieving: Sendable {
|
||||
func retrieve(
|
||||
query: String,
|
||||
options: RDAIRetrievalOptions
|
||||
) async throws -> [RDAIRetrievalMatch]
|
||||
}
|
||||
```
|
||||
|
||||
检索分数只用于同一索引版本内排序,不承诺跨版本数值稳定。
|
||||
|
||||
## 10. 生成结果
|
||||
|
||||
### 10.1 摘要
|
||||
|
||||
```swift
|
||||
public enum RDAISummaryLength: String, Codable, Sendable {
|
||||
case brief
|
||||
case standard
|
||||
case detailed
|
||||
}
|
||||
|
||||
public struct RDAISummary: Codable, Sendable {
|
||||
public let title: String
|
||||
public let overview: String
|
||||
public let keyPoints: [RDAISourcedStatement]
|
||||
public let citations: [RDAICitation]
|
||||
public let metadata: RDAIGenerationMetadata
|
||||
}
|
||||
```
|
||||
|
||||
### 10.2 问答
|
||||
|
||||
```swift
|
||||
public enum RDAIAnswerStatus: String, Codable, Sendable {
|
||||
case answered
|
||||
case insufficientEvidence
|
||||
case unsupportedLanguage
|
||||
case unavailable
|
||||
}
|
||||
|
||||
public struct RDAIAnswer: Codable, Sendable {
|
||||
public let status: RDAIAnswerStatus
|
||||
public let text: String
|
||||
public let statements: [RDAISourcedStatement]
|
||||
public let citations: [RDAICitation]
|
||||
public let metadata: RDAIGenerationMetadata
|
||||
}
|
||||
|
||||
public struct RDAISourcedStatement: Codable, Sendable, Identifiable {
|
||||
public let id: String
|
||||
public let text: String
|
||||
public let citationIdentifiers: [String]
|
||||
}
|
||||
```
|
||||
|
||||
### 10.3 人物关系
|
||||
|
||||
```swift
|
||||
public enum RDAIRelationshipStatus: String, Codable, Sendable {
|
||||
case confirmed
|
||||
case possible
|
||||
case conflicting
|
||||
}
|
||||
|
||||
public struct RDAICharacter: Codable, Sendable, Identifiable {
|
||||
public let id: String
|
||||
public let displayName: String
|
||||
public let aliases: [String]
|
||||
public let description: String
|
||||
public let firstAppearance: RDAICitation?
|
||||
public let evidence: [RDAICitation]
|
||||
}
|
||||
|
||||
public struct RDAIRelationship: Codable, Sendable, Identifiable {
|
||||
public let id: String
|
||||
public let sourceCharacterIdentifier: String
|
||||
public let targetCharacterIdentifier: String
|
||||
public let label: String
|
||||
public let status: RDAIRelationshipStatus
|
||||
public let evidence: [RDAICitation]
|
||||
}
|
||||
```
|
||||
|
||||
### 10.4 生成元数据
|
||||
|
||||
```swift
|
||||
public struct RDAIGenerationMetadata: Codable, Sendable {
|
||||
public let providerIdentifier: String
|
||||
public let modelVersion: String?
|
||||
public let promptIdentifier: String
|
||||
public let promptVersion: Int
|
||||
public let generatedAt: Date
|
||||
public let scopeHash: String
|
||||
}
|
||||
```
|
||||
|
||||
元数据用于缓存失效和问题追踪,不向普通用户展示内部 Prompt。
|
||||
|
||||
## 11. 高层服务
|
||||
|
||||
```swift
|
||||
public protocol RDAIReaderServicing: AnyObject, Sendable {
|
||||
func prepare(options: RDAIIndexOptions) async throws
|
||||
|
||||
func summarize(
|
||||
scope: RDAIReadScope,
|
||||
length: RDAISummaryLength
|
||||
) async throws -> RDAISummary
|
||||
|
||||
func answer(
|
||||
question: String,
|
||||
scope: RDAIReadScope
|
||||
) async throws -> RDAIAnswer
|
||||
|
||||
func characters(
|
||||
scope: RDAIReadScope
|
||||
) async throws -> [RDAICharacter]
|
||||
|
||||
func relationships(
|
||||
scope: RDAIReadScope
|
||||
) async throws -> [RDAIRelationship]
|
||||
|
||||
func removeAllAIData() async throws
|
||||
}
|
||||
```
|
||||
|
||||
建议具体实现为 actor。若用户开始新的同类请求,UI 层负责决定取消旧请求或并行;同一 Foundation Models session 不允许并行请求。
|
||||
|
||||
## 12. Provider 协议
|
||||
|
||||
```swift
|
||||
public struct RDAIGenerationRequest: Sendable {
|
||||
public let task: RDAIGenerationTask
|
||||
public let userText: String?
|
||||
public let passages: [RDAIPassage]
|
||||
public let locale: Locale
|
||||
public let scope: RDAIReadScope
|
||||
}
|
||||
|
||||
public enum RDAIGenerationTask: Sendable {
|
||||
case summary(RDAISummaryLength)
|
||||
case answer
|
||||
case characters
|
||||
case relationships
|
||||
}
|
||||
|
||||
public protocol RDAIGenerativeProvider: Sendable {
|
||||
var identifier: String { get }
|
||||
func availability(locale: Locale) async -> RDAICapabilityAvailability
|
||||
func generate(_ request: RDAIGenerationRequest) async throws -> RDAIGeneratedArtifact
|
||||
}
|
||||
```
|
||||
|
||||
`RDAIGeneratedArtifact` 是 Core 内部或受控公共枚举,用于把 Provider 输出转换为第 10 节模型。Provider 不能直接保存结果或操作 Reader UI。
|
||||
|
||||
## 13. 错误模型
|
||||
|
||||
```swift
|
||||
public enum RDAIError: Error, Equatable, Sendable {
|
||||
case invalidDocument
|
||||
case resourceUnavailable(RDAIResourceIdentifier)
|
||||
case staleCitation
|
||||
case indexingFailed(code: String)
|
||||
case modelUnavailable(RDAIUnavailableReason)
|
||||
case unsupportedLanguage(String?)
|
||||
case contextLimitExceeded
|
||||
case invalidGeneratedStructure
|
||||
case invalidCitation
|
||||
case insufficientEvidence
|
||||
case cancelled
|
||||
case storageFailure(code: String)
|
||||
}
|
||||
```
|
||||
|
||||
公共错误不携带原文或数据库底层错误字符串。内部错误映射为稳定 code,并通过本地诊断系统保存脱敏详情。
|
||||
|
||||
## 14. PDF Adapter
|
||||
|
||||
建议公开:
|
||||
|
||||
```swift
|
||||
public extension RDPDFReaderViewController {
|
||||
func makeAIContentProvider() -> RDPDFAIContentProvider
|
||||
func makeAIReaderService(
|
||||
configuration: RDAIReaderConfiguration = .default
|
||||
) throws -> RDAIReaderServicing
|
||||
}
|
||||
```
|
||||
|
||||
映射要求:
|
||||
|
||||
- 页面资源 ID 为十进制页索引。
|
||||
- 文本顺序使用 `RDPDFReaderTextRun.readingOrder`。
|
||||
- `normalizedRects` 转换为 `RDAINormalizedRect`。
|
||||
- 原生文本标记为 `.native`,Vision OCR 标记为 `.ocr`。
|
||||
- AI 高亮复用或泛化现有 speech highlight,不同时维护两个相互覆盖的临时层。
|
||||
|
||||
## 15. EPUB Adapter
|
||||
|
||||
建议公开:
|
||||
|
||||
```swift
|
||||
public extension RDEPUBReaderController {
|
||||
func makeAIContentProvider() -> RDEPUBAIContentProvider
|
||||
func makeAIReaderService(
|
||||
configuration: RDAIReaderConfiguration = .default
|
||||
) throws -> RDAIReaderServicing
|
||||
}
|
||||
```
|
||||
|
||||
映射要求:
|
||||
|
||||
- 资源 ID 使用 ResourceResolver 规范化后的 `href`。
|
||||
- Passage 范围从章节 attributed content 的原始字符串计算。
|
||||
- 使用现有 index table 生成 `cfi` 和 `rangeCFI`。
|
||||
- 导航复用 `go(to:)`/位置恢复流程。
|
||||
- 固定版式或无法提取文本的章节返回明确 unavailable,不制造空 Passage。
|
||||
|
||||
## 16. TTS 集成
|
||||
|
||||
AI 层不依赖 RDSpeechReaderView。宿主可以把摘要或回答转换为临时 `RDSpeechContentProvider`。
|
||||
|
||||
后续可增加桥接 Pod:
|
||||
|
||||
```ruby
|
||||
pod 'RDSpeechReaderView/AI'
|
||||
```
|
||||
|
||||
桥接只负责朗读 AI 结果;Natural Language 的分句与语言识别实现应抽取为共享内部组件,避免同一文本产生不同范围。
|
||||
|
||||
## 17. 配置
|
||||
|
||||
```swift
|
||||
public struct RDAIReaderConfiguration: Sendable {
|
||||
public var spoilerPolicy: RDAISpoilerPolicy
|
||||
public var maximumRetrievedPassages: Int
|
||||
public var allowsEmbeddingAssetDownload: Bool
|
||||
public var storesGeneratedArtifacts: Bool
|
||||
public var diagnosticsLevel: RDAIDiagnosticsLevel
|
||||
|
||||
public static let `default`: RDAIReaderConfiguration
|
||||
}
|
||||
```
|
||||
|
||||
默认值:
|
||||
|
||||
- `spoilerPolicy = .readContentOnly`
|
||||
- `maximumRetrievedPassages = 4`
|
||||
- `allowsEmbeddingAssetDownload = false`
|
||||
- `storesGeneratedArtifacts = true`
|
||||
- `diagnosticsLevel = .metadataOnly`
|
||||
|
||||
## 18. API 演进规则
|
||||
|
||||
- 1.0 前可以调整命名,但每次调整同步更新五份设计文档。
|
||||
- 1.0 后删除或改变语义需要主版本升级。
|
||||
- Codable 枚举新增 case 时必须实现向后兼容策略。
|
||||
- 数据库 Schema 版本与 SDK 版本独立。
|
||||
- Prompt 版本与 SDK 版本独立。
|
||||
- Reader Adapter 可以增加格式能力,但不能改变 Core Locator 的 UTF-16 语义。
|
||||
|
||||
@@ -0,0 +1,431 @@
|
||||
# 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 版本化、模型版本分层评测 |
|
||||
| 上下文不足 | 回答遗漏 | 检索压缩、分层摘要、新会话 |
|
||||
| 同名人物 | 错误关系合并 | 不自动合并低置信候选,保留冲突 |
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
# RDAIReaderView Release Checklist
|
||||
|
||||
This checklist records the external validation required after the local build
|
||||
passes. It intentionally contains no book text, prompts, answers or user data.
|
||||
|
||||
> Status on 2026-07-25: Apple Intelligence eligible hardware, App Store privacy
|
||||
> submission and TestFlight rollout access are temporarily unavailable. The
|
||||
> unchecked physical-device and release gates below are deferred, not passed.
|
||||
|
||||
## Local Gates
|
||||
|
||||
- [x] Core, NaturalLanguage, FoundationModels and UI compile for iPhoneOS.
|
||||
- [x] PDF and EPUB adapters compile in the ReadViewDemo workspace.
|
||||
- [x] PDF/EPUB citations use stable locators and transient highlights.
|
||||
- [x] SQLite data, FTS and generated artifacts are deleted with a book.
|
||||
- [ ] Add fixture-backed XCTest coverage for locators, SQLite migration, scope,
|
||||
citation validation, pause/resume and artifact invalidation.
|
||||
- [ ] Add UI automation for index, summary, answer, citation jump, clear data
|
||||
and VoiceOver labels.
|
||||
|
||||
## Physical Device Gates
|
||||
|
||||
- [ ] On an eligible iOS 26 device, verify each `SystemLanguageModel`
|
||||
availability state and its UI fallback.
|
||||
- [ ] Run structured summary and question-answering evaluation fixtures; record
|
||||
citation validity, faithfulness and spoiler-safety without uploading text.
|
||||
- [ ] Verify Vision OCR quality and cancellation/retry on scanned PDF samples.
|
||||
- [ ] Measure index latency, memory, battery and citation jump P95 targets.
|
||||
|
||||
## Release Gates
|
||||
|
||||
- [ ] Create a feature flag/remote configuration policy owned by the host app.
|
||||
- [ ] Complete App Store privacy labels, Foundation Models acceptable-use review
|
||||
and network audit.
|
||||
- [ ] Run TestFlight rollout 5%, 25%, then 100% with P0/P1 stop conditions.
|
||||
- [ ] Confirm crash-free and AI quality metrics meet the published thresholds.
|
||||
@@ -0,0 +1,287 @@
|
||||
# RDAIReaderView 产品与开发规格
|
||||
|
||||
**文档状态:** Draft 0.1
|
||||
**最后更新:** 2026-07-25
|
||||
**目标版本:** RDAIReaderView 1.0
|
||||
**适用工程:** ReadViewSDK
|
||||
|
||||
## 1. 文档目的
|
||||
|
||||
本文档锁定 RDAIReaderView 首个商用版本的产品范围、系统兼容策略、功能要求、非功能要求和发布门槛。架构、公共 API、生成式 AI 约束和测试方法分别见同目录其他文档。
|
||||
|
||||
## 2. 背景与现状
|
||||
|
||||
ReadViewSDK 已具备以下基础:
|
||||
|
||||
- RDPDFReaderView:PDF 页面、原生文本、Vision OCR、页内文本矩形、跳页与临时朗读高亮。
|
||||
- RDEpubReaderView:EPUB 章节、`href`、CFI、UTF-16 文本范围、搜索与位置恢复。
|
||||
- RDSpeechReaderView:基于 Natural Language 的语言识别和分句、系统 TTS、断点续听、后台播放与锁屏控制。
|
||||
- 最低部署版本为 iOS 15,Demo 使用 iOS 15.6。
|
||||
|
||||
当前缺少统一的文档语义索引、可追溯引用、书内问答、章节摘要和人物关系能力。
|
||||
|
||||
## 3. 产品目标
|
||||
|
||||
RDAIReaderView 1.0 的目标是提供一个默认本地运行、可选启用 Apple Foundation Models、可被 PDF 和 EPUB 阅读器复用的智能阅读能力层。
|
||||
|
||||
首版必须实现:
|
||||
|
||||
1. 对书籍内容建立增量、可恢复的本地索引。
|
||||
2. 识别语言、句子、人物、地点、组织和关键词。
|
||||
3. 生成当前章节或已读范围摘要。
|
||||
4. 回答书内问题,并为事实性陈述提供可跳转的原文引用。
|
||||
5. 生成人物卡片和带证据的人物关系。
|
||||
6. Foundation Models 不可用时安全降级,不影响阅读、搜索和 TTS。
|
||||
7. 所有 AI 结果默认限制在用户已读内容,避免剧透。
|
||||
|
||||
## 4. 非目标
|
||||
|
||||
RDAIReaderView 1.0 不包含:
|
||||
|
||||
- 互联网百科、新闻或通用知识问答。
|
||||
- 无来源的文学评价、复杂逻辑推理或事实推断。
|
||||
- 自动改写、续写或批量导出版权书籍内容。
|
||||
- 云端上传书籍全文。
|
||||
- 自训练 Foundation Models Adapter。
|
||||
- 自动替用户发布内容、发送消息或执行购买行为。
|
||||
- 对 CBZ、漫画图片内容进行视觉剧情理解。
|
||||
- 对 DRM 内容绕过访问控制或持久化超出宿主授权范围的文本。
|
||||
|
||||
上述能力必须在后续版本单独评审产品价值、版权、隐私和审核风险。
|
||||
|
||||
## 5. 用户价值与首版场景
|
||||
|
||||
### 5.1 阅读回顾
|
||||
|
||||
用户重新打开书籍时,可请求:
|
||||
|
||||
- 上次阅读内容的 3 句回顾。
|
||||
- 当前章节摘要。
|
||||
- 已读部分的关键人物变化。
|
||||
|
||||
输入范围默认从最近一个自然章节边界到当前阅读位置,不得包含未读段落。
|
||||
|
||||
### 5.2 书内问答
|
||||
|
||||
用户可以询问当前书籍,例如:
|
||||
|
||||
- “这一章发生了什么?”
|
||||
- “张三为什么离开?”
|
||||
- “这里提到的组织是什么?”
|
||||
|
||||
系统先检索相关段落,再基于检索结果生成答案。答案中的事实性结论必须关联一个或多个 `RDAICitation`。没有充分证据时必须明确拒答,而不是依赖模型常识补全。
|
||||
|
||||
### 5.3 人物与关系
|
||||
|
||||
人物卡片包含:
|
||||
|
||||
- 标准显示名和已发现的别名。
|
||||
- 首次出现位置。
|
||||
- 仅基于已读内容的简短介绍。
|
||||
- 关键行为及证据。
|
||||
- 与其他人物的关系边及证据。
|
||||
|
||||
关系状态分为:
|
||||
|
||||
- `confirmed`:原文明确表达。
|
||||
- `possible`:模型推断但证据不充分,UI 必须显示“可能”。
|
||||
- `conflicting`:不同段落给出冲突信息,UI 展示冲突而非自动覆盖。
|
||||
|
||||
### 5.4 与阅读器联动
|
||||
|
||||
- 点击引用跳转到 PDF 页面或 EPUB CFI。
|
||||
- 跳转后高亮对应原文范围。
|
||||
- 摘要、答案和人物卡片可交给 RDSpeechReaderView 朗读。
|
||||
- 用户调整字体、页面尺寸或翻页方式后,EPUB 引用仍应通过 CFI/文本范围恢复。
|
||||
|
||||
## 6. 功能要求
|
||||
|
||||
### FR-001 文档导入
|
||||
|
||||
- AI 层只能通过 `RDAIContentProvider` 读取宿主已授权的文本快照。
|
||||
- 不直接读取宿主数据库或下载接口。
|
||||
- 支持取消导入、增量恢复和内容变更检测。
|
||||
|
||||
### FR-002 稳定定位
|
||||
|
||||
- PDF:使用文档 ID、页索引、页内 UTF-16 范围和归一化矩形。
|
||||
- EPUB:使用文档 ID、规范化 `href`、UTF-16 范围和 CFI;CFI 不可用时才使用 progression 兜底。
|
||||
- 所有引用必须保存源文本哈希,恢复时验证引用是否仍指向相同内容。
|
||||
|
||||
### FR-003 文本分析
|
||||
|
||||
- 使用 `NLLanguageRecognizer` 识别资源或段落语言。
|
||||
- 使用 `NLTokenizer` 切分句子,保持原始 UTF-16 偏移。
|
||||
- 使用 `NLTagger` 生成人名、地点、组织候选。
|
||||
- 实体候选必须保留每次出现的原文位置,不能只保存名称。
|
||||
- Natural Language 不支持或质量不足的语言,降级为字符/标点分段和关键词检索。
|
||||
|
||||
### FR-004 分块与索引
|
||||
|
||||
- 中文片段建议 600-900 个字符;拉丁文字建议 300-600 词。
|
||||
- 优先在章节、段落和句子边界切分,不截断组合字符。
|
||||
- 相邻片段保留 1-2 句重叠,便于跨边界检索。
|
||||
- 每个片段保存内容哈希、语言、顺序、定位和索引版本。
|
||||
- 索引任务在后台执行,并按当前章节、相邻章节、其余内容的优先级处理。
|
||||
|
||||
### FR-005 检索
|
||||
|
||||
- 首版采用关键词/BM25 风格评分与 Natural Language 语义相似度融合。
|
||||
- 结果必须经过文档 ID、已读范围和访问范围过滤。
|
||||
- 默认返回 3-4 个片段,最大不超过 5 个。
|
||||
- 检索结果必须包含分数、匹配原因和稳定定位。
|
||||
|
||||
### FR-006 Foundation Models 可用性
|
||||
|
||||
- 编译期使用可选子模块,不提高 Core 的 iOS 15 最低版本。
|
||||
- 运行时检查系统版本、设备资格、Apple Intelligence 开关、模型准备状态和语言支持。
|
||||
- UI 必须区分 `deviceNotEligible`、`appleIntelligenceNotEnabled`、`modelNotReady`、不支持语言和未知错误。
|
||||
- 不可用时隐藏生成入口或提供明确说明,Natural Language 索引、搜索和 TTS 保持可用。
|
||||
|
||||
### FR-007 结构化生成
|
||||
|
||||
- 摘要、答案、实体和关系均使用 `@Generable` 结构化输出。
|
||||
- 输出不得依赖字符串正则解析。
|
||||
- 每个事实项必须携带检索片段 ID;生成后由代码验证 ID 是否真实存在。
|
||||
- 无效引用、越权引用或未读范围引用必须删除;删除后答案无证据则转为拒答。
|
||||
|
||||
### FR-008 防剧透
|
||||
|
||||
- 默认分析范围为“当前位置及之前”。
|
||||
- 用户主动切换到整本书模式时必须进行一次明确确认。
|
||||
- 缓存键包含阅读范围;已读摘要不得复用整本书摘要。
|
||||
- 人物关系图默认只展示已读范围内已出现的人物和关系。
|
||||
|
||||
### FR-009 缓存与恢复
|
||||
|
||||
- 索引、实体、摘要和问答缓存均存储在应用沙盒。
|
||||
- 缓存键包含文档内容哈希、索引版本、Prompt 版本、模型版本和阅读范围。
|
||||
- 内容哈希变化时,失效受影响资源,不强制删除整本书其他有效索引。
|
||||
- 提供按书删除、删除全部 AI 数据和存储空间统计接口。
|
||||
|
||||
### FR-010 用户控制
|
||||
|
||||
- 所有长任务支持取消。
|
||||
- UI 展示索引或生成状态,不伪造确定进度。
|
||||
- 用户可关闭 AI、清除 AI 缓存、选择“仅本地处理”。
|
||||
- 生成失败不得阻塞翻页、搜索、标注或 TTS。
|
||||
|
||||
## 7. 系统兼容矩阵
|
||||
|
||||
| 环境 | 必须提供的能力 |
|
||||
|------|----------------|
|
||||
| iOS 15+ | 语言识别、分句、实体候选、关键词索引、基础检索 |
|
||||
| iOS 17+ | 可选 contextual embedding;资源不存在时允许下载或降级 |
|
||||
| iOS 26+ 且模型可用 | 摘要、问答、人物关系、结构化笔记 |
|
||||
| 不支持 Apple Intelligence | Natural Language 能力完整可用,生成式入口降级 |
|
||||
| 离线 | 已下载模型与本地索引可用;不得要求联网 |
|
||||
| 扫描 PDF | 使用现有 Vision OCR;OCR 失败的页面明确标记不可分析 |
|
||||
|
||||
## 8. 非功能要求
|
||||
|
||||
### 8.1 性能
|
||||
|
||||
- 索引不得在主线程执行文本分析、向量计算或数据库批量写入。
|
||||
- 当前章节索引优先完成,目标 P95 不超过 2 秒;具体阈值以目标真机基线校准。
|
||||
- 10 万中文字的基础索引目标 P95 不超过 30 秒,允许后台增量完成。
|
||||
- 索引期间阅读页面滚动/翻页帧率不得出现持续性下降。
|
||||
- 单次 Foundation Models 响应首个可展示结果目标 P95 不超过 5 秒。
|
||||
- AI 模块空闲 30 秒后应释放 contextual embedding 和不必要的内存缓存。
|
||||
|
||||
### 8.2 稳定性
|
||||
|
||||
- AI 相关 crash-free session 不低于 99.9%。
|
||||
- Foundation Models 不可用或生成失败时降级成功率为 100%。
|
||||
- 强制退出后索引可从最后一个已提交资源恢复。
|
||||
- 数据库迁移失败时保留原数据库备份,并允许重建索引。
|
||||
|
||||
### 8.3 准确性
|
||||
|
||||
- 引用定位有效率不低于 99%。
|
||||
- 事实性陈述有原文支持的比例不低于 98%。
|
||||
- 无答案问题正确拒答率不低于 95%。
|
||||
- 人物关系证据覆盖率为 100%。
|
||||
- 结构化输出通过本地校验的比例不低于 99.5%。
|
||||
|
||||
### 8.4 隐私与安全
|
||||
|
||||
- 默认不上传书籍文本、查询、摘要、人物关系和阅读历史。
|
||||
- 日志不得包含原文、用户问题全文或模型完整输出。
|
||||
- 调试日志必须经过显式编译配置才能包含脱敏片段。
|
||||
- AI 数据遵循宿主账户登出、删书和清除缓存生命周期。
|
||||
- 文件保护等级、备份策略和共享容器由宿主配置,SDK 提供明确接口和文档。
|
||||
|
||||
### 8.5 可访问性
|
||||
|
||||
- 所有 AI 控件支持 VoiceOver、Dynamic Type 和 Reduce Motion。
|
||||
- 状态变化使用可访问性公告,但不得连续播报索引细节。
|
||||
- “AI 生成”“可能关系”“无原文证据”等状态不能只靠颜色表达。
|
||||
|
||||
## 9. 商用验收门槛
|
||||
|
||||
以下条件全部满足后才可发布 1.0:
|
||||
|
||||
- Core、NaturalLanguage、FoundationModels、PDF Adapter、EPUB Adapter 均有单元测试。
|
||||
- 关键用户流有 UI 自动化测试。
|
||||
- 完成至少 100 条人工标注的产品评测集。
|
||||
- 所有准确性指标达到第 8.3 节门槛。
|
||||
- 在最低支持系统、主流支持设备和至少两代 Apple Intelligence 设备上完成真机验证。
|
||||
- 完成模型不可用、未下载、语言不支持、上下文溢出和生成取消测试。
|
||||
- 完成隐私清单、App Store 隐私申报和 AI 功能说明审核。
|
||||
- TestFlight 灰度无 P0/P1 缺陷,AI 相关 crash-free session 达标。
|
||||
- 现有 PDF、EPUB、搜索、标注和 TTS 回归全部通过。
|
||||
|
||||
## 10. 实施路线
|
||||
|
||||
以下排期按 2 名 iOS 工程师、1 名测试工程师、产品/内容评测兼职参与估算,总周期 12-14 周。单人开发建议按 18-22 周估算。
|
||||
|
||||
| 周期 | 阶段 | 主要交付 | 退出条件 |
|
||||
|------|------|----------|----------|
|
||||
| 第 1 周 | 合同与工程骨架 | 五份开发文档、Podspec、目录、CI Scheme、ADR | 文档评审通过,空库支持 iOS 15 编译 |
|
||||
| 第 2-3 周 | Core 与存储 | 公共模型、SQLite Schema、迁移、Job/Checkpoint、删除接口 | 崩溃恢复和增量失效单测通过 |
|
||||
| 第 4-5 周 | Natural Language | 分句、语言、实体候选、词法/语义检索 | 基础检索评测达标,TTS 范围无漂移 |
|
||||
| 第 6 周 | PDF Adapter | 原生文本/OCR 快照、Locator、引用跳转和高亮 | PDF 引用恢复率达到门槛 |
|
||||
| 第 7 周 | EPUB Adapter | href/CFI/rangeCFI 快照、Locator、跳转和高亮 | 重排后引用恢复率达到门槛 |
|
||||
| 第 8-9 周 | Foundation Models | 可用性、摘要、问答、结构化输出、引用校验 | 不可用降级与 AI 评测通过 |
|
||||
| 第 10 周 | 人物关系 | 人物、别名、关系、冲突和证据合并 | 人物/关系指标达到门槛 |
|
||||
| 第 11 周 | 商用 UI | AI 面板、状态、取消、引用、防剧透、无障碍 | 核心 UI 自动化通过 |
|
||||
| 第 12 周 | 性能与隐私 | 内存、耗电、数据库、日志、清除数据、隐私说明 | 无 P0/P1,性能与隐私门禁通过 |
|
||||
| 第 13-14 周 | TestFlight 灰度 | 5%→25%→100% 分阶段发布 | Crash-free 和质量反馈持续达标 |
|
||||
|
||||
每阶段要求:
|
||||
|
||||
- 功能代码、单元测试和文档同一阶段完成。
|
||||
- 公共 API 变更必须先更新 API 文档。
|
||||
- Prompt 变更必须增加版本并跑 AI 回归集。
|
||||
- 阶段退出条件未满足时不得把未验证能力带入下一阶段默认开启。
|
||||
|
||||
## 11. 版本范围
|
||||
|
||||
### 1.0
|
||||
|
||||
- 本地索引。
|
||||
- 章节摘要。
|
||||
- 带引用的书内问答。
|
||||
- 人物卡片和基础人物关系。
|
||||
- PDF/EPUB 引用跳转。
|
||||
- 防剧透和完整降级。
|
||||
|
||||
### 1.1 候选
|
||||
|
||||
- 关系时间线与冲突关系展示。
|
||||
- 用户划线/笔记参与问答。
|
||||
- 多本书对照,仅限用户主动选择的本地书籍。
|
||||
- 可选 Core ML/MLX 或云端 Provider。
|
||||
|
||||
### 2.0 候选
|
||||
|
||||
- 多模态图片理解。
|
||||
- 漫画/图文书内容理解。
|
||||
- 经过独立法律和产品评审的云端增强能力。
|
||||
|
||||
## 12. 依赖文档
|
||||
|
||||
- [RDAIReaderView-ARCHITECTURE.md](RDAIReaderView-ARCHITECTURE.md)
|
||||
- [RDAIReaderView-API.md](RDAIReaderView-API.md)
|
||||
- [RDAIReaderView-AI-SPEC.md](RDAIReaderView-AI-SPEC.md)
|
||||
- [RDAIReaderView-TEST-PLAN.md](RDAIReaderView-TEST-PLAN.md)
|
||||
@@ -0,0 +1,473 @@
|
||||
# RDAIReaderView 商用测试与发布计划
|
||||
|
||||
**文档状态:** Draft 0.1
|
||||
**最后更新:** 2026-07-25
|
||||
**目标版本:** RDAIReaderView 1.0
|
||||
|
||||
## 1. 目标
|
||||
|
||||
测试计划验证以下结论:
|
||||
|
||||
1. AI 模块不会破坏现有 PDF、EPUB、搜索、标注和 TTS。
|
||||
2. 索引和引用在书籍更新、分页变化、OCR 和应用中断后仍然可靠。
|
||||
3. Foundation Models 的输出有证据、可拒答、不剧透并可安全降级。
|
||||
4. 性能、内存、耗电、隐私和可访问性达到商用要求。
|
||||
5. Prompt 或系统模型更新后,可以通过可重复评测发现质量回归。
|
||||
|
||||
## 2. 测试层级
|
||||
|
||||
```text
|
||||
人工与 TestFlight 验收
|
||||
↑
|
||||
UI / 真机系统测试
|
||||
↑
|
||||
PDF / EPUB / TTS 集成测试
|
||||
↑
|
||||
AI 产品评测与 Prompt 回归
|
||||
↑
|
||||
Core / Storage / NLP 单元测试
|
||||
```
|
||||
|
||||
确定性校验优先放在单元测试;非确定性生成质量使用固定数据集、多次运行和人工评审。
|
||||
|
||||
## 3. 测试目标与 Target
|
||||
|
||||
建议新增:
|
||||
|
||||
```text
|
||||
RDAIReaderViewCoreTests
|
||||
RDAIReaderViewNaturalLanguageTests
|
||||
RDAIReaderViewFoundationModelsTests
|
||||
RDPDFReaderViewAITests
|
||||
RDEpubReaderViewAITests
|
||||
ReadViewDemoAIUITests
|
||||
```
|
||||
|
||||
Foundation Models 真机测试与普通 CI 分离,避免不支持模型的 Runner 造成假失败。
|
||||
|
||||
## 4. 测试数据
|
||||
|
||||
### 4.1 数据来源
|
||||
|
||||
只使用:
|
||||
|
||||
- 公版书籍。
|
||||
- 项目拥有测试授权的书籍。
|
||||
- 团队自行编写的合成文本。
|
||||
- 经过脱敏、明确允许进入测试仓库的样本。
|
||||
|
||||
不得把商业书籍全文或用户内容提交到测试仓库。
|
||||
|
||||
### 4.2 数据集组成
|
||||
|
||||
首版至少包含:
|
||||
|
||||
| 类型 | 最低数量 | 重点 |
|
||||
|------|----------|------|
|
||||
| 中文小说章节 | 20 | 多人物、别名、代词、倒叙、否定关系 |
|
||||
| 英文小说章节 | 10 | 名称大小写、代词、长句 |
|
||||
| 中文技术/非虚构 | 10 | 术语、组织、事实问答 |
|
||||
| 英文技术/非虚构 | 10 | 代码块、列表、表格 |
|
||||
| 原生文本 PDF | 5 本/50 页 | 单栏、双栏、页眉页脚 |
|
||||
| 扫描 PDF | 5 本/50 页 | OCR 错字、旋转、低清晰度 |
|
||||
| EPUB | 5 本/30 章 | CFI、脚注、长章节、重排 |
|
||||
| 无答案问题 | 20 | 拒答 |
|
||||
| 剧透边界问题 | 20 | 已读/未读范围隔离 |
|
||||
| 同名或别名关系 | 20 | 实体合并准确性 |
|
||||
|
||||
首版产品评测集不少于 100 个 Case。每个 Case 保存输入、允许范围、期望证据、可接受答案要点和禁止行为。
|
||||
|
||||
### 4.3 Case 格式
|
||||
|
||||
建议使用 JSONL:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "qa-zh-001",
|
||||
"task": "questionAnswering",
|
||||
"documentFixture": "novel-zh-01",
|
||||
"readScope": {
|
||||
"resourceOrderUpperBound": 3,
|
||||
"utf16UpperBound": 8200
|
||||
},
|
||||
"input": "林川为什么离开村庄?",
|
||||
"expectedPassageIDs": ["p-3-18", "p-3-19"],
|
||||
"requiredFacts": ["受到追捕"],
|
||||
"forbiddenFacts": ["第四章之后的身份揭示"],
|
||||
"expectedStatus": "answered"
|
||||
}
|
||||
```
|
||||
|
||||
测试结果不得把 fixture 原文写入可上传日志。
|
||||
|
||||
## 5. Core 单元测试
|
||||
|
||||
### 5.1 文本范围
|
||||
|
||||
- 空文本、空白文本和超长文本。
|
||||
- Emoji、组合字符、代理对、中文标点和换行。
|
||||
- UTF-16 范围与 Swift String Index 双向转换。
|
||||
- 搜索规范化不能改变 source range。
|
||||
- Passage 重叠不能产生错误 Locator。
|
||||
|
||||
### 5.2 哈希与失效
|
||||
|
||||
- 相同内容产生相同哈希。
|
||||
- 只改变一个章节时只失效该资源。
|
||||
- Prompt 版本变化只失效相关 Artifact。
|
||||
- embedding 模型 revision 变化只重建对应向量。
|
||||
- 阅读范围扩大不复用越界缓存。
|
||||
|
||||
### 5.3 存储与迁移
|
||||
|
||||
- 首次建库、重复打开和并发读取。
|
||||
- 每个 Schema 版本向下一版本迁移。
|
||||
- 迁移中断后恢复或回滚。
|
||||
- 数据库损坏时保留诊断并可安全重建。
|
||||
- 按书删除和删除全部数据。
|
||||
- 登出/删书回调后无孤立 Passage、向量或 Artifact。
|
||||
|
||||
### 5.4 索引调度
|
||||
|
||||
- 当前章节优先。
|
||||
- 暂停、恢复、取消和重复 prepare。
|
||||
- 应用强制退出后从 checkpoint 恢复。
|
||||
- 内存警告取消低优先级任务。
|
||||
- 内容 Provider 释放后任务安全失败,不野指针或永久等待。
|
||||
|
||||
## 6. Natural Language 测试
|
||||
|
||||
### 6.1 语言与分句
|
||||
|
||||
- 中文、英文、中英混排。
|
||||
- 无标点长段落。
|
||||
- 缩写、小数、网址和引号。
|
||||
- 句子范围与 RDSpeechReaderView 结果一致。
|
||||
- 不支持语言的降级分块。
|
||||
|
||||
### 6.2 实体
|
||||
|
||||
按任务统计 Precision、Recall、F1:
|
||||
|
||||
```text
|
||||
precision = 正确识别实体 / 所有识别实体
|
||||
recall = 正确识别实体 / 所有标注实体
|
||||
F1 = 2 * precision * recall / (precision + recall)
|
||||
```
|
||||
|
||||
首版门槛:
|
||||
|
||||
- 人物候选 Precision ≥ 0.95。
|
||||
- 人物候选 Recall ≥ 0.85。
|
||||
- 地点/组织作为辅助信息,F1 ≥ 0.80。
|
||||
|
||||
人物候选宁可少召回,也不能大量创建虚假人物。
|
||||
|
||||
### 6.3 检索
|
||||
|
||||
- 关键词命中、同义表达、别名和错别字。
|
||||
- Top 5 包含正确证据的 Recall@5 ≥ 0.90。
|
||||
- 无 embedding 资源时词法检索仍可返回结果。
|
||||
- 已读范围外 Passage 召回数必须为 0。
|
||||
- 相同输入和索引版本的词法结果顺序稳定。
|
||||
|
||||
## 7. PDF Adapter 测试
|
||||
|
||||
- 原生文本 run 按 `readingOrder` 正确拼接。
|
||||
- 双栏页面不会按几何坐标错误穿插。
|
||||
- run 间换行计入 UTF-16 范围。
|
||||
- Passage 范围映射回正确 normalized rects。
|
||||
- characterRects 存在/缺失均可高亮。
|
||||
- OCR 与原生文本来源正确标记。
|
||||
- OCR 缓存命中、失败、取消和重试。
|
||||
- 页面缓存裁剪后 Citation 仍可重新加载。
|
||||
- 跳转后目标页和高亮正确。
|
||||
- 旋转、横屏、竖滑、双页模式下高亮位置正确。
|
||||
- 页面导航取消 OCR 时,AI 索引任务不应永久丢失。
|
||||
|
||||
PDF 引用定位有效率必须 ≥ 99%。
|
||||
|
||||
## 8. EPUB Adapter 测试
|
||||
|
||||
- `href` 规范化一致。
|
||||
- UTF-16 range、rangeAnchor、CFI 和 rangeCFI 互相映射。
|
||||
- 改字号、行距、边距、字体和横竖屏后 Citation 可恢复。
|
||||
- 长章节按需加载时可提取目标资源。
|
||||
- 脚注、列表、图片替代文本和代码块类型正确。
|
||||
- EPUB 更新导致 source hash 变化时旧 Citation 标记 stale。
|
||||
- CFI 缺失时 progression 只作兜底。
|
||||
- 引用跳转复用标准位置恢复流程。
|
||||
- 固定版式无文本章节返回明确不可分析状态。
|
||||
|
||||
EPUB 重排后引用定位有效率必须 ≥ 99%。
|
||||
|
||||
## 9. Foundation Models 产品评测
|
||||
|
||||
### 9.1 运行方式
|
||||
|
||||
- 每个 Case 至少运行 3 次,避免偶然结果掩盖问题。
|
||||
- 按系统模型版本、系统语言和设备分桶。
|
||||
- Prompt 新版本同时运行旧版和新版,生成差异报告。
|
||||
- 代码校验先执行,再进入人工/模型评分。
|
||||
|
||||
### 9.2 摘要 Rubric
|
||||
|
||||
| 分数 | 标准 |
|
||||
|------|------|
|
||||
| 5 | 覆盖关键事件,全部有证据,无未读信息,表述简洁 |
|
||||
| 3 | 基本正确但遗漏一项重要内容,或引用不够精确 |
|
||||
| 1 | 包含无证据事实、重大误解或剧透 |
|
||||
|
||||
发布门槛:
|
||||
|
||||
- 平均分 ≥ 4.0。
|
||||
- 任一剧透 Case 失败即阻断发布。
|
||||
- 无证据事实比例 ≤ 2%。
|
||||
|
||||
### 9.3 问答 Rubric
|
||||
|
||||
检查:
|
||||
|
||||
- 是否回答用户问题。
|
||||
- 每个事实是否被引用支持。
|
||||
- 是否遗漏关键反证。
|
||||
- 证据不足时是否拒答。
|
||||
- 是否泄漏未读内容。
|
||||
|
||||
发布门槛:
|
||||
|
||||
- Context faithfulness ≥ 98%。
|
||||
- 无答案正确拒答率 ≥ 95%。
|
||||
- Citation validity ≥ 99%。
|
||||
- Spoiler safety = 100%。
|
||||
|
||||
### 9.4 人物与关系 Rubric
|
||||
|
||||
检查:
|
||||
|
||||
- 人物真实出现。
|
||||
- 别名有明确证据。
|
||||
- 同名人物未误合并。
|
||||
- 关系方向正确。
|
||||
- `confirmed` 与 `possible` 分类合理。
|
||||
- 冲突关系没有被静默覆盖。
|
||||
|
||||
发布门槛:
|
||||
|
||||
- Character precision ≥ 97%。
|
||||
- Alias merge precision ≥ 98%。
|
||||
- 关系证据覆盖率 = 100%。
|
||||
- 无证据关系数 = 0。
|
||||
|
||||
### 9.5 LLM Judge
|
||||
|
||||
LLM Judge 只作为辅助:
|
||||
|
||||
- 使用固定 Rubric,不使用泛化“是否有帮助”问题。
|
||||
- 先对至少 30 个 Case 与人工评分校准。
|
||||
- Spearman/Pearson 相关性低于 0.7 时不得作为发布门禁。
|
||||
- Judge 分歧、低分和边界 Case 必须人工复核。
|
||||
- 若使用云端 Judge,测试原文必须为可上传的公版或合成数据。
|
||||
|
||||
## 10. 可用性与错误测试
|
||||
|
||||
覆盖:
|
||||
|
||||
- iOS 15/17:Foundation Models 模块不参与运行。
|
||||
- iOS 26+ 不支持设备。
|
||||
- Apple Intelligence 未开启。
|
||||
- 模型正在下载或未准备。
|
||||
- 当前语言不支持。
|
||||
- context limit exceeded。
|
||||
- guardrail 拒绝输入或输出。
|
||||
- 生成中取消、切书、关闭页面、进入后台。
|
||||
- 同一 session 并发请求。
|
||||
- 低存储空间和数据库写入失败。
|
||||
|
||||
每种情况必须产生稳定枚举状态,并保持阅读器可操作。
|
||||
|
||||
## 11. UI 与可访问性
|
||||
|
||||
### 11.1 UI 自动化
|
||||
|
||||
- 打开/关闭 AI 面板。
|
||||
- 当前章节索引状态。
|
||||
- 发起问题、取消和重试。
|
||||
- 点击引用并跳转高亮。
|
||||
- 仅已读范围默认开启。
|
||||
- 整本书模式确认。
|
||||
- Foundation Models 不可用状态。
|
||||
- 清除本书和全部 AI 数据。
|
||||
- AI 结果交给 TTS 朗读。
|
||||
|
||||
### 11.2 可访问性
|
||||
|
||||
- VoiceOver 顺序和标签。
|
||||
- Dynamic Type 最大辅助字号。
|
||||
- Reduce Motion。
|
||||
- 深色模式和高对比度。
|
||||
- `possible`/`conflicting` 不只依赖颜色。
|
||||
- 加载、取消和失败状态有可访问性公告。
|
||||
|
||||
## 12. 性能与资源测试
|
||||
|
||||
目标设备至少覆盖:
|
||||
|
||||
- 最低性能 iOS 15 支持设备。
|
||||
- iOS 17 中档设备。
|
||||
- 一台首代支持 Apple Intelligence 的设备。
|
||||
- 一台当前系统的高性能设备。
|
||||
|
||||
基准:
|
||||
|
||||
| 指标 | 1.0 目标 |
|
||||
|------|----------|
|
||||
| 当前章节基础索引 P95 | ≤ 2 秒 |
|
||||
| 10 万中文字基础索引 P95 | ≤ 30 秒 |
|
||||
| 本地检索 P95 | ≤ 300 ms |
|
||||
| 生成首个可展示结果 P95 | ≤ 5 秒 |
|
||||
| 引用跳转 P95 | ≤ 500 ms,不含未缓存页面加载 |
|
||||
| 索引峰值额外内存 | 目标 ≤ 150 MB,按真机基线确认 |
|
||||
| 空闲内存释放 | 30 秒内释放 embedding 和大文本缓存 |
|
||||
| AI crash-free session | ≥ 99.9% |
|
||||
|
||||
测试同时记录:
|
||||
|
||||
- CPU time。
|
||||
- 主线程卡顿。
|
||||
- thermal state。
|
||||
- 电量变化。
|
||||
- 数据库大小/万字。
|
||||
- embedding 资源加载耗时。
|
||||
- 缓存命中率。
|
||||
|
||||
性能基线变化超过 15% 时 CI 或发布报告必须提示。
|
||||
|
||||
## 13. 隐私与安全测试
|
||||
|
||||
- 网络抓包确认默认实现不上传书籍或问题。
|
||||
- 搜索日志、控制台日志和 crash breadcrumbs 不含原文。
|
||||
- 清除 AI 数据后数据库、缓存和临时文件均删除。
|
||||
- 删除书籍和退出账户触发相同清除路径。
|
||||
- Scope 过滤在检索前和生成后均执行。
|
||||
- 构造伪造 Passage ID,确认 Citation Validator 拒绝。
|
||||
- 构造路径、超长查询和大量 Tool 参数,确认边界限制。
|
||||
- Tool Calling 最大次数和重复调用检测生效。
|
||||
- 数据库迁移和诊断包不泄漏原文。
|
||||
|
||||
## 14. 回归测试
|
||||
|
||||
每次合入必须运行:
|
||||
|
||||
- Core 单元测试。
|
||||
- Natural Language 确定性测试。
|
||||
- PDF/EPUB Adapter fixture 测试。
|
||||
- 现有 PDF、EPUB 和 TTS 编译。
|
||||
- `git diff --check` 和公共 API 兼容检查。
|
||||
|
||||
每日或候选发布运行:
|
||||
|
||||
- UI smoke。
|
||||
- 完整 AI 评测集。
|
||||
- 大书索引性能。
|
||||
- Foundation Models 真机矩阵。
|
||||
- 现有 `ReadViewDemoUITests` 回归。
|
||||
|
||||
## 15. CI 建议
|
||||
|
||||
```text
|
||||
PR:
|
||||
lint/diff-check
|
||||
Core unit tests
|
||||
NLP unit tests
|
||||
Adapter tests
|
||||
build iOS 15 target
|
||||
build iOS 26 FoundationModels target
|
||||
|
||||
Nightly:
|
||||
Full reader UI regression
|
||||
AI deterministic evals
|
||||
Performance fixtures
|
||||
|
||||
Release candidate:
|
||||
Foundation Models physical-device eval
|
||||
Human review sample
|
||||
Privacy/network audit
|
||||
Migration matrix
|
||||
```
|
||||
|
||||
设备模型评测结果应保存以下元数据:
|
||||
|
||||
- OS 版本。
|
||||
- 模型版本或可识别 profile。
|
||||
- Prompt identifier/version。
|
||||
- fixture version。
|
||||
- SDK commit。
|
||||
- 各指标与失败 Case ID。
|
||||
|
||||
不得保存生产用户原文。
|
||||
|
||||
## 16. 缺陷分级
|
||||
|
||||
### P0
|
||||
|
||||
- 泄漏书籍内容或阅读历史。
|
||||
- 绕过已读范围造成剧透。
|
||||
- 删除用户原书、标注或笔记。
|
||||
- 大面积崩溃或数据库不可恢复损坏。
|
||||
|
||||
### P1
|
||||
|
||||
- 无引用或错误引用的事实作为确定答案展示。
|
||||
- 人物关系大面积误合并。
|
||||
- Foundation Models 不可用导致阅读器不可用。
|
||||
- 引用跳转到错误章节/页面。
|
||||
|
||||
### P2
|
||||
|
||||
- 摘要遗漏、检索质量下降、局部 UI 或性能问题。
|
||||
- 可重试且不影响阅读主流程的生成失败。
|
||||
|
||||
发布时 P0/P1 必须为 0;P2 必须有明确接受记录和后续版本计划。
|
||||
|
||||
## 17. TestFlight 灰度
|
||||
|
||||
### 阶段 A:内部
|
||||
|
||||
- 团队和测试设备。
|
||||
- 至少 7 天。
|
||||
- 完整日志仅限脱敏元数据。
|
||||
|
||||
### 阶段 B:5%
|
||||
|
||||
- 只开启摘要和问答。
|
||||
- 观察 crash-free、取消率、拒答率、引用点击成功率。
|
||||
- 人物关系仍受远程/本地 feature flag 控制。
|
||||
|
||||
### 阶段 C:25%
|
||||
|
||||
- 开启人物卡片。
|
||||
- 关系图只对达到索引完整度的书籍开放。
|
||||
- 至少稳定 7 天。
|
||||
|
||||
### 阶段 D:100%
|
||||
|
||||
- 所有发布门禁持续达标。
|
||||
- 保留快速关闭 Foundation Models 功能的配置,但关闭后基础阅读和 NLP 正常。
|
||||
|
||||
## 18. 最终发布门禁
|
||||
|
||||
- [ ] 五份开发文档与实现一致。
|
||||
- [ ] 公共 API 兼容检查通过。
|
||||
- [ ] Core/NLP/Adapter 单元和集成测试通过。
|
||||
- [ ] 现有 Reader 与 TTS 回归通过。
|
||||
- [ ] 100+ AI Case 全量运行并达到指标。
|
||||
- [ ] Foundation Models 支持与不支持路径均完成真机测试。
|
||||
- [ ] PDF/EPUB Citation validity ≥ 99%。
|
||||
- [ ] Context faithfulness ≥ 98%。
|
||||
- [ ] Spoiler safety = 100%。
|
||||
- [ ] AI crash-free session ≥ 99.9%。
|
||||
- [ ] 隐私和网络审计通过。
|
||||
- [ ] 无 P0/P1 缺陷。
|
||||
- [ ] TestFlight 灰度指标稳定。
|
||||
|
||||
+7
-1
@@ -1,6 +1,6 @@
|
||||
# ReadViewSDK 文档索引
|
||||
|
||||
> 最后更新:2026-06-18
|
||||
> 最后更新:2026-07-25
|
||||
|
||||
---
|
||||
|
||||
@@ -33,6 +33,12 @@
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [RDAIReaderView/RDAIReaderView-SPEC.md](RDAIReaderView/RDAIReaderView-SPEC.md) | AI 阅读能力产品范围、兼容策略、实施路线与商用验收门槛 |
|
||||
| [RDAIReaderView/RDAIReaderView-ARCHITECTURE.md](RDAIReaderView/RDAIReaderView-ARCHITECTURE.md) | RDAIReaderView 模块、索引、检索、存储、引用和降级架构 |
|
||||
| [RDAIReaderView/RDAIReaderView-API.md](RDAIReaderView/RDAIReaderView-API.md) | RDAIReaderView 公共模型、Provider、Reader Adapter 和服务 API 合同 |
|
||||
| [RDAIReaderView/RDAIReaderView-AI-SPEC.md](RDAIReaderView/RDAIReaderView-AI-SPEC.md) | Natural Language 与 Foundation Models 的 Prompt、结构化输出、安全和评测合同 |
|
||||
| [RDAIReaderView/RDAIReaderView-TEST-PLAN.md](RDAIReaderView/RDAIReaderView-TEST-PLAN.md) | AI 商用测试集、质量指标、真机矩阵、CI、灰度与发布门禁 |
|
||||
| [RDAIReaderView/RDAIReaderView-RELEASE-CHECKLIST.md](RDAIReaderView/RDAIReaderView-RELEASE-CHECKLIST.md) | 本地构建后所需的真机、隐私、TestFlight 与发布验证清单 |
|
||||
| [TYPESetter_PIPELINE.md](TYPESetter_PIPELINE.md) | Typesetter 排版管线详解:HTML 规范化、语义标记注入、CFI 标记、样式合成为、字体规范化、片段标记 |
|
||||
| [CHAPTER_RUNTIME.md](CHAPTER_RUNTIME.md) | 章节运行时详解:按需加载、章节窗口协调、页图管理、磁盘缓存、后台补全 |
|
||||
| [CFI_SUBSYSTEM.md](CFI_SUBSYSTEM.md) | CFI 子系统详解:EPUB CFI 解析、生成、序列化、范围、恢复引擎 |
|
||||
|
||||
Reference in New Issue
Block a user