#![allow(clippy::uninlined_format_args)]
#![allow(clippy::no_effect_underscore_binding)]
#![allow(clippy::doc_markdown)]
#![allow(clippy::cast_possible_wrap)]
#![allow(clippy::cast_precision_loss)]
#![allow(clippy::too_many_lines)]
#![allow(clippy::missing_docs_in_private_items)]
#![allow(clippy::unused_async)]
#![allow(clippy::cast_possible_truncation)]
#![allow(clippy::cast_lossless)]
#![allow(clippy::items_after_statements)]
#![allow(clippy::cast_sign_loss)]
#![allow(unused_variables)]
#![allow(unused_imports)]
#![allow(missing_docs)]
#![allow(dead_code)]
use openai_ergonomic::{builders::uploads::UploadBuilder, Client, UploadPurpose};
#[derive(Debug, Clone)]
pub struct UploadInfo {
pub id: String,
pub filename: String,
pub bytes: i32,
pub purpose: String,
pub status: String,
}
impl UploadInfo {
pub fn new(
id: impl Into<String>,
filename: impl Into<String>,
bytes: i32,
purpose: impl Into<String>,
status: impl Into<String>,
) -> Self {
Self {
id: id.into(),
filename: filename.into(),
bytes,
purpose: purpose.into(),
status: status.into(),
}
}
pub fn display(&self) {
println!(" Upload ID: {}", self.id);
println!(" Filename: {}", self.filename);
println!(
" Size: {} bytes ({:.2} MB)",
self.bytes,
self.bytes as f64 / (1024.0 * 1024.0)
);
println!(" Purpose: {}", self.purpose);
println!(" Status: {}", self.status);
}
pub fn formatted_size(&self) -> String {
let bytes = self.bytes as f64;
if bytes < 1024.0 {
format!("{:.0} B", bytes)
} else if bytes < 1024.0 * 1024.0 {
format!("{:.2} KB", bytes / 1024.0)
} else if bytes < 1024.0 * 1024.0 * 1024.0 {
format!("{:.2} MB", bytes / (1024.0 * 1024.0))
} else {
format!("{:.2} GB", bytes / (1024.0 * 1024.0 * 1024.0))
}
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!(" OpenAI Ergonomic - Comprehensive Uploads Example\n");
println!(" Initializing OpenAI client...");
let client = match Client::from_env() {
Ok(c) => {
println!(" Client initialized successfully\n");
c.build()
}
Err(e) => {
eprintln!(" Failed to initialize client: {}", e);
eprintln!(" Make sure OPENAI_API_KEY is set");
return Ok(());
}
};
println!();
println!(" Example 1: Create Multipart Upload");
println!("\n");
let filename = "large_training_dataset.jsonl";
let file_size_mb = 750; let file_size_bytes = file_size_mb * 1024 * 1024;
let mime_type = "application/jsonl";
println!("Creating multipart upload...");
println!(" Filename: {}", filename);
println!(" Size: {} MB ({} bytes)", file_size_mb, file_size_bytes);
println!(" Purpose: fine-tune");
println!(" MIME Type: {}", mime_type);
let builder = client.uploads().builder(
filename,
UploadPurpose::FineTune,
file_size_bytes,
mime_type,
);
println!("\n Note: This would create a real multipart upload session.");
println!(" Commented out to avoid accidental API calls.\n");
let demo_upload = UploadInfo::new(
"upload-demo123",
filename,
file_size_bytes,
"fine-tune",
"pending",
);
println!(" Demo Upload Created:");
demo_upload.display();
println!("\n");
println!(" Example 2: Upload File Parts");
println!("\n");
let upload_id = "upload-demo123";
let part_size_mb = 64; let total_parts = (file_size_mb + part_size_mb - 1) / part_size_mb;
println!(
"Uploading {} parts ({} MB each)...\n",
total_parts, part_size_mb
);
for part_num in 1..=total_parts {
let progress_percent = (part_num as f64 / total_parts as f64) * 100.0;
println!(
" Uploading part {}/{} ({:.1}% complete)",
part_num, total_parts, progress_percent
);
}
println!("\n All {} parts uploaded successfully", total_parts);
println!("\n");
println!(" Example 3: Complete Upload");
println!("\n");
println!("Completing upload: {}\n", upload_id);
println!(" Demo: Would finalize the upload and create a file object");
println!(" File ID: file-abc123");
println!(" Filename: {}", filename);
println!(" Status: ready");
println!("\n");
println!(" Example 4: Upload Smaller File");
println!("\n");
let small_filename = "training_data.jsonl";
let small_size_mb = 10;
let small_size_bytes = small_size_mb * 1024 * 1024;
println!("Creating upload for smaller file...");
println!(" Filename: {}", small_filename);
println!(" Size: {} MB", small_size_mb);
println!(" Purpose: assistants");
let small_builder = client.uploads().builder(
small_filename,
UploadPurpose::Assistants,
small_size_bytes,
"application/jsonl",
);
println!("\n Note: For files < 512 MB, consider using the regular Files API");
println!(" The Uploads API is optimized for large files.");
println!("\n");
println!(" Example 5: Error Handling & Retry");
println!("\n");
println!("Demonstrating retry logic for failed part uploads...\n");
let max_retries = 3;
let failed_part = 5;
for retry in 1..=max_retries {
println!(" Attempt {} to upload part {}", retry, failed_part);
}
println!("\n Tip: Implement exponential backoff for retry logic");
println!("\n");
println!(" Example 6: Progress Tracking");
println!("\n");
struct UploadProgress {
total_bytes: i32,
uploaded_bytes: i32,
total_parts: i32,
uploaded_parts: i32,
}
impl UploadProgress {
fn percentage(&self) -> f64 {
(self.uploaded_bytes as f64 / self.total_bytes as f64) * 100.0
}
fn eta_seconds(&self, bytes_per_second: f64) -> i32 {
let remaining_bytes = self.total_bytes - self.uploaded_bytes;
(remaining_bytes as f64 / bytes_per_second) as i32
}
fn display(&self, bytes_per_second: f64) {
let progress_bar_width = 40;
let filled = ((self.percentage() / 100.0) * progress_bar_width as f64) as usize;
let empty = progress_bar_width - filled;
print!(" [");
print!("{}", "".repeat(filled));
print!("{}", "".repeat(empty));
print!("] ");
println!(
"{:.1}% ({}/{} parts, {} MB/s, ETA: {}s)",
self.percentage(),
self.uploaded_parts,
self.total_parts,
bytes_per_second / (1024.0 * 1024.0),
self.eta_seconds(bytes_per_second)
);
}
}
let progress = UploadProgress {
total_bytes: file_size_bytes,
uploaded_bytes: (file_size_bytes as f64 * 0.65) as i32,
total_parts,
uploaded_parts: (total_parts as f64 * 0.65) as i32,
};
println!("Current upload progress:");
progress.display(10.0 * 1024.0 * 1024.0);
println!("\n");
println!(" Summary");
println!("\n");
println!(" Uploads API examples completed!");
println!("\n Key Takeaways:");
println!(" • Uploads API is designed for large files (>512 MB)");
println!(" • Files are uploaded in parts for reliability");
println!(" • Each part can be retried independently");
println!(" • Progress can be tracked during upload");
println!(" • Upload must be completed after all parts are uploaded");
println!("\n Best Practices:");
println!(" 1. Use appropriate part sizes (typically 64 MB)");
println!(" 2. Implement retry logic with exponential backoff");
println!(" 3. Track progress and provide user feedback");
println!(" 4. Handle upload cancellation gracefully");
println!(" 5. Verify file integrity after upload");
println!("\n When to Use:");
println!(" • Large training datasets for fine-tuning");
println!(" • Big files for assistants (>512 MB)");
println!(" • Batch processing input files");
println!(" • Any file where reliability is critical");
println!("\n Example completed successfully!");
Ok(())
}