use crate::eval::evaluator::{EvalResult, Metric};
#[derive(Clone, Debug)]
pub struct ModelCard {
pub model_name: String,
pub description: String,
pub license: Option<String>,
pub language: Vec<String>,
pub tags: Vec<String>,
pub metrics: Vec<(String, f64)>,
pub training_details: Option<String>,
pub base_model: Option<String>,
}
impl ModelCard {
#[must_use]
pub fn from_eval_result(result: &EvalResult) -> Self {
let metrics: Vec<(String, f64)> = result
.scores
.iter()
.map(|(metric, &value)| (metric_to_yaml_key(metric), value))
.collect();
Self {
model_name: result.model_name.clone(),
description: format!("Model: {}", result.model_name),
license: None,
language: Vec::new(),
tags: vec!["entrenar".to_string()],
metrics,
training_details: None,
base_model: None,
}
}
#[must_use]
pub fn to_markdown(&self) -> String {
let mut out = String::new();
out.push_str("---\n");
if let Some(license) = &self.license {
out.push_str(&format!("license: {license}\n"));
}
if !self.language.is_empty() {
out.push_str("language:\n");
for lang in &self.language {
out.push_str(&format!("- {lang}\n"));
}
}
if !self.tags.is_empty() {
out.push_str("tags:\n");
for tag in &self.tags {
out.push_str(&format!("- {tag}\n"));
}
}
if let Some(base) = &self.base_model {
out.push_str(&format!("base_model: {base}\n"));
}
if !self.metrics.is_empty() {
out.push_str("model-index:\n");
out.push_str(&format!("- name: {}\n", self.model_name));
out.push_str(" results:\n");
out.push_str(" - metrics:\n");
for (name, value) in &self.metrics {
out.push_str(&format!(" - type: {name}\n"));
out.push_str(&format!(" value: {value}\n"));
}
}
out.push_str("---\n\n");
out.push_str(&format!("# {}\n\n", self.model_name));
out.push_str(&format!("{}\n\n", self.description));
if !self.metrics.is_empty() {
out.push_str("## Evaluation Results\n\n");
out.push_str("| Metric | Value |\n");
out.push_str("|--------|-------|\n");
for (name, value) in &self.metrics {
out.push_str(&format!("| {name} | {value:.4} |\n"));
}
out.push('\n');
}
if let Some(details) = &self.training_details {
out.push_str("## Training Details\n\n");
out.push_str(details);
out.push('\n');
}
out.push_str("\n---\n*Generated by [entrenar](https://github.com/paiml/entrenar)*\n");
out
}
}
fn metric_to_yaml_key(metric: &Metric) -> String {
match metric {
Metric::WER => "wer".to_string(),
Metric::RTFx => "rtfx".to_string(),
Metric::BLEU => "bleu".to_string(),
Metric::ROUGE(v) => format!("{v}").to_lowercase().replace('-', "_"),
Metric::Perplexity => "perplexity".to_string(),
Metric::MMLUAccuracy => "mmlu_accuracy".to_string(),
Metric::PassAtK(k) => format!("pass_at_{k}"),
Metric::NDCGAtK(k) => format!("ndcg_at_{k}"),
other => other.name().to_lowercase(),
}
}