use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
#[serde(rename_all = "snake_case")]
pub enum ExportFormat {
OpenAi,
Anthropic,
HuggingFace,
}
impl std::fmt::Display for ExportFormat {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ExportFormat::OpenAi => write!(f, "openai"),
ExportFormat::Anthropic => write!(f, "anthropic"),
ExportFormat::HuggingFace => write!(f, "huggingface"),
}
}
}
impl std::str::FromStr for ExportFormat {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"openai" => Ok(ExportFormat::OpenAi),
"anthropic" => Ok(ExportFormat::Anthropic),
"huggingface" | "hf" => Ok(ExportFormat::HuggingFace),
other => Err(format!("Unknown export format: {other}")),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum ExportStatus {
Pending,
Running,
Complete,
Error,
}
impl std::fmt::Display for ExportStatus {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ExportStatus::Pending => write!(f, "pending"),
ExportStatus::Running => write!(f, "running"),
ExportStatus::Complete => write!(f, "complete"),
ExportStatus::Error => write!(f, "error"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FineTuneExport {
pub id: Uuid,
pub run_id: Uuid,
pub format: ExportFormat,
pub status: ExportStatus,
pub row_count: Option<u32>,
pub file_path: Option<String>,
pub error_message: Option<String>,
pub created_at: DateTime<Utc>,
pub completed_at: Option<DateTime<Utc>>,
}
pub const MIN_TRACES_FOR_EXPORT: usize = 500;
#[cfg(test)]
mod tests {
use super::*;
use std::str::FromStr;
#[test]
fn format_roundtrip() {
for (s, expected) in [
("openai", ExportFormat::OpenAi),
("anthropic", ExportFormat::Anthropic),
("huggingface", ExportFormat::HuggingFace),
("hf", ExportFormat::HuggingFace),
] {
let parsed: ExportFormat = s.parse().unwrap();
assert_eq!(parsed, expected);
assert_eq!(
expected.to_string(),
ExportFormat::from_str(s).unwrap().to_string()
);
}
}
#[test]
fn unknown_format_errors() {
assert!("parquet".parse::<ExportFormat>().is_err());
}
}