ollama v0.23.4 于 2026年5月14日发布,这次版本更新虽然只有 2 个 commit,但实际涉及 18 个文件、815 行新增、109 行删除,改动集中在两个核心方向:一是 launch/opencode 终于支持 vision models 的 image inputs;二是修复了 Claude 在使用本地图片路径时 tool results 的格式问题。对于经常使用 Ollama 做多模态推理、以及通过 OpenCode 进行模型接入和编辑的用户来说,这次更新非常关键,属于“看起来是小版本,实际上体验变化很大”的一次升级。
一、v0.23.4 发布概览
本次更新信息如下:
- 版本:v0.23.4
- 发布日期:2026年5月14日
- 变更说明:
- ollama launch opencode now supports vision models with image inputs
- Fixed formatting of Claude tool results when using local image paths
从提交记录看,主要是两项变化:
- anthropic:保留 Claude 本地图片路径的 tool results 在 renderer 中的格式
- launch/opencode:为 vision models 增加 image modalities 支持
也就是说,这次更新不是单纯补丁,而是同时覆盖了 Anthropic 适配、OpenCode 启动器、多个模型 renderer、server prompt 处理逻辑,以及大量单元测试。
二、核心更新一:OpenCode 现在支持 vision models 的 image inputs
这是这次更新里最受关注的部分。
1. OpenCode 配置构建逻辑升级
在cmd/launch/opencode.go中,buildInlineConfig和buildModelEntries都发生了变化。过去构建 OpenCode 的 inline config 时,只是简单把模型列表写进去,而这次新增了通过api.ClientFromEnvironment()获取客户端,并尝试调用client.Show()去探测模型能力。
如果客户端可用,就会在构建模型条目时判断该模型是否具备vision能力;如果具备,就给模型补上:
modalities.input = ["text", "image"]modalities.output = ["text"]
这意味着 OpenCode 在对接 Ollama 模型时,不再只是把它当成纯文本模型,而是可以把视觉输入能力显式告诉上层配置。
2. 视觉能力探测采用 Show API
新增逻辑中,构建模型条目时会对每个模型执行一次Show请求,读取返回的Capabilities。当能力列表中包含vision时,就自动写入图像输入模态。
这部分实现还有一个重要细节:引入了openCodeModelShowTimeout = 2 * time.Second,并且在buildModelEntries中为所有模型探测共享一个超时预算。
换句话说,多个模型一起探测时,不会每个都无限等待,而是共享同一个上下文时间窗口,避免 OpenCode 配置构建被拖慢。
3. 模型限额逻辑保持兼容
本次修改还保留了云模型限额逻辑:
- 如果是云模型名称
- 就继续通过
lookupCloudModelLimit补充limit.context limit.output
也就是说,新加的 vision modalities 不会破坏原有的 cloud model 配置能力。
三、OpenCode 相关测试大幅增强
这次更新在cmd/launch/opencode_test.go中增加了大量测试,说明这项改动不是简单接入,而是经过了完整验证。
1. 视觉模型获得 image input modalities
新增测试验证:当client.Show()返回capabilities=["vision"]时,buildModelEntries会为模型写入:
modalities.input = ["text", "image"]modalities.output = ["text"]
测试中对gemma4:26b做了模拟返回,确认配置完全符合预期。
2. 当无法探测能力时保持默认行为
新增测试还验证了:
- 如果没有 API client
- 就不设置
modalities - 只保留默认
name
这说明新逻辑是渐进增强,不会影响非 vision 场景。
3. 多模型共享超时预算
还有一个很重要的测试:
- 构造两个慢请求模型
- 使用
context.WithTimeout - 验证共享超时只会阻塞一个探测流程
这说明新增的 capability probe 逻辑在性能和资源控制上考虑得很细。
四、核心更新二:Claude 本地图片路径的 tool results 格式修复
第二个 changelog 点是:
- Fixed formatting of Claude tool results when using local image paths
这部分对应anthropic/anthropic.go的修改。
1. 新增 OutputConfig
在MessagesRequest中新增了:
OutputConfig *OutputConfig
其中OutputConfig定义了:
Effort string
这说明 Anthropic 请求结构里现在可以携带输出努力等级,并且会参与 think 值的转换。
2. Think 逻辑调整
FromMessagesRequest中新增了对OutputConfig.Effort的归一化处理:
- 去空格
- 转小写
- 把
xhigh映射到high
然后根据逻辑决定ThinkValue:
Thinking.Type == "enabled"时,think = trueThinking.Type == "disabled"时,think = false- 如果没显式设置 Thinking,就从
OutputConfig.Effort映射为:highmediumlowmax
这说明本次更新不仅修了 tool result,也顺带把 thinking/output_config 的兼容性做完整了。
3. 图片源结构调整
ImageSource结构也发生了变化:
- 去掉了原先对
"url"的支持提示 - 当前仅保留
"base64"
并且新增resolveImageSource:
- 只允许
base64 - 解码失败就报错
- 统一从 base64 解析 image data
这与本次“本地图片路径 tool results”修复相关,因为工具结果里如果带图片内容,需要能正确转换成内部图像数据。
4. 新增 convertToolResultContent
这是本次修复最关键的函数之一。
convertToolResultContent(content any)支持三类内容:
nilstring[]any
当 content 是数组时,会逐项解析:
type = "text":拼接文本type = "image":读取source,解析 base64 图片,加入 images
最终返回:
- 文本内容
- 图片列表
- 错误
这就让 tool_result 不再只能是纯文本,而是可以保留图片结果。
5. tool_result 处理方式更合理
在convertMessage中,tool_result的处理逻辑也升级了:
- 先统计 tool result block 数量
- 调用
convertToolResultContent - 将结果转成
api.Message{Role: "tool"} - 填充
Content - 填充
Images - 填充
ToolCallID
同时还修复了 user message 和 tool results 的拼接顺序,避免在用户消息中包含工具结果时丢失内容或重复内容。
五、Anthropic 相关测试新增,确保 tool_result 图片可用
anthropic/anthropic_test.go新增的测试很多,说明这个修复是有明确回归保护的。
1. tool_result 携带图片
新增测试TestFromMessagesRequest_WithToolResultImage验证:
- tool_result 内容可以是数组
- 数组中同时包含:
- text
- image
- image 源使用
base64 - 解析后:
Role是toolToolCallID保留Content是文本部分Images数量正确- 图像字节与原始 base64 解码结果一致
2. tool_result 后面接 user 文本
另一个测试验证:
- assistant 先发 tool_use
- user 再发 tool_result
- 同时还有普通文本
最终转换后:
- tool message 保留
- user message 也保留
- 顺序正确
这类测试很重要,因为它直接对应了“本地图片路径工具结果格式”这类复杂场景,避免数据在中间层丢失。
3. output_config 和 thinking 的交互
新增的几组测试分别验证:
OutputConfig.Effort = high时,think 设为 highOutputConfig.Effort = xhigh也会映射成 highThinking.disabled会覆盖 output_configThinking.adaptive会继续使用 output_config 努力等级
也就是说,这次更新不只是修图像,连输出控制逻辑也一并校准了。
六、renderer 层统一支持 image tags 与 tool response 图像渲染
这次更新不仅改了 Anthropic 和 OpenCode,还大范围触及了多个 renderer。
整体方向非常明确:让各种模型 renderer 在处理图像时,既能支持原始视觉格式,也能支持[img-x]这种统一占位符风格,并且保证 tool response 中的图像不会被漏掉。
1. 新增 image_tags 统一辅助函数
新增文件model/renderers/image_tags.go,提供:
renderContentWithImageTags(content, imageCount, imageOffset)
它的逻辑可以概括为:
- 如果没有图片,直接返回原内容
- 如果内容里已经包含
[img-,则视为已编号占位符,直接保持 - 如果内容中有
[img],就按顺序替换成[img-0]、[img-1]... - 如果没有占位符,就把图片标签前置
- 若前置标签后面紧跟非空白文本,则自动补一个空格
- 返回新内容和新的 imageOffset
这个工具函数的意义很大,因为它统一了多个 renderer 的图像占位符行为。
2. 新增 image_tags 单元测试
model/renderers/image_tags_test.go覆盖了多个典型场景:
- 没有占位符时前置图片标签
[img]依次替换成[img-3]、[img-4]- 图片多于占位符时,剩余图片继续前置
- 占位符多于图片时,剩余占位符保持原样
- 已经编号的占位符不重复改写
这组测试说明统一图像标签逻辑已经进入稳定阶段。
七、Gemma4、GLM-OCR、LFM2、Nemotron3Nano、Qwen35、Qwen3VL 渲染逻辑同步调整
本次更新中,多个 renderer 都做了相同方向的优化:统一调用renderContentWithImageTags,并修正 tool response 和图片内容渲染。
1. Gemma4 Renderer
model/renderers/gemma4.go中,tool response 的渲染不再直接写loopMessages[k].Content,而是调用renderToolResponseContent。
同时renderContent在图片存在且使用 img tags 时,会先输出[img-x],再拼接内容,并在必要时补空格。
这解决了图像和文本拼接时的格式问题。
2. GLM-OCR Renderer
model/renderers/glmocr.go调整后:
renderContent直接依赖renderContentWithImageTagsRender中 tool response 部分使用渲染后的 content,而不是原始 message.Content
测试也同步调整为:
[img-0] Describe this image.[img-0][img-1] Describe these images.
注意空格变化,这正是这次格式修正的一部分。
3. LFM2 Renderer
model/renderers/lfm2.go中,图片内容处理逻辑简化,借助统一 helper 做 image tag 处理,并修正了原先文本和图片拼接时的样式。
测试中同样从:
[img-0]Describe this image.
修正为:
[img-0] Describe this image.
4. Nemotron3Nano Renderer
model/renderers/nemotron3nano.go做了两类调整:
- tool response 渲染改为使用
renderMessageContent renderMessageContent内部改用统一的 image tag 处理函数
测试里也体现了空格格式调整,以及多图场景下[img-1][img-2] Compare these.的正确输出。
5. Qwen35 Renderer
model/renderers/qwen35.go中:
useImgTags模式下直接调用统一 helper- 非 img tags 模式仍输出
<|vision_start|><|image_pad|><|vision_end|>
这说明 Qwen35 仍兼容原始视觉 token,同时支持统一图片标签方案。
6. Qwen3VL Renderer
model/renderers/qwen3vl.go同样完成统一图像内容处理,并修正 tool_response 输出:
- 不再直接输出 message.Content
- 改为输出渲染后的 content
- 保证 tool response 中的图片标签也能正确落地
对应测试也将预期文本中的图片标签和空格样式更新为正确版本。
八、server/prompt.go 的关键改动:渲染与消息内容分离
这次更新对server/prompt.go的改动也很关键。
过去在 prompt 构建过程中,消息内容会直接被修改;而现在做了更稳妥的处理:
- 先复制一份
msgs到renderMsgs - 在渲染流程中,如果是 renderer 模式,就修改
renderMsgs - 原始
msgs尽量保持不变
这样做的好处是:
- 避免原始消息被渲染逻辑污染
- 更适合在不同 renderer 间复用消息
- 在处理图像标签时,图像和文本的结构更可控
同时,prompt.go还新增了对[img]占位符的前置替换逻辑,让所有 renderer 在 prompt 生成阶段更一致。
九、server/prompt_test.go 大量新增测试,覆盖图像标签与工具图像
这次最“爆炸”的测试更新就在server/prompt_test.go。
1. GLM-OCR 添加 image tags
新增测试验证:
- prompt 中会出现
[img-0][img-1] extract text - tool response 也会正确携带图片标签
2. renderer 为 tool 消息添加图片标签
新增测试覆盖以下 renderer:
- gemma4
- qwen3-vl
- qwen3.5
- glm-ocr
- nemotron-3-nano
测试内容包括:
- user 消息中的图片标签位置
- tool response 中的图片标签位置
- 多个 renderer 的输出一致性
3. 保留显式图片占位符
新增测试验证:
- 如果用户内容中已经有
[img] - 那就按顺序替换成
[img-0]、[img-1] - 不会重复插入,不会丢失
这说明占位符规则已经稳定地统一到了各个 renderer。
十、这次 v0.23.4 的实际价值
从开发者视角看,这次更新的价值主要体现在三点:
1. OpenCode 能更好地接入视觉模型
这会让 Ollama + OpenCode 的多模态使用场景更完整,vision models 不再只是“能跑”,而是能被上层工具正确识别为图像输入模型。
2. Claude 本地图片路径结果不再容易格式异常
这对工具调用、文件读取、图片输出类场景非常重要,尤其是在工具结果里混合文本和图片时,格式修复能减少很多前端展示或中间层解析问题。
3. 多个 renderer 的图像标签行为统一了
这使得:
- 图像占位符更一致
- tool response 更稳定
- 多图场景更清晰
- prompt 渲染更可预测
尤其对于需要精确控制图像插入位置的任务来说,这次更新很实用。
十一、总结
代码地址:github.com/ollama/ollama
ollama v0.23.4 不是一个简单的小修小补版本,而是围绕“多模态输入”和“工具结果图像处理”做了一次系统性增强。
本次更新的重点可以概括为:
- OpenCode 支持 vision models 的 image inputs
- Claude 本地图片路径 tool results 格式修复
- Anthropic 增强 tool_result 图片解析能力
- OutputConfig 与 Thinking 逻辑进一步统一
- 新增统一的 image tags 处理函数
- Gemma4、GLM-OCR、LFM2、Nemotron3Nano、Qwen35、Qwen3VL 等 renderer 同步优化
- server prompt 构建逻辑更稳健
- 大量测试覆盖确保行为一致