use super::*;
use crate::error::CanddingError;
pub(crate) const V1: &str = r#"{
"activation_function": "swiglu",
"causal": false,
"layer_norm_epsilon": 1e-12,
"max_position_embeddings": 8192,
"mlp_fc1_bias": false,
"mlp_fc2_bias": false,
"n_embd": 768,
"n_head": 12,
"n_inner": 3072,
"n_layer": 12,
"pad_token_id": 0,
"prenorm": false,
"qkv_proj_bias": false,
"rotary_emb_base": 1000,
"rotary_emb_fraction": 1.0,
"rotary_emb_interleaved": false,
"rotary_emb_scale_base": null,
"rotary_scaling_factor": 2,
"type_vocab_size": 2,
"vocab_size": 30528
}"#;
pub(crate) const V1_5: &str = r#"{
"activation_function": "swiglu",
"causal": false,
"layer_norm_epsilon": 1e-12,
"max_position_embeddings": 2048,
"max_trained_positions": 2048,
"mlp_fc1_bias": false,
"mlp_fc2_bias": false,
"n_embd": 768,
"n_head": 12,
"n_inner": 3072,
"n_layer": 12,
"pad_token_id": 0,
"prenorm": false,
"qkv_proj_bias": false,
"rotary_emb_base": 1000,
"rotary_emb_fraction": 1.0,
"rotary_emb_interleaved": false,
"rotary_emb_scale_base": null,
"rotary_scaling_factor": null,
"type_vocab_size": 2,
"vocab_size": 30528
}"#;
const SNOWFLAKE: &str = r#"{
"activation_function": "swiglu",
"causal": false,
"layer_norm_epsilon": 1e-12,
"max_trained_positions": 2048,
"mlp_fc1_bias": false,
"mlp_fc2_bias": false,
"n_embd": 768,
"n_head": 12,
"n_inner": 3072,
"n_layer": 12,
"prenorm": false,
"qkv_proj_bias": false,
"rotary_emb_base": 1000,
"rotary_emb_fraction": 1.0,
"rotary_emb_interleaved": false,
"rotary_emb_scale_base": null,
"rotary_scaling_factor": 2,
"type_vocab_size": 2,
"vocab_size": 30528
}"#;
#[test]
fn reads_the_three_published_configs() {
let cases: [(&str, &str, Option<usize>, Option<f64>); 3] = [
("v1", V1, Some(8192), Some(2.0)),
("v1.5", V1_5, Some(2048), None),
("snowflake", SNOWFLAKE, None, Some(2.0)),
];
for (name, json, max_position_embeddings, scaling_factor) in cases {
let config: NomicBertConfig = serde_json::from_str(json).unwrap();
assert_eq!(config.head_dim(), 64, "{name}");
config.ensure_supported().unwrap();
assert_eq!(config.scaling_factor(), scaling_factor, "{name}");
assert_eq!(config.max_trained_positions, 2048, "{name}");
assert_eq!(
config.max_position_embeddings, max_position_embeddings,
"{name}"
);
}
}
#[test]
fn a_missing_rotary_emb_base_is_a_deserialization_error() {
let stripped = V1.replace("\"rotary_emb_base\": 1000,\n ", "");
assert!(serde_json::from_str::<NomicBertConfig>(&stripped).is_err());
}
#[test]
fn an_absent_rotary_scaling_factor_is_none() {
let stripped = V1.replace("\"rotary_scaling_factor\": 2,\n ", "");
assert_ne!(
stripped, V1,
"rotary_scaling_factor: mutation did not match anything in V1"
);
let config: NomicBertConfig = serde_json::from_str(&stripped).unwrap();
assert_eq!(config.scaling_factor(), None);
}
#[test]
fn each_refusal_names_the_field_and_the_value() {
let cases = [
(
"\"activation_function\": \"swiglu\",",
"\"activation_function\": \"gelu\",",
"activation_function \"gelu\" is not supported",
),
(
"\"activation_function\": \"swiglu\",",
"\"activation_function\": \"glu\",",
"activation_function \"glu\" is not supported",
),
(
"\"prenorm\": false,",
"\"prenorm\": true,",
"prenorm true is not supported",
),
(
"\"causal\": false,",
"\"causal\": true,",
"causal true is not supported",
),
(
"\"rotary_emb_fraction\": 1.0,",
"\"rotary_emb_fraction\": 0.5,",
"rotary_emb_fraction 0.5 is not supported",
),
(
"\"rotary_emb_fraction\": 1.0,",
"\"rotary_emb_fraction\": 0.0,",
"rotary_emb_fraction 0 is not supported",
),
(
"\"rotary_emb_interleaved\": false,",
"\"rotary_emb_interleaved\": true,",
"rotary_emb_interleaved true is not supported",
),
(
"\"qkv_proj_bias\": false,",
"\"qkv_proj_bias\": true,",
"qkv_proj_bias true is not supported",
),
(
"\"mlp_fc1_bias\": false,",
"\"mlp_fc1_bias\": true,",
"mlp_fc1_bias true is not supported",
),
(
"\"mlp_fc2_bias\": false,",
"\"mlp_fc2_bias\": true,",
"mlp_fc2_bias true is not supported",
),
(
"\"rotary_emb_scale_base\": null,",
"\"rotary_emb_scale_base\": 8,",
"rotary_emb_scale_base 8 is not supported",
),
(
"\"n_layer\": 12,",
"\"n_layer\": 12,\n \"norm_mlp\": true,",
"norm_mlp true is not supported",
),
];
for (from, to, needle) in cases {
let mutated = V1.replace(from, to);
assert_ne!(
mutated, V1,
"{needle}: mutation did not match anything in V1"
);
let config: NomicBertConfig = serde_json::from_str(&mutated).unwrap_or_else(|e| {
panic!("{needle}: mutated body failed to parse: {e}");
});
let err = config.ensure_supported().unwrap_err();
assert!(
matches!(err, CanddingError::UnsupportedArchitecture(ref m) if m.contains(needle)),
"{needle}: got {err}"
);
}
}