pub mod request;
pub mod response;
pub use request::{CreateFineTuningJobRequest, FineTuning};
pub use response::{
CheckpointMetrics, DpoConfig, FineTuningCheckpoint, FineTuningCheckpointListResponse, FineTuningError, FineTuningEvent,
FineTuningEventListResponse, FineTuningJob, FineTuningJobListResponse, FineTuningJobStatus, Hyperparameters, Integration, MethodConfig,
SupervisedConfig,
};
#[cfg(test)]
mod tests {
use super::*;
use crate::common::models::FineTuningModel;
#[test]
fn test_create_fine_tuning_job_request_new() {
let request = CreateFineTuningJobRequest::new(FineTuningModel::Gpt4oMini_2024_07_18, "file-abc123");
assert_eq!(request.model, FineTuningModel::Gpt4oMini_2024_07_18);
assert_eq!(request.training_file, "file-abc123");
assert!(request.validation_file.is_none());
assert!(request.suffix.is_none());
assert!(request.seed.is_none());
assert!(request.method.is_none());
}
#[test]
fn test_create_fine_tuning_job_request_with_options() {
let request = CreateFineTuningJobRequest::new(FineTuningModel::Gpt4oMini_2024_07_18, "file-abc123")
.with_validation_file("file-def456")
.with_suffix("my-model")
.with_seed(42);
assert_eq!(request.validation_file, Some("file-def456".to_string()));
assert_eq!(request.suffix, Some("my-model".to_string()));
assert_eq!(request.seed, Some(42));
}
#[test]
fn test_create_fine_tuning_job_request_with_supervised_method() {
let hyperparams = Hyperparameters { n_epochs: Some(3), batch_size: Some(4), learning_rate_multiplier: Some(0.1) };
let request = CreateFineTuningJobRequest::new(FineTuningModel::Gpt4oMini_2024_07_18, "file-abc123").with_supervised_method(Some(hyperparams));
assert!(request.method.is_some());
let method = request.method.unwrap();
assert_eq!(method.method_type, "supervised");
assert!(method.supervised.is_some());
assert!(method.dpo.is_none());
}
#[test]
fn test_create_fine_tuning_job_request_with_dpo_method() {
let request = CreateFineTuningJobRequest::new(FineTuningModel::Gpt4oMini_2024_07_18, "file-abc123").with_dpo_method(None);
assert!(request.method.is_some());
let method = request.method.unwrap();
assert_eq!(method.method_type, "dpo");
assert!(method.supervised.is_none());
assert!(method.dpo.is_some());
}
#[test]
fn test_create_fine_tuning_job_request_serialization() {
let request = CreateFineTuningJobRequest::new(FineTuningModel::Gpt4oMini_2024_07_18, "file-abc123").with_suffix("test-model");
let json = serde_json::to_string(&request).unwrap();
assert!(json.contains("\"model\":\"gpt-4o-mini-2024-07-18\""));
assert!(json.contains("\"training_file\":\"file-abc123\""));
assert!(json.contains("\"suffix\":\"test-model\""));
assert!(!json.contains("validation_file")); }
#[test]
fn test_fine_tuning_job_status_deserialization() {
let json = r#"{"id":"ftjob-123","object":"fine_tuning.job","model":"gpt-4o-mini","created_at":1234567890,"organization_id":"org-123","result_files":[],"status":"running","training_file":"file-123","hyperparameters":{},"seed":0}"#;
let job: FineTuningJob = serde_json::from_str(json).unwrap();
assert_eq!(job.status, FineTuningJobStatus::Running);
let json = r#"{"id":"ftjob-123","object":"fine_tuning.job","model":"gpt-4o-mini","created_at":1234567890,"organization_id":"org-123","result_files":[],"status":"succeeded","training_file":"file-123","hyperparameters":{},"seed":0}"#;
let job: FineTuningJob = serde_json::from_str(json).unwrap();
assert_eq!(job.status, FineTuningJobStatus::Succeeded);
let json = r#"{"id":"ftjob-123","object":"fine_tuning.job","model":"gpt-4o-mini","created_at":1234567890,"organization_id":"org-123","result_files":[],"status":"failed","training_file":"file-123","hyperparameters":{},"seed":0}"#;
let job: FineTuningJob = serde_json::from_str(json).unwrap();
assert_eq!(job.status, FineTuningJobStatus::Failed);
}
#[test]
fn test_hyperparameters_default() {
let hp = Hyperparameters::default();
assert!(hp.n_epochs.is_none());
assert!(hp.batch_size.is_none());
assert!(hp.learning_rate_multiplier.is_none());
}
#[test]
fn test_fine_tuning_event_deserialization() {
let json = r#"{"id":"ftevent-123","object":"fine_tuning.job.event","created_at":1234567890,"level":"info","message":"Training started","type":"message"}"#;
let event: FineTuningEvent = serde_json::from_str(json).unwrap();
assert_eq!(event.id, "ftevent-123");
assert_eq!(event.level, "info");
assert_eq!(event.message, "Training started");
assert_eq!(event.event_type, "message");
}
#[test]
fn test_fine_tuning_checkpoint_deserialization() {
let json = r#"{"id":"ftckpt-123","object":"fine_tuning.job.checkpoint","created_at":1234567890,"fine_tuning_job_id":"ftjob-123","fine_tuned_model_checkpoint":"ft:gpt-4o-mini:org:suffix:ckpt-1","step_number":100,"metrics":{"step":100,"train_loss":0.5,"train_mean_token_accuracy":0.8}}"#;
let checkpoint: FineTuningCheckpoint = serde_json::from_str(json).unwrap();
assert_eq!(checkpoint.id, "ftckpt-123");
assert_eq!(checkpoint.step_number, 100);
assert_eq!(checkpoint.metrics.train_loss, 0.5);
assert_eq!(checkpoint.metrics.train_mean_token_accuracy, 0.8);
}
#[test]
fn test_fine_tuning_job_list_response_deserialization() {
let json = r#"{"object":"list","data":[],"has_more":false}"#;
let response: FineTuningJobListResponse = serde_json::from_str(json).unwrap();
assert_eq!(response.object, "list");
assert!(response.data.is_empty());
assert!(!response.has_more);
}
#[test]
fn test_fine_tuning_error_deserialization() {
let json = r#"{"code":"invalid_training_file","message":"The training file is invalid","param":"training_file"}"#;
let error: FineTuningError = serde_json::from_str(json).unwrap();
assert_eq!(error.code, "invalid_training_file");
assert_eq!(error.message, "The training file is invalid");
assert_eq!(error.param, Some("training_file".to_string()));
}
}