use crate::HubResult;
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::Path;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModelConfig {
#[serde(default)]
pub architectures: Vec<String>,
#[serde(default)]
pub hidden_size: usize,
#[serde(default)]
pub num_attention_heads: usize,
#[serde(default)]
pub num_key_value_heads: Option<usize>,
#[serde(default)]
pub num_hidden_layers: usize,
#[serde(default)]
pub intermediate_size: usize,
#[serde(default)]
pub vocab_size: usize,
#[serde(default)]
pub max_position_embeddings: usize,
#[serde(default = "default_rms_eps")]
pub rms_norm_eps: f32,
#[serde(default = "default_rope_theta")]
pub rope_theta: f32,
#[serde(default)]
pub tie_word_embeddings: bool,
#[serde(default)]
pub model_type: String,
}
fn default_rms_eps() -> f32 {
1e-5
}
fn default_rope_theta() -> f32 {
10000.0
}
impl ModelConfig {
pub fn from_file(path: &Path) -> HubResult<Self> {
let content = fs::read_to_string(path)?;
Ok(serde_json::from_str(&content)?)
}
pub fn from_model_dir(model_dir: &Path) -> HubResult<Self> {
Self::from_file(&model_dir.join("config.json"))
}
pub fn head_dim(&self) -> usize {
self.hidden_size / self.num_attention_heads
}
pub fn kv_heads(&self) -> usize {
self.num_key_value_heads.unwrap_or(self.num_attention_heads)
}
pub fn uses_gqa(&self) -> bool {
self.kv_heads() != self.num_attention_heads
}
}
impl Default for ModelConfig {
fn default() -> Self {
Self {
architectures: vec![],
hidden_size: 4096,
num_attention_heads: 32,
num_key_value_heads: None,
num_hidden_layers: 32,
intermediate_size: 11008,
vocab_size: 32000,
max_position_embeddings: 4096,
rms_norm_eps: 1e-5,
rope_theta: 10000.0,
tie_word_embeddings: false,
model_type: "llama".to_string(),
}
}
}