Skip to content

Advanced SDK Usage

Use the underlying crates directly for full control over training loops, models, serving, model operations, and hardware-specific paths.

PMetal is a Rust workspace with 20 member crates plus the Tauri GUI package:

CratePurpose
pmetalFacade crate and CLI binary
pmetal-bridgeZero-allocation MLX C++ bridge and native inference/runtime helpers
pmetal-coreFoundation: configs, traits, types, error handling
pmetal-core-deriveProc macros for canonical job specs
pmetal-metalCustom Metal GPU kernels + ANE runtime
pmetal-mlxMLX backend integration
pmetal-modelsLLM architectures (Llama, Qwen, DeepSeek, etc.)
pmetal-loraLoRA/QLoRA training implementations
pmetal-trainerTraining loops (SFT, DPO, SimPO, ORPO, KTO, GRPO, pretraining, RLKD, etc.)
pmetal-dataDataset loading, chat templates, tokenization
pmetal-hubHuggingFace Hub integration + model fit estimation
pmetal-distillKnowledge distillation (online, offline, TAID)
pmetal-mergeModel merging, MoE alignment, dtype-aware saves, sanity checks
pmetal-ggufGGUF format with imatrix quantization
pmetal-mhcManifold-Constrained Hyper-Connections
pmetal-distributedDistributed training (mDNS, Ring All-Reduce)
pmetal-vocoderBigVGAN neural vocoder
pmetal-serveOpenAI-compatible inference server
pmetal-mcpMCP server tools
pmetal-pyPython bindings (maturin/PyO3)
use pmetal_trainer::TrainingLoop;
use pmetal_models::DynamicModel;
use pmetal_lora::DynamicLoraModel;
use pmetal_data::DataLoader;
// Load model with LoRA adapters
let model = DynamicLoraModel::from_pretrained("./Qwen3-0.6B", lora_config)?;
// Create data loader
let loader = DataLoader::from_file("train.jsonl")?;
// Run training loop
let mut loop = TrainingLoop::new(model, loader, training_config);
loop.add_callback(MyCustomCallback);
let result = loop.run().await?;
use pmetal_models::DynamicModel;
// Resolve from HuggingFace, then load from the local cache path
let model_path = pmetal_hub::resolve_model_path("Qwen/Qwen3-0.6B", None, None).await?;
let model = DynamicModel::load(&model_path)?;
// Load from local path
let model = DynamicModel::load("./my-model/")?;

The TrainingCallback trait provides lifecycle hooks:

use pmetal_trainer::TrainingCallback;
struct MyCallback;
impl TrainingCallback for MyCallback {
fn on_step_start(&mut self, step: usize) { /* ... */ }
fn on_step_end(&mut self, step: usize, loss: f32) { /* ... */ }
fn should_stop(&self) -> bool { false }
}