夜雨聆风学习资料网

ARTICLE · 1197892

Ollama 检索不报错,是它把后半个文档丢了.

Ollama 检索不报错,是它把后半个文档丢了.

我给自己的知识库喂了 5 份会议纪要,就 5 份,然后问它「本地办公类模型的真正瓶颈是什么」。正确的那句话在第三份文档里挂着。检索结果出来,它排第四。

我第一反应是模型太弱。nomic-embed-text 一共才 137M 参数,中文理解差一点,好像也说得过去。于是我把提问方式改了三遍,把问题拆得更具体,又换了个更大的 embedding 模型——排名没有变化。

卡到第三天,我才把注意力从「模型」挪到一个一直没看的地方:那 5 份文档,我都是一整篇丢进去的。

① 我先怀疑提示词,最后是 prompt_eval_count 把我说服了

Ollama 的 embedding 接口有个字段,平时没人看:prompt_eval_count。它告诉你这次请求实际送进模型多少 token。

我拿一段中文来回测,每加 200 字就问一次它是多少:

curl -s 127.0.0.1:11434/api/embed \ -d '{"model":"nomic-embed-text","input":"……"}' | jq '.prompt_eval_count'

结果是这样:

我送进去的字符数
prompt_eval_count
200 字
202
600 字
602
1200 字
1202
1500 字
1502
2000 字
2002
2500 字2048
3000 字2048
4000 字2048

到 2500 字就不再涨了。它卡在 2048,然后把剩下的都扔掉,接口照常返回 200,照常给你一个 768 维向量,一个字都不提。

我不信,就又测了一轮——这次不看数字,看向量本身。2200 字、2600 字、3000 字、4000 字、6000 字各算一次余弦相似度,相邻两个之间:

chars= 2200 → eval_count=2048 cos(上一档) = 0.99986134chars= 2600 → eval_count=2048 cos(上一档) = 1.00000000chars= 3000 → eval_count=2048 cos(上一档) = 1.00000000chars= 4000 → eval_count=2048 cos(上一档) = 1.00000000chars= 6000 → eval_count=2048 cos(上一档) = 1.00000000

1.00000000。 一个字都不差。

也就是说:2600 字的文档和 4000 字的文档,在这台机器上拿到的是同一个向量。你往后面多写 1400 字,模型压根没见过。

② 2048 token 到底是多少字

这是最容易踩空的地方。我一开始按「1 个汉字 ≈ 1 个 token」估算,以为 2048 token 能装下 2000 多字,够用了。

实测三组:

文本类型
实测折算
纯中文
0.990 字符/token
纯英文
5.098 字符/token
真实技术文本
(含英文缩写、数字、版本号)
1.596 字符/token

第三行是我自己产线里的文本,长这样:

这台机器上我用 ComfyUI 出图,SDXL base 1.0,1024x1024,seed 固定,显存 9134MiB,耗时 2.259s。

这种句子在写技术文档、会议纪要、周报时满地都是。按 1.596 折算,2048 token 只装得下约 1283 个字符。

一份正常的技术文档,很容易就 2500 字起步。从第一页读完之前,后面全部内容就已经被丢掉了。

③ 我做了一次严格对照:同样的 5 份文档,答案挪个位置

光看 token 数还不够,我想知道这件事到底会不会真的让检索失效。

于是我造了 5 份内容完全相同的文档——同一批格式雷同的会议纪要,每份都是 3108 字、都是 2048 token、4 份一个字不差。唯一差别是:正确答案只放在第 3 份里,而且我在「开头」和「末尾」两个位置各试了一遍。

提问是固定的:「本地办公类模型的真正瓶颈是什么」。

按大多数人的做法,整篇丢进去算向量。(下面是余弦相似度,越接近 1 越相关。)

正确答案的位置
文档3 的相似度
另外 4 份的相似度
差值
文档里根本没有
0.622509
0.622509
+0.000000
放在开头(截断线内)
0.685300
0.622509
+0.062791
放在末尾(截断线外)
0.622509
0.622509
+0.000000

第二行和第三行的对比就是全部结论:

答案放在开头,文档3 跳出来,高出 0.063;答案挪到末尾——文档3 和「压根没有答案的那 4 份」,相似度一模一样,小数点后六位都不差。

你那句最关键的结论,写得越靠后,对检索的贡献是精确的零。不是「变弱」,是零。

④ 修法:别整篇丢,切块

同一个实验,我把「整篇算一个向量」换成「按 400 字切块,每块单独算,最后取分数最高的那块」:

正确答案的位置
整篇做法
切 400 字块做法
放在开头
0.685300(可区分)
0.717245
(可区分)
放在末尾
0.622509 → 完全无法区分
0.682265 → 可区分

末尾那一行是这次改造的全部价值:同样的文档、同样的模型、同样的提问,只是不再整篇丢,那句丢掉的结论就回来了。

代价也不大。同一份 3108 字的文档:

· 整篇算一次:0.0422 秒

· 切成 8 块全算一遍:0.1893 秒

多花 0.147 秒。

这台机器上还有更省的做法——把 240 份文档一次性丢进 input 数组,走批量接口:逐条送 240 份要 4.793 秒(50 份/秒),批量送 240 份只要 1.359 秒(176 份/秒),差 3.53 倍。也就是说,切块带来的额外开销,靠批量接口基本能抵回来。

⑤ 你要查自己的库,跑这三行就够

# 1. 先量:这一段到底送进去多少 tokencurl -s 127.0.0.1:11434/api/embed \ -d '{"model":"nomic-embed-text","input":"把你要入库的那一整段贴这里"}' \ | jq '.prompt_eval_count'

返回 2048,就是已经踩线了。 你那段文字后半截,一个字都没进过模型。

# 2. 再确认:把 truncate 关掉,让它必须报错curl -s 127.0.0.1:11434/api/embed \ -d '{"model":"nomic-embed-text","input":"同一段文字","truncate":false}'

我实测过这个参数:加上 "truncate": false,它会直接回你

{"error":"the input length exceeds the context length"}

这个报错就是你需要的那个哨兵。 默认状态下它永远不报,你也就永远不知道自己丢了东西。

# 3. 入库时按 300-500 字切块,别整篇塞

切完之后有一条纪律要守住:每块的开头,把关键词再写一遍。因为答案落在块的开头时,相似度是 0.7172;落在块末尾时是 0.6823——差 0.035。切块把「文档级截断」降级成了「块级局部稀释」,但没消灭它。

这三行查完,我自己库里的几处问题是一起暴露出来的:

· 有几份「产品说明 + 参数表」混在一起的文档,参数表全在最后。参数表对检索的贡献一直是零。

· 有几份周报是「先讲过程、最后才写结论」的写法。结论那句从来没被检索到过。

· 按 400 字切块重跑之后,同一个提问,排第一的文档从「碰巧开头有相似词的那份」变成了「真正写了答案的那份」。

我没有换模型。137M 参数的小模型,切完块照样用。

一句可以转发的判断

本地知识库检索不准,大多数人第一反应是换更大的 embedding 模型。我这次量完,卡住的地方根本不在模型——你的文档后半截从来没进过模型,换个 10 倍的模型也一样。

在动手换模型之前,先 curl 一次 prompt_eval_count。这个数字不花你一分钱,也不花你一分钟。它要么告诉你「你的库是好的,去别处找原因」,要么直接告诉你后半截文档一直在被静默丢弃。

这台机器到底跑不跑得动,先算一遍再下单

买错一张卡,沉没的不只是差价。把模型和机型对上,结论十秒出。

🧮 适配器 · 197 个模型 × 125 台机型 | 🔍 核验器 · 141 个项目商用判定

🚀 部署单 · 37 类场景 | 📈 对照台 · 9 台真机实测

扫码进入「丘山录」小程序

参考来源

1. 本机 RTX 5090D 32GB 实测,Ollama 0.40.4,模型 nomic-embed-text:latest(F16 / 137M 参数 / 上下文长度 2048),2026-10-17

2. 测试前后台另有一项长驻任务占卡(100% / 599.91W),已停;停后空载基线 11.4W,避免显存与功耗数据被污染

3. Ollama Embedding API 文档:POST /api/embed 的 truncate 参数与 prompt_eval_count 返回字段

4. 所有数字均为本机实测,未做四舍五入以外的加工;未公开数据不外推

数据说明

· prompt_eval_count 是本机 Ollama 返回的真实字段值,非估算。

· 余弦相似度在本机计算(Python 标准库手写点积与模长),未使用第三方库,避免归一化口径差异。

· 表内「无法区分」判定标准:差值 <1e-6。

· 测试机 GPU 上另有一项常驻服务占用约 13.5GB 显存,与本模型(335.7MB / 全量驻留显存)无关,已在基线中标注。

关注引导

扫码进入「丘山录」小程序,四十多个模型跑不跑得动,先在这里算一遍再下单。

🔔 深耕 AI 干货 | 点名片订阅,上新早知道

📊 丘山录 · 小程序

先算再买,别让一张卡决定你能跑什么。

197 个模型 × 125 台机型 · 37 类部署场景

微信搜索「丘山录」即可进入

#丘山录  #Ollama  #本地知识库  #大模型本地部署  

相关学习资料