本地把 Ollama 跑起来不难,难的是把它接进检索链路:embedding 接口路径和生成接口不是一套,批量发容易超时,维度对不上向量库还会直接报错。这篇按调用→批量→入库前校验三步给做法,只讲工程落地,协议与模型选型去看站内别的页。
本地把 Ollama 跑起来其实不难,难的是把它接进检索链路。embedding 接口和生成接口不是同一条路,路径、入参、返回结构都不一样;批量发容易超时,维度对不上向量库还会直接报错,而且有些错是静默的——向量照样入库,检索时却永远召不回你要的内容。
这篇只讲工程落地,按调用、批量、入库前校验三步给做法。协议细节和模型怎么选不在这里展开,去站内对应的资料页看当时的说明;下面每个环节都会给可执行的判断标准和排查顺序。
先确认往哪发、发什么
第一件事是确认本机这一版到底暴露了哪个向量化入口。别照抄别人的路径,先在本机实测一次,或者到站内 Ollama 本地部署相关页面核对当前版本的接口说明。输入字段就是纯文本或文本数组,不带消息角色那套结构,带错了服务器未必报错,可能直接按别的语义处理。
- 入口路径
- 向量化入口和对话生成入口是两条独立路径,别把生成接口的地址直接换字段用
- 模型名
- 必须显式写,不写会落到默认生成模型上,返回结构完全不同,报错信息还容易把人带偏
- 返回体
- 拿到的是浮点数组,长度由模型决定,不同模型不一样
- 探针请求
- 先发一条最短文本,把返回数组长度打出来,写进配置常量,别在业务代码里硬编一个记来的数字
- 先跑通单条调用,确认链路通的,再考虑批量;单条只适合验证,别拿它跑几百条文档
- 把探针得到的维度写进配置或环境变量,所有入库代码引用这一个来源
- 调用前先做一次服务探活,服务没起来时要给明确报错,不能让流程静默跑过去
- 同一批文本连发两次,比较向量是否稳定,用来排查有没有落到随机或截断路径上
批量与超时的取舍
单条一条条发,往返开销远大于计算本身,几百条文档会慢到不可接受。优先用数组一次传多条,但批不是越大越好:批越大,显存占用和首字节等待越长,反而更容易踩到超时。经验做法是把批大小压在十几到几十条这个量级,先小后大,用实测结果调,不要凭感觉定。
| 现象 | 大概率原因 | 先查什么 |
|---|---|---|
| 批处理频繁超时 | 批太大或首字节慢 | 把批减半重试,看是否稳定 |
| 单条也超时 | 服务没起来或端口被占 | 先探活,再确认端口占用 |
| 并发高反而更慢 | 本地服务排队执行 | 改回串行小批对比一次 |
| 返回正常但召回为空 | 向量被截断或维度不对 | 比探针维度,检查切片长度 |
超时时间不要一个固定值套全部批次,按「批大小乘以单条耗时」再留两三倍余量更合理。具体分档口径可以参考站内超时设置那篇,那里给了不同链路的取值思路。另外本地服务是排队执行的,开十路并发不会更快,只会互相拖慢,串行加小批往往又快又稳。
- 切片长文档先切成片段再向量化;片段超出模型窗口会被静默截断,截断后向量仍能入库,但检索时永远召不回后半段内容
- 小批试跑先拿十几条试一批,记录耗时和成功率,再往上加批大小
- 定超时按实测单条耗时乘批大小,再留两三倍余量,写进客户端配置
- 留日志每个批次记下批大小、耗时、失败条数,后面排查全靠它
入库前必须校验的三件事
向量生成完不等于能直接写库,入库前有三件事必须过一遍,顺序别颠倒。第一件是维度对齐:拿向量库当前集合的维度跟探针结果比一次,不一致就重建集合,不要试图补零凑数,凑出来的向量在检索里没有任何意义。
第二件是归一化与相似度口径。确认写入端和查询端用的是同一套距离度量,一边按余弦、一边按点积,分数会乱掉但程序不会报错,这种问题最难查。第三件是失败日志要能定位:批量失败的记录里必须带原文本片段和它在批次里的索引位置,只写「批次失败」四个字,重跑时根本不知道丢了哪些文档。
- 维度对齐:与探针结果比对,不一致直接重建集合
- 度量一致:写入端和查询端用同一种距离度量,改口径要两端一起改
- 日志可定位:失败记录带文本片段与批次内索引
- 口径留档:把当前维度、度量、批大小写进配置注释,换人接手能看懂
检索侧的整体链路,包括切片策略、召回、重排这些,站内 RAG 与检索那篇讲得更全;这篇只覆盖向量怎么生成这一段,两边分工看,别在这里找检索调优的答案。
降级与自测
本地服务可能没启动、端口被占、或者被别的进程压着跑不动,所以调用前先探活,失败时给出明确提示,不能让它静默退化成空向量——空向量入库后程序一切正常,检索却全不准,这是最麻烦的一类故障。降级按三级走:重试一次、换更小的批、跳过并记录。
- 重试一次单次失败先原样重试一次,排除偶发抖动
- 换小批仍失败就把这一批拆小重发,逐步定位是整体问题还是个别文本问题
- 跳过并记录拆到单条仍失败的,进待补队列并记录文本片段,不要阻断整批入库
- 回归对比固定一组小样本,每次改模型或切片参数后重跑,比较召回结果是否明显变化
如果同时用官方 API 和本地模型,先在路由层决定哪些请求走本地,别让两种来源的向量混进同一个集合。混用维度的向量是检索事故里很常见的一种起因,而且往往要等到效果差才被发现。想看各家接入方式和当时的额度、价格情况,到站内价格与模型资料库核对当时的数字,别抄别人截图里的值。
下一步把服务探活、探针维度、批大小这几个参数先固定下来,再对照站内工具做一次链路的实测;如果你还在挑本地模型和运行方式,先去资料库看当前可选范围再动手。→常见问题
ollama 的 embedding 接口和对话接口能共用一个客户端吗?
地址能共用,但路径、请求体和返回结构都不一样,最好封装成两个独立方法。硬塞进一个函数里,迟早会在字段名上踩坑,排查时也分不清是模型没加载还是参数发错了。
向量化几百个文档很慢,是不是该开并发?
本地模型大多是排队跑,开并发通常只会让每批都变慢,还更容易超时。先把批大小调合适、把切片长度压到模型窗口内,速度提升比调并发明显。真要提速,优先看有没有可用的加速硬件。
换了嵌入模型之后检索结果变差,先查什么?
先确认向量库里的旧向量有没有一起换掉。新旧向量混在同一个集合里,检索出来就是噪声,程序不会报错。正确做法是重建集合、整库重跑一遍向量化,再拿固定样本做一次前后对比。