1. 为什么要做这个项目:从“文件堆成山”到“一问就能找”
先交代一下背景。我手头长期积累了几千份本地文档——PDF论文、技术手册、产品需求书、会议纪要、Markdown笔记、各种导出的HTML存档,甚至还有一部分OCR出来的扫描件。这些文件躺在硬盘里的时候是财富,真到用的时候就是灾难。想找一个半年前写过的方案细节,文件名记不清,目录结构又改过好几轮,只能一层层翻,运气好五分钟,运气不好半小时起步。
后来我试过不少“本地知识库”方案,但要么依赖云端API,文档内容必须传出去,数据隐私这块过不去;要么配置链路太长,又是向量库又是中间件,折腾完已经没力气整理文档了。更关键的是,大多数方案默认跑在Windows或者Linux服务器上,桌面端体验很割裂。
正好HarmonyOS 6.0的PC端能力已经开放了不少,API稳定程度也够用了,我就决定在鸿蒙PC环境里自建一个智能文档管理APP。核心目标有三个:第一,把文档统一收进来,做本地索引;第二,用语义检索替代纯粹的关键词匹配,解决“想不起来关键词但记得大概意思”的检索痛点;第三,所有数据不出本机,保证隐私可控。
这个项目做完之后,我实际用得最多的场景是:打开APP,输入“上回讨论的那个降本方案里关于缓存淘汰策略的结论”,系统直接返回对应的段落和来源文件。不用记文件名,不用记精确词,语义对上就能找到。这篇文章就把整个落地过程拆开讲清楚,包括技术选型、语义检索的实现细节、PC端适配的坑,以及我踩过的那些文档处理层面的雷。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术选型与整体架构:为什么用本地小模型,而不是云端大接口
2.1 选型之前先想清楚三件事
动工之前,我先列了几个硬性约束,后面所有选型都围绕着它们展开:
- 数据不出本机。文档内容、索引结果、检索日志全部保存在本地,不调用任何公网API。
- PC端资源和移动端不一样,内存、CPU、存储都更宽裕,但也不能随便吃满,毕竟电脑还要干别的活。
- 语义检索要快。打开APP之后,索引要能秒级加载,单次检索不能让人等出焦虑感。
在这些约束下,面向云端的大模型接口方案直接出局。剩下来要解决的核心问题是:嵌入模型用哪个、向量索引怎么存、检索召回之后怎么给用户呈现结果。
2.2 嵌入模型选择:量化小模型是实用主义的最优解
语义检索的第一步,是把文本变成向量。这一步的模型选型直接决定了检索效果的上限。
我的选择是本地运行一个小规模嵌入模型,采用量化版本部署。量化的意思是把模型权重从FP32压缩到INT8甚至INT4,体积缩小、推理速度变快,精度损失在可接受范围内。对于中文文档检索场景,量化后的模型仍然能把语义相近的句子映射到比较接近的向量空间,足够支撑日常检索。
为什么不选更大的模型?因为在这个场景里,检索召回质量并不完全取决于模型参数量。更大模型带来的收益在“理解复杂语义”上更明显,而本地知识库检索面对的问题大多是“用一句话描述一个概念或结论”,中等规模的嵌入模型已经能处理得很好。再往上加参数量,边际收益不高,但内存占用和推理延迟的增长却很直接。为了省那一点准确率,让每次检索多等两三秒,不值。
2.3 为什么选择向量数据库而非直接暴力遍历
文本向量化之后,如果文档量小(几百个段落),直接遍历计算余弦相似度也没问题。但这个项目要面对的是几千份文档、几万个文本块,每次检索都对全量计算代价太高。所以需要建立向量索引。
在这个项目里,我采用了一个比较轻量的方案:把向量索引持久化为本地文件,启动时加载进内存,检索时使用近似最近邻(ANN)算法进行匹配,配合暴力精确检索作为兜底。具体参数和实现细节在下一节展开。
另外,PC端的优势在这里体现得非常明显。移动端做同样的事情,内存吃紧、存储空间有限;PC端随便几十GB存储加16GB内存,本地跑向量索引完全没有压力。
2.4 整体架构长什么样
整个应用可以分成四个层次:
- 数据接入层:负责文件导入、格式解析、文本抽取、编码清洗。
- 索引构建层:把清洗后的文本切块、向量化、写入本地向量索引。
- 语义检索层:接收查询,计算查询向量,召回TopK文本块,做重排过滤。
- 展示交互层:HarmonyOS ArkUI搭建的PC端界面,呈现检索结果、文件来源、命中位置。
应用本体使用ArkTS开发,基于HarmonyOS 6.0的PC端适配能力。数据存储使用SQLite保存文档元信息和文本块内容,向量索引使用本地文件存储。整个应用构建完成后,离线可以独立运行,不需要任何外部服务。
3. 文档处理链路:从导入到可检索,中间隔着一堆格式坑
3.1 文档解析:不要指望一个库通吃所有格式
文档管理APP的第一个难点不是界面,也不是检索,而是把不同格式的文档干净地变成纯文本。我遇到的格式类型包括:TXT、Markdown、PDF(文本型和扫描型)、Word文档、HTML导出页,以及EPUB电子书。
这里必须强调一个经验:没有哪个解析库能完美处理所有格式,老老实实按格式分流处理是最省心的做法。
- TXT和Markdown:直接按编码读取,注意处理UTF-8、UTF-16、GBK多种编码,乱码问题要靠检测编码解决。
- PDF:文本型PDF用解析库抽取文本;扫描型PDF需要搭配OCR模块,识别
