ollama v0.30.10更新详解:Apple Silicon原生支持Command A与North家族,llama.cpp升级到b9672,Cohere2 MoE全链路接入MLX



ollama v0.30.10 已发布,发布时间为 2026 年 6 月 18 日。
从这次更新内容来看,版本体量并不只是一次常规修复,而是围绕 Apple Silicon、MLX 引擎、Cohere2 MoE 模型体系、解析器与渲染器能力、导入量化策略以及发布构建链路,做了一次非常完整的增强。
如果用一句话概括这个版本,那就是:
- Command A 和 North 家族模型正式在 Apple Silicon 上通过 MLX 引擎运行
- 底层 llama.cpp 引擎升级到 b9672
- MLX 构建产物问题得到修复
- 新增 Cohere2 MoE 模型的解析、渲染、导入、量化、注册与运行支持
- Darwin 发布流程固定 Xcode 版本,提升 macOS 构建稳定性
从变更范围看,本次对 14 个文件进行了修改,包含 3 次提交,总计新增 1916 行、删除 16 行。
这说明 v0.30.10 的重点并不在表层功能描述,而在底层兼容性、模型接入链路和推理运行体验的整体完善。
一、v0.30.10 核心更新一览
这次版本更新的官方要点非常明确,主要包括三项:
- Command A 和 North 家族模型现在可以在 Apple Silicon 上通过 MLX 引擎运行
- 底层 llama.cpp 引擎更新到 b9672
- 修复 MLX 的构建产物问题
这三项内容看似简短,但结合代码变更来看,实际落地远不止一句“支持运行”那么简单。因为要让一类新模型真正可用,至少要打通以下几个环节:
- 模型识别
- 渲染模板适配
- 输出解析适配
- 工具调用格式支持
- 思维链标记支持
- 模型导入与张量量化策略适配
- 目标引擎的模型导入注册
- 平台侧构建与发布稳定性保证
而 v0.30.10 正是在这些环节里,把 Cohere2 MoE,也就是 Command A / North 这一家族,完整接入到了 Ollama 的体系中。
二、Apple Silicon 上的 Command A / North 家族正式跑通 MLX
本次更新最重要的变化,就是 Command A 和 North 家族模型现在能够通过 MLX 引擎在 Apple Silicon 上运行。
这不是单点支持,而是从模型导入、渲染、解析、MLX 运行时注册到构建流程都做了适配。
相关变更中最直接的一项,是在 MLX runner 的导入列表里新增了:
x/models/cohere2_moe
这意味着 MLX 运行时已经把 Cohere2 MoE 模型纳入了支持范围。对应代码中,在 x/mlxrunner/imports.go 里增加了对 github.com/ollama/ollama/x/models/cohere2_moe 的导入注册。
这一步非常关键,因为没有这一层注册,即使前面的模型识别和渲染都做好了,也无法在 MLX 侧真正执行。
同时,本次还新增了一个非常大的模型实现文件:
x/models/cohere2_moe/cohere2_moe.go
这个文件本次新增了 770 行,说明 Cohere2 MoE 在 MLX 侧并不是“简单套壳式接入”,而是已经具备相对完整的模型实现基础。虽然这里没有展开文件内部全部逻辑,但仅从新增体量就能看出,这次支持是实打实的底层接入,而不是表面上的识别兼容。
三、llama.cpp 升级到 b9672,底层能力同步增强
本次版本还更新了底层 llama.cpp 版本:
- 从
b9626升级到b9672
这个改动体现在 LLAMA_CPP_VERSION 文件中,直接从原来的 b9626 变更为 b9672。
别看只是一个版本号变化,这类更新通常意味着:
- 后端推理能力同步上游改进
- 模型兼容性进一步提升
- 某些模板、采样、解析、量化或平台编译问题得到解决
- 为新模型接入提供更稳定的底层基础
而结合本次新增 Cohere2 MoE 支持来看,这次升级显然也是整个版本能力扩展的一部分。因为上层接入新模型家族,往往需要底层引擎具备相应兼容能力,尤其是面对新架构、新 tokenizer 标记和新工具调用模板时,后端能力同步非常重要。
四、修复 MLX 构建产物问题,macOS 发布链路进一步稳定
除了模型支持,v0.30.10 还对构建发布侧进行了明确修复,重点是:
- 修复 MLX 的构建产物问题
- Darwin 发布流程固定 Xcode 版本
在 .github/workflows/release.yaml 中,本次更新新增了对 macOS 构建环境的明确约束:
DEVELOPER_DIR固定为/Applications/Xcode_26.4.1.app/Contents/DeveloperCGO_CFLAGS设置为-mmacosx-version-min=14.0 -O3CGO_CXXFLAGS设置为-mmacosx-version-min=14.0 -O3CGO_LDFLAGS设置为-mmacosx-version-min=14.0 -O3
同时新增了一个专门的 Xcode 选择步骤,用于:
- 检查指定的
DEVELOPER_DIR是否存在 - 若不存在则输出错误并列出
/Applications下的 Xcode 目录 - 使用
xcode-select切换到指定 Xcode - 打印系统版本信息
- 打印 Xcode 版本
- 打印 macOS SDK 版本
- 检查
metal工具是否存在
这些动作说明,之前 Darwin 侧构建过程可能存在环境漂移问题,而本次通过固定 Xcode 版本和显式检查 Metal 工具链,来保证 MLX 相关构建产物的一致性与可用性。
这对 Apple Silicon 用户非常重要。因为 MLX 的运行质量不仅取决于模型逻辑是否接入,更取决于构建链条是否稳定。如果发布产物本身出现偏差,那么用户侧即便升级版本,也可能表现为模型无法加载、二进制行为不一致或运行异常。
本次在 CI 流程里直接把 Darwin release 的 Xcode 固定下来,本质上是在给 Apple Silicon 支持“兜底”。
五、删除旧补丁文件,说明底层依赖状态进一步演进
本次更新还删除了一个补丁文件:
llama/compat/002-llama-cpp-ui-empty-assets.patch
这个文件被整体删除,共 15 行。
虽然变更说明没有进一步展开,但从版本上下文看,这通常意味着:
- 原先需要通过补丁修复的兼容问题,已经不再需要额外补丁
- 随着 llama.cpp 版本升级,相关问题可能已在上游处理
- 本地兼容层得到简化
这类删除虽然不显眼,但往往意味着项目对底层依赖的维护负担在下降,兼容逻辑更加干净。
六、新增 Cohere 解析器:完整支持思维链、文本块、工具调用块与旧模板标记
这次更新中最值得技术细看的部分,就是新增了:
model/parsers/cohere.gomodel/parsers/cohere_test.go
也就是说,Ollama 为 Cohere2 MoE 家族专门增加了一套输出解析器。
这个解析器的定位非常明确,它用于解析 Cohere North / Command A 2026 模型输出,尤其是像 North-Mini-Code-1.0 这一类模型的生成格式。
从代码注释可以看出,这类模型的生成提示末尾有两种典型形式:
- 开启思维链时,以思维开始标记结尾
- 关闭思维链时,以思维开始标记紧跟思维结束标记结尾
也就是说,模型在 reasoning 开启时,输出会直接从思维块内部开始。
这个解析器主要支持以下几类标记结构:
- 思维块开始与结束
- 文本块开始与结束
- 工具动作块开始与结束
- 回合结束标记
- 旧版响应开始与结束标记
它定义的保留 token 包括:
- 思维开始
- 思维结束
- 文本开始
- 文本结束
- 工具动作开始
- 工具动作结束
- 旧版响应开始
- 旧版响应结束
这意味着 Ollama 不只是“能读懂正常格式”,而是连旧模板中偶尔出现的 legacy response markers 也兼容了。对于真实生成环境来说,这一点尤其重要,因为模型采样输出不一定总是严格遵循最新模板。
七、Cohere 解析器的状态机设计非常完整
从实现来看,这个解析器采用了状态机设计,主要包含四种状态:
- 收集思维内容
- 等待下一块内容
- 收集正文内容
- 收集工具动作
初始化逻辑也比较清晰:
- 默认 reasoning 为开启状态
- 如果最后一条消息是 assistant 且内容非空,则视为 assistant prefill continuation,直接进入正文收集状态
- 如果 reasoning 开启,则从思维收集状态开始
- 如果 reasoning 关闭,则进入等待块状态
这里有两个非常实用的细节:
- 支持 assistant prefill continuation
- 支持 reasoning 显式关闭
前者意味着,如果对话历史最后一条 assistant 回复是一个未闭合的文本块,那么解析器会继续承接它,而不是错误重置状态。
后者则保证当 think=false 时,模型不会被强行按“必须先输出思维”的路径解析。
八、对流式输出的处理很细,避免“假死式等待”
解析器在 Add 和 eat 的设计上,明显考虑了流式输出场景。
它会不断把增量输出写入 buffer,然后循环消费。
其中一个很关键的问题是:当标记被切碎到多个 chunk 中时,不能把半截 tag 泄漏到用户内容里,也不能因为等待完整 tag 而把内容一直卡住。
为了解决这个问题,解析器做了几件事:
- 对思维结束标记做重叠检测
- 对正文结束标记、旧响应结束标记和回合结束标记做重叠检测
- 保留可能构成 partial tag 的尾部内容,避免拆断
- 在等待块状态下,只对“可能继续长成合法 tag”的内容继续等待
- 一旦不是合法 tag 前缀,就把它当作正文内容流出,而不是无限缓冲
这个逻辑直接对应测试里的一个回归场景:
- 输出在思维结束后,如果开头是无法识别的 tag,内容必须在
done=false时就流出,不能等到整个生成结束
这类问题在实际产品里会表现成:
- 用户看到回答像卡住一样不动
- 服务端其实还在产出内容,但客户端迟迟收不到
本次测试明确覆盖了三类情况:
- 旧版响应标记
- 无法识别的新标记
- 裸文本内容
只要思维结束之后接的是这些内容,就必须能在流式阶段提前输出。
这说明 v0.30.10 在解析器层面对“流式可见性”做了专门修正。
九、工具调用解析增强,面对畸形 JSON 也尽量保住有效调用
Cohere 解析器的另一大重点,是工具调用解析。
它把动作块内部视为一个 JSON 数组,数组里的每个元素结构为:
tool_call_idtool_nameparameters
正常情况下,会直接整体反序列化这个数组。
但模型输出在真实采样时经常会出现格式瑕疵,比如:
- 两个调用之间少了逗号
- 某个值没有加引号
- 局部对象损坏
为此,本次新增的 parseCohereActions 做了降级策略:
- 如果整体 JSON 数组解析失败
- 就退回到逐个扫描顶层平衡对象
- 每个对象再分别解析
- 一个坏对象不会拖垮其他对象
这里还专门实现了 scanJSONObjects,用于扫描顶层 {...} 对象,并且会正确处理:
- 字符串内容
- 转义字符
- 字符串内部的花括号
这样就可以避免把字符串里的花括号误判为对象边界。
这个增强非常实用。因为在工具调用场景下,最怕的是:
- 模型本来已经正确输出了多个工具调用
- 结果因为其中一个参数写坏了,导致整个动作数组全部丢失
现在的策略变成:
- 能保住的调用尽量保住
- 无法解析的调用单独丢弃
- 还会记录告警日志
这意味着工具链路的鲁棒性明显提升了。
十、Cohere 解析器测试覆盖非常全面
从 model/parsers/cohere_test.go 的 268 行新增内容来看,本次不仅新增了解析器,而且做了非常细致的测试。
测试覆盖的场景包括:
- 思维块后接文本块
- tag 跨 chunk 拆分
- 工具调用解析
- reasoning 关闭
- 思维后直接输出裸文本
- 没有文本结束标记但有回合结束标记
- assistant prefill continuation
- parser 注册验证
- malformed actions 容错
- 旧版响应标记兼容
- 未结束状态下的流式输出
- 块之间出现回合结束标记
- 裸文本后接回合结束标记
这些测试基本把真实部署中最容易踩坑的流式解析问题都覆盖到了。
尤其是以下几个点,非常能说明这次接入不是“写完就算”:
- split tags 不能泄漏到输出
- legacy markers 必须兼容
- bare content 不能被吞掉
- malformed tool call 不能影响其他有效 call
- stream before done 的卡顿回归问题必须修复
因此,从工程质量上看,v0.30.10 对 Cohere 家族解析支持的完成度是相当高的。
十一、解析器正式注册,模型识别链路打通
仅有解析器文件还不够,还必须进入统一注册表。
本次在 model/parsers/parsers.go 中新增:
- 名称为
cohere时,返回CohereParser
这意味着后续只要模型识别阶段命中 cohere,就会使用这一套专用解析器。
十二、新增 Cohere 渲染器:把对话历史、工具定义、思维链、动作块、工具结果都按模板写对
与解析器对应的,是本次新增的渲染器:
model/renderers/cohere.gomodel/renderers/cohere_test.go
这部分非常关键,因为解析器解决的是“读懂模型输出”,而渲染器解决的是“把输入喂给模型”。
如果模板渲染不正确,模型就可能:
- 不按预期输出
- 不进入工具调用模式
- 思维链结构错位
- assistant continuation 失效
本次渲染器专门适配的是 Cohere North / Command A 2026 的 chat template。
它支持以下能力:
- 平台 system turn
- 可用工具列表
- 文本块包装
- 思维块
- 工具动作块
- 工具结果块
它还明确指出,模型特定的平台系统指令,比如 identity 和默认 policies,不在渲染器里硬编码,而是依赖模型的 Modelfile SYSTEM prompt 或请求中的第一条 system message。
这一点非常重要,因为它说明渲染器职责清晰,只做模板编排,不做额外内容注入。
十三、渲染器的系统消息与工具区块组织方式非常明确
渲染器输出以 LeadingBOS 开始,返回的是:
<BOS_TOKEN>
然后会构造平台 system turn,包含两部分:
- system prompt 内容
- 可用工具区块
工具区块无论是否有工具,都会被渲染出来。
这在实现上通过 writeToolsSection 完成,格式非常严格:
- 先输出工具标题区
- 再输出 json fenced block
- 空工具列表和非空工具列表的空白布局都按模板复刻
工具项本身通过 cohereToolJSON 序列化,包含:
namedescriptionparametersresponses: null
从实现上看,渲染器非常强调空白与分隔符的一致性,包括:
,和:的空格风格- 多个工具项之间的空行
- 空列表时的换行结构
这说明这次接入不是“语义接近即可”,而是尽量按原模板格式去还原。
对于大模型模板来说,这种严格性往往会直接影响输出稳定性。
十四、支持 assistant 文本、思维链、工具调用、工具结果和 prefill
在消息渲染逻辑上,CohereRenderer 处理了多种角色:
- system
- user
- assistant 或 chatbot
- tool
其中 assistant 分两种情况:
- 有工具调用
- 纯文本回答
如果 assistant 包含工具调用,则会输出:
- chatbot turn
- 可选思维块
- action 数组
这里有一个细节:
渲染器保留了思维与动作前面的空白布局,以匹配模板中的未裁剪 jinja 空白。
这在测试中也有严格校验。
如果 assistant 是纯文本,则会输出:
- 可选思维块
- 文本开始标记
- 文本内容
如果这条 assistant 消息正好是最后一条消息,那么它会被视为 assistant prefill:
- 文本块不会闭合
- 以便后续继续续写
这与解析器里的 continuation 逻辑正好首尾呼应,形成闭环。
十五、工具调用 ID 重建与工具结果映射逻辑也已补齐
对于工具调用,渲染器并不是简单沿用原始 ID,而是维护了一套连续编号逻辑:
- 工具调用在整个会话范围内按顺序生成新的索引 ID
- 如果原始 ID 存在,会记录原 ID 到新索引的映射
- 工具结果消息则根据原始
ToolCallID找回对应的重建索引
这个逻辑保证了两件事:
- 模型看到的 tool call id 是连续的、规范的
- tool result 能稳定引用到对应调用
对于没有提供 ID 的情况,结果侧会退回到调用顺序或原值。
同时,连续的 tool 消息会被合并为一个 TOOL_RESULT 数组块。
也就是说,如果前面 assistant 一次发出多个工具调用,后续多个工具结果不会拆成多个 turn,而会按模板要求聚合在一起。
这在多工具协同场景中非常关键。
十六、渲染器测试同样覆盖到了模板关键路径
model/renderers/cohere_test.go 一共新增了 189 行测试,覆盖了多个核心场景:
- 只有 user 消息时的渲染
- 带 system 历史与思维链的渲染
- reasoning 关闭
- 完整工具调用流程
- 多工具调用与多工具结果合并
- assistant prefill
- renderer 注册与 BOS 验证
其中有几个点值得特别提炼出来。
第一,system turn 中即使没有工具,也会输出工具区块。
第二,reasoning 关闭时,生成提示会输出“空思维块”,即思维开始后立刻结束。
第三,工具调用数组和工具结果数组的空白、缩进、换行布局都做了严格比对。
第四,assistant prefill 会留下一个未闭合的文本块,用于续写。
这说明 Cohere 模板支持不是“能跑就行”,而是对模板细节做了较高还原。
十七、渲染器正式注册,BOS 行为明确
在 model/renderers/renderer.go 中,本次也新增了注册逻辑:
- 名称为
cohere时,返回CohereRenderer
同时测试还验证了:
LeadingBOSForRenderer("cohere")返回<BOS_TOKEN>
这意味着渲染器已经完整进入统一调度体系,不是孤立文件。
十八、模型识别逻辑新增 cohere2moe 与 cohere2_moe 映射
要让 parser 和 renderer 真正生效,还必须保证模型被正确识别。
本次在 x/create/client/create.go 中,对 parser name 和 renderer name 的识别逻辑都做了扩展。
新增识别条件包括:
cohere2moecohere2_moe
在不同判断分支中,命中这些字段后都会返回:
cohere
也就是说,只要模型目录中的架构名或类型名包含这些关键字,Ollama 就会自动选中这套 Cohere 专用 parser 与 renderer。
这一步非常关键,因为它把“模型文件元信息”与“模板/解析能力”真正关联起来了。
十九、新增 Cohere2 MoE 导入变换:量化策略专门优化
本次在模型导入链路上还新增了:
x/create/cohere2moe.go
这个文件新增 106 行,用于 Cohere2 MoE 导入时的张量量化策略调整。
其核心目标很明确:
- 针对 Command A 家族 / North 模型做专用量化优化
这个 transform 会先尝试读取模型目录下的 config.json,解析其中的:
num_hidden_layers
如果读取或解析失败,则回退为无启发式策略,不报错中断。
其后定义了专门的 quantizationType 逻辑,重点处理几类张量。
二十、嵌入层量化策略:优先走 8 位变体,降低解码带宽压力
针对 embed_tokens.weight,本次逻辑给出了明确策略:
- 如果是二维 embedding tensor
- 考虑到它同时承担 lookup 和 tied lm_head projection
- 在超大词表规模下,bf16 embedding 会显著主导 lm_head matmul 的解码带宽
- 因此优先量化到请求模式的 8 位变体
具体来说:
int4或int8请求模式下,优先尝试int8mxfp4、nvfp4、mxfp8请求模式下,优先尝试mxfp8- 如果对齐不满足,则返回空字符串,表示不量化或交由后续处理
这说明本次更新对 Cohere2 MoE 的性能关注并不是泛泛而谈,而是已经细化到了 embedding 与 lm_head 共用权重带来的 decode bandwidth 问题。
二十一、MoE router gate 权重保持源精度,降低专家选择误差
另一个非常关键的策略,是对 .mlp.gate.weight 的处理。
代码中明确写到:
- MoE router 负责 top-k 专家选择
- 如果这里引入量化噪声,可能改变专家选择结果
- 这种误差会向后续层层放大
- 而 gate 权重本身体积很小,因此保留源精度更合适
所以对于 .mlp.gate.weight:
- 直接返回空字符串
- 即不进行量化提升或压缩
这体现出这次更新对 MoE 模型特性的理解是比较深入的。
因为 MoE 模型里最敏感的并不总是大矩阵本身,而是“决定走哪个专家”的路由器。
二十二、敏感投影层采用按层位置启发式提升精度,避免默认策略的过度带宽开销
对于以下敏感张量:
v_projk_projdown_proj
本次更新没有沿用默认策略中的“统一更高精度提升”,而是采用了按层位置的启发式方案。
实现中说明了几点:
- 默认策略对
down_proj的统一 int8 提升会带来明显 decode bandwidth 成本 - 在 top-8 MoE 中,这种开销大约可达 25 百分比
- 因此改为只在量化敏感层位上提升精度
- 使用的层位启发式沿用了
useMoreBits(layerIdx, numLayers)的思路 - 也就是早期层、后期层以及中间每隔若干层,采用更高比特精度
- 其他层则保持请求的基础量化类型
具体规则上:
- 如果请求是
int4,提升目标为int8 - 如果请求是
mxfp4或nvfp4,提升目标为mxfp8
当满足以下条件时才提升:
- 是敏感张量
- 已成功解析层号
- 层号命中高精度启发式
- 张量 shape 满足目标量化对齐要求
如果层号已识别但不命中提升规则,则:
- 如果基础量化不对齐,返回空字符串
- 否则直接返回基础量化类型
- 明确绕过默认策略中的 blanket promotion
这套策略的核心就是一句话:
- 把更高精度留给真正更敏感的层位置,而不是一刀切拉高所有敏感张量精度
这对于 MoE 模型推理效率非常关键。
二十三、导入变换正式进入注册表
在 x/create/create.go 中,本次把:
Cohere2MoeForCausalLM
注册到了 tensorImportTransformRegistry,对应工厂为:
newCohere2MoeImportTransform
这意味着只要导入到对应模型类型,Ollama 就会自动启用这套专门量化策略。
也就是说,Cohere2 MoE 的支持不只是“运行时能推”,而是从导入阶段开始就采用针对性优化。
二十四、从创建、解析、渲染、导入到运行,Cohere2 MoE 已形成完整闭环
如果把这次更新的相关变更串起来看,会发现它其实构成了一条完整链路:
- 在
x/create/client/create.go中识别cohere2moe与cohere2_moe - 识别后选择
cohereparser 和 renderer - 在
model/renderers/cohere.go中按 Cohere 模板渲染输入 - 在
model/parsers/cohere.go中解析思维、文本、动作和工具结果相关输出 - 在
x/create/cohere2moe.go中对导入量化策略做专门优化 - 在
x/create/create.go中将该导入策略注册到模型类型 - 在
x/mlxrunner/imports.go中把cohere2_moe纳入 MLX runner - 再配合
x/models/cohere2_moe/cohere2_moe.go的底层实现 - 最终让 Command A / North 家族模型在 Apple Silicon 上通过 MLX 真正可运行
这就是为什么说 v0.30.10 的重点,不只是“支持一个新模型”,而是“打通一条新模型家族的全链路能力”。
二十五、这次更新的价值,几乎都集中在可用性与工程完整度上
从最终效果来看,v0.30.10 的价值主要体现在以下几个层面:
- 对 Apple Silicon 用户来说,Command A 与 North 家族进入 MLX 可运行范围
- 对底层能力来说,llama.cpp 升级到 b9672
- 对发布稳定性来说,Darwin/Xcode/Metal 构建路径被显式固定
- 对模板适配来说,新增了 Cohere 专用 renderer
- 对输出解析来说,新增了支持思维链、文本块、工具调用和 legacy markers 的 parser
- 对工具调用鲁棒性来说, malformed JSON 不再轻易拖垮整个 action block
- 对模型导入效率来说,Cohere2 MoE 有了专门量化策略
- 对系统集成来说,parser、renderer、import transform、MLX runtime 全部完成注册
而且从测试数量和覆盖范围看,这次并不是只把功能接进来,而是尽量把流式、容错、模板细节和多工具场景都一并考虑到了。
二十六、v0.30.10 更新总结
代码地址:github.com/ollama/ollama
ollama v0.30.10 这次更新,表面上看只有几条发布说明,但从代码层面拆开后可以发现,它实际完成了以下几件大事:
- 让 Command A 和 North 家族模型正式跑上 Apple Silicon 的 MLX 引擎
- 把底层 llama.cpp 升级到 b9672
- 修复 MLX 构建产物问题,并通过固定 Darwin 发布环境来增强稳定性
- 删除一个旧的兼容补丁文件,简化底层兼容层
- 新增 Cohere parser,支持思维链、文本块、动作块、回合结束标记和旧版响应标记
- 新增 Cohere renderer,完整适配系统消息、工具区块、工具调用、工具结果和 assistant prefill
- 新增模型识别逻辑,将
cohere2moe与cohere2_moe自动映射到cohere - 新增 Cohere2 MoE 导入变换,针对 embedding、router gate、敏感投影层做更合理的量化决策
- 在创建注册表和 MLX runner 中完成 Cohere2 MoE 的正式接入
- 通过大量测试确保渲染、解析、流式输出、容错与工具链路的稳定性
更多推荐


所有评论(0)