ollama v0.40.13更新:LFM3正式覆盖Linux与Windows,语音能力接入llama-server

网易专栏6小时前发布 admin
1 0 0

🤖 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更新:LFM3正式覆盖Linux与Windows,语音能力接入llama-server

ollama v0.40.13更新:LFM3正式覆盖Linux与Windows,语音能力接入llama-server

ollama v0.40.13更新:LFM3正式覆盖Linux与Windows,语音能力接入llama-server

发布时间与版本概览

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助力您的未来发展。

    © 版权声明

    相关文章