Muse Spark Open 是 Meta 推出的开源权重模型。这个混合专家模型将文本、图像、音频和视频整合进一个约 8160 亿参数的模型中,每 token 约 420 亿活跃参数,上下文窗口最高可达 100 万 token。它生成文本,为开发者提供了一个统一的接口,可就不同类型的输入提问。

继 Muse Glimmer 之后,Muse Spark Open 以更大规模引入了混合专家架构,是迄今为止能力最强的美国开源权重模型。

Meta 针对智能体编程训练了 Muse Spark Open:读取代码库、编写和调试代码,以及调用工具。它还能接收图像、音频和视频作为输入,因此同一个模型在处理你的代码时,可以读取截图、收听语音备忘,或观看屏幕录制。本文介绍如何运行它、如何微调它,以及我们用它构建了什么。查看所有模型此处。

整体能力与架构

Meta 将 Muse Spark Open 描述为一个针对编码优化的模型,基于真实开发者工作流训练,例如多文件重构和长时间调试会话。Muse Spark Open 是一个以智能体为核心的模型,能在长任务中进行规划、行动、观察和自我纠正,包括带图像浏览网页。

特性 Muse Spark Open
模型规模 总参数约 816B;每 token 约 42B 活跃参数
专家路由 每个 MoE 层 256 个专家;每 token 选择 8 个
输入 文本、图像、音频和视频
输出 文本
上下文窗口 最高 100 万 token
检查点格式 BF16 和 NVFP4

检查点仓库为 Muse-Spark-Open-816B-A42B 和 Muse-Spark-Open-816B-A42B-NVFP4。

model diagram

Muse Spark Open 是 Muse 系列模型中的全尺寸模型。Meta 于 8 月发布的 Muse Glimmer 是同一系列中的小型稠密模型,适合在本地运行。两个模型使用相同的分词器和词表。聊天模板沿用 Muse Glimmer 模板,并为新模态做了补充。在 Muse Spark Open 中,输入嵌入和输出层是各自约 16.6 亿参数的独立矩阵。

混合专家

该语言模型有 62 层,隐藏维度为 8192。每层有 128 个查询头和 16 个键值头(分组查询注意力)。每个头有 64 维。注意力块有一个输出门和一个输出归一化层。模型还对查询和键应用归一化(QK-norm)。每个块通过一个学习到的残差门将其输入和输出结合,而不是通过简单的求和。

Muse Glimmer 在每一层使用一个稠密前馈网络。Muse Spark Open 将这个稠密网络替换为混合专家(MoE)块。每个 MoE 块有 256 个专家,路由器为每个 token 选择 8 个专家。每个专家是一个前馈网络,从 8192 维投影到 4096 维再回到 8192 维,然后对其输出应用自己的归一化。专家持有约 97% 的模型总参数。

每个 token 只运行 8 个专家,因此模型用约 42B 参数计算每个 token。全部 256 个专家都保留在内存中,所以部署需要 816B 参数模型的内存,但以 42B 模型快得多的速度运行。BF16 检查点采用 safetensors 格式,约 1.5 TB。NVFP4 检查点以 4 位精度存储参数,精度损失可忽略不计,专为 NVIDIA Blackwell GPU 设计。在 transformers 中,BF16 检查点跨 4 个节点、每节点 8 块 H200 GPU 以张量并行(TP=32)运行,NVFP4 则在单个 B200 节点上运行。如果你想部署 Muse Spark Open,请查看下面的llama.cpp、vLLM 和 SGLang 配方。

感知编码器

感知编码器将图像和视频帧转换为语言模型的 token,就像 Muse Glimmer 一样。该编码器有 1.8B 参数、50 层、隐藏维度 1536、16 个注意力头。它将每张图像分割为 14×14 的 patch,并生成 4096 维的特征。位置信息来自学习到的绝对嵌入和 2D RoPE。每一层的前馈网络使用 LayerNorm 和 GELU。每第四层和最后一层使用全注意力,其他层使用稀疏注意力。

image pipeline diagram

Muse Glimmer 30B 使用相同架构的编码器。该设计遵循感知编码器来自 Meta 的工作。视频输入经过与图像相同的编码器。

音频编码器

audio diagram

Muse Spark Open 通过其音频编码器接受音频作为输入。音频分词器将音频转换为 token,聊天模板用以下内容标记音频位置:<|audio|>token。编码器每 80 ms 输出一个音频 token,即每秒 12.5 个 token。所以,假设你有一段 10 秒的音频,输入的音频 token 数量将是 125。 编码器本身是一个卷积金字塔,其中每个阶段由一个不同 patch 大小的 patch embedder 和 2 个卷积块组成,卷积块使用大小为 7、步长为 1 的一维卷积核。这些阶段按 patch 大小 [16, 6, 5, 4] 重复。在最后阶段结束时,时间帧被送入最后一个块:RMSNorm → 线性投影 → RMSNorm。

长上下文

推理时的上下文窗口为 1M token。配置将max_position_embeddings设置为 1,048,576。这包括与文本处于同一窗口中的图像、视频和音频 token。

分组查询注意力使这种规模模型的 KV 缓存保持较小。每个 token 向缓存添加 2 × 16 个头 × 64 维 × 62 层 = 126,976 个值。在 BF16 下,这大约是每个 token 250 KB,完整 1M token 上下文约 266 GB。

推理支持

Transformers

Muse Spark Open 实现提供了MuseSparkForConditionalGeneration用于从多模态输入生成文本,以及MuseSparkProcessor用于准备对话。处理器结合了分词器、图像和视频处理器、音频特征提取器和聊天模板。

使用一个DistributedConfig来配置并行设置。tp_size是稠密层分片所跨的设备数量,而ep_size是专家分布所跨的设备数量。

你可以按如下方式初始化模型和处理器。

import os

from transformers import AutoModelForMultimodalLM, AutoTokenizer, DistributedConfig

distributed_config = DistributedConfig(
    tp_size=int(os.environ["WORLD_SIZE"]),
    ep_size=int(os.environ["WORLD_SIZE"]),
)

tokenizer = AutoTokenizer.from_pretrained("meta-models/Muse-Spark-Open-816B-A42B
")
model = AutoModelForMultimodalLM.from_pretrained(
    "meta-models/Muse-Spark-Open-816B-A42B",
    distributed_config=distributed_config,
)

messages = [
    {"role": "user", "content": "用一句话解释为什么天空通常是蓝色的。"},
]
inputs = tokenizer.apply_chat_template(
    messages,
    reasoning_effort="medium",  # 默认值:xhigh,选项:low/medium/high/xhigh
    add_generation_prompt=True,
    tokenize=True,
    return_dict=True,
    return_tensors="pt",
).to(model.device).to(model.dtype)

input_len = inputs["input_ids"].shape[-1]

outputs = model.generate(**inputs, max_new_tokens=2000)

纯文本推理

准备对话,然后将消息传给processor.apply_chat_template,启用add_generation_prompt=True,tokenize=True,return_dict=True,以及return_tensors="pt"。将处理器输出传给model.generate并解码新生成的 token,排除输入前缀。处理器有一个用于推理力度的控制项,将符号级别(low/medium/high/xhigh)映射为模型本身接受的整数(16、64、256、512)。注意,Muse Spark Open 无法关闭推理,因此如果你想用更少的 token 解决较简单的任务,请将模型推理保持在 "low"。你也可以通过加入类似下面的一行来设置数值力度Reasoning strength: 1在系统提示中。

messages = [
    {"role": "system", "content": "你应当只用一个数字回答。"},
    {"role": "user", "content": "17 * 23 等于多少?"},
]

inputs = processor.apply_chat_template(
    messages,
    add_generation_prompt=True,
    tokenize=True,
    return_dict=True,
    return_tensors="pt",
    reasoning_effort="high", # 选项:low/medium/high/xhigh
).to(model.device).to(model.dtype)

output = model.generate(**inputs, max_new_tokens=2000)
generated_tokens = output[0][inputs["input_ids"].shape[1] :]
print(processor.decode(generated_tokens, skip_special_tokens=False))

图像与文本

Muse Spark Open 处理器会将每个图像标记扩展为处理后图像所需的 patch token 数量,并在其两侧加上图像边界 token。这种扩展使文本位置与传给模型的视觉特征保持对齐。该处理器还能处理单个提示中的多张图像。

image_url = (
    "https://hf-mirror.com/datasets/merve/vl-test-suite/"
    "resolve/main/pills.jpg"
)
messages = [
    {
        "role": "user",
        "content": [
            {
                "type": "image",
                "image": image_url,
            },
            {
                "type": "text",
                "text": "这种补充剂中的任何成分会相互作用吗?",
            },
        ],
    },
]

inputs = processor.apply_chat_template(
    messages,
    tokenize=True,
    add_generation_prompt=True,
    reasoning_effort="medium",
    return_dict=True,
    return_tensors="pt",
).to(model.device).to(model.dtype)
input_len = inputs["input_ids"].shape[-1]

outputs = model.generate(**inputs, max_new_tokens=2000)
response = processor.decode(outputs[0][input_len:], skip_special_tokens=False)

processor.parse_response(response)

视频推理

视频提示包含帧时间信息以及视觉内容。该处理器能处理带音频的视频(得益于音频编码器,这是相较 Muse Glimmer 的升级)。处理器会对视频帧和音频进行下采样,以将帧对齐在一起。默认情况下,视频以 2 FPS 采样,最多 96 帧。你可以通过设置视频处理器的 fps 来修改这一点:

processor.video_processor.fps = 4.0

一般经验法则是,视频是按时间顺序排列的帧,下采样越多,特定事件之间丢失的帧就越多,因此如果想要更准确的生成结果,就需要保持较高的 fps。但这也是一种权衡,因为会需要更多内存并增加预填充的延迟。帧会与标明时间戳的文本输入交错(例如 "Time: 3.5s")。要传入带音频的视频,请将load_audio_from_video=True传给apply_chat_template。

在使用以下方式准备输入时保留视频的元数据return_metadata=True以便处理器能分配正确的帧率。

import torch

messages = [
    {
        "role": "user",
        content: [
            {
                type: text,
                text: (
                    描述这个视频中发生了什么。
                    使用时间戳,并包含相关的语音或声音。
                ),
            },
            {
                type: video,
                url: https://hf-mirror.com/datasets/merve/vlm_test_images/resolve/main/ramen.mp4
            },
        ],
    }
]

inputs = processor.apply_chat_template(
    messages,
    add_generation_prompt=True,
    tokenize=True,
    return_dict=True,
    return_tensors=pt,
    load_audio_from_video=True,
    return_metadata=True,
).to(model.device).to(model.dtype)

with torch.inference_mode():
    output_ids = model.generate(
        **inputs,
        max_new_tokens=256,
        do_sample=False,
    )

generated_ids = output_ids[:, inputs[input_ids].shape[1] :]
response = processor.batch_decode(
    generated_ids,
    skip_special_tokens=True,
)[0]

print(response)

音频推理

Muse Spark Open 音频塔接收原始波形。处理器期望 24 kHz 的单声道音频,并将波形填充到 1,920 个采样点的倍数,对应每 80 毫秒一个音频嵌入。以其他采样率直接提供给处理器的音频必须先重采样。你可以使用load_audiotransformers 的 util 来完成。load_audio使用 torchcodec、librosa 或 torchaudio 后端,因此请确保在运行推理前本地已安装其中之一。

如果你只想简单地使用apply_chat_template配合 messages,这一切都会在底层为你处理:

import torch
from transformers import AutoProcessor, AutoModelForMultimodalLM

model_id = "meta-models/Muse-Spark-Open-816B-A42B"
processor = AutoProcessor.from_pretrained(model_id)

model = AutoModelForMultimodalLM.from_pretrained(model_id).eval()

messages = [
    {
        "role": "user",
        "content": [
            {
                "type": "audio",
                "url": "https://hf-mirror.com/buckets/huggingface/audio-samples/resolve/bbaudio_question_39.mp3",
            },
            {
                "type": "text",
                "text": "回答这个问题。",
            },
        ],
    }
]

# 下载音频,将其解码为单声道,重采样到 24 kHz,填充,创建 input_values_mask,并扩展音频占位符。
inputs = processor.apply_chat_template(
    messages,
    add_generation_prompt=True,
    tokenize=True,
    return_dict=True,
    return_tensors="pt",
    load_audio_backend="auto",
).to(model.device).to(model.dtype)

with torch.inference_mode():
    output_ids = model.generate(
        **inputs,
        max_new_tokens=128,
        do_sample=False,
    )

# 仅解码新生成的 token
prompt_length = inputs["input_ids"].shape[1]
generated_text = processor.batch_decode(
    output_ids[:, prompt_length:],
    skip_special_tokens=True,
)

print(generated_text[0])

处理器会在音频边界标记之间插入匹配数量的音频 token。它还会返回一个标识真实采样点的掩码,使模型能够排除填充的音频嵌入。

工具调用

Muse Spark Open 可以执行纯文本和多模态工具调用。你可以按如下方式让模型调用工具。


from transformers import AutoProcessor, AutoModelForMultimodalLM

MODEL_ID = "meta-models/Muse-Spark-Open-816B-A42B"

# 加载模型
processor = AutoProcessor.from_pretrained(MODEL_ID)
model = AutoModelForMultimodalLM.from_pretrained(
    MODEL_ID,
    dtype="auto",
    device_map="auto"
)

tools = [
    {
        "type": "function",
        "function": {
            "name": "weather.get",
            "description": "获取某个城市的当前天气。",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {"type": "string"},
                },
                "required": ["city"],
            },
        },
    }
]


messages = [
    {
        "role": "user",
        "content": [
            {"type": "image", "image": "https://hf-mirror.com/datasets/merve/vl-test-suite/resolve/main/SF.png"},
            {"type": "text", "text": "我要去这张图片里的城市。我应该穿什么衣服?"},
        ],
    },
]

inputs = processor.apply_chat_template(
    messages,
    tools=tools,
    tokenize=True,
    return_dict=True,
    return_tensors="pt",
    add_generation_prompt=True,
    reasoning_strength="high"
).to(model.device).to(model.dtype)

input_len = inputs["input_ids"].shape[-1]
outputs = model.generate(**inputs)
response = processor.parse_response(
      completion,
      prefix=inputs["input_ids"][0],
      tools=tools,
  )
print(response)

Muse Spark Open 使用基于通道的聊天模板(Harmony,最早由 gpt-oss 引入)。注意你无需了解其内部细节,但检查模型路由到的通道很有用,以防你得到低质量的输出。在下面的输入消息中:

<|begin_of_text|>
  <|start|>system<|message|>
  You are a helpful AI assistant.
  Knowledge cutoff: 2026-01-04.
  Current date: ...
  ...
  <|eot|>
  <|start|>user<|message|>...
  <|eot|>
  <|start|>assistant

<|start|>assistant被有意留空,由模型来选择 recipient,使用to=。模型有不同的 recipient,例如self要求模型进行推理,

to=self<|message|>the model reasons here<|eom|> # reasoning
<|start|>assistant to=user<|message|>final answer<|eot|> # final answer

self用于推理,commentary是工具调用之前和之间对最终用户可见的注释,user是最终回复。
工具调用路由的解析方式如下(假设你已将tools传给apply_chat_template:

<|start|>assistant to=weather.get<|message|>
  <atem:function_calls>
  <atem:invoke name="weather.get">
  <atem:parameter name="city">San Francisco</atem:parameter>
  </atem:invoke>
  </atem:function_calls>
  <|eot|>

Llama.cpp

在 Llama Server 上运行的 Muse Spark 2-bit

Muse Spark Open 已集成到 llama.cpp 中,并包含在预构建的二进制文件里。你可以用以下命令安装:

curl -LsSf https://llama.app/install.sh | sh

你可以按如下方式启动服务器,并在模型 ID 后附加量化后缀:


llama serve -hf ggml-org/Muse-Spark-Open-816B-A42B-GGUF:Q2_K

包含量化版本的仓库位于此处。服务器启动后,你可以访问 localhost:9931 使用内置的 WebUI 进行聊天。在 Web UI 中你可以添加音频和图像进行推理,并调整推理档位。
注意,Muse Spark Open 无法关闭推理,因此如果你想用更少的 token 解决较简单的任务,请将模型推理保持在“low”。
我们在 Mac M3 Ultra(512GB)上测试了量化版本。经过 imatrix 校准的 2-bit 量化版本运行速度为 18 tokens/s,并且还有充足的空间留给 KV 缓存(模型占用 304 GB)。

你也可以按如下方式查询服务器。欢迎查看API 参考文档了解多模态、工具调用等更多内容。

## Text-only inference
curl http://localhost:8080/v1/chat/completions \
    -H "Content-Type: application/json" \
    -d '{
        "messages": [
            {"role": "system", "content": "You are a helpful assistant."},
            {"role": "user", "content": "Write a limerick about python exceptions"}
        ]
    }'

## Image-text inference
curl -s http://127.0.0.1:8080/v1/chat/completions \
  -H "Content-Type: application/json" -H "Authorization: Bearer <your-key>" \
  -d '{"model":"muse-spark-open","messages":[{"role":"user","content":[
        {"type":"text","text":"What is in this image?"},
        {"type":"image_url","image_url":{"url":"data:image/png;base64,..."}}
      ]}],"temperature":0}'

## Audio-text inference
curl -s http://127.0.0.1:8080/v1/chat/completions \
  -H "Content-Type: application/json" -H "Authorization: Bearer <your-key>" \
  -d '{"model":"muse-spark-open","messages":[{"role":"user","content":[
        {"type":"text","text":"Transcribe this audio."},
        {"type":"input_audio","input_audio":{"data":"data:audio/wav;base64,..."}}
      ]}],"temperature":0}'

llama.cpp 团队提供了不同的量化版本。我们在 Apple Silicon 芯片上测试了 Q2_K、Q4_K_S 和 Q_8。你可以通过添加量化 id 作为后缀来运行每个量化版本,llama serve -hf ggml-org/Muse-Spark-Open-816B-A42B:Q2_K。

SGLang

SGLang 的 Muse Spark Open 集成支持文本、图像、音频和视频输入。NVFP4 参考配置运行在四块 GB300 GPU 上。

在 SGLang 集成环境中,从 HF Mirror Hub 下载检查点并启动服务器:

export MODEL_ID=meta-models/Muse-Spark-Open-816B-A42B-NVFP4
export CKPT="$(hf download "$MODEL_ID")"

SGLANG_FLASHINFER_NVFP4_PER_TOKEN_ACTIVATION=1 \
uv run sglang_meta serve \
  --model-path "$CKPT" \
  --served-model-name "$MODEL_ID" \
  --quantization modelopt_fp4 \
  --moe-runner-backend flashinfer_trtllm \
  --tp-size 4 \
  --ep-size 4 \
  --port 30000

检查点包含聊天模板,我们显式传入它。启动器会配置 Muse 推理和工具调用解析器。

通过 OpenAI 兼容 API 发送请求:

curl http://localhost:30000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "meta-models/Muse-Spark-Open-816B-A42B-NVFP4",
    "messages": [{
      "role": "user",
      "content": "Explain how a mixture-of-experts model works."
    }],
    "max_tokens": 2048
  }'

响应将推理轨迹分离在reasoning_content中,将最终答案放在content中。

vLLM

Muse Spark Open 的 vLLM 参考集成支持文本和图像输入,使用 NVFP4 检查点,需要 Blackwell 系列 GPU。

安装参考插件及其依赖后,从 HF Mirror Hub 下载检查点并启动服务器:

export MODEL_ID=meta-models/Muse-Spark-Open-816B-A42B-NVFP4
export CKPT="$(hf download "$MODEL_ID")"

VLLM_ALLOW_LONG_MAX_MODEL_LEN=1 \
VLLM_PLUGINS=musespark1x_models,ptq_nvfp4 \
vllm serve "$CKPT" \
  --served-model-name "$MODEL_ID" \
  --tokenizer-mode musespark1x \
  --config-format auto \
  --load-format internal_safetensor \
  --tensor-parallel-size 4 \
  --enable-expert-parallel \
  --max-model-len 131072 \
  --gpu-memory-utilization 0.92 \
  --reasoning-parser musespark1x \
  --tool-call-parser musespark1x \
  --enable-auto-tool-choice \
  --port 8000

此配置设置了 128K token 的服务上下文。该插件提供模型实现、检查点加载器以及推理和工具调用解析器。

使用相同的 Hub 模型 ID 发送请求:

curl http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "meta-models/Muse-Spark-Open-816B-A42B-NVFP4",
    "messages": [{
      "role": "user",
      "content": "Explain how a mixture-of-experts model works."
    }],
    "max_tokens": 2048
  }'

MLX

Muse Spark Open 现已可在oMLX和mlx-lm中使用。针对 oMLX 优化的 oQ 量化版本现已提供3-bit和4-bit,可直接使用。

我们在 M3 Ultra(512 GB)上测试了 oQ3e 量化版本。模型占用约 344 GB,为 KV 缓存留出了空间,在 1024 token 提示和生成 128 token 的情况下,预填充速度约为 225 tok/s,生成速度约为 21 tok/s。

通过 oMLX 界面下载模型后,你可以在内置聊天 UI 中与其对话。在聊天 UI 中,你可以添加图像并即时调整推理强度,从 low 到 xhigh。模型的推理过程会显示为可折叠的思考块,与最终答案分开。

请注意,无法关闭推理,默认(Auto)使用 xhigh。如果你想在较简单的任务上使用更少的 token,请将其设置为“low”。omlx

该语言模型也可在此 PR中使用,属于官方 mlx-lm 仓库。你可以像这样在同样高质量的 oQ3e 量化版本上运行它:

mlx_lm.generate --model mlx-community/Muse-Spark-Open-816B-A42B-oQ3e \
  --prompt "Explain convolutional networks like I am 5" \
  --max-tokens 5000

这是一个大模型,如上所述,即使是 3-bit 量化也需要超过 256 GB 的 RAM。你也可以跨多台计算机进行分布式推理,详情请参阅文档。

使用 Inference Endpoints 部署 Muse Spark Open

你可以在 Inference Endpoints 上使用经过预验证的 SGLang 配方部署 Muse Spark Open 的 NVFP4 变体,该变体可运行在 8 × NVIDIA RTX Pro 6000 98 GB(上下文长度 131072)上,或者如果你需要 1048576 的上下文长度,可运行在 8 × NVIDIA H200 141GB 上。

要部署,请使用 HF Mirror CLI 运行一条命令:

hf endpoints catalog deploy --repo meta-models/Muse-Spark-Open-816B-A42B-NVFP4 --name muse-spark

或者打开endpoints.hf-mirror.com/new/meta-models/Muse-Spark-Open-816B-A42B-NVFP4并选择 Create Endpoint。

该端点暴露一个 OpenAI 兼容 API,包括 Chat Completions API,位于/v1/chat/completions以及 Responses API,位于/v1/responses。

curl "https://<your-endpoint>.endpoints.huggingface.cloud/v1/chat/completions" \
  -H "Authorization: Bearer$HF_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
"model": "meta-models/Muse-Spark-Open-816B-A42B-NVFP4",
"messages": [{
"role": "user",
"content": [
{"type": "image_url", "image_url": {"url": "https://hf-mirror.com/datasets/merve/vl-test-suite/resolve/main/pills.jpg"}},
{"type": "text", "text": "这个补充剂中的任何成分会相互作用吗?"}
]
}],
"chat_template_kwargs": {"enable_thinking": false}
}'

任何兼容 OpenAI 的客户端都可以使用相同的 URL 和你的 HF Mirror token 作为 API key。

使用 TRL 进行微调

你可以使用 TRL 对 816B 检查点进行微调SFTTrainer。本节展示我们如何在 8 个节点、每个节点 8 块 H100 GPU 上用 TRL 对它进行微调。该方案在注意力层上训练 LoRA 适配器。专家保持冻结。完整脚本位于TRL 示例。

首先,我们需要将模型拆分到 64 块 GPU 设备上。鉴于模型规模庞大,我们需要跨多个维度对它进行并行化。我们用 FSDP 对模型进行分片,并将专家拆分到各 GPU 上,使用DistributedConfig,它告诉transformers模型在加载时如何拆分:

from transformers.distributed import DistributedConfig

distributed_config = DistributedConfig(fsdp_size=64, ep_size=8)

在上面的代码片段中,fsdp_size=64使用 FSDP2 将模型分片到全部 64 块 GPU 上,而ep_size=8将每一层的 256 个专家拆分为 8 组。Transformers 会将每个 token 发送到持有其专家的 GPU,因此每块 GPU 都在自己那部分批次上训练。

现在,我们可以为训练运行配置SFTConfig。我们在这里执行了一个简单任务,在开源数据集上适配模型的聊天模板,但你可以将其应用到自己的用例中。

import torch
from datasets import load_dataset
from peft import LoraConfig
from transformers.distributed import DistributedConfig
from trl import SFTConfig, SFTTrainer

train_dataset = load_dataset("allenai/tulu-3-sft-mixture", split="train[:500000]")

training_args = SFTConfig(
    output_dir="muse-spark-lora-sft",
    model_init_kwargs={"dtype": torch.bfloat16, "distributed_config": DistributedConfig(fsdp_size=64, ep_size=8)},
    per_device_train_batch_size=1,
    max_steps=500,
    max_length=2048,
    packing=True,
    save_only_model=True,
    logging_steps=1,
    report_to="trackio",
)

trainer = SFTTrainer(
    model="meta-models/Muse-Spark-Open-816B-A42B",
    args=training_args,
    train_dataset=train_dataset,
    peft_config=LoraConfig(r=16, lora_alpha=32, target_modules=["q_proj", "k_proj", "v_proj", "o_proj"]),
)
trainer.train()

这里的核心部分是packing=True它将示例拼接成 2048 token 的序列且不进行填充。块对角掩码使各示例保持相互独立。save_only_model=True保存适配器而不保存优化器状态,因为训练器无法恢复在加载时已被分片的模型。LoraConfig以四个注意力投影为目标,每一层的 256 个专家保持冻结。

然后我们可以在每个节点上运行这条命令:

torchrun --nnodes 8 --nproc_per_node 8 --rdzv_backend c10d --rdzv_endpoint "$MASTER_IP:29700" sft_muse_spark_open.py

我们训练了 500 步,在 64 块 H100 上耗时约 2 小时,速度约为每秒 8,000 个 token。平均 token 准确率从 72% 升至 84%,loss 从 1.26 降至 0.57,这表明这是一次不错的微调运行。

Loss

Acc

演示

Muse Spark Open 是一个编码与智能体模型。我们想亲自验证这一点,于是尝试了一系列多模态与智能体任务,用到了该模型的图像和音频输入。下面所有内容都是你可以运行或 fork 的。

3D 资产生成器

我们将 2-bit 量化的 Muse Spark open(部署在 llama.cpp 上)与 Pi 编码智能体结合,用于生成并迭代改进 3D 资产,基于Three.js。你可以在这里找到提示词这里,由于模型经过量化,需要更多的引导。在 Mac Ultra 上,我们在 llama.cpp 上获得 18 TPS。

Pi demo

我们首先描述资产,Pi 使用该模型为资产生成 Three.js 代码,在浏览器中渲染结果,并从多个角度截取屏幕截图。然后它将这些图像发回 llama server 上的同一模型以获取视觉反馈。Pi 利用该反馈来修改代码,并重复这一过程。

使用 OpenEnv 和 HF Mirror Sandbox 进行浏览器交互

我们在 computer use 任务上测试了 Spark,其表现令我们惊叹,因此我们构建了一个精简的演示,同时也能教你 computer use 智能体是如何工作的。你还可以根据自己的需求进一步定制。这既是一个教学示例,也是几行代码就能运行的东西。你可以在这里找到它这里。

使用 OpenEnv 和 HF Sandboxes 的 Muse Spark NVFP4 浏览器智能体

HF Mirror Sandboxes是基于 HF Mirror Jobs 构建的沙箱,用于便捷的代码执行。该演示由三个组件组成:

  1. 通过 Inference Endpoints 部署的 Muse Spark Open,
  2. OpenEnv 使用 helium 和 selenium 封装 Web 驱动操作(点击、输入、滚动等),定义浏览器环境的 reset、step、observation、termination 接口,
  3. Chromium 网页浏览器

其中远程沙箱包含环境与浏览器,如下图所示。

Diagram

你可以通过几个步骤轻松尝试,示例中已有说明。用 Muse Spark Open 启动推理端点(NVFP4 也可以很好地工作!),将你的端点 URL 添加为环境变量,在 Spaces 中发布你的 OpenEnv 服务器并提供该地址,然后就可以运行智能体循环了。Muse Spark Open 会查看之前的操作、系统提示、URL 以及浏览器截图来采取行动,除此之外不看任何其他内容(没有 DOM、没有 HTML 代码、什么都没有),因此这是一个真正的多模态浏览器演示。

调用你的浏览器

最后,我们想将 Spark 的智能体多模态能力推向极限,因此我们搭建了这个 space它将模型的音频、图像和智能体特性结合成一个浏览器智能体。我们给模型一个所需物品的概括性描述,它会与集成的浏览器交互,在 Amazon 上寻找选项。

Muse Spark Open 接收语音输入,推理出符合描述的产品类型,在 Amazon 上搜索它,并根据标准选出最合适的一个。

总结

Muse Spark Open 是 Muse 系列中的一个全尺寸开源权重模型。从BF16或NVFP4检查点开始,或者试试那些出色的llama.cpp quants。如果你用 Muse Spark Open 构建了什么,请分享出来,并在仓库的讨论区告诉我们。