use rlx_llama32::MetalGgufPrefillMode;
use rlx_runtime::Device;
#[derive(Debug, Clone)]
pub struct BackboneLoadOptions {
pub metal_prefill: MetalGgufPrefillMode,
pub use_fast_kv: Option<bool>,
pub memory_efficient: bool,
}
impl Default for BackboneLoadOptions {
fn default() -> Self {
Self::synthesis()
}
}
impl BackboneLoadOptions {
pub fn synthesis() -> Self {
Self {
metal_prefill: MetalGgufPrefillMode::CpuF32,
use_fast_kv: Some(true),
memory_efficient: true,
}
}
pub fn gpu(device: Device) -> Self {
Self {
metal_prefill: metal_prefill_for_device(device),
use_fast_kv: Some(true),
memory_efficient: true,
}
}
pub fn for_device(device: Device) -> Self {
Self::for_tts(device)
}
pub fn for_tts(device: Device) -> Self {
if super::rlx::low_mem_mode() {
return Self::synthesis();
}
match device {
Device::Cpu => Self::synthesis(),
Device::Metal | Device::Cuda | Device::Rocm => Self {
metal_prefill: metal_prefill_for_device(device),
use_fast_kv: Some(true),
memory_efficient: false,
},
Device::Gpu | Device::Vulkan => Self {
metal_prefill: MetalGgufPrefillMode::CpuF32,
use_fast_kv: Some(true),
memory_efficient: false,
},
_ => Self::synthesis(),
}
}
pub fn reference_parity() -> Self {
Self {
metal_prefill: MetalGgufPrefillMode::CpuF32,
use_fast_kv: Some(true),
memory_efficient: false,
}
}
pub fn fast_prefill() -> Self {
Self {
metal_prefill: MetalGgufPrefillMode::PackedGguf,
use_fast_kv: Some(true),
memory_efficient: true,
}
}
pub fn with_memory_efficient(mut self, enabled: bool) -> Self {
self.memory_efficient = enabled;
self
}
pub fn with_metal_prefill(mut self, mode: MetalGgufPrefillMode) -> Self {
self.metal_prefill = mode;
self
}
pub fn with_fast_kv(mut self, enabled: bool) -> Self {
self.use_fast_kv = Some(enabled);
self
}
}
fn metal_prefill_for_device(device: Device) -> MetalGgufPrefillMode {
for key in prefill_env_keys(device) {
if let Ok(s) = std::env::var(key) {
if let Some(m) = MetalGgufPrefillMode::parse(&s) {
return m;
}
}
}
match device {
Device::Metal | Device::Gpu | Device::Vulkan | Device::Cuda | Device::Rocm => {
MetalGgufPrefillMode::CpuF32
}
_ => MetalGgufPrefillMode::Auto,
}
}
fn prefill_env_keys(device: Device) -> &'static [&'static str] {
match device {
Device::Cuda => &["ORPHEUS_CUDA_PREFILL", "ORPHEUS_METAL_PREFILL"],
Device::Rocm => &["ORPHEUS_ROCM_PREFILL", "ORPHEUS_METAL_PREFILL"],
_ => &["ORPHEUS_METAL_PREFILL"],
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn gpu_on_metal_uses_cpu_gguf_prefill() {
let opts = BackboneLoadOptions::gpu(Device::Metal);
assert_eq!(opts.metal_prefill, MetalGgufPrefillMode::CpuF32);
}
#[test]
fn for_device_wgpu_uses_cpu_gguf_path() {
let opts = BackboneLoadOptions::for_device(Device::Gpu);
assert_eq!(opts.metal_prefill, MetalGgufPrefillMode::CpuF32);
assert_eq!(opts.use_fast_kv, Some(true));
}
#[test]
fn for_device_matches_for_tts() {
let opts = BackboneLoadOptions::for_device(Device::Metal);
let tts = BackboneLoadOptions::for_tts(Device::Metal);
assert_eq!(opts.metal_prefill, tts.metal_prefill);
assert_eq!(opts.memory_efficient, tts.memory_efficient);
}
#[test]
fn for_tts_enables_bucket_decode_budget_on_metal() {
let opts = BackboneLoadOptions::for_tts(Device::Metal);
assert_eq!(opts.metal_prefill, MetalGgufPrefillMode::CpuF32);
assert!(!opts.memory_efficient);
}
#[test]
fn for_tts_cpu_uses_synthesis() {
let opts = BackboneLoadOptions::for_tts(Device::Cpu);
assert!(opts.memory_efficient);
assert_eq!(opts.metal_prefill, MetalGgufPrefillMode::CpuF32);
}
#[test]
fn for_tts_cuda_uses_host_prefill() {
let opts = BackboneLoadOptions::for_tts(Device::Cuda);
assert_eq!(opts.metal_prefill, MetalGgufPrefillMode::CpuF32);
assert!(!opts.memory_efficient);
}
}