HarmonyOS 7 新特性(十二)|文本搜图:从语义检索到隐私索引

本文讨论 HarmonyOS 7(API 26)新增的“通过文本搜索图片”能力。接口仍处于 Beta 阶段,模型资源、支持设备和输入限制请以 Core Vision Kit 当前文档为准。
传统相册检索依赖文件名、日期、位置和人工标签。用户记得的往往是“海边的落日”“戴红帽子的猫”“白板上的架构图”,却不知道拍摄时间。文本搜图将自然语言与图片内容映射到同一语义空间,使用户可以按记忆寻找素材。
一个可用的文本搜图功能不只是搜索框,还要解决授权范围、索引版本、排序阈值、隐私日志和回退。本文以项目素材库为例设计完整链路。
一、搜索前先明确数据范围
应用只能处理用户授权的相册或私有项目素材。首次进入时说明检索范围,并允许选择具体相册、时间段或项目。撤回权限、退出账号或删除项目后,相关索引必须同步清理。
不要默认扫描整个图库。语义能力越强,越要坚持最小数据原则。
二、把查询建模为结构化对象
interface ImageSearchQuery {
requestId: string
text: string
albumIds?: string[]
startTime?: number
endTime?: number
contentTypes?: Array<'photo' | 'screenshot' | 'document'>
limit: number
}
interface SearchHit {
assetId: string
semanticScore: number
capturedAt: number
groupId?: string
}
语义模型负责判断内容相似度,时间、相册与权限过滤负责决定结果能否出现。原始查询文本只在本次任务中使用,不应进入普通日志。
三、输入先做规范化
去除首尾空格、限制长度、合并重复空白,并对空查询明确提示。时间表达如“去年夏天”可以转换为时间范围,但要把转换结果展示给用户;人名和地点不能擅自扩展为未经授权的数据来源。
function normalizeQuery(input: string): string {
return input.trim().replace(/\s+/g, ' ').slice(0, 120)
}
function validateQuery(query: ImageSearchQuery): void {
if (!query.text) throw new SearchError('EMPTY_QUERY')
if (query.limit < 1 || query.limit > 100) {
throw new SearchError('INVALID_LIMIT')
}
}

四、索引、增量更新与查询分离
首次索引、增量索引和查询是三类任务。首次扫描可分批进行并展示进度;新增、删除、编辑图片时只更新受影响资产;查询只读取一个稳定索引版本。
interface IndexSnapshot {
version: number
indexedAssets: number
lastAssetChangeId: string
createdAt: number
}
async function applyAssetChanges(changes: AssetChange[]) {
for (const change of changes) {
if (change.type === 'deleted') await index.remove(change.assetId)
else await index.upsert(await analyzer.describe(change.assetId))
}
await index.commitNextVersion()
}
索引重建时仍可读取旧版本,并提示结果可能不完整。不要边修改边暴露半成品索引。
五、结果排序不能只看相似度
最终排序可以组合语义分数、拍摄时间、清晰度、收藏状态与重复项惩罚。相似连拍应聚合,避免前十条都是同一秒拍摄的照片。低于可信阈值时宁可显示“没有足够匹配的图片”,也不要硬凑结果。
function finalScore(hit: SearchHit, meta: AssetMeta): number {
const quality = Math.min(meta.shortEdge / 2000, 1) * 0.08
const favorite = meta.favorite ? 0.05 : 0
const duplicatePenalty = meta.isNearDuplicate ? 0.12 : 0
return hit.semanticScore * 0.87 + quality + favorite - duplicatePenalty
}
权重只是示例,项目应通过真实查询集标定,并为排序规则保留版本。
六、请求竞态需要 Latest-Only 策略
用户输入“海边”后立刻改成“海边落日”,第一次查询可能更晚返回。界面只能接收当前 requestId 对应结果,旧任务完成后丢弃。
class SearchCoordinator {
private activeRequestId = ''
async search(query: ImageSearchQuery) {
this.activeRequestId = query.requestId
const result = await repository.search(query)
if (query.requestId !== this.activeRequestId) return
store.replace(result)
}
}
七、隐私和日志边界
查询可能包含姓名、地点和私人事件。埋点记录耗时、结果数量、索引版本和错误码,不记录查询原文、图片 URI 与缩略图。若必须分析失败样本,应使用用户明确同意的脱敏反馈流程。
应用私有索引与账号绑定;退出登录、删除账户和撤回图库权限后执行清理。缓存缩略图同样属于用户数据,不能被遗漏。
八、设计清晰的降级路径
模型未下载、设备不支持、资源不足或索引损坏时,回退到时间、地点、文件名和用户标签搜索。界面应注明当前使用智能语义还是普通条件搜索,不能把两类能力混成一个无法解释的结果。
九、测试集合怎么建
准备同义表达、长短查询、抽象场景、颜色主体组合、否定表达和无结果查询。数据覆盖人物、文档、截图、风景、连拍与重复文件。每个查询都标注期望 TopK、允许候选和不应出现的结果。
describe('semantic image search', () => {
it('filters assets outside authorized albums', async () => {
const hits = await search(queryInAlbumA)
expect(hits.every(x => x.albumId === 'album-a')).toBe(true)
})
it('does not let stale query replace latest results', async () => {
coordinator.search(firstQuery)
await coordinator.search(secondQuery)
await fakeRepository.finish(firstQuery.requestId)
expect(store.queryId).toBe(secondQuery.requestId)
})
})
十、上线清单
- 索引范围来自用户明确授权;
- 查询对象有长度、范围和 limit 校验;
- 增量索引与稳定查询版本分离;
- 结果包含阈值、去重和可解释筛选;
- 迟到请求不能覆盖新结果;
- 日志不保存查询原文与图片路径;
- 撤权、退出和删除账户会清理索引;
- 能力不可用时回退条件搜索。

结语
文本搜图的价值,是让用户按记忆而不是文件组织方式找图片。把授权范围、索引版本、结果排序、竞态处理和隐私清理一起做好,语义检索才能从模型演示变成可靠的相册入口。
官方参考
- Harmony Intelligence:https://developer.huawei.com/consumer/cn/harmonyos-ai
- Core Vision Kit API 导航:https://developer.huawei.com/consumer/cn/doc/doccenter-capabilities/api/ts-basic-components-navigation
更多推荐



所有评论(0)