🤖 AI总结
主题
Ollama v0.40.13版本更新,扩展LFM3模型及语音能力至Linux和Windows平台。
摘要
Ollama v0.40.13将LFM3模型及语音能力扩展至Linux和Windows,新增llama-server语音实现,并升级llama.cpp版本。
关键信息
- 1 LFM3模型及语音能力现支持Linux、Windows和Apple silicon。
- 2 新增llama-server语音实现,支持文本转语音流程。
- 3 升级llama.cpp版本并修复多个兼容性问题。
![]()
![]()
![]()
发布时间与版本概览
ollama v0.40.13 为 Latest 版本,发布时间为 2026 年 10 月 31 日。
本次更新的核心焦点是 Liquid AI 的 LFM3 模型支持范围扩大。此前相关能力主要面向 Apple silicon,而在 v0.40.13 中,LFM3 模型现已能够运行于 Linux 和 Windows,同时继续支持 Apple silicon。
此次覆盖的不只是文本模型能力,还包括 lfm3-audio 与 lfm3-omni 中的文本转语音能力。也就是说,LFM3 的语音相关支持不再局限于 Apple silicon 环境,Linux 与 Windows 平台也获得了对应支持。
本次比较中共包含:
• 4 个提交
• 29 个文件发生变化
• 2 位贡献者参与
• 新增 1,260 行
• 删除 410 行
更新涉及模型导入、语音渲染、llama-server 请求、重复惩罚参数处理、分词器 BOS 行为、Metal 编译兼容处理,以及命令行无参数行为调整等多个部分。
本次版本的核心变化:LFM3 跨平台支持
v0.40.13 最受关注的变化,是 Liquid AI 的 LFM3 模型现在可以在 Linux、Windows 和 Apple silicon 上运行。
更新说明明确指出,LFM3 模型包含文本转语音能力,其中 lfm3-audio 和 lfm3-omni 均涉及语音能力支持。此次更新将这部分能力扩展到了 Linux 与 Windows。
从代码改动来看,LFM3 的 GGUF 相关修复以及 llama-server 的 speech 支持,是本次跨平台语音能力落地的重要组成部分。
对应提交内容包括:
• LFM3 GGUF 修复与 llama-server speech 支持
• llama.cpp 版本升级
• 无参数运行 ollama 时显示帮助信息
• 修复 Metal unary 相关崩溃问题
llama.cpp 版本升级
本次更新中,LLAMA_CPP_VERSION文件的版本号发生变化:
b11901
更新为:
b11963
这意味着 ollama v0.40.13 所集成的 llama.cpp 版本由 b11901 升级至 b11963。
llama.cpp 的升级与本次 LFM3 GGUF 修复、语音支持以及 Metal 兼容性修复共同构成了本版本的重要基础。
命令行行为变化:直接运行 ollama 显示帮助
在cmd/cmd.go中,命令行入口逻辑进行了调整。
原先的逻辑使用Run,在没有额外参数时会进入欢迎流程,并尝试运行交互式界面。更新后改为了RunE,并在完成版本判断后直接返回命令帮助。
核心变化可以概括为:
Run: func(cmd *cobra.Command, args []string) {
调整为:
RunE: func(cmd *cobra.Command, args []string) error {
当使用版本参数时,仍然会执行版本处理逻辑:
if version, _ := cmd.Flags().GetBool("version"); version {
versionHandler(cmd, args)
return nil
}
而无参数运行时,不再执行原有的欢迎界面逻辑和交互式 TUI 流程,改为:
return cmd.Help()
也就是说,直接运行ollama时,行为变为显示帮助内容。
与此对应,原先的欢迎流程文件被删除:
cmd/welcome.go
cmd/welcome_test.go
其中:
•cmd/welcome.go被删除,共删除 37 行
•cmd/welcome_test.go被删除,共删除 36 行
这部分调整与提交说明中“运行 ollama 时显示帮助”相对应。
launch 命令说明同步调整
在cmd/launch/launch.go中,launch 命令的说明文字也进行了更新。
原有描述中,无参数运行的说明是:
Without arguments, this is equivalent to running 'ollama' directly.
更新后变为:
Without arguments, choose a model or app from the interactive menu.
同时,命令说明保留了以下含义:
•launch可以启动 ollama 交互菜单,或直接启动某个特定集成
• 如果传入标志或额外参数,则需要指定集成名称
• 支持的集成会在说明中列出
这项文案调整与主命令无参数时显示帮助的变化一同出现。
LFM3 语音配置改用渲染器提供的语音列表
在create/lfm3.go中,LFM3 模型导入时涉及语音列表的逻辑发生变化。
原代码通过 LFM3 speech 包获取语音名称:
cfg.Voices = lfm3speech.VoiceNames()
更新后改为通过渲染器获取 LFM3 Speech 的语音配置:
cfg.Voices = renderers.LFM3SpeechVoices()
对应的导入也发生调整。
原先依赖:
"github.com/ollama/ollama/mlxrunner/model/lfm3/lfm3speech"
更新为:
"github.com/ollama/ollama/model/renderers"
相关逻辑位于augmentConfig中。当模型具备 speech 属性时,配置将写入语音信息:
if t.speech {
cfg.Voices = renderers.LFM3SpeechVoices()
}
这意味着 LFM3 的语音配置来源由原有的lfm3speech包转向renderers中的 LFM3 Speech 语音定义。
新增 llama-server 语音实现
本次更新新增了文件:
llm/llama_server_speech.go
该文件共新增 179 行代码,核心目标是让llamaServerRunner实现Speaker接口:
var _ Speaker = (*llamaServerRunner)(nil)
新增的Speech方法用于通过 llama-server 的/tts接口朗读文本。
接口逻辑首先会判断请求中是否存在 SpeechPrompter:
if req.Prompter == nil {
return api.StatusError{
StatusCode: http.StatusNotImplemented,
ErrorMessage: "this model does not support speech",
}
}
如果没有 SpeechPrompter,则返回“不支持 speech”的状态错误。
随后,逻辑还会检查模型是否携带 projector:
if len(s.launch.projectors) == 0 {
return api.StatusError{
StatusCode: http.StatusNotImplemented,
ErrorMessage: "this model was created without its projector, which holds the speech codec; recreate it with the mmproj to use speech",
}
}
这里明确指出,speech codec 位于 projector 中。如果模型创建时没有带上 projector,则无法使用 speech。错误信息也明确提示,需要使用 mmproj 重新创建模型后才能使用语音能力。
语音名称与语音语言的解析
在进行 TTS 请求之前,代码通过请求中的 Prompter 解析所选语音:
voice, err := req.Prompter.SpeechVoice(req.Voice)
如果语音名称无效,返回 HTTP 400 状态错误:
return api.StatusError{
StatusCode: http.StatusBadRequest,
ErrorMessage: err.Error(),
}
解析后的语音对象包含语音名称和语言信息,后续会一起传递给 llama-server 的/tts请求。
语音生成过程使用并发控制与服务状态检查
新增的 Speech 实现中,会先获取信号量:
if err := s.sem.Acquire(ctx, 1); err != nil {
return err
}
defer s.sem.Release(1)
之后检查 llama-server 的状态:
status, err := s.getServerStatusRetry(ctx)
如果服务状态并非 Ready,则返回错误:
return fmt.Errorf("unexpected server status: %s", status)
因此,语音生成请求会在服务就绪状态下进行。
文本语音分块与 token 计数逻辑
语音生成并不是直接将全部输入一次性发送,而是通过渲染器提供的规则进行分块。
代码注释指出,SpeechPrompter 来自模型的 renderer,其作用包括:
• 确定语音名称
• 按发布方文档规定的方式拆分输入文本
分块前需要进行 token 计数。代码维护了一个缓存:
counts := map[string]int{}
计数函数会调用:
s.tokenize(ctx, text, false)
并记录每段文本的 token 数量。
代码特别说明,分块过程会计数许多重叠片段,每次计数都对应一次/tokenize调用。
随后调用:
chunks := req.Prompter.SpeechChunks(req.Input, count)
生成要朗读的文本块。
如果 token 计数过程发生错误,则返回:
count speech tokens
相关错误。
如果输入文本无法形成任何语音块,则返回 HTTP 400 错误:
input has no text to speak
因此,空输入或没有可朗读文本的输入不会进入后续 TTS 生成过程。
每个文本块对应一次 /tts 生成
在生成阶段,每个文本块都会调用speakChunk。
代码注释明确表示:
• 每个 chunk 对应一次生成
• llama-server 负责根据 voice 和 language 渲染模型的tts模板
请求体结构为:
type llamaServerTTSRequest struct {
Input string `json:"input"`
Voice string `json:"voice"`
Lang string `json:"lang"`
ResponseFormat string `json:"response_format"`
Stream bool `json:"stream"`
NPredict int `json:"n_predict"`
}
实际请求会包含以下字段:
Input: chunk.Text,
Voice: voice.Voice,
Lang: voice.Language,
ResponseFormat: "pcm",
Stream: true,
NPredict: chunk.MaxFrames,
也就是说:
• 输入内容来自当前文本块
• 语音字段来自选择后的 voice
• 语言字段来自 voice 的 language
• 返回格式指定为pcm
• 使用流式输出
• 最大预测帧数由 chunk 的MaxFrames决定
请求通过 HTTP POST 发送到:
http://127.0.0.1:端口/tts
请求头为:
Content-Type: application/json
JSON 编码时设置:
enc.SetEscapeHTML(false)
语音请求失败时的错误处理
当 HTTP 请求本身失败时,如果错误属于上下文取消,则直接返回该错误。
否则会记录 llama-server TTS 错误,并检查 runner 中是否存在最后错误信息。
如果存在最后错误信息,则会返回包含详细说明的错误:
model runner has unexpectedly stopped, this may be due to resource limitations or an internal error, check ollama server logs for details
并在结尾附带最后错误信息。
如果没有最后错误信息,则返回不包含附加详情的同类错误提示。
当/tts返回的 HTTP 状态不是 200 时,代码会读取响应体,并将其转换为状态错误:
return api.StatusError{
StatusCode: res.StatusCode,
ErrorMessage: s.statusErrorMessage(data),
}
llama-server 返回 PCM 格式的严格校验
/tts返回成功后,代码会检查响应头的Content-Type。
新增的checkLlamaServerPCM函数会解析媒体类型参数,并验证返回结果是否符合预期。
要求包括:
媒体类型:audio/pcm
编码:float
位数:32
采样率:SpeechSampleRate
代码逻辑为:
if mediaType != "audio/pcm" ||
params["encoding"] != "float" ||
params["bits"] != "32" ||
rate != SpeechSampleRate {
如果格式不符合预期,会返回错误:
llama-server tts returned 某个类型, want 32-bit float PCM at 指定采样率 Hz
代码注释说明,llama-server 在response_format为pcm时返回的是单声道 float32 PCM 数据,其采样率应当符合Speaker所承诺的采样率。
float32 PCM 实时转换为 16 位 PCM
新增的streamPCM16函数负责处理流式音频数据。
该函数从响应流中读取数据:
buf := make([]byte, 32<<10)
每次读取后,以 4 字节为一个完整 float32 样本进行处理。
对于每个 float32 音频样本,代码执行如下流程:
• 按小端序读取 float32 数据
• 使用math.Float32frombits转换为浮点样本
• 调用audio.PCM16(sample)转换为 PCM16
• 使用小端序写入 16 位 PCM 数据
• 将转换后的 PCM 数据通过回调函数输出
核心代码包括:
sample := math.Float32frombits(binary.LittleEndian.Uint32(buf[i:]))
binary.LittleEndian.PutUint16(pcm[i/2:], uint16(audio.PCM16(sample)))
注释指出,这一逻辑可以处理被拆分到多次读取中的单个样本。
如果读取结束时仍然存在未构成完整 float32 样本的残留字节,则会报错:
llama-server tts stream ended mid-sample
这保证了输出音频流以完整样本为单位进行处理。
repeat_last_n 参数兼容处理
在llm/llama_server.go中,新增了llamaServerRepeatLastN函数:
func llamaServerRepeatLastN(repeatLastN, numCtx int) int {
if repeatLastN < 0 {
return numCtx
}
return repeatLastN
}
代码注释解释了调整原因:
Ollama 的 repeat_last_n=-1 表示整个上下文;
llama-server 不接受负数值。
因此,当repeat_last_n小于 0 时,系统会将其映射为上下文大小numCtx。
该逻辑同时应用在两类请求中。
一类是 Completion 请求:
RepeatLastN: llamaServerRepeatLastN(req.Options.RepeatLastN, s.options.NumCtx),
另一类是 Chat 请求中的参数映射:
"repeat_last_n": llamaServerRepeatLastN(req.Options.RepeatLastN, s.options.NumCtx),
这项调整确保 Ollama 中代表“整个上下文”的负数设置,能够转换为 llama-server 可接受的上下文长度数值。
LFM2 分词器 BOS 逻辑修复
同样位于llm/llama_server.go的tokenizerAddsBOS方法,也进行了调整。
此前代码在发现:
tokenizer.ggml.pre = lfm2
时,会直接返回true。
更新后,这一提前返回逻辑被移除,转而优先检查是否显式设置了:
tokenizer.ggml.add_bos_token
新逻辑为:
if kv.Has("tokenizer.ggml.add_bos_token") {
return kv.Bool("tokenizer.ggml.add_bos_token")
}
return kv.String("tokenizer.ggml.pre") == "lfm2"
对应注释明确说明:
• 在其他情况下,显式的add_bos_token设置优先
•lfm2预分词器只会改变 llama.cpp 的默认行为
• 如果 GGUF 明确设置了add_bos_token,则以该显式设置为准
同时,Gemma4 的既有特殊处理逻辑仍然保留。注释说明,llama.cpp 会在加载时强制为 Gemma4 开启add_bos,即使某些 GGUF 的tokenizer.ggml.add_bos_token元数据明确为 false。
因此,本次调整的重点在于:对于 LFM2 预分词器,显式的 BOS 配置不再被默认判断覆盖。
Metal unary 崩溃临时修复
本次版本还新增了补丁文件:
llama/compat/002-metal-unary-cast-constexpr.patch
该补丁针对 Metal unary 相关问题进行处理。
补丁修改了ggml-metal/kernels/unary.metal中的函数定义,将多个函数的:
inline constexpr
改为:
inline
涉及的函数包括通用转换函数:
template
inline T ggml_metal_unary_cast(U x) {
return (T) x;
}
以及在GGML_METAL_HAS_BF16条件下的 bfloat4 转换特化。
原有的:
inline constexpr bfloat4 ggml_metal_unary_cast
(float4 x)
改为:
inline bfloat4 ggml_metal_unary_cast
(float4 x)
另一个 float 转 bfloat4 的特化也进行了同样调整。
补丁内容表明,这项修改用于处理 Metal unary 的崩溃问题。
本次更新涉及的提交方向
从提交内容可以归纳出 v0.40.13 的几个关键方向。
第一,LFM3 GGUF 修复与 llama-server speech 支持。
这部分包含 LFM3 语音配置来源调整、llama-server 新增/tts调用、语音文本分块、token 计数、音频流式处理、PCM 格式校验,以及 float32 PCM 到 PCM16 的转换。
第二,llama.cpp 版本升级。
版本由 b11901 更新至 b11963,为本次更新提供新的 llama.cpp 基础。
第三,命令行入口调整。
直接运行ollama时改为显示帮助内容,原有 welcome 相关文件被移除。
第四,Metal unary 崩溃规避。
通过移除相关 Metal 函数的constexpr,处理 unary 相关崩溃问题。
第五,llama-server 请求兼容性改进。
包括repeat_last_n=-1映射到上下文长度,以及 LFM2 分词器在显式 BOS 配置下的行为调整。
总结
代码地址:github.com/ollama/ollama
ollama v0.40.13 的重点是将 LFM3 模型及其语音能力扩展至 Linux 与 Windows,并继续支持 Apple silicon。
围绕这一目标,版本中新增了 llama-server 的 speech 实现,通过/tts接口支持文本转语音流程。该实现覆盖了语音与语言选择、输入分块、token 计数、流式请求、服务状态检查、PCM 响应校验、float32 音频转换为 16 位 PCM,以及异常处理。
与此同时,更新还完成了 llama.cpp 从 b11901 到 b11963 的升级,修复了 LFM3 相关 GGUF 与 BOS 行为问题,增加了repeat_last_n的 llama-server 兼容映射,并针对 Metal unary 崩溃提供了补丁。
在命令行体验上,直接运行ollama不再进入原有欢迎与交互式流程,而是显示命令帮助;原有 welcome 相关实现和测试文件也随之删除。
我们相信人工智能为普通人提供了一种“增强工具”,并致力于分享全方位的AI知识。在这里,您可以找到最新的AI科普文章、工具评测、提升效率的秘籍以及行业洞察。 欢迎关注“福大大架构师每日一题”,发消息可获得面试资料,让AI助力您的未来发展。