From cd3c864eff07724a1bd5189e266099e29ca591a1 Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Mon, 24 Mar 2025 21:46:25 -0400 Subject: [PATCH] runs on mac --- Cargo.lock | 10 ++++ Cargo.toml | 2 + crates/desktop/ml_models/Cargo.toml | 1 + crates/desktop/ml_models/src/ml/mod.rs | 3 +- .../infer_clip_text_embeddings.rs | 2 +- .../src/ml/stable_diffusion/lcm_pipeline.rs | 20 +++---- crates/desktop/ml_weights_registry/Cargo.toml | 18 ++++++ crates/desktop/ml_weights_registry/src/lib.rs | 1 + .../src}/weights_registry/mod.rs | 0 .../weights_registry/weight_descriptor.rs | 0 .../weight_descriptor_builder.rs | 4 +- .../src}/weights_registry/weights.rs | 4 +- crates/desktop/src-tauri/Cargo.toml | 9 ++- .../src/endpoints/realtime_image_endpoint.rs | 58 ++++++++++-------- .../endpoints/remove_background_endpoint.rs | 39 ++++++++---- .../src/endpoints/text_to_image_endpoint.rs | 60 +++++++++++-------- crates/desktop/src-tauri/src/lib.rs | 7 ++- .../desktop/src-tauri/src/state/app_config.rs | 2 +- crates/desktop/src-tauri/src/state/app_dir.rs | 2 +- crates/desktop/src-tauri/src/stubs/mod.rs | 3 + .../src-tauri/src/stubs/model_cache.rs | 14 +++++ .../src-tauri/src/stubs/model_config.rs | 14 +++++ .../src-tauri/src/stubs/prompt_cache.rs | 15 +++++ .../src/threads/downloader_thread.rs | 6 +- frontend/realtime/yarn.lock | 22 +++---- 25 files changed, 218 insertions(+), 98 deletions(-) create mode 100644 crates/desktop/ml_weights_registry/Cargo.toml create mode 100644 crates/desktop/ml_weights_registry/src/lib.rs rename crates/desktop/{ml_models/src/ml => ml_weights_registry/src}/weights_registry/mod.rs (100%) rename crates/desktop/{ml_models/src/ml => ml_weights_registry/src}/weights_registry/weight_descriptor.rs (100%) rename crates/desktop/{ml_models/src/ml => ml_weights_registry/src}/weights_registry/weight_descriptor_builder.rs (73%) rename crates/desktop/{ml_models/src/ml => ml_weights_registry/src}/weights_registry/weights.rs (91%) create mode 100644 crates/desktop/src-tauri/src/stubs/mod.rs create mode 100644 crates/desktop/src-tauri/src/stubs/model_cache.rs create mode 100644 crates/desktop/src-tauri/src/stubs/model_config.rs create mode 100644 crates/desktop/src-tauri/src/stubs/prompt_cache.rs diff --git a/Cargo.lock b/Cargo.lock index 190ad0c1fe..fd1550a587 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -672,6 +672,7 @@ dependencies = [ "log", "memory_caching", "ml_models", + "ml_weights_registry", "once_cell", "primitives", "rand 0.8.5", @@ -6819,6 +6820,7 @@ dependencies = [ "libloading 0.8.6", "log", "memory_caching", + "ml_weights_registry", "ndarray", "nvidia-checker", "once_cell", @@ -6839,6 +6841,14 @@ dependencies = [ "tokio-util", ] +[[package]] +name = "ml_weights_registry" +version = "0.0.1" +dependencies = [ + "anyhow", + "const_format", +] + [[package]] name = "mockall" version = "0.12.1" diff --git a/Cargo.toml b/Cargo.toml index ba5ddaee9b..8bc0a9c791 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,8 @@ members = [ # Desktop apps "crates/desktop/src-tauri", + "crates/desktop/ml_models", + "crates/desktop/ml_weights_registry", # Shared libraries "crates/lib/actix_cors_configs", diff --git a/crates/desktop/ml_models/Cargo.toml b/crates/desktop/ml_models/Cargo.toml index dc8e074868..a22cb0b0b0 100644 --- a/crates/desktop/ml_models/Cargo.toml +++ b/crates/desktop/ml_models/Cargo.toml @@ -21,6 +21,7 @@ normal = ["my-workspace-hack"] # Internal filesys = { path = "../../lib/files/filesys" } memory_caching = { path = "../../lib/caching/memory_caching" } +ml_weights_registry = { path = "../ml_weights_registry" } primitives = { path = "../../lib/data/primitives" } # Bypass cudarc issues on Windows https://github.com/coreylowman/cudarc/issues/332 diff --git a/crates/desktop/ml_models/src/ml/mod.rs b/crates/desktop/ml_models/src/ml/mod.rs index e9c0a3f46a..c889cdbae0 100644 --- a/crates/desktop/ml_models/src/ml/mod.rs +++ b/crates/desktop/ml_models/src/ml/mod.rs @@ -4,5 +4,4 @@ pub mod model_cache; pub mod model_config; pub mod model_file; pub mod prompt_cache; -pub mod stable_diffusion; -pub mod weights_registry; \ No newline at end of file +pub mod stable_diffusion; \ No newline at end of file diff --git a/crates/desktop/ml_models/src/ml/stable_diffusion/infer_clip_text_embeddings.rs b/crates/desktop/ml_models/src/ml/stable_diffusion/infer_clip_text_embeddings.rs index 4c1591bc44..96fb0fddeb 100644 --- a/crates/desktop/ml_models/src/ml/stable_diffusion/infer_clip_text_embeddings.rs +++ b/crates/desktop/ml_models/src/ml/stable_diffusion/infer_clip_text_embeddings.rs @@ -7,7 +7,7 @@ use candle_transformers::models::stable_diffusion; use std::path::{Path, PathBuf}; use crate::ml::model_file::{ModelFile, StableDiffusionVersion}; -use crate::ml::weights_registry::weights::{CLIP_JSON, SDXL_TURBO_CLIP_TEXT_ENCODER, SDXL_TURBO_CLIP_TEXT_ENCODER_2}; +use ml_weights_registry::weights_registry::weights::{CLIP_JSON, SDXL_TURBO_CLIP_TEXT_ENCODER, SDXL_TURBO_CLIP_TEXT_ENCODER_2}; use anyhow::Error as E; use candle_core::{DType, Device, Module, Tensor, D}; use log::info; diff --git a/crates/desktop/ml_models/src/ml/stable_diffusion/lcm_pipeline.rs b/crates/desktop/ml_models/src/ml/stable_diffusion/lcm_pipeline.rs index 515717b9b1..041dd3bdf7 100644 --- a/crates/desktop/ml_models/src/ml/stable_diffusion/lcm_pipeline.rs +++ b/crates/desktop/ml_models/src/ml/stable_diffusion/lcm_pipeline.rs @@ -1,6 +1,15 @@ use std::path::{Path, PathBuf}; use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard}; +use anyhow::{anyhow, Error as E, Result}; +use candle_core::{DType, Device, IndexOp, Tensor, D}; +use candle_nn::VarBuilder; +use candle_transformers::models::stable_diffusion::StableDiffusionConfig; +use candle_transformers::models::stable_diffusion::lcm::{LCMScheduler, LCMSchedulerConfig}; +use candle_transformers::models::stable_diffusion::unet_2d::BlockConfig; +use candle_transformers::models::stable_diffusion::unet_2d::UNet2DConditionModel; +use candle_transformers::models::stable_diffusion::unet_2d::UNet2DConditionModelConfig; +use candle_transformers::models::stable_diffusion::vae::{AutoEncoderKL, DiagonalGaussianDistribution}; use crate::ml::image::dynamic_image_to_tensor::dynamic_image_to_tensor; use crate::ml::image::tensor_to_image_buffer::{tensor_to_image_buffer, RgbImage}; use crate::ml::model_cache::ModelCache; @@ -10,18 +19,9 @@ use crate::ml::prompt_cache::PromptCache; use crate::ml::stable_diffusion::get_vae_scale::get_vae_scale; use crate::ml::stable_diffusion::infer_clip_text_embeddings::{infer_clip_text_embeddings, ClipArgs}; use crate::ml::stable_diffusion::remap_lcm_strength_range::remap_lcm_strength_range; -use crate::ml::weights_registry::weights::{LYKON_DEAMSHAPER_7_TEXT_ENCODER_FP16, LYKON_DEAMSHAPER_7_VAE, SIMIANLUO_LCM_DREAMSHAPER_V7_UNET}; -use anyhow::{anyhow, Error as E, Result}; -use candle_core::{DType, Device, IndexOp, Tensor, D}; -use candle_nn::VarBuilder; -use candle_transformers::models::stable_diffusion::lcm::{LCMScheduler, LCMSchedulerConfig}; -use candle_transformers::models::stable_diffusion::unet_2d::BlockConfig; -use candle_transformers::models::stable_diffusion::unet_2d::UNet2DConditionModel; -use candle_transformers::models::stable_diffusion::unet_2d::UNet2DConditionModelConfig; -use candle_transformers::models::stable_diffusion::vae::{AutoEncoderKL, DiagonalGaussianDistribution}; -use candle_transformers::models::stable_diffusion::StableDiffusionConfig; use image::DynamicImage; use log::info; +use ml_weights_registry::weights_registry::weights::{LYKON_DEAMSHAPER_7_TEXT_ENCODER_FP16, LYKON_DEAMSHAPER_7_VAE, SIMIANLUO_LCM_DREAMSHAPER_V7_UNET}; use rand::Rng; const DEFAULT_STRENGTH : f64 = 75.0; diff --git a/crates/desktop/ml_weights_registry/Cargo.toml b/crates/desktop/ml_weights_registry/Cargo.toml new file mode 100644 index 0000000000..7d3455d42a --- /dev/null +++ b/crates/desktop/ml_weights_registry/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "ml_weights_registry" +edition = "2021" +version = "0.0.1" +authors = ["storyteller"] +publish = false +description = "" +license = "" +repository = "" + +[lib] +name = "ml_weights_registry" +path = "src/lib.rs" + +# External +[dependencies] +anyhow = "1.0" +const_format = "0.2.34" diff --git a/crates/desktop/ml_weights_registry/src/lib.rs b/crates/desktop/ml_weights_registry/src/lib.rs new file mode 100644 index 0000000000..ec8cab49f0 --- /dev/null +++ b/crates/desktop/ml_weights_registry/src/lib.rs @@ -0,0 +1 @@ +pub mod weights_registry; diff --git a/crates/desktop/ml_models/src/ml/weights_registry/mod.rs b/crates/desktop/ml_weights_registry/src/weights_registry/mod.rs similarity index 100% rename from crates/desktop/ml_models/src/ml/weights_registry/mod.rs rename to crates/desktop/ml_weights_registry/src/weights_registry/mod.rs diff --git a/crates/desktop/ml_models/src/ml/weights_registry/weight_descriptor.rs b/crates/desktop/ml_weights_registry/src/weights_registry/weight_descriptor.rs similarity index 100% rename from crates/desktop/ml_models/src/ml/weights_registry/weight_descriptor.rs rename to crates/desktop/ml_weights_registry/src/weights_registry/weight_descriptor.rs diff --git a/crates/desktop/ml_models/src/ml/weights_registry/weight_descriptor_builder.rs b/crates/desktop/ml_weights_registry/src/weights_registry/weight_descriptor_builder.rs similarity index 73% rename from crates/desktop/ml_models/src/ml/weights_registry/weight_descriptor_builder.rs rename to crates/desktop/ml_weights_registry/src/weights_registry/weight_descriptor_builder.rs index 78f0a25fa4..61d7ce4e24 100644 --- a/crates/desktop/ml_models/src/ml/weights_registry/weight_descriptor_builder.rs +++ b/crates/desktop/ml_weights_registry/src/weights_registry/weight_descriptor_builder.rs @@ -5,10 +5,10 @@ pub (super) const R2_BUCKET_URL : &str = "https://pub-bc5e2bc0cdee4bb5ae8fca9d64 // and variables (even if they're known to be &'static) and keep allocations static. macro_rules! weight { ($name: literal, $file_name:literal, $weight_function:expr) => { - $crate::ml::weights_registry::weight_descriptor::WeightDescriptor { + $crate::weights_registry::weight_descriptor::WeightDescriptor { name: $name, filename: $file_name, - r2_download_url: const_format::concatcp!(crate::ml::weights_registry::weight_descriptor_builder::R2_BUCKET_URL, $file_name), + r2_download_url: const_format::concatcp!(crate::weights_registry::weight_descriptor_builder::R2_BUCKET_URL, $file_name), function: $weight_function, } }; diff --git a/crates/desktop/ml_models/src/ml/weights_registry/weights.rs b/crates/desktop/ml_weights_registry/src/weights_registry/weights.rs similarity index 91% rename from crates/desktop/ml_models/src/ml/weights_registry/weights.rs rename to crates/desktop/ml_weights_registry/src/weights_registry/weights.rs index f2d35f50da..5c3e0cef93 100644 --- a/crates/desktop/ml_models/src/ml/weights_registry/weights.rs +++ b/crates/desktop/ml_weights_registry/src/weights_registry/weights.rs @@ -1,5 +1,5 @@ -use crate::ml::weights_registry::weight_descriptor::{WeightDescriptor, WeightFunction}; -use crate::ml::weights_registry::weight_descriptor_builder::weight; +use crate::weights_registry::weight_descriptor::{WeightDescriptor, WeightFunction}; +use crate::weights_registry::weight_descriptor_builder::weight; pub const CLIP_JSON : WeightDescriptor = weight!( "CLIP", diff --git a/crates/desktop/src-tauri/Cargo.toml b/crates/desktop/src-tauri/Cargo.toml index ef66671ade..83d504da8c 100644 --- a/crates/desktop/src-tauri/Cargo.toml +++ b/crates/desktop/src-tauri/Cargo.toml @@ -23,11 +23,12 @@ tauri-build = { version = "2.0.4", features = [] } # Internal filesys = { path = "../../lib/files/filesys" } memory_caching = { path = "../../lib/caching/memory_caching" } +ml_weights_registry = { path = "../ml_weights_registry" } primitives = { path = "../../lib/data/primitives" } # Internal ML # TODO: Only on Windows and Linux -ml_models = { path = "../ml_models" } +ml_models = { path = "../ml_models", optional = true } # External #openssl = { version = "0.10", features = ["vendored"] } @@ -62,6 +63,12 @@ libloading = "0.8.6" serial_test = "3.2.0" assertor = "0.0.3" +[target.'cfg(target_os = "macos")'.features] +default = [] + +[target.'cfg(not(target_os = "macos"))'.features] +default = ["dep:ml_models"] + [profile.dev] incremental = true # Compile your binary in smaller steps. diff --git a/crates/desktop/src-tauri/src/endpoints/realtime_image_endpoint.rs b/crates/desktop/src-tauri/src/endpoints/realtime_image_endpoint.rs index 33b29afedb..ad87bc7957 100644 --- a/crates/desktop/src-tauri/src/endpoints/realtime_image_endpoint.rs +++ b/crates/desktop/src-tauri/src/endpoints/realtime_image_endpoint.rs @@ -1,17 +1,23 @@ +#[cfg(feature = "ml_models")] +use { + ml_models::ml::stable_diffusion::lcm_pipeline::{lcm_pipeline, Args}, +}; + use crate::state::app_config::AppConfig; use crate::state::app_dir::AppDataRoot; +use crate::stubs::model_cache::ModelCache; +use crate::stubs::prompt_cache::PromptCache; use crate::utils::image::decode_base64_image::decode_base64_image; +use crate::utils::image::encode_dynamic_image_base64_png::encode_dynamic_image_base64_png; use crate::utils::image::encode_rgb_image_base64_png::encode_rgb_image_base64_png; use image::imageops::FilterType; use image::{DynamicImage, RgbImage}; use log::{error, info}; -use ml_models::ml::model_cache::ModelCache; -use ml_models::ml::prompt_cache::PromptCache; -use ml_models::ml::stable_diffusion::lcm_pipeline::{lcm_pipeline, Args}; -use ml_models::ml::weights_registry::weights::{CLIP_JSON, LYKON_DEAMSHAPER_7_TEXT_ENCODER_FP16, LYKON_DEAMSHAPER_7_VAE, SDXL_TURBO_CLIP_TEXT_ENCODER, SIMIANLUO_LCM_DREAMSHAPER_V7_UNET}; +use ml_weights_registry::weights_registry::weights::{CLIP_JSON, LYKON_DEAMSHAPER_7_TEXT_ENCODER_FP16, LYKON_DEAMSHAPER_7_VAE, SDXL_TURBO_CLIP_TEXT_ENCODER, SIMIANLUO_LCM_DREAMSHAPER_V7_UNET}; use std::path::PathBuf; use tauri::{AppHandle, State}; + const PROMPT_FILENAME : &str = "prompt.txt"; const PROMPT: &str = "shiba inu, cute dog, detailed, walking in a wooded forest, photorealistic, 8k"; @@ -43,27 +49,30 @@ pub async fn infer_image( .map_err(|err| format!("Couldn't hydrate image from base64: {}", err))?; // TODO(bt,2025-02-17): Running out of vram with full image buffer size - let image = image.resize(512, 512, FilterType::CatmullRom); + let mut image = image.resize(512, 512, FilterType::CatmullRom); - let result = do_infer_image( - &prompt, - image, - strength, - &model_config, - &model_cache, - prompt_cache, - &app_data_root - ).await; - - let image = match result { - Ok(image) => image, - Err(err) => { - error!("There was an error generating the image: {:?}", err); - return Err(format!("There was an error generating the image: {}", err)); - } - }; + #[cfg(feature = "ml_models")] + { + let result = infer_image_impl( + &prompt, + image, + strength, + &model_config, + &model_cache, + prompt_cache, + &app_data_root + ).await; - let bytes = encode_rgb_image_base64_png(image) + image = match result { + Ok(img) => DynamicImage::ImageRgb8(img), + Err(err) => { + error!("There was an error generating the image: {:?}", err); + return Err(format!("There was an error generating the image: {}", err)); + } + }; + } + + let bytes = encode_dynamic_image_base64_png(image) .map_err(|err| format!("failure to encode image: {:?}", err))?; info!("Inference successful; image converted to base64, serving back to browser..."); @@ -71,7 +80,8 @@ pub async fn infer_image( Ok(bytes) } -async fn do_infer_image( +#[cfg(feature = "ml_models")] +async fn infer_image_impl( prompt: &str, image: DynamicImage, strength: Option, diff --git a/crates/desktop/src-tauri/src/endpoints/remove_background_endpoint.rs b/crates/desktop/src-tauri/src/endpoints/remove_background_endpoint.rs index 72621249cb..6291f57948 100644 --- a/crates/desktop/src-tauri/src/endpoints/remove_background_endpoint.rs +++ b/crates/desktop/src-tauri/src/endpoints/remove_background_endpoint.rs @@ -1,37 +1,50 @@ //! Adapted from https://github.com/dnanhkhoa/rust-background-removal +#[cfg(feature = "ml_models")] +use { + ml_models::ml::background_removal::onnx_session::onnx_session, + ml_models::ml::background_removal::remove_image_background::remove_image_background, +}; + use crate::state::app_dir::AppDataRoot; +use crate::stubs::model_cache::ModelCache; +use crate::stubs::prompt_cache::PromptCache; use crate::utils::image::decode_base64_image::decode_base64_image; use crate::utils::image::encode_dynamic_image_base64_png::encode_dynamic_image_base64_png; use image::{imageops, DynamicImage}; use log::{error, info}; -use ml_models::ml::background_removal::onnx_session::onnx_session; -use ml_models::ml::background_removal::remove_image_background::remove_image_background; -use ml_models::ml::model_cache::ModelCache; -use ml_models::ml::weights_registry::weights::{DIS_MEDIUM_ONNX, SIMIANLUO_LCM_DREAMSHAPER_V7_UNET}; +use ml_weights_registry::weights_registry::weights::{DIS_MEDIUM_ONNX, SIMIANLUO_LCM_DREAMSHAPER_V7_UNET}; use tauri::{AppHandle, State}; /// This handler removes the background from an image. #[tauri::command] pub async fn remove_background( image: &str, - model_cache: State<'_, ModelCache>, app_data_root: State<'_, AppDataRoot>, - app: AppHandle, ) -> Result { info!("remove_background endpoint called."); - let image = decode_base64_image(image) - .map_err(|err| format!("Couldn't hydrate image from base64: {}", err))?; + let mut image = decode_base64_image(image) + .map_err(|err| format!("Couldn't hydrate image from base64: {}", err))?; - let model_path = app_data_root.weights_dir().weight_path(&DIS_MEDIUM_ONNX); - - let image = remove_image_background(model_path, image) - .await - .map_err(|err| format!("Couldn't remove image from image: {}", err))?; + #[cfg(feature = "ml_models")] + { + image = remove_background_impl(&app_data_root, image).await?; + } let image = encode_dynamic_image_base64_png(image) .map_err(|err| format!("failure to encode image: {:?}", err))?; Ok(image) } + +#[cfg(feature = "ml_models")] +async fn remove_background_impl(app_data_root: &AppDataRoot, image: DynamicImage) -> Result { + let model_path = app_data_root.weights_dir().weight_path(&DIS_MEDIUM_ONNX); + + let image = remove_image_background(model_path, image) + .await + .map_err(|err| format!("Couldn't remove image from image: {}", err))?; + + Ok(image) +} diff --git a/crates/desktop/src-tauri/src/endpoints/text_to_image_endpoint.rs b/crates/desktop/src-tauri/src/endpoints/text_to_image_endpoint.rs index e7b9b2c5a1..c1fff1ee4b 100644 --- a/crates/desktop/src-tauri/src/endpoints/text_to_image_endpoint.rs +++ b/crates/desktop/src-tauri/src/endpoints/text_to_image_endpoint.rs @@ -1,18 +1,24 @@ +#[cfg(feature = "ml_models")] +use { + ml_models::ml::stable_diffusion::lcm_pipeline::{lcm_pipeline, Args}, +}; + use crate::state::app_config::AppConfig; use crate::state::app_dir::AppDataRoot; +use crate::stubs::model_cache::ModelCache; +use crate::stubs::prompt_cache::PromptCache; use crate::utils::image::decode_base64_image::decode_base64_image; +use crate::utils::image::encode_dynamic_image_base64_png::encode_dynamic_image_base64_png; use crate::utils::image::encode_rgb_image_base64_png::encode_rgb_image_base64_png; use image::imageops::FilterType; use image::{DynamicImage, ImageReader, RgbImage}; use log::{error, info}; -use ml_models::ml::model_cache::ModelCache; -use ml_models::ml::prompt_cache::PromptCache; -use ml_models::ml::stable_diffusion::lcm_pipeline::{lcm_pipeline, Args}; +use ml_weights_registry::weights_registry::weights::{CLIP_JSON, LYKON_DEAMSHAPER_7_TEXT_ENCODER_FP16, LYKON_DEAMSHAPER_7_VAE, SDXL_TURBO_CLIP_TEXT_ENCODER, SIMIANLUO_LCM_DREAMSHAPER_V7_UNET}; + use once_cell::sync::Lazy; use std::io::Cursor; use std::path::PathBuf; use tauri::{AppHandle, State}; -use ml_models::ml::weights_registry::weights::{CLIP_JSON, LYKON_DEAMSHAPER_7_TEXT_ENCODER_FP16, LYKON_DEAMSHAPER_7_VAE, SDXL_TURBO_CLIP_TEXT_ENCODER, SIMIANLUO_LCM_DREAMSHAPER_V7_UNET}; const RANDOM_SEED: u32 = 42; @@ -39,28 +45,31 @@ pub async fn text_to_image( ) -> Result { info!("text_to_image endpoint called."); - let image = IMAGE.resize(512, 512, FilterType::CatmullRom); + let mut image = IMAGE.resize(512, 512, FilterType::CatmullRom); - let result = do_infer_image( - &prompt, - image, - Some(STRENGTH), - &model_config, - &model_cache, - prompt_cache, - app, - &app_data_root - ).await; - - let image = match result { - Ok(image) => image, - Err(err) => { - error!("There was an error generating the image: {:?}", err); - return Err(format!("There was an error generating the image: {}", err)); - } - }; + #[cfg(feature = "ml_models")] + { + let result = text_to_image_impl( + &prompt, + image, + Some(STRENGTH), + &model_config, + &model_cache, + prompt_cache, + app, + &app_data_root + ).await; - let bytes = encode_rgb_image_base64_png(image) + image = match result { + Ok(img) => DynamicImage::ImageRgb8(img), + Err(err) => { + error!("There was an error generating the image: {:?}", err); + return Err(format!("There was an error generating the image: {}", err)); + } + }; + } + + let bytes = encode_dynamic_image_base64_png(image) .map_err(|err| format!("failure to encode image: {:?}", err))?; info!("Inference successful; image converted to base64, serving back to browser..."); @@ -68,7 +77,8 @@ pub async fn text_to_image( Ok(bytes) } -async fn do_infer_image( +#[cfg(feature = "ml_models")] +async fn text_to_image_impl( prompt: &str, image: DynamicImage, strength: Option, diff --git a/crates/desktop/src-tauri/src/lib.rs b/crates/desktop/src-tauri/src/lib.rs index a80c30796a..169a4c9c6f 100644 --- a/crates/desktop/src-tauri/src/lib.rs +++ b/crates/desktop/src-tauri/src/lib.rs @@ -1,6 +1,7 @@ pub mod endpoints; pub mod events; pub mod state; +pub mod stubs; pub mod threads; pub mod transfer; pub mod utils; @@ -11,10 +12,11 @@ use crate::endpoints::remove_background_endpoint::remove_background; use crate::endpoints::test_counter::test_counter; use crate::endpoints::text_to_image_endpoint::text_to_image; use crate::state::app_config::AppConfig; +use crate::stubs::model_cache::ModelCache; +use crate::stubs::prompt_cache::PromptCache; use crate::threads::downloader_thread::downloader_thread; use crate::utils::log_environment_details::log_environment_details; -use ml_models::ml::model_cache::ModelCache; -use ml_models::ml::prompt_cache::PromptCache; + use tauri_plugin_log::Target; use tauri_plugin_log::TargetKind; @@ -27,6 +29,7 @@ pub fn run() { let config = AppConfig::init() .expect("config should load"); + let prompt_cache = PromptCache::with_capacity(8) .expect("prompt cache should load"); diff --git a/crates/desktop/src-tauri/src/state/app_config.rs b/crates/desktop/src-tauri/src/state/app_config.rs index 37bca072fa..fe2e602ddc 100644 --- a/crates/desktop/src-tauri/src/state/app_config.rs +++ b/crates/desktop/src-tauri/src/state/app_config.rs @@ -1,7 +1,7 @@ use crate::state::app_dir::AppDataRoot; use crate::state::os_platform::OsPlatform; use crate::state::yaml_config::YamlConfig; -use ml_models::ml::model_config::ModelConfig; +use crate::stubs::model_config::ModelConfig; const DEFAULT_SD_IMAGE_WIDTH: usize = 1024; const DEFAULT_SD_IMAGE_HEIGHT: usize = 1024; diff --git a/crates/desktop/src-tauri/src/state/app_dir.rs b/crates/desktop/src-tauri/src/state/app_dir.rs index 61b02f9977..0d515edf75 100644 --- a/crates/desktop/src-tauri/src/state/app_dir.rs +++ b/crates/desktop/src-tauri/src/state/app_dir.rs @@ -2,7 +2,7 @@ use crate::state::expanduser::expanduser; use crate::state::os_platform::OsPlatform; use anyhow::anyhow; use directories::UserDirs; -use ml_models::ml::weights_registry::weight_descriptor::WeightDescriptor; +use ml_weights_registry::weights_registry::weight_descriptor::WeightDescriptor; use std::path::{Path, PathBuf}; use tempdir::TempDir; use tempfile::{Builder, NamedTempFile}; diff --git a/crates/desktop/src-tauri/src/stubs/mod.rs b/crates/desktop/src-tauri/src/stubs/mod.rs new file mode 100644 index 0000000000..62ecaceb95 --- /dev/null +++ b/crates/desktop/src-tauri/src/stubs/mod.rs @@ -0,0 +1,3 @@ +pub mod model_cache; +pub mod model_config; +pub mod prompt_cache; \ No newline at end of file diff --git a/crates/desktop/src-tauri/src/stubs/model_cache.rs b/crates/desktop/src-tauri/src/stubs/model_cache.rs new file mode 100644 index 0000000000..9737dc1a07 --- /dev/null +++ b/crates/desktop/src-tauri/src/stubs/model_cache.rs @@ -0,0 +1,14 @@ +#[cfg(feature = "ml_models")] +use ml_models::ml::model_cache::ModelCache; + +#[cfg(not(feature = "ml_models"))] +pub struct ModelCache { + // Intentionally left blank +} + +#[cfg(not(feature = "ml_models"))] +impl ModelCache { + pub fn new() -> Self { + Self {} + } +} diff --git a/crates/desktop/src-tauri/src/stubs/model_config.rs b/crates/desktop/src-tauri/src/stubs/model_config.rs new file mode 100644 index 0000000000..0047bb375a --- /dev/null +++ b/crates/desktop/src-tauri/src/stubs/model_config.rs @@ -0,0 +1,14 @@ +#[cfg(feature = "ml_models")] +use ml_models::ml::model_config::ModelConfig; + +#[cfg(not(feature = "ml_models"))] +pub struct ModelConfig { + // Intentionally left blank +} + +#[cfg(not(feature = "ml_models"))] +impl ModelConfig { + pub fn init() -> anyhow::Result { + Ok(Self {}) + } +} diff --git a/crates/desktop/src-tauri/src/stubs/prompt_cache.rs b/crates/desktop/src-tauri/src/stubs/prompt_cache.rs new file mode 100644 index 0000000000..907a657246 --- /dev/null +++ b/crates/desktop/src-tauri/src/stubs/prompt_cache.rs @@ -0,0 +1,15 @@ + +#[cfg(feature = "ml_models")] +pub use ml_models::ml::prompt_cache::PromptCache; + +#[cfg(not(feature = "ml_models"))] +pub struct PromptCache { + // Intentionally left blank +} + +#[cfg(not(feature = "ml_models"))] +impl PromptCache { + pub fn with_capacity(capacity: usize) -> anyhow::Result { + Ok(Self {}) + } +} diff --git a/crates/desktop/src-tauri/src/threads/downloader_thread.rs b/crates/desktop/src-tauri/src/threads/downloader_thread.rs index 0f7d8a5c07..b9bf7813d3 100644 --- a/crates/desktop/src-tauri/src/threads/downloader_thread.rs +++ b/crates/desktop/src-tauri/src/threads/downloader_thread.rs @@ -1,11 +1,11 @@ use crate::events::notification_event::{NotificationEvent, NotificationModelType}; use crate::state::app_dir::AppDataRoot; use crate::transfer::download::{download_async, ProgressUpdate}; -use futures::stream::FuturesUnordered; use futures::StreamExt; +use futures::stream::FuturesUnordered; use log::{debug, error, info}; -use ml_models::ml::weights_registry::weight_descriptor::WeightFunction; -use ml_models::ml::weights_registry::weights::{CLIP_JSON, DIS_MEDIUM_ONNX, LYKON_DEAMSHAPER_7_TEXT_ENCODER_FP16, LYKON_DEAMSHAPER_7_VAE, SDXL_TURBO_CLIP_TEXT_ENCODER, SDXL_TURBO_CLIP_TEXT_ENCODER_2, SDXL_TURBO_UNET, SDXL_TURBO_VAE, SIMIANLUO_LCM_DREAMSHAPER_V7_UNET}; +use ml_weights_registry::weights_registry::weight_descriptor::WeightFunction; +use ml_weights_registry::weights_registry::weights::{CLIP_JSON, DIS_MEDIUM_ONNX, LYKON_DEAMSHAPER_7_TEXT_ENCODER_FP16, LYKON_DEAMSHAPER_7_VAE, SDXL_TURBO_CLIP_TEXT_ENCODER, SDXL_TURBO_CLIP_TEXT_ENCODER_2, SDXL_TURBO_UNET, SDXL_TURBO_VAE, SIMIANLUO_LCM_DREAMSHAPER_V7_UNET}; use std::collections::VecDeque; use std::path::PathBuf; use std::sync::mpsc::Receiver; diff --git a/frontend/realtime/yarn.lock b/frontend/realtime/yarn.lock index 53d6272415..0f745335c0 100644 --- a/frontend/realtime/yarn.lock +++ b/frontend/realtime/yarn.lock @@ -222,11 +222,6 @@ resolved "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz" integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== -"@esbuild/win32-x64@0.21.5": - version "0.21.5" - resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz" - integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== - "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz" @@ -741,10 +736,10 @@ resolved "https://registry.npmjs.org/@remix-run/router/-/router-1.19.1.tgz" integrity sha512-S45oynt/WH19bHbIXjtli6QmwNYvaz+vtnubvNpNDvUOoA/OWh6j1OikIP3G+v5GHdxyC6EXoChG3HgYGEUfcg== -"@rollup/rollup-win32-x64-msvc@4.24.0": +"@rollup/rollup-darwin-arm64@4.24.0": version "4.24.0" - resolved "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz" - integrity sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw== + resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz" + integrity sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA== "@sigstore/bundle@^2.3.2": version "2.3.2" @@ -816,10 +811,10 @@ resolved "https://registry.npmjs.org/@tauri-apps/api/-/api-2.2.0.tgz" integrity sha512-R8epOeZl1eJEl603aUMIGb4RXlhPjpgxbGVEaqY+0G5JG9vzV/clNlzTeqc+NLYXVqXcn8mb4c5b9pJIUDEyAg== -"@tauri-apps/cli-win32-x64-msvc@2.2.7": +"@tauri-apps/cli-darwin-arm64@2.2.7": version "2.2.7" - resolved "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.2.7.tgz" - integrity sha512-ZB8Kw90j8Ld+9tCWyD2fWCYfIrzbQohJ4DJSidNwbnehlZzP7wAz6Z3xjsvUdKtQ3ibtfoeTqVInzCCEpI+pWg== + resolved "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.2.7.tgz" + integrity sha512-54kcpxZ3X1Rq+pPTzk3iIcjEVY4yv493uRx/80rLoAA95vAC0c//31Whz75UVddDjJfZvXlXZ3uSZ+bnCOnt0A== "@tauri-apps/cli@^2.2.7": version "2.2.7" @@ -2082,6 +2077,11 @@ fs-minipass@^3.0.0, fs-minipass@^3.0.3: dependencies: minipass "^7.0.3" +fsevents@~2.3.2, fsevents@~2.3.3: + version "2.3.3" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + function-bind@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz"