metrale_model_arch/weight_loader/
nllb.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3//! 2026-09-25: Marker loader for NLLB / M2M-100 (`model_type` `m2m_100` or `nllb`), an
4//! encoder-decoder model this decoder-only loader interface cannot build.
5//!
6//! In a `cuda` build, model-engine's `build_model` (`factory/build.rs`) serves these model
7//! types with `NllbGpuModel` and returns before `loader_for_config`; there this loader is
8//! reached only when that path is bypassed.
9//!
10//! Owner: model-arch weight loader.
11//! Invariants:
12//! - `load_layers`, `load_embedding`, `load_final_norm` and `load_lm_head` always return an
13//!   error; `load_mtp_weights` returns `Ok(None)` and `supports_tp` is false.
14
15use anyhow::{Result, bail};
16use metrale_cache::kv_cache::KvCacheDtype;
17use metrale_config::ModelConfig;
18use metrale_gpu_runtime::gpu::GpuBackend;
19use metrale_model_weights::weights::WeightStore;
20
21use crate::weight_loader::ModelWeightLoader;
22use metrale_model_layers::layer::TransformerLayer;
23use metrale_model_layers::weight_map::{DenseWeight, MtpWeights};
24
25pub struct NllbWeightLoader;
26
27impl NllbWeightLoader {
28    fn unsupported() -> anyhow::Error {
29        anyhow::anyhow!(
30            "NLLB / m2m_100 is served by the dedicated GPU encoder-decoder runtime (metrale_model_engine::model::nllb::NllbGpuModel), which build_model selects before this loader; the generic decoder-only ModelWeightLoader pipeline cannot serve it. Reaching this loader means the dedicated serve path was bypassed."
31        )
32    }
33}
34
35impl ModelWeightLoader for NllbWeightLoader {
36    fn supports_tp(&self) -> bool {
37        false
38    }
39
40    fn load_layers(
41        &self,
42        _store: &WeightStore,
43        _config: &ModelConfig,
44        _gpu: &dyn GpuBackend,
45        _layer_kv_dtypes: &[KvCacheDtype],
46    ) -> Result<Vec<Box<dyn TransformerLayer>>> {
47        bail!(Self::unsupported())
48    }
49
50    fn load_embedding(
51        &self,
52        _store: &WeightStore,
53        _config: &ModelConfig,
54        _gpu: &dyn GpuBackend,
55    ) -> Result<DenseWeight> {
56        bail!(Self::unsupported())
57    }
58
59    fn load_final_norm(
60        &self,
61        _store: &WeightStore,
62        _config: &ModelConfig,
63        _gpu: &dyn GpuBackend,
64    ) -> Result<DenseWeight> {
65        bail!(Self::unsupported())
66    }
67
68    fn load_lm_head(
69        &self,
70        _store: &WeightStore,
71        _config: &ModelConfig,
72        _gpu: &dyn GpuBackend,
73    ) -> Result<DenseWeight> {
74        bail!(Self::unsupported())
75    }
76
77    fn load_mtp_weights(
78        &self,
79        _store: &WeightStore,
80        _config: &ModelConfig,
81        _gpu: &dyn GpuBackend,
82    ) -> Result<Option<MtpWeights>> {
83        Ok(None)
84    }
85}