use std::num::NonZeroU32;
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct AttnTemperature {
pub scale: f32,
pub floor_scale: NonZeroU32,
pub offset: f32,
pub unrotated_layers_only: bool,
}
impl AttnTemperature {
#[inline]
pub fn scale_at(self, pos: usize) -> f32 {
let pos = pos as f32;
let floored = ((pos + self.offset) / (self.floor_scale.get() as f32)).floor();
((f64::from(floored) + 1.0).ln() * f64::from(self.scale) + 1.0) as f32
}
pub fn apply_rows(self, q: &mut [f32], q_width: usize, pos_of_row: impl Fn(usize) -> usize) {
for (b, row) in q.chunks_mut(q_width).enumerate() {
let s = self.scale_at(pos_of_row(b));
if s != 1.0 {
for v in row.iter_mut() {
*v *= s;
}
}
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FloorSource {
OrigCtxYarn,
TemperatureLengthKey,
}
pub const ATTN_TEMPERATURE_READERS: &[(&str, FloorSource, &str)] = &[
(
"mistral3",
FloorSource::OrigCtxYarn,
"src/models/mistral3.cpp:5,14-17,153-156",
),
(
"deepseek2",
FloorSource::TemperatureLengthKey,
"src/models/deepseek2.cpp:46-49,595-598,632-635",
),
(
"mistral4",
FloorSource::TemperatureLengthKey,
"src/models/models.h:1311-1318 (reuses deepseek2's hparams and graph)",
),
];
pub const LITERAL_ATTN_TEMPERATURE: &[(&str, AttnTemperature, &str)] = &[(
"llama4",
AttnTemperature {
scale: 0.1,
floor_scale: NonZeroU32::new(8192).unwrap(),
offset: 1.0,
unrotated_layers_only: true,
},
"src/models/llama4.cpp:15-17,175-176",
)];
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct DeclaredTemperature {
pub scale: Option<f32>,
pub length: Option<u64>,
pub n_ctx_orig_yarn: Option<u64>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AttnTemperatureError {
ZeroFloor(FloorSource),
FloorTooLarge(u64),
}
impl AttnTemperatureError {
pub fn message(&self, arch: &str) -> String {
match self {
AttnTemperatureError::ZeroFloor(FloorSource::OrigCtxYarn) => format!(
"`{arch}.attention.temperature_scale` is nonzero but the floor it divides \
positions by -- `{arch}.rope.scaling.original_context_length`, else \
`{arch}.context_length` (llama-model.cpp:1164-1165) -- is zero or absent; \
llama.cpp refuses the same file (`invalid n_ctx_orig_yarn for attention \
temperature scaling`, src/models/mistral3.cpp:16-17)"
),
AttnTemperatureError::ZeroFloor(FloorSource::TemperatureLengthKey) => format!(
"`{arch}.attention.temperature_scale` is nonzero but \
`{arch}.attention.temperature_length` is zero or absent; llama.cpp reads \
the floor from that key (src/models/deepseek2.cpp:47) and aborts on a zero \
one at the first batch (llama-graph.cpp:160)"
),
AttnTemperatureError::FloorTooLarge(v) => format!(
"`{arch}`'s attention-temperature floor {v} does not fit the uint32 \
llama.cpp stores `n_attn_temp_floor_scale` in"
),
}
}
}
pub fn resolve_attn_temperature(
arch: &str,
declared: DeclaredTemperature,
) -> Result<Option<AttnTemperature>, AttnTemperatureError> {
if let Some((_, literal, _)) = LITERAL_ATTN_TEMPERATURE
.iter()
.find(|(name, _, _)| *name == arch)
{
return Ok(Some(*literal));
}
let Some((_, floor_source, _)) = ATTN_TEMPERATURE_READERS
.iter()
.find(|(name, _, _)| *name == arch)
else {
return Ok(None);
};
let scale = match declared.scale {
Some(s) if s != 0.0 => s,
_ => return Ok(None),
};
let floor = match floor_source {
FloorSource::OrigCtxYarn => declared.n_ctx_orig_yarn,
FloorSource::TemperatureLengthKey => declared.length,
}
.unwrap_or(0);
let floor = u32::try_from(floor).map_err(|_| AttnTemperatureError::FloorTooLarge(floor))?;
let floor_scale =
NonZeroU32::new(floor).ok_or(AttnTemperatureError::ZeroFloor(*floor_source))?;
Ok(Some(AttnTemperature {
scale,
floor_scale,
offset: 0.0,
unrotated_layers_only: false,
}))
}
#[cfg(test)]
mod tests {
use super::*;
fn temp(scale: f32, floor: u32) -> AttnTemperature {
AttnTemperature {
scale,
floor_scale: NonZeroU32::new(floor).unwrap(),
offset: 0.0,
unrotated_layers_only: false,
}
}
#[test]
fn llama4_takes_its_literals_and_ignores_a_declared_key() {
let declared = DeclaredTemperature {
scale: Some(0.5),
length: Some(16),
n_ctx_orig_yarn: Some(16),
};
let got = resolve_attn_temperature("llama4", declared)
.unwrap()
.expect("llama4 always scales");
assert_eq!(got, LITERAL_ATTN_TEMPERATURE[0].1);
assert!(got.unrotated_layers_only);
assert_eq!(got.scale_at(8190), 1.0);
assert!(got.scale_at(8191) > 1.0);
for (name, _, _) in ATTN_TEMPERATURE_READERS {
assert!(
!LITERAL_ATTN_TEMPERATURE.iter().any(|(n, _, _)| n == name),
"{name} reads a key and cannot also seed a literal"
);
}
}
#[test]
fn the_scale_steps_at_every_floor_boundary_and_is_one_before_the_first() {
let t = temp(0.5, 2);
for pos in 0..2 {
assert_eq!(t.scale_at(pos), 1.0, "position {pos} is below the floor");
}
for pos in 2..4 {
let want = (2f64.ln() * 0.5 + 1.0) as f32;
assert_eq!(t.scale_at(pos), want, "position {pos} is on period 1");
}
for pos in 4..6 {
let want = (3f64.ln() * 0.5 + 1.0) as f32;
assert_eq!(t.scale_at(pos), want, "position {pos} is on period 2");
}
assert!(t.scale_at(5) > t.scale_at(3) && t.scale_at(3) > t.scale_at(1));
}
#[test]
fn the_offset_moves_the_step_by_one_position() {
let no_offset = temp(0.1, 8192);
let llama4 = AttnTemperature {
offset: 1.0,
..no_offset
};
assert_eq!(no_offset.scale_at(8191), 1.0);
assert!(llama4.scale_at(8191) > 1.0, "llama4 steps at 8191");
assert_eq!(llama4.scale_at(8191), no_offset.scale_at(8192));
}
#[test]
fn apply_rows_scales_each_row_by_its_own_position() {
let t = temp(0.5, 2);
let mut q = vec![1.0f32; 3 * 4];
let positions = [1usize, 2, 5];
t.apply_rows(&mut q, 4, |b| positions[b]);
assert_eq!(&q[..4], &[1.0; 4], "position 1 is untouched");
for v in &q[4..8] {
assert_eq!(*v, t.scale_at(2));
}
for v in &q[8..] {
assert_eq!(*v, t.scale_at(5));
}
assert_ne!(
q[4], q[8],
"the two scaled rows must differ, or this saw one scale"
);
}
#[test]
fn every_key_driven_reader_resolves_to_a_temperature() {
for (arch, source, line) in ATTN_TEMPERATURE_READERS {
let declared = DeclaredTemperature {
scale: Some(0.25),
length: Some(64),
n_ctx_orig_yarn: Some(4096),
};
let got = resolve_attn_temperature(arch, declared)
.unwrap_or_else(|e| panic!("{arch} ({line}): {e:?}"))
.unwrap_or_else(|| panic!("{arch} ({line}) reads the key and must resolve"));
let want_floor = match source {
FloorSource::OrigCtxYarn => 4096,
FloorSource::TemperatureLengthKey => 64,
};
assert_eq!(got.floor_scale.get(), want_floor, "{arch}'s floor source");
assert_eq!(got.scale, 0.25);
assert_eq!(got.offset, 0.0);
}
}
#[test]
fn a_nonzero_key_on_an_architecture_whose_graph_never_reads_it_is_dead_metadata() {
let declared = DeclaredTemperature {
scale: Some(0.5),
length: Some(64),
n_ctx_orig_yarn: Some(4096),
};
for arch in ["llama", "qwen3", "gemma3", "olmo2", "granite", "smollm3"] {
assert_eq!(
resolve_attn_temperature(arch, declared),
Ok(None),
"{arch} has no build_inp_attn_scale in src/models/"
);
}
}
#[test]
fn a_zero_or_absent_scale_is_no_temperature() {
for scale in [None, Some(0.0)] {
let declared = DeclaredTemperature {
scale,
length: Some(64),
n_ctx_orig_yarn: Some(4096),
};
assert_eq!(resolve_attn_temperature("mistral3", declared), Ok(None));
assert_eq!(resolve_attn_temperature("deepseek2", declared), Ok(None));
}
}
#[test]
fn each_reader_takes_its_own_floor_and_refuses_the_other_ones() {
let only_length = DeclaredTemperature {
scale: Some(0.5),
length: Some(64),
n_ctx_orig_yarn: None,
};
assert_eq!(
resolve_attn_temperature("mistral3", only_length),
Err(AttnTemperatureError::ZeroFloor(FloorSource::OrigCtxYarn))
);
let only_ctx = DeclaredTemperature {
scale: Some(0.5),
length: None,
n_ctx_orig_yarn: Some(4096),
};
assert_eq!(
resolve_attn_temperature("deepseek2", only_ctx),
Err(AttnTemperatureError::ZeroFloor(
FloorSource::TemperatureLengthKey
))
);
let zero_len = DeclaredTemperature {
length: Some(0),
..only_length
};
assert_eq!(
resolve_attn_temperature("deepseek2", zero_len),
Err(AttnTemperatureError::ZeroFloor(
FloorSource::TemperatureLengthKey
))
);
let msg = AttnTemperatureError::ZeroFloor(FloorSource::OrigCtxYarn).message("mistral3");
assert!(
msg.contains("mistral3.rope.scaling.original_context_length"),
"{msg}"
);
assert!(msg.contains("mistral3.cpp:16-17"), "{msg}");
let msg =
AttnTemperatureError::ZeroFloor(FloorSource::TemperatureLengthKey).message("deepseek2");
assert!(
msg.contains("deepseek2.attention.temperature_length"),
"{msg}"
);
}
}