# 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 与审核要求已复核。