直接回答
要搜索本地 AI 历史,应把 AppSearch 作为派生查询索引,而不是历史记录的权威数据库。应用 Repository 仍保存真源;索引仅包含用户明确需要查找的字段。每个索引文档都应指向稳定的历史记录 ID 和修订号;搜索命中后必须先重新读取当前仍获授权的真源记录,才能显示或导出全文。RAG-01 支持把源数据、索引和检索分成独立核验阶段。PRIVACY-01 提醒:本地推理不能证明应用的所有数据路径都在本机或符合用户预期。这两个事实都不能证明 Cove 已集成 AppSearch。 截至本次审核日,AndroidX AppSearch release table 列出 1.1.0 为稳定版,1.2.0-alpha02 为 alpha;开发指南代码片段使用 alpha。因此不能照抄示例版本,也不能在未核 resolved dependency 与 API 引入版本前假设 Cove 可用。LocalStorage 把索引保存在 app 自己的存储空间;其全局搜索覆盖该 app 的本地数据库,不搜索其他 app。私有历史默认使用 LocalStorage,不默认发到 PlatformStorage 或 PlayServicesStorage 中央索引。只有另有明确需求时才使用中央后端;AndroidX SetSchemaRequest.Builder.setSchemaTypeVisibilityForPackage 用于指定允许读取的包,PlatformStorage 的系统界面呈现可用 setSchemaTypeDisplayedBySystem(schemaType, false) 关闭并需检查 feature 支持;schema 更新时也要重设,因为该设置不跨 schema 调用保留。不能仅凭 app-local storage 就说数据不会进入备份或换机迁移;需单独审计规则。 搜索文档应由稳定 namespace 和 ID 加精心选择的字段组成。可包含历史记录 ID、输出修订、任务类别、语言方向、创建时间,以及用户允许索引的短标题或摘要。除非功能确实需要且用户理解这一选择,否则不要索引完整提示词、私人原文档、凭据或未经审核的生成文本。用 AppSearch schema 声明哪些字符串字段参与索引。本文配置 StringPropertyConfig 词法 token 搜索;AppSearch 另有独立且受 feature/version 约束的 embedding property API,但本文不配置它们,也不声称特定 app 依赖一定支持。搜索片段或排序不能暗示命中是经过验证的答案。 AndroidX AppSearch 1.1 的 putAsync(PutDocumentsRequest) 返回 ListenableFuture,成功完成后得到 AppSearchBatchResult;其中成功/失败 key 仅是 document ID,不包含复合身份 (namespace, ID)。若 future 本身异常结束,就没有可检查的逐文档 map。每个 batch 保留 namespace 上下文;按单一 namespace 分批,或保证跨 namespace ID 不重复,再由应用状态映射复合身份。数据库事务与 AppSearch 写入是独立操作,中断或乱序工作可能导致暂时不一致。源删除时先持久化 tombstone 或新修订,串行执行或协调旧投影任务,并在返回命中前重新读取当前获授权的源行。索引写失败不能删除有效历史,也不能让旧 put/rebuild 复活已删摘要。 schema 更改要有兼容策略。AndroidX AppSearch 1.1 使用 AppSearchSession.setSchemaAsync(SetSchemaRequest);先处理 ListenableFuture 异常,因为该路径没有 SetSchemaResponse。仅在正常完成后检查 getIncompatibleTypes()、getDeletedTypes()、getMigratedTypes() 与 getMigrationFailures()。不兼容类型需要明确 Migrator 或重建策略;force-override 会删除不兼容文档,不能当普通恢复按钮。保留 schema/索引代次并用旧版填充夹具测试中断和迁移。删除请求通过 RemoveByDocumentIdRequest.Builder(namespace).addIds(ids).build() 构造,再传入 AppSearchSession.removeAsync,并检查返回的 AppSearchBatchResult;其 key 仍是 ID,须保留 namespace。remove 成功后文档不再出现在 search 中,但 Android 文档说明物理删除可能要等数据库数量或字节阈值达到后才回收;这不是取证级安全擦除保证,备份和其他副本也要单独处理。旧 put/rebuild 需通过源 tombstone 协调。关闭 AppSearchSession 会持久化 schema/文档变更,不是删除。这里说的是 androidx.appsearch API,不是同名 android.app.appsearch framework API。 将检索评价为词法搜索,而非 AI 质量基准。先固定一组合成查询及预期历史 ID,再调整实现。覆盖确切姓名、标点、短前缀、多语言文本、重复标题、已删除记录、变化的修订号,以及只出现在不应索引的隐私字段中的词。记录零结果与过期引用行为。不要因为库宣传多语言或本机性能,就声称语义相似度、普适分词、隐私认证或延迟优势。合理的验收结论应更窄:某个明确的应用构建和 AppSearch 后端,对某个有版本的夹具集合返回预期且获授权的历史记录,并在删除后不再返回。
用户搜索一条已保存的本地译文
旅行者数月后想通过一句短语找到先前保存的译文。历史 Repository 保存完整原文和已审核输出,但列表页没有快速定位方式。有些记录含敏感源文本,不应默认全部变成可搜索字段。
决策
增加应用本地的词法索引,设置明确字段白名单和稳定记录引用,并在显示全文前按当前记录重新授权校验。
预期结果
搜索返回可核对的历史记录或无结果,不会展示过期副本或来自未授权字段的文字。
需要收集的证据
只有将以下证据与同一模型文件和测试运行关联起来,结论才可复核:
- RAG-01:索引与检索是需要独立核验的数据管线阶段;这不意味着必须使用向量或生成式 RAG。
- PRIVACY-01:本地推理并不能证明应用其他网络、备份、分享路径都不存在。
- ANDROID-APPSEARCH-HISTORY-2026-10:AppSearch 的本地存储、schema 与词项查询是平台能力;不代表 Cove 已集成或解析了特定库版本。
- AndroidX 官方文档分别描述 AppSearch LocalStorage、本地 schema 和字符串字段索引能力;不代表 Cove 已集成或解析了特定库版本。
任务质量需要有版本记录的语料和验收规则;流畅的单条样例不等于准确度结果。
实施流程
- 选择存储并固定依赖版本. 记录解析得到的 AndroidX AppSearch artifact、后端、Android API 范围和功能检查。当前指南示例使用 alpha 版本,而发布表也列有稳定版本;报告实际测试版本。默认使用应用本地 LocalStorage。只有明确需求才选择中央后端;若使用,要在每个 schema request 配置包可见性和系统界面可见性并核对 feature 支持,同时另查备份恢复。
- 定义最小搜索投影. 使用确定的 namespace 和 document ID 关联真源历史行与修订。只挑选用户允许搜索的字段,显式声明索引和 tokenizer 类型;默认不放完整提示词或文档。标题/摘要是索引投影,不是源记录。
- 同步真源行和索引结果. 先写入或更新权威历史记录,再用 AndroidX AppSearchSession.putAsync 投影修订。future 异常与正常完成后的 AppSearchBatchResult 分开处理;result key 只有 document ID。每个 batch 按 namespace 分开,或避免跨 namespace 使用重复 ID,再在应用状态中映射复合身份。保留中断后的待处理工作,并对账过期修订和 tombstone。
- 给 schema 与查询行为定版本. 调用 AndroidX AppSearchSession.setSchemaAsync(SetSchemaRequest) 并先处理 future 异常;只有成功返回后才检查 schema response。不兼容、被删除、已迁移类型和迁移失败都要有处理路径,不要强制 override 用户历史。测试旧版填充夹具、精确/前缀字符串查询、分页、多语言夹具和零命中。本文使用词法匹配;embedding-property API 是另一项版本/feature 合同。
- 删除并审计完整生命周期. 源记录删除时先保存 tombstone/修订,再用 AndroidX AppSearchSession.removeAsync(RemoveByDocumentIdRequest) 删除该 namespace/ID;检查逐文档结果并协调旧 put/rebuild。查询前仍核验获授权源记录。remove 不等于立即物理安全擦除,磁盘回收可能延迟,备份也需另外审计。close 持久化更改但不删除;close/requestFlushAsync 与备份恢复分别测试。
让每个阶段的状态都可观察。失败信息应指出阶段、模型、运行时和恢复动作,同时避免记录用户私密内容。
验收标准
- 规范历史 Repository 保持权威;每条搜索结果在展示全文前,都通过稳定 namespace、ID 和修订号重新读取。
- 只索引声明且经用户允许的字段,并记录已解析 AppSearch 版本下的精确/前缀 tokenizer 行为。
- AndroidX AppSearch 1.1 异步 future 异常先独立处理;每份文档结果按 document ID 解释,namespace 单独保留,同一个 batch 内避免跨 namespace ID 碰撞。
- schema future 异常时不假设有 response;正常完成后才检查兼容/迁移/删除结果。tombstone 与投影协调可阻止旧任务作为当前历史返回。
- removeAsync 结果、session close 和 flush 分开测试;返回命中前协调旧投影。逻辑查询移除不说成立即物理安全擦除;备份/恢复单独审计。
决策对照表
| 维度 | 选择或证据 | 解读方式 |
|---|---|---|
| 权威历史数据库 | Room 或既有 Repository 保存完整记录 | 负责用户编辑、来源和删除,也是重建搜索索引的数据来源。 |
| AppSearch LocalStorage 投影 | 保存 app 专属索引字段用于全文词项查找 | 可支持本地 lexical search,但部分写入和 schema 版本必须显式对账。 |
| Platform / Play Services storage | 使用带额外系统集成面的中央索引后端 | 共享、系统呈现和可用性行为不同;不应为私有历史静默切换。 |
| Embedding / vector index | 对向量化内容进行相似度检索 | 是另一种检索合同;AppSearch 另有 embedding-property API,但本文不配置或评价它。 |
需要避免的失败模式
- 把派生搜索索引当成历史记录唯一真源。
- 把“在设备本地”说成绝不进入系统备份或导出。
- 把 exact/prefix token 检索说成向量语义相似度。
- session.close() 时只关闭连接却未删除对应的索引文档。
还要避免静默回退、版本未固定、缺少取消处理,以及把不同配置的结果混在一起下结论。失败运行也应与成功记录一并保存。
最小复现记录
| 层级 | 记录内容 |
|---|---|
| 设备 | 厂商、型号、芯片、内存档位、操作系统版本 |
| 软件 | 应用版本和 Git 提交号 |
| 模型 | 系列、变体、版本、格式、文件长度、摘要、量化方式 |
| 运行时 | 名称、版本、请求后端及实际后端证据 |
| 工作负载 | 样例版本、输入摘要、提示词摘要、输出策略 |
| 结果 | 完成、失败、取消、回退及保护隐私的诊断信息 |
发布检查表
- ☐ 主要搜索问题已回答,且没有未经支持的数字。
- ☐ 所有模型文件和运行时版本均已固定。
- ☐ 代表性任务和失败处理策略均有说明。
- ☐ 生命周期、取消、清理和回退均已测试。
- ☐ 用户内容与网络边界均有说明。
- ☐ 结论只适用于被记录的配置。
- ☐ 新增测试结果时链接到原始方法或证据。
来源与相关证据
- Android Developers — AppSearch 指南
- Android Developers — LocalStorage API
- Android Developers — StringPropertyConfig API
- Android Developers — AppSearchBatchResult API
- Android Developers — SetSchemaRequest API
- Android Developers — SetSchemaRequest.Builder API
- Android Developers — SetSchemaResponse API
- Android Developers — RemoveByDocumentIdRequest API
- Android Developers — AppSearchSession API
- Android Developers — EmbeddingPropertyConfig API
- Android Developers — Auto Backup
- Android Developers — AppSearch 发布说明
中文部署与排错专题见。奇连 AI 端侧专题。
常见问题
AppSearch 是 AI 历史记录的真源吗?
不是。规范历史行仍在应用 Repository 中,AppSearch 是派生投影。显示全文前,要按当前 ID 与修订重新读取真源,并检查当前状态与授权。
LocalStorage 能保证历史永不离开设备吗?
不能。它是 app-specific 本地索引,但备份、换机迁移、导出和其他网络请求各有规则。须独立审计,不能把本地推理说成整个应用的隐私保证。
前缀索引等于语义搜索吗?
不等于。本文的 StringPropertyConfig exact/prefix 设置是词法检索。AppSearch 某些版本/后端也有独立且受 feature 限制的 embedding-property API;使用它需要另行核对依赖、能力与评价合同。
关闭 AppSearchSession 会删除索引文档吗?
不会。close() 持久化 schema 和文档变更,不移除记录。AndroidX AppSearchSession.removeAsync(RemoveByDocumentIdRequest) 按 namespace/ID 删除搜索文档;它仍不能代替真源 tombstone 或旧任务协调。
批次结果 key 会同时包含 namespace 和 ID 吗?
不会。AndroidX AppSearch 1.1 putAsync 的结果只以 document ID 为 key。每个 batch 保留 namespace;不同 namespace 的相同 ID 不要放进同一结果 map,并在应用状态保存复合身份。
removeAsync 能保证物理安全擦除吗?
不能。remove 完成后文档不再从 AppSearch 查询返回,但 Android 文档说明磁盘回收可能等数据库达到大小阈值;备份、其他投影和旧的在途写入还需分别清理或协调。