Memoria 项目实训日志 #3 | 端侧感知起步:多维特征打标与自然语言检索 MVP 落地
文章目录
项目名称:智能影记 - Memoria
团队名称:Mnemosyne
时间:2026.03.30 - 2026.04.05 (实训第三周)
当前阶段:Phase 2 (端侧感知攻坚) - 视觉唤醒与 MVP 验证
一、 本周核心任务:赋予 AI “视觉神经”与交互 MVP
随着 Phase 1 基建期完成,Memoria 本周正式迈入深水区。如果说前两周我们搭建了一个极速的数据容器(Isar)和通信管道(FFI),那么本周的核心任务就是向容器内注入有价值的“灵魂”。
为了保证团队并行开发的效率,本周我们采用了典型的敏捷迭代策略:在底层核心模型转换的同时,应用层与数据层快速推出了基于标签匹配的核心交互验证版本。团队达成了三大技术里程碑:
- 多维相册打标体系落地:确立了“视觉标签 (AI Tags) + 文本标签 (OCR Tags)”的双擎特征提取规范,并实现了数据入库前的智能清洗。
- 交互验证 (MVP):完成“自然语言搜图” V1 版(基于 LLM 标签泛化)的端到端链路打通。
- AI 底座预热:完成 MobileCLIP 模型端侧转换工具链的 Python 侧精度校验。
二、 数据模型完善:多维特征打标体系
散乱的照片无法构成故事,要让 Memoria 成为合格的“智能导演”,第一步是让它“看懂”相册里的每一张图。本周,数据与前端组联合确立了 PhotoEntity 的精细化打标体系:
2.1 视觉语义打标
我们摒弃了传统的粗粒度分类,在 Isar 数据库中设计了原生支持多重索引的 List<String> aiTags 字段。为了承接后续端侧 MobileCLIP 模型的推理输出,我们构建了一套多层级的标签字典(Taxonomy)。当模型对图像进行编码后,能够自动为其打上“沙滩”、“海浪”、“聚餐”等高频视觉标签。
2.2 文本特征补充
在实际的手机相册中,除了风景和人物,还充斥着大量的文档、幻灯片和截图。为了弥补纯视觉模型的盲区,我们引入了轻量级 OCR 策略,将提取出的有效短文本存储为 ocrTags。这使得用户不仅能搜“画面”,还能直接搜索照片里的“文字内容”。
2.3 数据清洗逻辑下沉
优质的标签来源于干净的数据。在打标入库的瞬间,我们在实体类(Entity)内部下沉了清洗逻辑:通过计算照片的极端宽高比(aspectRatio < 0.52)并正则匹配底层文件路径(如包含 screenshot 关键字),系统会前置拦截并过滤掉无意义的超长广告截图,极大节省了后续端侧 AI 的推理算力。
// lib/models/entity/photo_entity.dart
import 'package:isar/isar.dart';
part 'photo_entity.g.dart';
()
class PhotoEntity {
Id id = Isar.autoIncrement;
late String path;
late int width;
late int height;
// 预留的标签字段,Isar 对 List 有良好的原生查询支持
List<String>? aiTags;
List<String>? ocrTags;
double get aspectRatio => width > 0 ? width / height : 1.0;
// 业务逻辑内聚:通过宽高比和路径特征过滤无效长截图
bool get isProbablyScreenshot {
final normalizedPath = path.toLowerCase();
const screenshotKeywords = <String>['screenshot', 'capture', '截图'];
if (screenshotKeywords.any(normalizedPath.contains)) return true;
// 拦截极端比例的长截图,避免浪费后续 AI 分析算力
return aspectRatio > 0 && aspectRatio < 0.52;
}
}
三、 交互 MVP 验证:自然语言检索 (V1 版)
3.1 检索架构设计
该方案的核心思路是“标签泛化匹配”:
- 用户在端侧输入自然语言 Query。
- 客户端调用云端大语言模型(LLM),将 Query 扩展为一组相关的高频短标签。
- 客户端拿到扩展标签后,在本地 Isar 数据库中进行多条件的
OR查询匹配。
3.2 核心代码实现
首先是在服务端,我们基于 FastAPI 搭建了一个简易的 Prompt 泛化接口(模拟逻辑):
# ai_tools/api_server.py
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class QueryRequest(BaseModel):
user_query: str
@app.post("/api/v1/expand_query")
async def expand_query(request: QueryRequest):
"""
调用 LLM 将自然语言泛化为本地图库可能存在的标签
"""
query = request.user_query
# TODO: 实际接入 LLM API,此处为逻辑演示
if "去海边" in query or "沙滩" in query:
return {"tags": ["大海", "沙滩", "海浪", "比基尼", "蓝天"]}
elif "好吃" in query:
return {"tags": ["美食", "餐厅", "聚餐", "火锅"]}
return {"tags": ["日常"]}
随后在 Flutter 客户端,利用 Isar 的高级查询语法 anyOf 实现本地秒级匹配:
// lib/services/search_service.dart
import 'package:isar/isar.dart';
Future<List<PhotoEntity>> semanticSearchV1(String queryText) async {
// 1. 请求云端接口获取泛化标签
List<String> targetTags = await fetchExpandedTagsFromCloud(queryText);
if (targetTags.isEmpty) return [];
// 2. 本地 Isar 数据库匹配查询
final isar = PhotoService().isar;
final results = await isar.photoEntitys.filter()
// 匹配 AI 视觉标签
.anyOf(targetTags, (q, String tag) => q.aiTagsElementEqualTo(tag))
.or()
// 匹配 OCR 文本标签
.anyOf(targetTags, (q, String tag) => q.ocrTagsElementEqualTo(tag))
.findAll();
return results;
}
通过上述代码,我们在不依赖端侧向量计算的前提下,初步跑通了自然语言搜图的端到端数据流。
四、 端侧 AI 底座:MobileCLIP 工具链与精度对齐
在应用层跑通 MVP 的同时,AI 组在 ai_tools 目录下完成了大模型端侧上机的最后预演。
本周,团队构建了 MobileCLIP 的特征提取验证脚本,并着手编写 ONNX 与 NCNN 的导出与量化工具。通过将 PyTorch 提取的向量与 NCNN 模拟运行的向量进行严格的对比校验,我们成功验证了模型在低精度量化下的特征损失率处于可控范围内。这标志着 Memoria 具备了在移动设备上离线理解图像特征的坚实基础。
五、 总结与问题反思
本周我们按计划跑通了 V1 版的搜索链路,但也确认了“基于标签匹配”的方案存在明显局限性:
- 语义鸿沟:文本标签是离散的。如果用户搜索“海边”,而某张照片由于拍摄角度仅被打上了“晴天”和“风景”的标签,系统便无法将其召回。
- 云端依赖:目前方案强依赖云端 LLM 进行词汇扩展,如果在弱网或无网环境下,检索功能将大打折扣。
下周迭代计划(V2 版搜索):
针对上述问题,V1 方案将被作为基准线(Baseline)保留,团队下周将全面转向 V2 版架构:端侧向量检索。
- 将验证通过的 NCNN 库通过 Dart FFI 接入客户端。
- 利用 MobileCLIP 的多模态特性,在本地将照片与用户的搜索文本统一映射到高维向量空间,通过计算余弦相似度实现真正的语义搜图。
更多推荐

所有评论(0)