Skip to main content

ftts_artifacts/
census.rs

1//! The load-time weights census: prove the checkpoint is the one we conformed against.
2//!
3//! A wrong or stale checkpoint that loads "successfully" does not fail loudly — it produces
4//! plausible-looking garbage audio hours later, and the bug gets blamed on a kernel. So every load
5//! is checked against an expected `(name, shape, dtype)` inventory and any divergence is a
6//! **named, itemized refusal** at load time.
7//!
8//! Three finding classes, all fatal by default:
9//!
10//! - [`Finding::Missing`] — we need a tensor the file does not have. Certain failure downstream.
11//! - [`Finding::ShapeMismatch`] / [`Finding::DtypeMismatch`] — the tensor exists but is not what we
12//!   compiled kernels for. This is the class that silently produces garbage rather than crashing.
13//! - [`Finding::Extra`] — the file has tensors we do not know about. Not dangerous on its own, but
14//!   it is the signature of a *different checkpoint* (a sibling size, a newer revision), which is
15//!   exactly what we want to catch before anyone spends a day debugging the audio.
16//!
17//! The expected inventory itself comes from the OQ-2 tensor census over the pinned weights; this
18//! module is the mechanism, not the data.
19
20use std::collections::BTreeMap;
21use std::fmt;
22
23use crate::safetensors::{Dtype, SafetensorsIndex};
24
25/// One tensor the manifest requires, as the OQ-2 inventory recorded it.
26#[derive(Clone, Debug, PartialEq, Eq)]
27pub struct ExpectedTensor {
28    /// Tensor name, exactly as it appears in the checkpoint directory.
29    pub name: String,
30    /// Required shape.
31    pub shape: Vec<usize>,
32    /// Required storage dtype.
33    pub dtype: Dtype,
34}
35
36impl ExpectedTensor {
37    /// Build an expectation.
38    #[must_use]
39    pub fn new(name: impl Into<String>, shape: impl Into<Vec<usize>>, dtype: Dtype) -> Self {
40        Self {
41            name: name.into(),
42            shape: shape.into(),
43            dtype,
44        }
45    }
46}
47
48/// How a checkpoint diverged from the manifest.
49#[derive(Clone, Debug, PartialEq, Eq)]
50pub enum Finding {
51    /// The manifest requires a tensor the checkpoint does not contain.
52    Missing {
53        /// Tensor name.
54        name: String,
55        /// Shape we required.
56        expected_shape: Vec<usize>,
57        /// Dtype we required.
58        expected_dtype: Dtype,
59    },
60    /// The tensor exists with the wrong shape.
61    ShapeMismatch {
62        /// Tensor name.
63        name: String,
64        /// Shape we required.
65        expected: Vec<usize>,
66        /// Shape the checkpoint declares.
67        actual: Vec<usize>,
68    },
69    /// The tensor exists with the wrong storage dtype.
70    DtypeMismatch {
71        /// Tensor name.
72        name: String,
73        /// Dtype we required.
74        expected: Dtype,
75        /// Dtype the checkpoint declares.
76        actual: Dtype,
77    },
78    /// The checkpoint contains a tensor the manifest does not mention.
79    Extra {
80        /// Tensor name.
81        name: String,
82        /// Shape the checkpoint declares.
83        shape: Vec<usize>,
84        /// Dtype the checkpoint declares.
85        dtype: Dtype,
86    },
87}
88
89impl Finding {
90    /// The tensor this finding is about.
91    #[must_use]
92    pub fn name(&self) -> &str {
93        match self {
94            Self::Missing { name, .. }
95            | Self::ShapeMismatch { name, .. }
96            | Self::DtypeMismatch { name, .. }
97            | Self::Extra { name, .. } => name,
98        }
99    }
100
101    /// Short, greppable class label.
102    #[must_use]
103    pub const fn class(&self) -> &'static str {
104        match self {
105            Self::Missing { .. } => "MISSING",
106            Self::ShapeMismatch { .. } => "SHAPE-MISMATCH",
107            Self::DtypeMismatch { .. } => "DTYPE-MISMATCH",
108            Self::Extra { .. } => "EXTRA",
109        }
110    }
111}
112
113impl fmt::Display for Finding {
114    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115        match self {
116            Self::Missing {
117                name,
118                expected_shape,
119                expected_dtype,
120            } => write!(
121                f,
122                "MISSING        {name}: manifest requires {expected_shape:?} {expected_dtype}, \
123                 checkpoint has no such tensor"
124            ),
125            Self::ShapeMismatch {
126                name,
127                expected,
128                actual,
129            } => write!(
130                f,
131                "SHAPE-MISMATCH {name}: manifest requires {expected:?}, checkpoint has {actual:?}"
132            ),
133            Self::DtypeMismatch {
134                name,
135                expected,
136                actual,
137            } => write!(
138                f,
139                "DTYPE-MISMATCH {name}: manifest requires {expected}, checkpoint has {actual}"
140            ),
141            Self::Extra { name, shape, dtype } => write!(
142                f,
143                "EXTRA          {name}: checkpoint has {shape:?} {dtype}, manifest does not \
144                 mention it"
145            ),
146        }
147    }
148}
149
150/// The expected tensor inventory for one checkpoint.
151#[derive(Clone, Debug, Default)]
152pub struct WeightsManifest {
153    label: String,
154    expected: BTreeMap<String, ExpectedTensor>,
155}
156
157impl WeightsManifest {
158    /// Create an empty manifest labelled for diagnostics (e.g. `"talker"`).
159    #[must_use]
160    pub fn new(label: impl Into<String>) -> Self {
161        Self {
162            label: label.into(),
163            expected: BTreeMap::new(),
164        }
165    }
166
167    /// Build a manifest from an iterator of expectations.
168    #[must_use]
169    pub fn from_expectations(
170        label: impl Into<String>,
171        expectations: impl IntoIterator<Item = ExpectedTensor>,
172    ) -> Self {
173        let mut manifest = Self::new(label);
174        for expectation in expectations {
175            manifest.expect(expectation);
176        }
177        manifest
178    }
179
180    /// Add one expectation, replacing any prior entry for the same name.
181    pub fn expect(&mut self, tensor: ExpectedTensor) -> &mut Self {
182        self.expected.insert(tensor.name.clone(), tensor);
183        self
184    }
185
186    /// Diagnostic label.
187    #[must_use]
188    pub fn label(&self) -> &str {
189        &self.label
190    }
191
192    /// Number of tensors required.
193    #[must_use]
194    pub fn len(&self) -> usize {
195        self.expected.len()
196    }
197
198    /// Whether the manifest requires nothing.
199    #[must_use]
200    pub fn is_empty(&self) -> bool {
201        self.expected.is_empty()
202    }
203
204    /// Compare a parsed checkpoint against this manifest.
205    ///
206    /// Never short-circuits: the report lists *every* divergence, because a first-failure-only
207    /// diagnostic turns a wrong-checkpoint diagnosis into a game of whack-a-mole.
208    #[must_use]
209    pub fn audit(&self, index: &SafetensorsIndex) -> CensusReport {
210        let mut findings = Vec::new();
211
212        for (name, expectation) in &self.expected {
213            match index.entry(name) {
214                None => findings.push(Finding::Missing {
215                    name: name.clone(),
216                    expected_shape: expectation.shape.clone(),
217                    expected_dtype: expectation.dtype,
218                }),
219                Some(actual) => {
220                    if actual.shape != expectation.shape {
221                        findings.push(Finding::ShapeMismatch {
222                            name: name.clone(),
223                            expected: expectation.shape.clone(),
224                            actual: actual.shape.clone(),
225                        });
226                    }
227                    // Reported independently of shape: a tensor can be right-shaped and
228                    // wrong-typed, and each misleads a different consumer.
229                    if actual.dtype != expectation.dtype {
230                        findings.push(Finding::DtypeMismatch {
231                            name: name.clone(),
232                            expected: expectation.dtype,
233                            actual: actual.dtype,
234                        });
235                    }
236                }
237            }
238        }
239
240        for entry in index.entries() {
241            if !self.expected.contains_key(&entry.name) {
242                findings.push(Finding::Extra {
243                    name: entry.name.clone(),
244                    shape: entry.shape.clone(),
245                    dtype: entry.dtype,
246                });
247            }
248        }
249
250        CensusReport {
251            label: self.label.clone(),
252            expected_count: self.expected.len(),
253            actual_count: index.len(),
254            findings,
255        }
256    }
257
258    /// Audit and refuse if anything diverged.
259    ///
260    /// # Errors
261    ///
262    /// Returns the full [`CensusReport`] when any finding is present. Callers should surface
263    /// [`CensusReport::render`] verbatim — it is the diagnosis.
264    pub fn verify(&self, index: &SafetensorsIndex) -> Result<(), Box<CensusReport>> {
265        let report = self.audit(index);
266        if report.is_green() {
267            Ok(())
268        } else {
269            Err(Box::new(report))
270        }
271    }
272}
273
274/// The outcome of auditing one checkpoint.
275#[derive(Clone, Debug)]
276pub struct CensusReport {
277    label: String,
278    expected_count: usize,
279    actual_count: usize,
280    findings: Vec<Finding>,
281}
282
283impl CensusReport {
284    /// Whether the checkpoint matched the manifest exactly.
285    #[must_use]
286    pub fn is_green(&self) -> bool {
287        self.findings.is_empty()
288    }
289
290    /// Every divergence found.
291    #[must_use]
292    pub fn findings(&self) -> &[Finding] {
293        &self.findings
294    }
295
296    /// Count of findings in one class.
297    #[must_use]
298    pub fn count_of(&self, class: &str) -> usize {
299        self.findings
300            .iter()
301            .filter(|finding| finding.class() == class)
302            .count()
303    }
304
305    /// The manifest label this report is for.
306    #[must_use]
307    pub fn label(&self) -> &str {
308        &self.label
309    }
310
311    /// A loud, itemized, greppable diff suitable for printing verbatim on refusal.
312    #[must_use]
313    pub fn render(&self) -> String {
314        use fmt::Write as _;
315
316        if self.is_green() {
317            return format!(
318                "weights census `{}`: GREEN ({} tensors matched)",
319                self.label, self.expected_count
320            );
321        }
322
323        let mut out = format!(
324            "weights census `{}`: REFUSED — {} divergence(s)\n  manifest expects {} tensor(s); \
325             checkpoint declares {}\n  MISSING {} · SHAPE-MISMATCH {} · DTYPE-MISMATCH {} · EXTRA \
326             {}\n",
327            self.label,
328            self.findings.len(),
329            self.expected_count,
330            self.actual_count,
331            self.count_of("MISSING"),
332            self.count_of("SHAPE-MISMATCH"),
333            self.count_of("DTYPE-MISMATCH"),
334            self.count_of("EXTRA"),
335        );
336        for finding in &self.findings {
337            // Writing to a String cannot fail; the Result is discarded deliberately.
338            let _ = writeln!(out, "  {finding}");
339        }
340        out.push_str(
341            "  this is a wrong or stale checkpoint — refusing to load rather than synthesize \
342             garbage",
343        );
344        out
345    }
346}
347
348impl fmt::Display for CensusReport {
349    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
350        f.write_str(&self.render())
351    }
352}
353
354impl std::error::Error for CensusReport {}
355
356#[cfg(test)]
357mod tests {
358    use super::*;
359    use crate::safetensors::SafetensorsIndex;
360    use serde_json::{Value, json};
361
362    fn checkpoint(parts: &[(&str, Dtype, &[usize])]) -> Vec<u8> {
363        let mut directory = serde_json::Map::new();
364        let mut offset = 0usize;
365        for (name, dtype, shape) in parts {
366            let elements: usize = shape.iter().product();
367            let bytes = elements * dtype.size();
368            directory.insert(
369                (*name).to_owned(),
370                json!({
371                    "dtype": dtype.as_str(),
372                    "shape": shape,
373                    "data_offsets": [offset, offset + bytes],
374                }),
375            );
376            offset += bytes;
377        }
378        let header = serde_json::to_vec(&Value::Object(directory)).expect("serializes");
379        let mut out = (header.len() as u64).to_le_bytes().to_vec();
380        out.extend_from_slice(&header);
381        out.extend_from_slice(&vec![0u8; offset]);
382        out
383    }
384
385    fn manifest(parts: &[(&str, &[usize], Dtype)]) -> WeightsManifest {
386        WeightsManifest::from_expectations(
387            "test",
388            parts
389                .iter()
390                .map(|(name, shape, dtype)| ExpectedTensor::new(*name, shape.to_vec(), *dtype)),
391        )
392    }
393
394    #[test]
395    fn matching_checkpoint_is_green() {
396        let buffer = checkpoint(&[("a", Dtype::Bf16, &[2, 2]), ("b", Dtype::F32, &[4])]);
397        let index = SafetensorsIndex::parse(&buffer).expect("parses");
398        let manifest = manifest(&[("a", &[2, 2], Dtype::Bf16), ("b", &[4], Dtype::F32)]);
399
400        let report = manifest.audit(&index);
401        assert!(report.is_green(), "{}", report.render());
402        assert!(manifest.verify(&index).is_ok());
403        assert!(report.render().contains("GREEN"));
404    }
405
406    #[test]
407    fn missing_tensor_is_named_and_refused() {
408        let buffer = checkpoint(&[("a", Dtype::Bf16, &[2, 2])]);
409        let index = SafetensorsIndex::parse(&buffer).expect("parses");
410        let manifest = manifest(&[("a", &[2, 2], Dtype::Bf16), ("b", &[4], Dtype::F32)]);
411
412        let report = manifest.verify(&index).expect_err("must refuse");
413        assert_eq!(report.count_of("MISSING"), 1);
414        let rendered = report.render();
415        assert!(rendered.contains("MISSING"));
416        assert!(rendered.contains('b'));
417        assert!(rendered.contains("REFUSED"));
418    }
419
420    #[test]
421    fn shape_mismatch_is_named_and_refused() {
422        let buffer = checkpoint(&[("w", Dtype::Bf16, &[2, 4])]);
423        let index = SafetensorsIndex::parse(&buffer).expect("parses");
424        let manifest = manifest(&[("w", &[2, 2], Dtype::Bf16)]);
425
426        let report = manifest.verify(&index).expect_err("must refuse");
427        assert_eq!(report.count_of("SHAPE-MISMATCH"), 1);
428        let rendered = report.render();
429        assert!(rendered.contains("[2, 2]"), "{rendered}");
430        assert!(rendered.contains("[2, 4]"), "{rendered}");
431    }
432
433    #[test]
434    fn dtype_mismatch_is_reported_independently_of_shape() {
435        // Right shape, wrong dtype: exactly the case that loads fine and sounds wrong.
436        let buffer = checkpoint(&[("w", Dtype::F32, &[2, 2])]);
437        let index = SafetensorsIndex::parse(&buffer).expect("parses");
438        let manifest = manifest(&[("w", &[2, 2], Dtype::Bf16)]);
439
440        let report = manifest.verify(&index).expect_err("must refuse");
441        assert_eq!(report.count_of("DTYPE-MISMATCH"), 1);
442        assert_eq!(report.count_of("SHAPE-MISMATCH"), 0);
443    }
444
445    #[test]
446    fn wrong_shape_and_dtype_both_report() {
447        let buffer = checkpoint(&[("w", Dtype::F32, &[8])]);
448        let index = SafetensorsIndex::parse(&buffer).expect("parses");
449        let manifest = manifest(&[("w", &[2, 2], Dtype::Bf16)]);
450
451        let report = manifest.verify(&index).expect_err("must refuse");
452        assert_eq!(report.count_of("SHAPE-MISMATCH"), 1);
453        assert_eq!(report.count_of("DTYPE-MISMATCH"), 1);
454    }
455
456    #[test]
457    fn extra_tensor_is_reported() {
458        // The signature of a different checkpoint revision.
459        let buffer = checkpoint(&[("a", Dtype::Bf16, &[2, 2]), ("surprise", Dtype::F32, &[1])]);
460        let index = SafetensorsIndex::parse(&buffer).expect("parses");
461        let manifest = manifest(&[("a", &[2, 2], Dtype::Bf16)]);
462
463        let report = manifest.verify(&index).expect_err("must refuse");
464        assert_eq!(report.count_of("EXTRA"), 1);
465        assert!(report.render().contains("surprise"));
466    }
467
468    #[test]
469    fn every_divergence_is_listed_not_just_the_first() {
470        let buffer = checkpoint(&[
471            ("keep", Dtype::Bf16, &[2, 2]),
472            ("wrong_shape", Dtype::Bf16, &[9]),
473            ("wrong_dtype", Dtype::F32, &[2]),
474            ("unexpected", Dtype::F32, &[1]),
475        ]);
476        let index = SafetensorsIndex::parse(&buffer).expect("parses");
477        let manifest = manifest(&[
478            ("keep", &[2, 2], Dtype::Bf16),
479            ("wrong_shape", &[4], Dtype::Bf16),
480            ("wrong_dtype", &[2], Dtype::Bf16),
481            ("absent", &[7], Dtype::Bf16),
482        ]);
483
484        let report = manifest.verify(&index).expect_err("must refuse");
485        assert_eq!(report.count_of("MISSING"), 1);
486        assert_eq!(report.count_of("SHAPE-MISMATCH"), 1);
487        assert_eq!(report.count_of("DTYPE-MISMATCH"), 1);
488        assert_eq!(report.count_of("EXTRA"), 1);
489        assert_eq!(report.findings().len(), 4);
490    }
491
492    #[test]
493    fn report_is_greppable_by_class() {
494        let buffer = checkpoint(&[("a", Dtype::Bf16, &[1])]);
495        let index = SafetensorsIndex::parse(&buffer).expect("parses");
496        let manifest = manifest(&[("b", &[1], Dtype::Bf16)]);
497        let report = manifest.audit(&index);
498
499        let classes: Vec<_> = report.findings().iter().map(Finding::class).collect();
500        assert!(classes.contains(&"MISSING"));
501        assert!(classes.contains(&"EXTRA"));
502        assert_eq!(report.findings()[0].name(), "b");
503    }
504}