alt.freeweights.speech / moss-va-sft3-quality-dpo-lora
From: laion <huggingface.co/laion>Newsgroups: alt.freeweights.speechSubject:

moss-va-sft3-quality-dpo-lora

Date: 2026-11-15Commit: 5b0ab69Signed: 2DC28CC7B26A283B ✓

Text to speech model. Safetensors weights, 825 MB in all. Published by laion under Apache-2.0.

speech825MBmoss-va-sft3-quality-dpo-lorasafetensorspermissive
FactsParamsnot statedSize825 MBFormatssafetensorsTasktext to speechLicenseApache-2.0From sourcepermissive
$ fw get laion/moss-va-sft3-quality-dpo-lora
# manifest sha256 f7b50414bcec… · 825 MB · 14 files
$ fw verify ./moss-va-sft3-quality-dpo-lora laion/moss-va-sft3-quality-dpo-lora
From sourceHosted (signed)laion/moss-va-sft3-quality-dpo-loraLast check: 2026-11-15 05:28 UTC

Get help: custom fine-tune or private deploy. We review your setup before we quote.

Adapter of moss-tts-local-transformer-4.55b-voice-acting-v2-sft3.

Works with

Overview

Size
825 MB
Weights
825 MB (safetensors)
Parameters
not stated
Formats
safetensors
Task
text to speech
License
Apache-2.0 (permissive)
Files
14, each with a sha256
Publisher
laion
Added
2026-11-15
Section
alt.freeweights.speech
Lineage

Original release from the publisher.

Base model: laion/moss-tts-local-transformer-4.55b-voice-acting-v2-sft3

Where these bytes come from
Publisher at the pinned commit→You

Sources are tried in order. A file counts only when its size and sha256 match the manifest. Sources are checked when you ask for them, not on a timer.

Sources
BadgeHostLast checkResult
From sourcehuggingface.co2026-11-15 05:28 UTCpassed

Model card

From the publisher at commit 5b0ab69. Shown as plain text with links; images open at the publisher.

MOSS VA SFT3 — audio-quality DPO LoRA (rank 16)#

⚠️ Do not merge this adapter into the base weights#

merge_and_unload(), merge_adapter(), and any offline "bake the LoRA into the checkpoint" script will destroy the model irrecoverably. This is not a performance caveat. Read this before you write a deployment script.

Why#

This adapter targets audio_lm_heads.0 … audio_lm_heads.11 and text_lm_head — 12 of its 23 target modules. In this architecture those output heads are weight-tied to the input embeddings: tie_weights() sets

audio_lm_heads[i].weight  IS  audio_embeddings[i].weight     # the same tensor, not a copy
text_lm_head.weight       IS  transformer.embed_tokens.weight

They are one allocation with two names. So when a merge adds B @ A * (alpha/r) into the head weight, it writes that delta straight into the embedding table at the same time. The model then reads its own inputs through a matrix that has been shifted by an output-side correction. Generation does not fail loudly — it degrades into noise or into a fixed babble, and the damage is inside the checkpoint you just saved. There is nothing to unmerge afterwards, because the original values are gone.

Verify it yourself in three lines#

Do not take our word for it:

m = base.model if hasattr(base, "model") else base
print(m.audio_lm_heads[0].weight.data_ptr() == m.audio_embeddings[0].weight.data_ptr())
# True  -> same storage, merging corrupts the embeddings
What to do instead#

Load with PEFT and leave the adapter unmerged. Set its strength through the scaling factor:

from peft import PeftModel

model = PeftModel.from_pretrained(base, "<this repo>", adapter_name="a").to(dev).eval()
# do NOT call model.merge_and_unload()

def set_weight(model, name, w):
    """Scale one named adapter's contribution.  alpha/r is its own base scaling."""
    for module in model.modules():
        scaling = getattr(module, "scaling", None)
        if isinstance(scaling, dict) and name in scaling:
            if not hasattr(module, "_base_scaling"):
                module._base_scaling = {}
            module._base_scaling.setdefault(name, scaling[name])
            scaling[name] = module._base_scaling[name] * float(w)

set_weight(model, "a", 1.0)
model.base_model.set_adapter(["a"])      # several adapters can be active at once

This sounds identical to a merge. An unmerged LoRA computes Wx + (B @ A)x * (alpha/r), which is exactly what the merged weight W + B @ A * (alpha/r) would compute — the same arithmetic, in a different order. You give up a small amount of inference speed and you keep the ability to change the weight, stack several adapters, or turn one off. Nothing about the sound changes.

If you are stacking adapters#

Set each one's scaling separately and activate them together with model.base_model.set_adapter([...]). Note that stacking is not free: in our own measurements a deep stack held audio quality but destroyed intelligibility (word error 0.063 → 0.554). Add adapters deliberately and measure.

If you maintain code that merges#

A regex over module names is not enough — the reliable test is identity of storage. Group the modules by weight.data_ptr() and refuse to merge into any group with more than one member. lora_bank.py in LAION-AI/Humaneness-Voice-Demo-Server does this and asserts on the merge path.


Preference-trained to prefer cleaner recordings of the same performance.

Read this first: in our own evaluation this adapter does not improve generated audio quality. Across 16 prompts, paired against the base model, the best checkpoint scores +0.017 DNSMOS (t +0.45) — indistinguishable from no adapter — and the most heavily trained checkpoint is −0.119 (t −2.14), i.e. slightly worse. We publish it with the numbers rather than without them; the null result is the finding.

What it was trained to do, in plain language#

We had 24,379 real recordings that were run through a speech enhancer (SIDON). For each one we kept the pair (enhanced take, original take) — the same performance, the same speaker, the same words, one cleaner than the other. Then we used Direct Preference Optimization to nudge the model toward producing audio that looks like the cleaner half of each pair.

The point of pairing the same take against itself is that the model cannot learn "prefer a different voice" or "prefer a calmer delivery" — those are held constant. The only thing that varies is signal cleanliness.

Three guardrails decided which pairs were allowed in:

  • the enhanced version had to score at least +0.10 DNSMOS better (mean gain +0.253, max +1.927);
  • it had to stay closer to the same speaker than a same-voice baseline (mean cosine margin 0.490), so quality could not be bought by changing the voice;
  • its emotion embedding had to stay close to the original, so the performance could not be ironed flat.

Honest limitation of the data#

All 24,379 pairs come from one enhancer (enhanced_variant = raw_sidon). A second arm using voice conversion did not survive the gates. So this adapter learned one tool's notion of "clean", not a general one.

Results#

DNSMOS is the right primary metric here because it is what selected the training data. If the adapter learned the objective, generated audio should score higher. It does not.

16 prompts × 3 samples per checkpoint, all conditions generated from the same prompts under the same seed, samples averaged within a prompt first, so n = 16 and the t is over prompts.

checkpointDNSMOSΔ vs basetWERΔ WERgenuinenessΔ genu
base (no adapter)3.338——0.058—4.004—
step1883.208−0.130−2.050.099+0.0424.020+0.016
step376 ← repo root3.355+0.017+0.450.072+0.0154.014+0.010
step7523.288−0.050−1.690.073+0.0164.039+0.034
step11283.306−0.032−0.850.078+0.0204.081+0.077
step1504 (final)3.219−0.119−2.140.081+0.0244.202+0.197

With ten conditions tested at n = 16, |t| ≈ 2.1 is roughly what chance produces, so the two apparently significant negatives should be read as "suspicious", not "established". The defensible summary is: no checkpoint is better than the base model, and the extremes look worse.

One counter-signal worth naming: step1504 has the highest genuineness of any condition (+0.197, t +1.90) while having the worst DNSMOS. If that survives a listening test it would matter, because genuineness is closer to what a voice-acting model is for than DNSMOS is. It has not been listening-tested.

The preference task is solved by step 376: accuracy hits 1.0000 and validation loss goes flat. Everything after that inflates the margin without learning anything.

steppref. accuracyval lossreward(chosen)reward(rejected)
1880.99030.8111+8.57+1.39
3761.00000.7442+13.67+0.70
5641.00000.7406+17.00+0.12
7521.00000.7385+21.56−0.92
9401.00000.7365+26.32−2.74
11281.00000.7354+28.81−4.03
13161.00000.7350+29.68−4.52
15041.00000.7349+29.91−4.70

reward(chosen) more than doubles from step 376 to the end at constant accuracy — about 1.0 nat per token of drift away from the supervised reference model, for nothing.

A warning for anyone selecting checkpoints by validation loss: for DPO a lower validation loss just means a larger margin, so that criterion prefers the most aggressive checkpoint by construction. It is not a quality criterion. Every checkpoint here was preserved specifically because the trainer's own pruning would have discarded the early ones.

How it was trained#

baselaion/moss-tts-local-transformer-4.55b-voice-acting-v2-sft3
initialised fromlaion/moss-va-sft3-rate-lora (536 tensors, load asserted) — one rank-16 adapter carrying both stages rather than two that must be stacked
data24,379 preference pairs, chosen = SIDON-repaired take, rejected = the same raw take
objectiveDPO, β 30, length-normalised, NLL anchor 0.013 (keeps the policy from suppressing the chosen sequences along with the rejected ones)
schedule2 epochs, 1,504 updates, lr 1e-6, 10 % warmup, 4 pairs per device × 4 GPUs
hardware4 GPUs, 1 h 25 min

Inference#

⚠️ Never merge this adapter into the base weights. Its target modules include audio_lm_heads.0 … audio_lm_heads.11, whose tensors share storage with audio_embeddings.N.weight (weight tying). Merging corrupts the embedding table irrecoverably.

import torch
from transformers import AutoConfig, AutoModel, AutoProcessor
from peft import PeftModel

BASE = "laion/moss-tts-local-transformer-4.55b-voice-acting-v2-sft3"
dev = "cuda:0"

proc = AutoProcessor.from_pretrained(BASE, trust_remote_code=True)
proc.audio_tokenizer = proc.audio_tokenizer.to(dev).eval()
cfg = AutoConfig.from_pretrained(BASE, trust_remote_code=True)
base = AutoModel.from_pretrained(BASE, trust_remote_code=True,
                                 dtype=torch.bfloat16,
                                 attn_implementation="sdpa").to(dev).eval()

model = PeftModel.from_pretrained(base, "laion/moss-va-sft3-quality-dpo-lora",
                                  adapter_name="qual").to(dev).eval()
# do NOT call model.merge_and_unload()

batch = proc([[{"role": "user", "content": prompt, "audio_codes_list": []}]],
             mode="generation")
out = model.generate(input_ids=batch["input_ids"].to(dev),
                     attention_mask=batch["attention_mask"].to(dev).to(torch.bool),
                     max_new_tokens=340, do_sample=True,
                     temperature=1.0, top_p=0.95, top_k=50)

Pick a different checkpoint with subfolder:

model = PeftModel.from_pretrained(base, "laion/moss-va-sft3-quality-dpo-lora",
                                  subfolder="checkpoints/step1504",
                                  adapter_name="qual")

Adapter strength (base scaling is α/r = 32/16 = 2.0; all measurements used w = 1.0):

for module in model.modules():
    scaling = getattr(module, "scaling", None)
    if isinstance(scaling, dict) and "qual" in scaling:
        module.scaling["qual"] = 2.0 * w

Prompt format#

Trained under prompt format hash 090c4ca315519a57 (inherited from the rate stage). A duration-only script is byte-identical to the project's standard 073aeb09dc923376, so ordinary prompts work unchanged.

Checkpoints#

checkpoints/step{188,376,752,1128,1504} — exactly the five that were evaluated above. Nothing is published here without numbers. The root copy is step376.

Files

14 files · 825 MBWeights 825 MB (safetensors). Sizes and sha256 from the signed manifest.
Hide all 14 files with their sha256
FileSizesha256
.gitattributes1.52 KB11ad7efa24975ee4b0c3c3a38ed18737f0658a5f75a0a96787b576a78a023361
README.md12.0 KBc3d48021515470fb21d82483ec65b15e308f50ce2070f5498a77195797314f59
adapter_config.json1.66 KBeeaf5676e53643b978b2d6edf3117583b68293af7454d2750906f6e8b4311d7a
adapter_model.safetensors138 MB1124939ca90a955f3d859edc6c301de9d7ae8284bca9b764d7617c9500408580
checkpoints/step1128/adapter_config.json1.66 KBeeaf5676e53643b978b2d6edf3117583b68293af7454d2750906f6e8b4311d7a
checkpoints/step1128/adapter_model.safetensors138 MBd436bdaa2122f624ba7ed17aa1cb77c51a8810fefa254520f0393fa774cf4083
checkpoints/step1504/adapter_config.json1.66 KBeeaf5676e53643b978b2d6edf3117583b68293af7454d2750906f6e8b4311d7a
checkpoints/step1504/adapter_model.safetensors138 MB44c12a5c40c52d9865c82b7bff7224f924fcbf5f940d20094870db70470b5702
checkpoints/step188/adapter_config.json1.66 KBeeaf5676e53643b978b2d6edf3117583b68293af7454d2750906f6e8b4311d7a
checkpoints/step188/adapter_model.safetensors138 MBe4fb7228f9925304b1a055b61b82daed5fd09661eee14c42f492ae72772f6282
checkpoints/step376/adapter_config.json1.66 KBeeaf5676e53643b978b2d6edf3117583b68293af7454d2750906f6e8b4311d7a
checkpoints/step376/adapter_model.safetensors138 MB1124939ca90a955f3d859edc6c301de9d7ae8284bca9b764d7617c9500408580
checkpoints/step752/adapter_config.json1.66 KBeeaf5676e53643b978b2d6edf3117583b68293af7454d2750906f6e8b4311d7a
checkpoints/step752/adapter_model.safetensors138 MB41a5bfcf4638d40d7c2e1002da7e4f3e7944b5d861d5d308af9d33934c145b11
VersionsEach time the pinned upstream commit or file list changed in this repo. Newest first.
Upstream commitDateContents
5b0ab699b6 pinned now2026-11-15 05:28 UTC14 files · 825 MB

Use it

$ fw get laion/moss-va-sft3-quality-dpo-lora
# manifest sha256 f7b50414bcec… · 825 MB · 14 files
$ fw verify ./moss-va-sft3-quality-dpo-lora laion/moss-va-sft3-quality-dpo-lora
fw.pyChecks the signature and every sha256, tries each source in order, resumes.
$ python3 fw.py get https://freeweights.allternit.com/manifests/laion/moss-va-sft3-quality-dpo-lora.json --dir ./moss-va-sft3-quality-dpo-lora $ python3 fw.py verify ./moss-va-sft3-quality-dpo-lora ./laion__moss-va-sft3-quality-dpo-lora.json
hfThe Hugging Face CLI with one setting. Same repo id.
$ HF_ENDPOINT=https://freeweights.allternit.com hf download laion/moss-va-sft3-quality-dpo-lora --revision 5b0ab699b686636e9500f93d4414e4d888b4a8fa --local-dir ./moss-va-sft3-quality-dpo-lora

License

Name
Apache License 2.0
Id
Apache-2.0
Class
Permissive
Redistribution
yes
Listing
Hosted (signed)
Decided
License as declared by the publisher. No person read it. 2026-11-15
Text in
README.md
Text sha256
c3d48021515470fb21d82483ec65b15e308f50ce2070f5498a77195797314f59
Terms gate
No extra terms beyond the license.

Read the license text

Licenses are checked against the license table. A custom license passes only after a person reads it.

Provenance

From: laion <huggingface.co/laion>Newsgroups: alt.freeweights.speechSubject: moss-va-sft3-quality-dpo-loraDate: 2026-11-15Commit: 5b0ab69Signed: 2DC28CC7B26A283B ✓
Upstream
laion/moss-va-sft3-quality-dpo-lora
Pinned commit
5b0ab699b686636e9500f93d4414e4d888b4a8fa
Manifest
moss-va-sft3-quality-dpo-lora.json · .minisig
Manifest sha256
f7b50414bcec5036755c8c2589c76f422a4957054117c4779e48f7b9be0320c9
Signature
minisign, Ed25519, key 2DC28CC7B26A283B
Created
2026-11-15 05:28 UTC
Generator
freeweights-manifest/0.1.0
Takedowns
None.

How to verify

$ curl -O https://freeweights.allternit.com/manifests/laion/moss-va-sft3-quality-dpo-lora.json $ curl -O https://freeweights.allternit.com/manifests/laion/moss-va-sft3-quality-dpo-lora.json.minisig $ minisign -Vm moss-va-sft3-quality-dpo-lora.json -P RWQ7KGqyx4zCLXtUFOqvfv8L3g+8fpKJ1FsuxPyOYMF+4KufbUxKq1Oq $ shasum -a 256 <file> # compare with the Files tab

A manifest whose signature fails must be rejected. A file whose size or sha256 does not match must be discarded. Verify a download

Model tree

No model in the catalog names this one as its parent.

Get it
Download
$ HF_ENDPOINT=https://freeweights.allternit.com hf download laion/moss-va-sft3-quality-dpo-lora
Open in Freeweights Studio

Pull, verify and run it in the Allternit app on Desktop, web or phone.

Signed manifest
minisign, key 2DC28CC7B26A283B. moss-va-sft3-quality-dpo-lora.json. Provenance. Takedown history: none.
From: MIT <huggingface.co/MIT>Subject: ast-finetuned-audioset-10-10-0.4593
From: onnx-community <huggingface.co/onnx-community>Subject: ast-finetuned-audioset-10-10-0.4593-ONNX
From: Edge0 <huggingface.co/Edge0>Subject: Audio8-TTS-Preview-0.6b
From: Edge0 <huggingface.co/Edge0>Subject: Audio8-TTS-Realistic-Air
From: facebook <huggingface.co/facebook>Subject: audiobox-aesthetics
From: mlx-community <huggingface.co/mlx-community>Subject: chatterbox-4bit