本地嵌入模型怎么选
25MB 中文优先、23MB 英文优先、120MB 中英混排,三档怎么取舍。附维度与体积的关系、量化带来的精度代价,以及换模型为什么必须重建索引。
作者 SecureRAG Team · · 9 分钟阅读
本地嵌入模型负责把每个文本块变成一串定长的数字,选哪一档,决定了哪些问题能找到哪些段落。本站提供三档:25MB 的中文优先、23MB 的英文优先、120MB 的中英混排;在它们之间做选择,主要看你文档的语言构成,跟“谁更强”关系不大。
嵌入模型到底做了什么
嵌入这一步,是让检索能在“意思”上工作,而不是只认字面。文档被切成的每一块都会过一遍一个小神经网络,输出一个向量——本站这三档是 384 维或 512 维的浮点数——向量连同文本一起存进浏览器的 IndexedDB。向量在输出时已经做过 L2 归一化,所以后面比较两个向量时,只是在算点积。
这个设计带来两个后果:
- 模型是每个文档库的长期决策。 一个模型算出的向量,对另一个模型没有意义,因为坐标里编码的是特定模型的相似度观念。换模型,已存的向量全部作废。
- 模型只下载一次,之后走缓存。 首次访问用一个普通的 GET 取权重,之后浏览器缓存直接命中,断网也能继续用。
三档对照
| 模型 | 下载体积 | 维度 | 语言 | 适合 | 要注意 |
|---|---|---|---|---|---|
bge-small-zh-v1.5 |
约 25MB | 512 | 中文 | 纯中文资料库,中文文档的默认选择 | 对纯英文段落和代码标识符较弱 |
all-MiniLM-L6-v2 |
约 23MB | 384 | 英文 | 英文资料库,三档里最小最快 | 基本不懂中文,混排库会明显掉点 |
multilingual-e5-small |
约 120MB | 384 | 100+ 种 | 同一个库里确实中英混排 | 首次下载是前者的五倍,逐块嵌入也慢一些 |
表里是真实的下载体积。超过 30MB 的那一档不会在你不点确认的情况下开始下载,也就是说,代价总是先摆在你面前再发生。
下载一次要花什么,之后又占多少
有两笔账要分开算,它们不是同一笔。
一次性下载。 首次访问用普通的 GET 取权重,不经过任何第三方 CDN,文件和页面同一个源。权重会进浏览器的 HTTP 缓存,之后再来,网络面板基本是安静的。
每个文档库的常驻开销。 向量不太能压缩。按 32 位浮点算,384 维模型下一个块约占 1.5KB,512 维约 2KB。往前推一下:
| 库的规模 | 典型块数 | 384 维的向量占用 | 512 维的向量占用 |
|---|---|---|---|
| 一份合同,约 30 页 | 约 120 | 约 0.2MB | 约 0.25MB |
| 十份文档混排 | 约 1,200 | 约 1.8MB | 约 2.5MB |
| 四十份文档,总量接近 200MB | 约 6,000–12,000 | 约 9–18MB | 约 12–25MB |
| 顶到 20,000 块上限 | 20,000 | 约 31MB | 约 41MB |
也就是说,向量比多数人想的便宜,占地方的大头往往是模型权重,不是索引。这个结论有两个用法:内容真的需要跨语言时,120MB 花得值;只是“以防万一”,在计流量的手机网络上就不值得。
维度和体积不是一回事
很容易把 512 维读成“比 384 维更好”。维度决定一个向量能承载多少细节,但实际使用中,另外两件事往往更要紧:
- 词表覆盖。 以中文为主的模型,对英文标识符、错误码、产品名产生的向量质量很差。维度再高,也修不好一个把你的术语切成碎片的切词器。
- 训练数据。 512 维的
bge-small-zh-v1.5在中文检索上能赢过通用的 768 维模型,因为它是拿中文句对训出来的。
中英混排那一档正好说明了这点:384 维,文件更大,多出来的字节全花在词表和多语言训练上,而不是花在维度上。体积买到的是覆盖面,不是分辨率。
q8 量化改了什么
这里下载的权重是 8 位量化(q8),大概是 float32 全精度权重的四分之一。两条要如实讲清楚的代价:
- 检索质量会略微下降。 对嵌入模型来说,这个损失小到在 top-6 结果里通常看不出来,但它不是零。如果你要横向评测两套检索方案,这不该是评测时使用的设置。
- 内存表现变好,而这是它存在的真正理由。 一个 120MB 的下载如果在标签页里展开成五百多 MB 常驻内存,那就是另一个产品了。量化是浏览器方案能成立的前提——可选生成档用 4-bit 也是同一个道理。
一分钟做决定
- 文档全是中文? 选
bge-small-zh-v1.5。25MB、512 维,这里没有需要妥协的地方。 - 文档全是英文? 选
all-MiniLM-L6-v2。23MB 是三档里最小的下载,逐块嵌入也最快,导入一份三百页的 PDF 时这点差别能感觉到。 - 中英混排,或者你用中文提问、文档是英文? 选
multilingual-e5-small,120MB 忍一次。一个 30% 英文、70% 中文的库,小模型在少数语言那一侧会明显失手,而混排库恰恰会把这个失手放大成答错。 - 拿不准? 先导入三四份文档,用你真正会问的问题试一遍,看引用对不对。如果正确的段落总是出现在前面,模型是称职的;如果你明知文件里有某段却总也召不回来,先换混排档,再回头怀疑分块。
换模型等于重建索引
真的要换,先知道会发生什么:文本块还在,向量不在。每个块都要过一遍新模型重新嵌入——一份两百页的文档是几百个块,在单线程 WASM 上,等待时间按几十秒计,不是瞬间完成。网络慢的话,还要加上重新下载 120MB 的时间。
几条实操建议:
- 在规模变大之前定下来。 两份文档时换模型是几秒钟的事,导入四十份之后再换,就是几分钟。
- 不会重新上传。 重建用的是浏览器里已经解析好的文本,你甚至可以断网重建。
- 原始文件不会被改动。 索引坏了就重建,你导入的那份文件始终原样。
在工具里试,而不是对着表格想
对照表读得再熟,也替代不了自己试一遍,而把问题定下来的流程只花二十分钟。选一档模型,导入三份你熟悉的文档,问六个你能手工核对答案的问题,数一数正确的段落出现在前三名引用里几次。
六次里中了五次或六次,就不用再调了,这已经是这份语料能达到的上限,而且够用。只中两三次,瓶颈通常在语言混排或分块边界,跟维度数量没多大关系。如果你明知文件里有那段内容、它却一次都没出现过,先去怀疑解析:没有被抽出来的文字,三档模型里的任何一档都嵌不进去,也召不回来。
动手前知道一个不对称会有帮助。23MB 的 all-MiniLM-L6-v2 嵌入几百个块很快,重新导入几乎无感;120MB 的混排档差不多把这件事反过来。所以省事的测试顺序是先上小的那档,看清哪些问题答不出来,再决定要不要为多语言付那 120MB。
这些选择解决不了什么
再多嵌入模型也救不了一份解析失败的文档。PDF 没有文字层,任何模型都嵌入不了它——你得先在工具之外做 OCR。表格在抽取时丢了表头,嵌入会忠实地表示出一列没有含义的数字,检索还会理直气壮地在错误的提问下把它返回给你。选模型是第二位的决定,切分和解析才是第一位的。