ollama api embedding 使用

接入与开发

面向开发者讲清 Ollama embedding 接口怎么调、批量怎么发、维度与超时怎么兜底,让向量检索的入库环节跑得稳。

本地把 Ollama 跑起来不难,难的是把它接进检索链路:embedding 接口路径和生成接口不是一套,批量发容易超时,维度对不上向量库还会直接报错。这篇按调用→批量→入库前校验三步给做法,只讲工程落地,协议与模型选型去看站内别的页。

本地把 Ollama 跑起来其实不难,难的是把它接进检索链路。embedding 接口和生成接口不是同一条路,路径、入参、返回结构都不一样;批量发容易超时,维度对不上向量库还会直接报错,而且有些错是静默的——向量照样入库,检索时却永远召不回你要的内容。

这篇只讲工程落地,按调用、批量、入库前校验三步给做法。协议细节和模型怎么选不在这里展开,去站内对应的资料页看当时的说明;下面每个环节都会给可执行的判断标准和排查顺序。

先确认往哪发、发什么

第一件事是确认本机这一版到底暴露了哪个向量化入口。别照抄别人的路径,先在本机实测一次,或者到站内 Ollama 本地部署相关页面核对当前版本的接口说明。输入字段就是纯文本或文本数组,不带消息角色那套结构,带错了服务器未必报错,可能直接按别的语义处理。

入口路径
向量化入口和对话生成入口是两条独立路径,别把生成接口的地址直接换字段用
模型名
必须显式写,不写会落到默认生成模型上,返回结构完全不同,报错信息还容易把人带偏
返回体
拿到的是浮点数组,长度由模型决定,不同模型不一样
探针请求
先发一条最短文本,把返回数组长度打出来,写进配置常量,别在业务代码里硬编一个记来的数字
  • 先跑通单条调用,确认链路通的,再考虑批量;单条只适合验证,别拿它跑几百条文档
  • 把探针得到的维度写进配置或环境变量,所有入库代码引用这一个来源
  • 调用前先做一次服务探活,服务没起来时要给明确报错,不能让流程静默跑过去
  • 同一批文本连发两次,比较向量是否稳定,用来排查有没有落到随机或截断路径上

批量与超时的取舍

单条一条条发,往返开销远大于计算本身,几百条文档会慢到不可接受。优先用数组一次传多条,但批不是越大越好:批越大,显存占用和首字节等待越长,反而更容易踩到超时。经验做法是把批大小压在十几到几十条这个量级,先小后大,用实测结果调,不要凭感觉定。

现象大概率原因先查什么
批处理频繁超时批太大或首字节慢把批减半重试,看是否稳定
单条也超时服务没起来或端口被占先探活,再确认端口占用
并发高反而更慢本地服务排队执行改回串行小批对比一次
返回正常但召回为空向量被截断或维度不对比探针维度,检查切片长度

超时时间不要一个固定值套全部批次,按「批大小乘以单条耗时」再留两三倍余量更合理。具体分档口径可以参考站内超时设置那篇,那里给了不同链路的取值思路。另外本地服务是排队执行的,开十路并发不会更快,只会互相拖慢,串行加小批往往又快又稳。

  1. 切片长文档先切成片段再向量化;片段超出模型窗口会被静默截断,截断后向量仍能入库,但检索时永远召不回后半段内容
  2. 小批试跑先拿十几条试一批,记录耗时和成功率,再往上加批大小
  3. 定超时按实测单条耗时乘批大小,再留两三倍余量,写进客户端配置
  4. 留日志每个批次记下批大小、耗时、失败条数,后面排查全靠它

入库前必须校验的三件事

向量生成完不等于能直接写库,入库前有三件事必须过一遍,顺序别颠倒。第一件是维度对齐:拿向量库当前集合的维度跟探针结果比一次,不一致就重建集合,不要试图补零凑数,凑出来的向量在检索里没有任何意义。

第二件是归一化与相似度口径。确认写入端和查询端用的是同一套距离度量,一边按余弦、一边按点积,分数会乱掉但程序不会报错,这种问题最难查。第三件是失败日志要能定位:批量失败的记录里必须带原文本片段和它在批次里的索引位置,只写「批次失败」四个字,重跑时根本不知道丢了哪些文档。

  • 维度对齐:与探针结果比对,不一致直接重建集合
  • 度量一致:写入端和查询端用同一种距离度量,改口径要两端一起改
  • 日志可定位:失败记录带文本片段与批次内索引
  • 口径留档:把当前维度、度量、批大小写进配置注释,换人接手能看懂

检索侧的整体链路,包括切片策略、召回、重排这些,站内 RAG 与检索那篇讲得更全;这篇只覆盖向量怎么生成这一段,两边分工看,别在这里找检索调优的答案。

降级与自测

本地服务可能没启动、端口被占、或者被别的进程压着跑不动,所以调用前先探活,失败时给出明确提示,不能让它静默退化成空向量——空向量入库后程序一切正常,检索却全不准,这是最麻烦的一类故障。降级按三级走:重试一次、换更小的批、跳过并记录。

  1. 重试一次单次失败先原样重试一次,排除偶发抖动
  2. 换小批仍失败就把这一批拆小重发,逐步定位是整体问题还是个别文本问题
  3. 跳过并记录拆到单条仍失败的,进待补队列并记录文本片段,不要阻断整批入库
  4. 回归对比固定一组小样本,每次改模型或切片参数后重跑,比较召回结果是否明显变化

如果同时用官方 API 和本地模型,先在路由层决定哪些请求走本地,别让两种来源的向量混进同一个集合。混用维度的向量是检索事故里很常见的一种起因,而且往往要等到效果差才被发现。想看各家接入方式和当时的额度、价格情况,到站内价格与模型资料库核对当时的数字,别抄别人截图里的值。

下一步把服务探活、探针维度、批大小这几个参数先固定下来,再对照站内工具做一次链路的实测;如果你还在挑本地模型和运行方式,先去资料库看当前可选范围再动手。

常见问题

ollama 的 embedding 接口和对话接口能共用一个客户端吗?

地址能共用,但路径、请求体和返回结构都不一样,最好封装成两个独立方法。硬塞进一个函数里,迟早会在字段名上踩坑,排查时也分不清是模型没加载还是参数发错了。

向量化几百个文档很慢,是不是该开并发?

本地模型大多是排队跑,开并发通常只会让每批都变慢,还更容易超时。先把批大小调合适、把切片长度压到模型窗口内,速度提升比调并发明显。真要提速,优先看有没有可用的加速硬件。

换了嵌入模型之后检索结果变差,先查什么?

先确认向量库里的旧向量有没有一起换掉。新旧向量混在同一个集合里,检索出来就是噪声,程序不会报错。正确做法是重建集合、整库重跑一遍向量化,再拿固定样本做一次前后对比。

本文依据各平台公开文档与官方公告整理,只做中文归纳;具体做法、参数与限制以官方文档为准。