A companion to the MOSS voice-acting technical report. Hidden states were extracted from the model while it followed real recordings; probes were trained to read five different things out of them; the resulting directions were then injected back into generation to see whether the model could be steered. The probes found a clear, stable, replicated ordering. The steering destroyed the output at every strength tested, and this page reports that as the result it is.
The one-paragraph version. Voice quality is almost fully recoverable from a single middle layer — macro R² 0.82 over 57 VoiceNet dimensions, against 0.20 for a probe that sees only metadata. Genuineness reaches 0.67, vocal-burst blend 0.50, and the 40 emotion scores 0.43. Every one of those peaks between layer 12 and layer 23 of a 36-layer stack; the embeddings are the worst tap for four of the five, and nothing peaks at the top. By the time the representation reaches the acoustic decoder, 39 % of the decodable emotion variance is gone. Injecting the probe directions during generation destroys the output at every strength tried: word error rate goes from 0.094 unsteered to 1.14 at the smallest non-zero strength, and the one condition that looks like a success is the scoring models saturating on 13.76 seconds of unintelligible audio.
The main report's central unresolved problem is that the model will not perform an emotion at a requested intensity. Ask for the 90th-to-98th percentile of a named emotion and it delivers something around the 35th. Four training objectives have been aimed at that gap and none of them moved it. Before spending compute on a fifth, there is a prior question, and it splits in two:
Question 1 is answered by probing: freeze the model, collect one hidden-state vector per clip, train a small supervised model to predict an attribute from that vector alone. If the attribute can be read out, it is present. Question 2 is answered by taking the direction and injecting it. Both were run. The answers are, respectively, largely yes, and it depends sharply on which attribute, and no.
One forward pass per corpus row, teacher-forced: the row's own audio codes are placed on the assistant side and the whole example is packed byte-identically to how the supervised trainer packs a training example. Nothing is generated and nothing is re-scored — the extraction code says so in its own docstring, in those words. The model is reading a real recording.
From that pass, a window of frames is averaged: from 80 % of the way through the assistant audio span to its end, capped at 100 frames (8.0 s at 12.5 frames per second) and floored at 8 frames for short clips. The tail of the utterance was chosen on the reasoning that whatever summary the model has assembled of the performance is most complete there.
The averaged state is kept at 38 taps:
| Tap | What it is |
|---|---|
h00 | The embedding output, before any transformer layer. |
h01…h35 | The output of each of the 35 transformer layers that carry a tap. |
h36 | The final norm. In this checkpoint the projection from the global
stack into the local one is the identity, so h36 is also the 80-millisecond
vector handed to the acoustic decoder — the two coincide, which is what makes §6
possible. |
loc | The frame-slot state of the one-layer local transformer that the
twelve audio heads actually read. It is genuinely a distinct object rather than a copy of
h36: the cosine between them is 0.156. |
Each tap is a 2,560-dimensional vector. Storage is float16 and tap-major — one
[N, 2560] array per tap rather than one array per row — because every downstream
operation reads one tap across all rows and none reads one row across all taps.
| Extraction | Rows | Size | What it is |
|---|---|---|---|
main | 58,377 | 11.36 GB | The primary split: clips drawn from the emotion and VoiceNet buckets |
p3 | 217,583 | 42.33 GB | The large extraction, from which the steering vectors are built |
pairs | 53,325 | 10.37 GB | Rows drawn from the preference corpus, for contrast directions |
neutral | 58,714 | 11.42 GB | A separate extraction on neutral-direction rows, used as a replication set |
| total | 387,999 | 75.49 GB | float16, tap-major. The containing directory is 144 GB; 75.5 GB is the tap tensors alone. |
These are teacher-forced activations, conditioned on a ground-truth audio prefix. A high probe score answers “is this attribute linearly present in layer L while the model follows a real recording”. It does not answer “does the model use this information when it generates on its own”. Those are different questions, and §10 is what happens when the second one is put directly.
The model under the taps is the SFT-3 export with the best preference adapter attached and
never merged — base out/sft3/export, adapter
out/dpo_sft3_p2/ckpt-step5022/adapter, 36 layers, hidden size 2,560. Those are the
artefacts published as
…-v2-sft3
and laion/moss-va-sft3-dpo-lora-p2.
(Merging is not an option here for the reason the main report gives in §17.2: the audio heads
are weight-tied to the audio embeddings.)
The results were originally reported by task letter, and the letters were not defined anywhere in
the released artefacts — a gap serious enough that the project's 28 August status record listed
“recover the A–E mapping before any of these numbers are quoted” as an open task. They
were recovered from actf_probe.py::build_targets, and every definition below is that
function's own.
| Task | Target | Outputs | ntest |
|---|---|---|---|
| A | The z-scored raw score of the one emotion head or
VoiceNet axis that this clip's bucket was built around. A clip drawn from the Anger bucket is scored
on emo_Anger; one from the S_WHIS-bottom bucket on vn_S_WHIS.
Standardised within each dimension on the training split, so the scales are comparable. |
1 | 6,203 |
| B | All 40 emotion scores at once — the raw output of every Empathic-Insight emotion head on this clip, each z-scored. Macro R² is the mean over the 40 heads. | 40 | 7,975 |
| C | All 57 VoiceNet dimensions at once — arousal, valence, tension, pace, timbre, clarity, breathiness, the style axes — each z-scored. | 57 | 7,975 |
| D | Genuineness: one number, the project's 0–6 measure of whether a performance sounds authentic rather than acted, z-scored. | 1 | 7,975 |
| E | Vocal-burst blend: one number, the 0–10 measure of how naturally a non-speech vocalisation is woven into the surrounding speech, z-scored. | 1 | 7,975 |
This is worth stating carefully because getting it backwards is the source of the error in §8. The primary split is by voice: no clip identifier and no speaker appears in both the training and the test half. That is the strong condition, and it is the default. A second run uses a uid-only split, where clips are disjoint but a speaker may appear on both sides — the weaker control. The gap between the two is the measurement of how much a probe is reading speaker identity rather than the attribute.
That gap is below 0.007 R² on four of the five tasks. The exception is Task D, where the uid-only split scores +0.062 higher — genuineness is partly a speaker property, which is unsurprising and is exactly what the control exists to reveal.
Two further checks were run. The neutral extraction repeats everything on a
different set of rows. And a caption control removes the emotion caption from the
prompt before extraction, to test whether the probe is reading the model's own instruction back out
rather than anything about the audio: stripping it costs at most 0.015 R², under 3.4 %
relative, on every task. The probes are reading the performance, not the prompt.
There is also a Task A2 in the same function — Task A with the question supplied
to the input as a one-hot of the assigned dimension — built specifically to measure what the missing
conditioning is worth. No A2 results exist. answers.json carries keys
A–E only and the layer ranking's task column holds only A…E. The
experiment was defined and queued and its numbers were never produced. It is the single most
informative missing number in this line of work, for the reason §7 sets out.
Best tap and macro R² under the MLP probe on the primary voice-disjoint split, ordered by result. The metadata-only baseline is the same probe trained on the row's metadata alone — speaker, language, duration — with no activations at all. It is the number to beat before any claim about the representation can be made.
| Task | What it reads | Best tap | Macro R² | Metadata-only | Ridge, same split |
|---|---|---|---|---|---|
| C | 57 VoiceNet dimensions | h12 | 0.8159 | 0.2042 | 0.7640 (h13) |
| D | genuineness | h23 | 0.6685 | 0.1965 | 0.5999 (h20) |
| E | vocal-burst blend | h22 | 0.4972 | 0.1049 | 0.4295 (h20) |
| B | 40 emotion scores | h20 | 0.4328 | 0.0507 | 0.4140 (h20) |
| A | the selected dimension's own score | h14 | 0.1321 | 0.0254 | 0.1327 (h21) |
| Probe / split | Peak tap | Macro R² |
|---|---|---|
| MLP probe, primary (voice-disjoint) split | h12 | 0.8159 |
| Ridge, same split | h13 | 0.7640 |
| uid-only split | h12 | 0.8154 |
| Neutral extraction | h12 | 0.8138 |
| Metadata-only baseline | — | 0.2042 |
This is the clearest result in the set and by far the most robust: the same peak tap and essentially the same number under four conditions, including one where no speaker is shared between training and test. The whole 57-dimension VoiceNet description of a clip is recoverable from one mid-stack layer at R² 0.82, and even the worst of the 57 dimensions reaches 0.675. It peaks earliest of the five, at h12, and is already at 0.39 in the embeddings. Timbre, pace and clarity are low-level properties; they are encoded early and they stay encoded.
It is also one of only two tasks whose peak resolves to a single layer rather than a band: h12's margin over its runner-up h26 is t = 10.38.
| Probe / split | Peak tap | Macro R² |
|---|---|---|
| MLP probe, primary (voice-disjoint) split | h23 | 0.6685 |
| Ridge, same split | h20 | 0.5999 |
| uid-only split | h20 | 0.7309 |
| Neutral extraction | h18 | 0.6712 |
| Metadata-only baseline | — | 0.1965 |
“Does this sound like a person rather than a reading?” is not an abstract judgement the model assembles at the top of the stack. It is legible in the middle, at R² 0.67 against a metadata baseline of 0.20. Two properties are specific to this task. It has the largest gap between the MLP probe and ridge of any task — 0.67 against 0.60 — so the encoding is real but not linear. And it is the only task where relaxing the split from voice-disjoint to uid-only buys a material gain (+0.062), which says that part of what a genuineness probe reads is who is speaking. Both matter for §10: a linear intervention is the wrong instrument for an attribute that a linear read-out recovers worst.
| Probe / split | Peak tap | Macro R² |
|---|---|---|
| MLP probe, primary (voice-disjoint) split | h22 | 0.4972 |
| Ridge, same split | h20 | 0.4295 |
| uid-only split | h18 | 0.4670 |
| Neutral extraction | h21 | 0.5081 |
| Metadata-only baseline | — | 0.1049 |
Blend peaks at h22, the latest peak of any task, and reaches only 0.50. Whether a sigh is woven in naturally is evidently a more distributed property than either voice quality or genuineness — consistent with what the quantity means, since it depends on the relation between a burst and the speech around it rather than on either alone. It is also the only task where the neutral extraction scores higher than the primary one, and the only one whose worst tap is h01 rather than the embeddings.
| Probe / split | Peak tap | Macro R² |
|---|---|---|
| MLP probe, primary (voice-disjoint) split | h20 | 0.4328 |
| Ridge, same split | h20 | 0.4140 |
| uid-only split | h18 | 0.4394 |
| Neutral extraction | h21 | 0.4224 |
| Metadata-only baseline | — | 0.0507 |
The macro R² of 0.43 against a metadata baseline of 0.05 says the representation carries far more about emotion than speaker and length do. But the spread across the 40 heads runs from 0.181 to 0.666. Some emotions are written clearly into the activations and others are barely there at all — the same asymmetry the generation-side work keeps finding, arriving this time from the inside. h18 is a statistical tie with the h20 peak (t = 1.08), so Task B's location should be read as “h18–h20” rather than as one layer.
The comparison that matters is C against B. Under one probe, on one model, at one capture window: how a voice sounds is recoverable at 0.82 and what it feels at 0.43, against metadata baselines of 0.20 and 0.05. The main report's running finding — that this model line controls timbre, pace and timing far better than it controls affect — has an internal correlate. That is not proof of a causal story; a representation can be legible and unused, which is exactly what §10 goes on to demonstrate. But it is the first evidence for that finding that does not come from generating audio and scoring it.
h00 — the embeddings — is the worst tap for four of the
five (E's worst is h01). Nothing peaks at the top of the network.Because the projection from the global stack into the local one is the identity in this
checkpoint, the final tap h36 is the vector handed to the acoustic decoder.
That makes one comparison available that is otherwise hard to get:
On Task B, h36 retains 0.262 against 0.433 at h20.
39 % of the decodable emotion variance is gone by the time the representation reaches the
decoder.
That is a single number and it should not be asked to carry more than it can. It does not establish that the loss causes the intensity ceiling — a decoder does not need a linearly decodable copy of an attribute in order to realise it, and 0.262 is still five times the metadata baseline. What it does say is that the emotion representation is at its strongest in the middle of the stack and is substantially attenuated by the point where audio codes are actually chosen, while the VoiceNet representation peaks eight layers earlier and is what the model demonstrably controls best. It is the most concrete internal candidate this project has for the emotion/timbre asymmetry, and it is cheap to follow up: the same measurement on C, D and E is already on disk in the layer ranking and has not been pulled out.
Task A is the one task the probe essentially fails, and the code says why in its own comment: the question is not in the input. The probe is handed a hidden state and asked for a number, but nothing tells it which dimension is being asked about. A row drawn from the Anger bucket and a row drawn from the whisper-bottom bucket present the probe with two vectors and two targets on unrelated axes, and it has no way to tell which is which.
The decomposition confirms it. On the test split, 54.8 % of Task A's target variance sits between the three bucket families — emotion, VoiceNet-high, VoiceNet-low — whose identity the probe cannot see. And within each family the probe scores worse than that family's own mean: R² of −0.02, −5.46 and −4.32 respectively. A negative R² of −5.46 is not a weak result; it is a probe answering a question it was never given.
R² = 0.13 is therefore a statement about an under-specified question, not about the representation. The strongest evidence that it is the question and not the model: Task B asks for all 40 emotion scores at once from the same activations and reaches 0.43.
This is exactly what Task A2 was written to measure, and A2 was never run. Task A should not be quoted as a result, and it is on this page only so that a reader who meets the number elsewhere knows what it is.
Two internal records report the probe table with different numbers for tasks B and D. The cause has been found, and it is worth publishing because it is a mistake that is easy to make and invisible without the source data.
| Task | Internal probe write-up | 28 August status record | Correct, from answers.json |
|---|---|---|---|
| A | 0.1321 · h14 | 0.132 · h14 | 0.1321 · h14 |
| B | 0.4394 · h18 | 0.433 · h20 | 0.4328 · h20 |
| C | 0.8159 · h12 | 0.816 · h12 | 0.8159 · h12 |
| D | 0.7309 · h20 | 0.669 · h23 | 0.6685 · h23 |
| E | 0.4972 · h22 | 0.497 · h22 | 0.4972 · h22 |
The write-up's B and D figures are the uid-split values reported as if they were the primary result. The tell is visible in the write-up itself: for exactly those two tasks its “main split” row and its second row are byte-identical, which cannot happen if they are two different splits. Two related errors travel with it — that page states ntest = 8,673 for B and D, which is the uid-split test-set size rather than the primary 7,975; and it labels the second row “speaker-disjoint split” when in fact the primary split is the speaker-disjoint one and the second is the weaker uid-only control.
The status record's numbers were right and were distrusted, because the status record also — and
correctly — said that the A–E mapping had not yet been recovered from the artefacts, and a table
whose row labels are unknown invites the assumption that its values are unreliable too. They were
not. The values used on this page are the primary-split values from
answers.json, cross-checked against the layer-ranking parquet and the run's own report
page.
None of this changes any conclusion. Corrected, D falls from 0.73 to 0.67 and B from 0.44 to 0.43; the ordering, the middle-of-the-stack finding, the C-against-B comparison and the steering result all stand unchanged. It is recorded because the alternative — quietly using the right numbers — would leave two of this project's own pages disagreeing with no explanation.
A probe direction is a vector in the 2,560-dimensional space of one tap. The vectors used here are difference-of-means directions rather than probe weights, which is the more common and more robust construction: take the mean activation of clips that are high on a dimension, subtract the mean of clips that are low, and the difference points from one to the other.
For each of 97 dimensions — the 40 emotion heads plus the 57 VoiceNet axes — and each of the 38
taps, three buckets are drawn: top1 (the top 1 % on the corpus percentile scale),
bot1 (the bottom 1 %) and mid (the 5–10 % slice). From those,
d_hi_lo, d_hi_mid and d_mid_lo.
Within each bucket, rows are sorted by mean quality — the average of the genuineness and blend percentiles — and cut at 2,000. The reason is the main report's §13.1 finding: the most intense recordings are on average the least genuine, with median genuineness percentile falling from 0.391 in the top 10 % of a head to 0.360 in the top 1 %. Without the cut, an “intensity” direction would be substantially a “bad recording” direction.
The vector code states the price of the fix in the same breath, which is the right way to record
a trade: mean(top1) − mean(bot1) is now a difference of two quality-matched
extremes, not of two raw extremes. Something real was removed along with the confound.
Two further vectors exist for the same reason. A quality vector
d_qual — the mean of the 2,000 highest-quality rows of the whole p3
extraction minus the mean of the 2,000 lowest — and an orthogonalised dimension
vector d_dim_orth, which is d_hi_lo with its quality component projected
out.
That orthogonalisation is not a formality. Measured:
| Direction pair | Signed cosine | What it means |
|---|---|---|
emotion d_hi_lo vs d_qual, at h20 | −0.75 | Moving toward more of an emotion moves substantially away from higher measured quality. |
emotion d_hi_lo vs d_qual, at loc | −0.954 | At the frame slot the two are very nearly anti-parallel. |
VoiceNet d_hi_lo vs d_qual | +0.46 | The opposite sign: more of a VoiceNet axis goes with higher quality. |
This is the §13.1 finding restated as geometry, and it is sharper inside the model than outside it. The corpus observation was a correlation between two scores. This is a cosine of −0.954 between two directions in the very last state before audio codes are chosen: at that point, in this model, “more emotional” and “more genuine” are close to opposite instructions. Any method that pushes on emotional intensity without controlling for it is pushing on quality in the wrong direction, and that includes every merge-weight sweep and every reward term in the main report. It is the strongest available argument for the quality gate that §13.1 imposes on training data, and it arrives from a completely different direction.
The injection rule is
h ← h + α · (v / ‖v‖) · ‖h‖
so α is dimensionless: it is the fraction of the current hidden state's own
magnitude added along the steering direction. α = 1 doubles the norm. Injection points are the taps
themselves — tap 0 into the input embeddings, taps 1–35 by a forward hook on the corresponding
layer, tap 36 into the last hidden state, and loc into the local transformer's state at
the frame slot only, not the eleven within-frame channel steps. Steering is applied during
generation only.
The grid is 393 clip records over 27 cells, each clip record being four sampled completions — 6 emotions × 2 languages × 4 samples per cell. Every clip is scored by the same instruments and the same harness as the rest of the project. The α = 0 control is shared across the grid and therefore carries 84 clip records rather than 12.
| α | Clip records | WER | Duration error | Emotion pct | Reward |
|---|---|---|---|---|---|
| −2.0 | 12 | 0.9941 | 9.54 s | 0.4033 | 0.2347 |
| −1.0 | 12 | 1.0760 | 2.58 s | 0.4833 | 0.2245 |
| −0.5 | 12 | 1.0623 | 0.68 s | 0.3959 | 0.2286 |
| 0 (control) | 84 | 0.0941 | 0.01 s | 0.4579 | 0.4925 |
| +0.5 | 12 | 1.1394 | 0.27 s | 0.4218 | 0.2425 |
| +1.0 | 12 | 1.0822 | 1.27 s | 0.3617 | 0.2266 |
| +2.0 | 12 | 0.9887 | 7.66 s | 0.3909 | 0.2196 |
At every non-zero strength, in both directions, the output collapses. Unsteered, the model transcribes at word error rate 0.094 and lands within 0.01 s of the length its own script asks for. At α = +0.5 — the smallest positive strength tried — the word error rate is already 1.14, which means the recogniser produces more errors than there are words in the script. The composite reward halves at every non-zero cell and never recovers. The emotion percentile does not rise: it is 0.458 unsteered and lower at +0.5, +1.0 and +2.0.
| Cell | Vector | Taps | α | WER | Duration error | Emotion pct |
|---|---|---|---|---|---|---|
| random control | rand | h20 | 0.5 | 0.9485 | 0.00 s | 0.3686 |
| random control | rand | h20 | 1.0 | 2.0654 | 0.04 s | 0.3978 |
| random control | rand | h20 | 2.0 | 0.9956 | 9.59 s | 0.3410 |
| quality-orthogonal | dim_orth | h20 | −1.0 | 1.1867 | 0.87 s | 0.2933 |
| quality-orthogonal | dim_orth | h20 | 1.0 | 1.1361 | 3.73 s | 0.3327 |
| quality-orthogonal | dim_orth | h20 | 2.0 | 1.0711 | 8.77 s | 0.2890 |
| two taps | dim | h20, h18 | 1.0 | 1.1205 | 4.80 s | 0.3943 |
| three taps | dim | h20, h18, h21 | 1.0 | 0.9900 | 11.54 s | 0.3020 |
| four taps | dim | + h19 | 1.0 | 0.9915 | 11.16 s | 0.3938 |
| five taps | dim | + h22 | 1.0 | 1.0495 | 6.14 s | 0.4810 |
| early layer | dim | h06 | 1.0 | 0.9978 | 13.03 s | 0.4774 |
| final norm | dim | h36 | 1.0 | 1.1522 | 0.26 s | 0.3506 |
| frame slot | dim | loc | 1.0 | 0.8626 | 1.32 s | 0.3746 |
| quality vector | qual | h22 | −1.0 | 1.1072 | 0.05 s | 0.2993 |
| quality vector | qual | h22 | 0.5 | 1.1620 | 2.99 s | 0.4957 |
| quality vector | qual | h22 | 1.0 | 1.0339 | 13.76 s | 0.5134 |
| quality vector | qual | h22 | 2.0 | 1.0297 | 13.76 s | 0.5482 |
| quality, two taps | qual | h22, h18 | 1.0 | 1.0754 | 13.76 s | 0.5120 |
| quality, three taps | qual | + h23 | 1.0 | 0.9903 | 14.25 s | 0.5015 |
| quality, five taps | qual | + h20, h24 | 1.0 | 0.9962 | 13.76 s | 0.5070 |
Tap order for the multi-tap stacks came from the ranking: the dimension vector
follows Task B's layer ordering (h20, h18, h21, h19, h22) and the quality vector follows Task E's
(h22, h18, h23, h20, h24). One cell (dim, five taps) lost one clip record to a
generation failure and carries 11 rather than 12.
The quality vector at α = 2.0 reports the highest emotion percentile of the grid (0.548) and, in the reward's own terms, a perfect 1.000 on both genuineness and vocal-burst blend. Read alone, that is a spectacular success. Read with its neighbours it is the opposite: the same clips transcribe at word error rate 1.030 and are 13.76 seconds away from their requested duration. What is being scored is not better speech.
And the “1.000” is worse than it looks, because it is a percentile reward term, not a score. The raw values at that cell are genuineness 1.31 out of 6 and blend 1.97 out of 10 — near the bottom of both scales. The percentile mapping, built on a corpus of speech, has no idea what to do with audio that is not speech, and it maps it to the top. Every quality-vector cell in the table, at every α and every tap stack, reports exactly 1.000 on both terms. That constancy is the giveaway.
This is the sharpest instance in the whole project of a measurement instrument being confidently wrong, and it is precisely the failure the main report's §16 was written about. A steering result reported on quality scores alone, without word-error and duration controls alongside, would have been published as a win.
The random-vector control is what makes the result clean. A random Gaussian direction of matched magnitude at α = 1.0 gives word error rate 2.065 — roughly twice as damaging as the probe direction at the same strength — so the probe directions are not merely noise; they do less damage than chance. But at α = 0.5 the random direction gives 0.949 against the dimension vector's 1.139, i.e. it is less damaging there, and its emotion percentiles (0.34–0.40) sit inside the same range as the real directions. No cell of the grid shows the dimension vector moving its own attribute in a way a matched random vector does not. That is the result.
The running protocol records an earlier reading of Phase 3 — “α = 1 at h20 raises
emo_pct by +0.075, but a random direction of the same magnitude raises it by
+0.135” — and correctly concludes from it that the causal claim is not established.
Those two figures come from the smoke test, taken when the full grid was still queued: the
aggregated artefacts under report/ hold one grid row and eight clips. The executed
grid, run the following evening into steer/*.jsonl, gives α = 1 at h20 an emotion
percentile of 0.362 against the control's 0.458 — a fall, not a rise — and the
random direction 0.398, also below control. The conclusion is unchanged and is if anything
stronger; only the supporting numbers move. The grid was never re-aggregated into the
report artefacts, so anything reading report/steer_grid.parquet is still reading the
smoke test. The tables above are aggregated from the raw per-clip records.
Four readings are consistent with the grid. They are not mutually exclusive and none is tested yet.
h36, the very last state, is one of the most damaging injection points
(WER 1.152) despite having the least network left to propagate through.d_hi_lo, d_qual) = −0.75 at h20 for emotion heads. Adding an emotion
direction is therefore substantially subtracting a quality direction, which is one concrete
mechanism for the degradation. The orthogonalised vector was built to test exactly this — and it
degrades the output too, at every α, so if this is part of the story it is not the whole of
it.Reading 1 is the cheapest to test; reading 3 is the most likely to be decisive. The practical conclusion for this project is narrower and firmer than any of them: activation steering is not currently a route to intensity control here, and the budget that would have gone into tuning it is better spent on the data-side levers the main report identifies.
h36 retention figure for C, D and E. The 39 % emotion
loss into the decoder is the most suggestive single number here, and the layer ranking already
contains everything needed to say whether the other four attributes survive the same journey better.
It costs no GPU time.pairs extraction. 53,325 rows were captured from the
preference corpus specifically so that a chosen-minus-rejected contrast direction could be built.
That direction is not in the grid above.report/steer_grid.parquet stops describing a smoke test.| Base model | out/sft3/export — published as
…-v2-sft3 |
| Adapter (stacked, never merged) | out/dpo_sft3_p2/ckpt-step5022/adapter —
published as laion/moss-va-sft3-dpo-lora-p2 |
| Shape | 36 layers, hidden 2,560; 38 taps per row |
| Capture window | from 80 % through the assistant audio span to its end, capped at 100 frames, floored at 8 |
| Extraction / consolidation | actf_extract.py, actf_consolidate.py |
| Task definitions | actf_probe.py::build_targets |
| Vector construction | actf_vectors.py; vectors at
vectors/p3_vectors.npz (97 dimensions × 38 taps × 2,560, plus the quality vector and
diagnostics) |
| Injection | actf_steer.py; executed grid plan
grids/prio_all.json (27 cells) |
| Probe results | report/answers.json, layer_ranking.parquet
(1,160 rows = 390 main/voice + 380 main/uid + 390 neutral/voice, where each 380 is 2 models ×
5 tasks × 38 taps and each 390 adds 10 baseline rows) |
| Steering results | steer/*.jsonl, 393 clip records over 27 cells. The
aggregated report/steer_grid.parquet is the earlier smoke test and should not be
read. |
| Activation taps on disk | 75.5 GB, float16, tap-major, out/actforensics/taps/
— not published. They encode the source corpus, and whether teacher-forced
activations of non-public recordings can be released, and under what licence, is unresolved. |
| Probe weights and steering vectors | 254 MB,
out/actforensics/{vectors,probe,probe2}/ — small and publishable |
Part of the MOSS voice-acting documentation set: the technical report · the trajectory corpus. Every number on this page was read from a named on-disk artefact; where two of this project's own records disagreed, §8 and §10 show both and say which is right and why.