diff --git a/Cargo.lock b/Cargo.lock index 9c3b1bd..0098f10 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -50,6 +50,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "aligned-vec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" + [[package]] name = "alloc-no-stdlib" version = "2.0.4" @@ -86,6 +92,23 @@ version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" + +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.59", +] + [[package]] name = "argh" version = "0.1.12" @@ -105,7 +128,7 @@ dependencies = [ "argh_shared", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.59", ] [[package]] @@ -278,7 +301,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.59", ] [[package]] @@ -289,13 +312,13 @@ checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" [[package]] name = "async-trait" -version = "0.1.77" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.59", ] [[package]] @@ -340,6 +363,29 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "av1-grain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6678909d8c5d46a42abcf571271e15fdbc0a225e3646cf23762cd415046c78bf" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876c75a42f6364451a033496a14c44bffe41f5f4a8236f697391f11024e596d2" +dependencies = [ + "arrayvec", +] + [[package]] name = "axum" version = "0.6.20" @@ -499,7 +545,7 @@ dependencies = [ "heck 0.4.1", "proc-macro-error", "quote", - "syn 2.0.50", + "syn 2.0.59", "ubyte", ] @@ -530,6 +576,12 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" + [[package]] name = "bindgen" version = "0.69.4" @@ -539,7 +591,7 @@ dependencies = [ "bitflags 2.4.2", "cexpr", "clang-sys", - "itertools", + "itertools 0.12.1", "lazy_static", "lazycell", "log", @@ -549,10 +601,27 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.50", + "syn 2.0.59", "which", ] +[[package]] +name = "bindgen_cuda" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f8489af5b7d17a81bffe37e0f4d6e1e4de87c87329d05447f22c35d95a1227d" +dependencies = [ + "glob", + "num_cpus", + "rayon", +] + +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + [[package]] name = "bitflags" version = "1.3.2" @@ -571,6 +640,12 @@ version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d084b0137aaa901caf9f1e8b21daa6aa24d41cd806e111335541eff9683bd6" +[[package]] +name = "bitstream-io" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06c9989a51171e2e81038ab168b6ae22886fe9ded214430dbb4f41c28cf176da" + [[package]] name = "blake3" version = "1.5.0" @@ -663,6 +738,12 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3240a4cb09cf0da6a51641bd40ce90e96ea6065e3a1adc46434029254bcc2d09" +[[package]] +name = "built" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41bfbdb21256b87a8b5e80fab81a8eed158178e812fd7ba451907518b2742f16" + [[package]] name = "bumpalo" version = "3.15.0" @@ -674,6 +755,20 @@ name = "bytemuck" version = "1.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4da9a32f3fed317401fa3c862968128267c3106685286e15d5aaa3d7389c2f60" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.59", +] [[package]] name = "byteorder" @@ -720,6 +815,71 @@ dependencies = [ "system-deps 6.2.0", ] +[[package]] +name = "candle-core" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f1b20174c1707e20f4cb364a355b449803c03e9b0c9193324623cf9787a4e00" +dependencies = [ + "byteorder", + "candle-kernels", + "cudarc", + "gemm", + "half", + "memmap2", + "num-traits", + "num_cpus", + "rand 0.8.5", + "rand_distr", + "rayon", + "safetensors", + "thiserror", + "yoke", + "zip", +] + +[[package]] +name = "candle-kernels" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5845911a44164ebb73b56a0e23793ba1b583bad102af7400fe4768babc5815b2" +dependencies = [ + "bindgen_cuda", +] + +[[package]] +name = "candle-nn" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66a27533c8edfc915a6459f9850641ef523a829fa1a181c670766c1f752d873a" +dependencies = [ + "candle-core", + "half", + "num-traits", + "rayon", + "safetensors", + "serde", + "thiserror", +] + +[[package]] +name = "candle-transformers" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5847699f0643da05e57fc473672566e93dc36d82c1b7eeb970c6154d3434fe1" +dependencies = [ + "byteorder", + "candle-core", + "candle-nn", + "num-traits", + "rand 0.8.5", + "rayon", + "serde", + "serde_json", + "serde_plain", + "tracing", +] + [[package]] name = "cargo_toml" version = "0.15.3" @@ -1083,6 +1243,12 @@ version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-common" version = "0.1.6" @@ -1117,7 +1283,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.50", + "syn 2.0.59", ] [[package]] @@ -1127,7 +1293,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30d2b3721e861707777e3195b0158f950ae6dc4a27e4d02ff9f67e3eb3de199e" dependencies = [ "quote", - "syn 2.0.50", + "syn 2.0.59", ] [[package]] @@ -1135,6 +1301,9 @@ name = "cudarc" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9395df0cab995685664e79cc35ad6302bf08fb9c5d82301875a183affe1278b1" +dependencies = [ + "half", +] [[package]] name = "darling" @@ -1181,7 +1350,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.50", + "syn 2.0.59", ] [[package]] @@ -1203,7 +1372,7 @@ checksum = "c5a91391accf613803c2a9bf9abccdbaa07c54b4244a5b64883f9c3c137c86be" dependencies = [ "darling_core 0.20.6", "quote", - "syn 2.0.50", + "syn 2.0.59", ] [[package]] @@ -1229,6 +1398,37 @@ dependencies = [ "serde", ] +[[package]] +name = "derive_builder" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0350b5cb0331628a5916d6c5c0b72e97393b8b6b03b47a9284f4e7f5a405ffd7" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d48cda787f839151732d396ac69e3473923d54312c070ee21e9effcaa8ca0b1d" +dependencies = [ + "darling 0.20.6", + "proc-macro2", + "quote", + "syn 2.0.59", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" +dependencies = [ + "derive_builder_core", + "syn 2.0.59", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -1337,6 +1537,16 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +[[package]] +name = "dyn-stack" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e53799688f5632f364f8fb387488dd05db9fe45db7011be066fc20e7027f8b" +dependencies = [ + "bytemuck", + "reborrow", +] + [[package]] name = "edgen" version = "0.1.5" @@ -1372,6 +1582,7 @@ name = "edgen_core" version = "0.1.0" dependencies = [ "ahash 0.8.9", + "async-trait", "dashmap", "derive_more", "directories", @@ -1380,7 +1591,7 @@ dependencies = [ "notify", "num_cpus", "once_cell", - "rubato 0.14.1", + "rubato", "serde", "serde_yaml", "smol", @@ -1408,6 +1619,22 @@ dependencies = [ "tracing", ] +[[package]] +name = "edgen_rt_image_generation_candle" +version = "0.1.0" +dependencies = [ + "async-trait", + "candle-core", + "candle-transformers", + "edgen_core", + "image 0.25.1", + "rand 0.8.5", + "thiserror", + "tokenizers", + "tokio", + "tracing", +] + [[package]] name = "edgen_rt_llama_cpp" version = "0.1.0" @@ -1453,6 +1680,7 @@ dependencies = [ "derive_more", "edgen_core", "edgen_rt_chat_faker", + "edgen_rt_image_generation_candle", "edgen_rt_llama_cpp", "edgen_rt_whisper_cpp", "either", @@ -1463,8 +1691,8 @@ dependencies = [ "levenshtein", "once_cell", "pin-project", - "reqwest", - "rubato 0.15.0", + "reqwest 0.12.3", + "rubato", "serde", "serde_derive", "serde_json", @@ -1535,6 +1763,18 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "enum-as-inner" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 2.0.59", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -1551,6 +1791,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "esaxx-rs" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d817e038c30374a4bcb22f94d0a8a0e216958d4c3dcde369b1439fec4bdda6e6" + [[package]] name = "event-listener" version = "2.5.3" @@ -1599,6 +1845,28 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "exr" +version = "1.72.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "887d93f60543e9a9362ef8a21beedd0a833c5d9610e18c67abe15a5963dcb1a4" +dependencies = [ + "bit_field", + "flume 0.11.0", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec", + "zune-inflate", +] + +[[package]] +name = "extended" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af9673d8203fcb076b19dfd17e38b3d4ae9f44959416ea532ce72415a6020365" + [[package]] name = "fastrand" version = "1.9.0" @@ -1629,7 +1897,7 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" dependencies = [ - "memoffset 0.9.0", + "memoffset", "rustc_version", ] @@ -1668,6 +1936,15 @@ dependencies = [ "spin", ] +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "spin", +] + [[package]] name = "fnv" version = "1.0.7" @@ -1801,7 +2078,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.59", ] [[package]] @@ -1929,6 +2206,124 @@ dependencies = [ "x11", ] +[[package]] +name = "gemm" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ab24cc62135b40090e31a76a9b2766a501979f3070fa27f689c27ec04377d32" +dependencies = [ + "dyn-stack", + "gemm-c32", + "gemm-c64", + "gemm-common", + "gemm-f16", + "gemm-f32", + "gemm-f64", + "num-complex", + "num-traits", + "paste", + "raw-cpuid", + "seq-macro", +] + +[[package]] +name = "gemm-c32" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9c030d0b983d1e34a546b86e08f600c11696fde16199f971cd46c12e67512c0" +dependencies = [ + "dyn-stack", + "gemm-common", + "num-complex", + "num-traits", + "paste", + "raw-cpuid", + "seq-macro", +] + +[[package]] +name = "gemm-c64" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbb5f2e79fefb9693d18e1066a557b4546cd334b226beadc68b11a8f9431852a" +dependencies = [ + "dyn-stack", + "gemm-common", + "num-complex", + "num-traits", + "paste", + "raw-cpuid", + "seq-macro", +] + +[[package]] +name = "gemm-common" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2e7ea062c987abcd8db95db917b4ffb4ecdfd0668471d8dc54734fdff2354e8" +dependencies = [ + "bytemuck", + "dyn-stack", + "half", + "num-complex", + "num-traits", + "once_cell", + "paste", + "pulp", + "raw-cpuid", + "rayon", + "seq-macro", + "sysctl", +] + +[[package]] +name = "gemm-f16" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ca4c06b9b11952071d317604acb332e924e817bd891bec8dfb494168c7cedd4" +dependencies = [ + "dyn-stack", + "gemm-common", + "gemm-f32", + "half", + "num-complex", + "num-traits", + "paste", + "raw-cpuid", + "rayon", + "seq-macro", +] + +[[package]] +name = "gemm-f32" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9a69f51aaefbd9cf12d18faf273d3e982d9d711f60775645ed5c8047b4ae113" +dependencies = [ + "dyn-stack", + "gemm-common", + "num-complex", + "num-traits", + "paste", + "raw-cpuid", + "seq-macro", +] + +[[package]] +name = "gemm-f64" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa397a48544fadf0b81ec8741e5c0fba0043008113f71f2034def1935645d2b0" +dependencies = [ + "dyn-stack", + "gemm-common", + "num-complex", + "num-traits", + "paste", + "raw-cpuid", + "seq-macro", +] + [[package]] name = "generator" version = "0.7.5" @@ -1976,6 +2371,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "gif" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" +dependencies = [ + "color_quant", + "weezl", +] + [[package]] name = "gimli" version = "0.28.1" @@ -2078,20 +2483,20 @@ dependencies = [ [[package]] name = "glommio" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f09bf53139d5680da6325b4e79c6bc1518e94a65ab74df14b7e3693a8c78b" +checksum = "e1f8bc1fce949d18098dc0a4e861314e40351a0144ebf61e59bdb5254a2273b2" dependencies = [ "ahash 0.7.8", "backtrace", - "bitflags 1.3.2", + "bitflags 2.4.2", "bitmaps", "buddy-alloc", "cc", "concurrent-queue 1.2.4", "crossbeam", "enclose", - "flume", + "flume 0.10.14", "futures-lite 1.13.0", "intrusive-collections", "lazy_static", @@ -2215,6 +2620,20 @@ dependencies = [ "tracing", ] +[[package]] +name = "half" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "bytemuck", + "cfg-if", + "crunchy", + "num-traits", + "rand 0.8.5", + "rand_distr", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -2413,7 +2832,7 @@ dependencies = [ "httpdate", "itoa 1.0.10", "pin-project-lite", - "socket2 0.4.10", + "socket2 0.5.5", "tokio", "tower-service", "tracing", @@ -2562,6 +2981,45 @@ dependencies = [ "num-traits", ] +[[package]] +name = "image" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd54d660e773627692c524beaad361aca785a4f9f5730ce91f42aabe5bce3d11" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "exr", + "gif", + "image-webp", + "num-traits", + "png", + "qoi", + "ravif", + "rayon", + "rgb", + "tiff", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "image-webp" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a84a25dcae3ac487bc24ef280f9e20c79c9b1a3e5e32cbed3041d1c514aa87c" +dependencies = [ + "byteorder", + "thiserror", +] + +[[package]] +name = "imgref" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44feda355f4159a7c757171a77de25daf6411e217b4cabd03bd6650690468126" + [[package]] name = "indexmap" version = "1.9.3" @@ -2635,13 +3093,24 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.59", +] + [[package]] name = "intrusive-collections" version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b694dc9f70c3bda874626d2aed13b780f137aab435f4e9814121955cf706122e" dependencies = [ - "memoffset 0.9.0", + "memoffset", ] [[package]] @@ -2659,6 +3128,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "0.4.8" @@ -2723,6 +3201,12 @@ dependencies = [ "libc", ] +[[package]] +name = "jpeg-decoder" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" + [[package]] name = "js-sys" version = "0.3.68" @@ -2789,6 +3273,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +[[package]] +name = "lebe" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" + [[package]] name = "levenshtein" version = "1.0.5" @@ -2825,6 +3315,17 @@ version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +[[package]] +name = "libfuzzer-sys" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7" +dependencies = [ + "arbitrary", + "cc", + "once_cell", +] + [[package]] name = "libloading" version = "0.7.4" @@ -2845,6 +3346,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + [[package]] name = "libredox" version = "0.0.1" @@ -2947,12 +3454,37 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" +dependencies = [ + "imgref", +] + [[package]] name = "mac" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" +[[package]] +name = "macro_rules_attribute" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a82271f7bc033d84bbca59a3ce3e4159938cb08a9c3aebbe54d215131518a13" +dependencies = [ + "macro_rules_attribute-proc_macro", + "paste", +] + +[[package]] +name = "macro_rules_attribute-proc_macro" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dd856d451cc0da70e2ef2ce95a18e39a93b7558bedf10201ad28503f918568" + [[package]] name = "malloc_buf" version = "0.0.6" @@ -2997,6 +3529,16 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", + "rayon", +] + [[package]] name = "memchr" version = "2.7.1" @@ -3004,12 +3546,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] -name = "memoffset" -version = "0.6.5" +name = "memmap2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322" dependencies = [ - "autocfg", + "libc", + "stable_deref_trait", ] [[package]] @@ -3071,6 +3614,27 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "monostate" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a20fffcd8ca4c69d31e036a71abc400147b41f90895df4edcb36497a1f8af8bf" +dependencies = [ + "monostate-impl", + "serde", +] + +[[package]] +name = "monostate-impl" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf307cbbbd777a9c10cec88ddafee572b3484caad5cce0c9236523c3803105a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.59", +] + [[package]] name = "multer" version = "3.0.0" @@ -3152,15 +3716,14 @@ checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" [[package]] name = "nix" -version = "0.23.2" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 1.3.2", - "cc", + "bitflags 2.4.2", "cfg-if", "libc", - "memoffset 0.6.5", + "memoffset", ] [[package]] @@ -3179,6 +3742,12 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + [[package]] name = "normpath" version = "1.2.0" @@ -3217,12 +3786,24 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-complex" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" dependencies = [ + "bytemuck", "num-traits", ] @@ -3232,6 +3813,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.59", +] + [[package]] name = "num-integer" version = "0.1.46" @@ -3241,6 +3833,18 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.18" @@ -3248,6 +3852,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -3341,6 +3946,28 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "onig" +version = "6.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c4b31c8722ad9171c6d77d3557db078cab2bd50afcc9d09c8b315c59df8ca4f" +dependencies = [ + "bitflags 1.3.2", + "libc", + "once_cell", + "onig_sys", +] + +[[package]] +name = "onig_sys" +version = "69.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b829e3d7e9cc74c7e315ee8edb185bf4190da5acde74afd7fc59c35b1f086e7" +dependencies = [ + "cc", + "pkg-config", +] + [[package]] name = "open" version = "3.2.0" @@ -3385,7 +4012,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.59", ] [[package]] @@ -3478,6 +4105,12 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + [[package]] name = "pathdiff" version = "0.2.1" @@ -3594,7 +4227,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.59", ] [[package]] @@ -3641,7 +4274,7 @@ checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.59", ] [[package]] @@ -3755,7 +4388,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" dependencies = [ "proc-macro2", - "syn 2.0.50", + "syn 2.0.59", ] [[package]] @@ -3809,13 +4442,32 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "a56dea16b0a29e94408b9aa5e2940a4eedbd128a1ba20e8f7ae60fd3d465af0e" dependencies = [ "unicode-ident", ] +[[package]] +name = "profiling" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd" +dependencies = [ + "quote", + "syn 2.0.59", +] + [[package]] name = "prost" version = "0.12.3" @@ -3833,10 +4485,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", - "itertools", + "itertools 0.11.0", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.59", ] [[package]] @@ -3848,6 +4500,33 @@ dependencies = [ "prost", ] +[[package]] +name = "pulp" +version = "0.18.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03457ac216146f43f921500bac4e892d5cd32b0479b929cbfc90f95cd6c599c2" +dependencies = [ + "bytemuck", + "libm", + "num-complex", + "reborrow", +] + +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + [[package]] name = "quick-xml" version = "0.31.0" @@ -3930,28 +4609,128 @@ dependencies = [ ] [[package]] -name = "rand_hc" -version = "0.2.0" +name = "rand_distr" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_pcg" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rav1e" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" +dependencies = [ + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools 0.12.1", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "once_cell", + "paste", + "profiling", + "rand 0.8.5", + "rand_chacha 0.3.1", + "simd_helpers", + "system-deps 6.2.0", + "thiserror", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc13288f5ab39e6d7c9d501759712e6969fcc9734220846fc9ed26cae2cc4234" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + +[[package]] +name = "raw-cpuid" +version = "10.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "raw-window-handle" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" + +[[package]] +name = "rayon" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ - "rand_core 0.5.1", + "either", + "rayon-core", ] [[package]] -name = "rand_pcg" -version = "0.2.1" +name = "rayon-cond" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +checksum = "059f538b55efd2309c9794130bc149c6a553db90e9d99c2030785c82f0bd7df9" dependencies = [ - "rand_core 0.5.1", + "either", + "itertools 0.11.0", + "rayon", ] [[package]] -name = "raw-window-handle" -version = "0.5.2" +name = "rayon-core" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] [[package]] name = "realfft" @@ -3962,6 +4741,12 @@ dependencies = [ "rustfft", ] +[[package]] +name = "reborrow" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03251193000f4bd3b042892be858ee50e8b3719f2b08e5833ac4353724632430" + [[package]] name = "redox_syscall" version = "0.4.1" @@ -4046,7 +4831,6 @@ dependencies = [ "js-sys", "log", "mime", - "mime_guess", "native-tls", "once_cell", "percent-encoding", @@ -4069,6 +4853,43 @@ dependencies = [ "winreg 0.50.0", ] +[[package]] +name = "reqwest" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e6cc1e89e689536eb5aeede61520e874df5a4707df811cd5da4aa5fbb2aae19" +dependencies = [ + "base64 0.22.0", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http 1.0.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.1.0", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "mime_guess", + "once_cell", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg 0.52.0", +] + [[package]] name = "reserve-port" version = "2.0.1" @@ -4103,6 +4924,15 @@ dependencies = [ "windows 0.37.0", ] +[[package]] +name = "rgb" +version = "0.8.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8" +dependencies = [ + "bytemuck", +] + [[package]] name = "ring" version = "0.17.8" @@ -4127,18 +4957,6 @@ dependencies = [ "libc", ] -[[package]] -name = "rubato" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6dd52e80cfc21894deadf554a5673002938ae4625f7a283e536f9cf7c17b0d5" -dependencies = [ - "num-complex", - "num-integer", - "num-traits", - "realfft", -] - [[package]] name = "rubato" version = "0.15.0" @@ -4274,6 +5092,16 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" +[[package]] +name = "safetensors" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d980e6bfb34436fb0a81e42bc41af43f11805bbbca443e7f68e9faaabe669ed" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "same-file" version = "1.0.6" @@ -4356,6 +5184,12 @@ dependencies = [ "serde", ] +[[package]] +name = "seq-macro" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4" + [[package]] name = "serde" version = "1.0.197" @@ -4373,7 +5207,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.59", ] [[package]] @@ -4398,6 +5232,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_plain" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1fc6db65a611022b23a0dec6975d63fb80a302cb3388835ff02c097258d50" +dependencies = [ + "serde", +] + [[package]] name = "serde_repr" version = "0.1.18" @@ -4406,7 +5249,7 @@ checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.59", ] [[package]] @@ -4479,7 +5322,7 @@ dependencies = [ "darling 0.20.6", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.59", ] [[package]] @@ -4578,6 +5421,15 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + [[package]] name = "siphasher" version = "0.3.11" @@ -4679,6 +5531,18 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spm_precompiled" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5851699c4033c63636f7ea4cf7b7c1f1bf06d0cc03cfb42e711de5a5c46cf326" +dependencies = [ + "base64 0.13.1", + "nom", + "serde", + "unicode-segmentation", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -4746,9 +5610,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "symphonia" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62e48dba70095f265fdb269b99619b95d04c89e619538138383e63310b14d941" +checksum = "815c942ae7ee74737bb00f965fa5b5a2ac2ce7b6c01c0cc169bbeaf7abd5f5a9" dependencies = [ "lazy_static", "symphonia-bundle-flac", @@ -4759,18 +5623,19 @@ dependencies = [ "symphonia-codec-pcm", "symphonia-codec-vorbis", "symphonia-core", + "symphonia-format-caf", "symphonia-format-isomp4", "symphonia-format-mkv", "symphonia-format-ogg", - "symphonia-format-wav", + "symphonia-format-riff", "symphonia-metadata", ] [[package]] name = "symphonia-bundle-flac" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f23b0482a7cb18fcdf9981ab0b78df800ef0080187d294650023c462439058d" +checksum = "72e34f34298a7308d4397a6c7fbf5b84c5d491231ce3dd379707ba673ab3bd97" dependencies = [ "log", "symphonia-core", @@ -4780,11 +5645,10 @@ dependencies = [ [[package]] name = "symphonia-bundle-mp3" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f31d7fece546f1e6973011a9eceae948133bbd18fd3d52f6073b1e38ae6368a" +checksum = "c01c2aae70f0f1fb096b6f0ff112a930b1fb3626178fba3ae68b09dce71706d4" dependencies = [ - "bitflags 1.3.2", "lazy_static", "log", "symphonia-core", @@ -4793,9 +5657,9 @@ dependencies = [ [[package]] name = "symphonia-codec-aac" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68bdd75b25ce4b84b12a4bd20bfea2460c2dbd7fc1d227ef5533504d3168109d" +checksum = "cdbf25b545ad0d3ee3e891ea643ad115aff4ca92f6aec472086b957a58522f70" dependencies = [ "lazy_static", "log", @@ -4804,9 +5668,9 @@ dependencies = [ [[package]] name = "symphonia-codec-adpcm" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "870e7dc1865d818c7b6318879d060553a73a3b2a3b8443dff90910f10ac41150" +checksum = "c94e1feac3327cd616e973d5be69ad36b3945f16b06f19c6773fc3ac0b426a0f" dependencies = [ "log", "symphonia-core", @@ -4814,9 +5678,9 @@ dependencies = [ [[package]] name = "symphonia-codec-alac" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a27e8763d1c9eff666faf903e73a99d4de2f7a93fca4e3c214c1d68432903b9" +checksum = "2d8a6666649a08412906476a8b0efd9b9733e241180189e9f92b09c08d0e38f3" dependencies = [ "log", "symphonia-core", @@ -4824,9 +5688,9 @@ dependencies = [ [[package]] name = "symphonia-codec-pcm" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47f1fbd220a06a641c8ce2ddad10f5ef6ee5cc0c54d9044d25d43b0d3119deaa" +checksum = "f395a67057c2ebc5e84d7bb1be71cce1a7ba99f64e0f0f0e303a03f79116f89b" dependencies = [ "log", "symphonia-core", @@ -4834,9 +5698,9 @@ dependencies = [ [[package]] name = "symphonia-codec-vorbis" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3953397e3506aa01350c4205817e4f95b58d476877a42f0458d07b665749e203" +checksum = "5a98765fb46a0a6732b007f7e2870c2129b6f78d87db7987e6533c8f164a9f30" dependencies = [ "log", "symphonia-core", @@ -4845,9 +5709,9 @@ dependencies = [ [[package]] name = "symphonia-core" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c73eb88fee79705268cc7b742c7bc93a7b76e092ab751d0833866970754142" +checksum = "798306779e3dc7d5231bd5691f5a813496dc79d3f56bf82e25789f2094e022c3" dependencies = [ "arrayvec", "bitflags 1.3.2", @@ -4856,11 +5720,22 @@ dependencies = [ "log", ] +[[package]] +name = "symphonia-format-caf" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e43c99c696a388295a29fe71b133079f5d8b18041cf734c5459c35ad9097af50" +dependencies = [ + "log", + "symphonia-core", + "symphonia-metadata", +] + [[package]] name = "symphonia-format-isomp4" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf14bae5cf352032416bc64151e5d6242d29d33cbf3238513b44d4427a1efb" +checksum = "abfdf178d697e50ce1e5d9b982ba1b94c47218e03ec35022d9f0e071a16dc844" dependencies = [ "encoding_rs", "log", @@ -4871,9 +5746,9 @@ dependencies = [ [[package]] name = "symphonia-format-mkv" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5c61dfc851ad25d4043d8c231d8617e8f7cd02a6cc0edad21ade21848d58895" +checksum = "1bb43471a100f7882dc9937395bd5ebee8329298e766250b15b3875652fe3d6f" dependencies = [ "lazy_static", "log", @@ -4884,9 +5759,9 @@ dependencies = [ [[package]] name = "symphonia-format-ogg" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bf1a00ccd11452d44048a0368828040f778ae650418dbd9d8765b7ee2574c8d" +checksum = "ada3505789516bcf00fc1157c67729eded428b455c27ca370e41f4d785bfa931" dependencies = [ "log", "symphonia-core", @@ -4895,11 +5770,12 @@ dependencies = [ ] [[package]] -name = "symphonia-format-wav" -version = "0.5.3" +name = "symphonia-format-riff" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da76614728fa27c003bdcdfbac51396bd8fcbf94c95fe8e62f1d2bac58ef03a4" +checksum = "05f7be232f962f937f4b7115cbe62c330929345434c834359425e043bfd15f50" dependencies = [ + "extended", "log", "symphonia-core", "symphonia-metadata", @@ -4907,9 +5783,9 @@ dependencies = [ [[package]] name = "symphonia-metadata" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89c3e1937e31d0e068bbe829f66b2f2bfaa28d056365279e0ef897172c3320c0" +checksum = "bc622b9841a10089c5b18e99eb904f4341615d5aa55bbf4eedde1be721a4023c" dependencies = [ "encoding_rs", "lazy_static", @@ -4919,9 +5795,9 @@ dependencies = [ [[package]] name = "symphonia-utils-xiph" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a450ca645b80d69aff8b35576cbfdc7f20940b29998202aab910045714c951f8" +checksum = "484472580fa49991afda5f6550ece662237b00c6f562c7d9638d1b086ed010fe" dependencies = [ "symphonia-core", "symphonia-metadata", @@ -4940,9 +5816,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.50" +version = "2.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb" +checksum = "4a6531ffc7b071655e4ce2e04bd464c4830bb585a61cabb96cf808f05172615a" dependencies = [ "proc-macro2", "quote", @@ -4955,6 +5831,31 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.59", +] + +[[package]] +name = "sysctl" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec7dddc5f0fee506baf8b9fdb989e242f17e4b11c61dfbb0635b705217199eea" +dependencies = [ + "bitflags 2.4.2", + "byteorder", + "enum-as-inner", + "libc", + "thiserror", + "walkdir", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -5026,7 +5927,7 @@ dependencies = [ "glib", "glib-sys", "gtk", - "image", + "image 0.24.8", "instant", "jni", "lazy_static", @@ -5110,7 +6011,7 @@ dependencies = [ "rand 0.8.5", "raw-window-handle", "regex", - "reqwest", + "reqwest 0.11.24", "rfd", "semver", "serde", @@ -5338,7 +6239,7 @@ checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.59", ] [[package]] @@ -5351,6 +6252,17 @@ dependencies = [ "once_cell", ] +[[package]] +name = "tiff" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" +dependencies = [ + "flate2", + "jpeg-decoder", + "weezl", +] + [[package]] name = "time" version = "0.3.34" @@ -5398,6 +6310,38 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "tokenizers" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e500fad1dd3af3d626327e6a3fe5050e664a6eaa4708b8ca92f1794aaf73e6fd" +dependencies = [ + "aho-corasick", + "derive_builder", + "esaxx-rs", + "getrandom 0.2.12", + "indicatif", + "itertools 0.12.1", + "lazy_static", + "log", + "macro_rules_attribute", + "monostate", + "onig", + "paste", + "rand 0.8.5", + "rayon", + "rayon-cond", + "regex", + "regex-syntax 0.8.2", + "serde", + "serde_json", + "spm_precompiled", + "thiserror", + "unicode-normalization-alignments", + "unicode-segmentation", + "unicode_categories", +] + [[package]] name = "tokio" version = "1.36.0" @@ -5436,7 +6380,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.59", ] [[package]] @@ -5637,7 +6581,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.59", ] [[package]] @@ -5746,6 +6690,15 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-normalization-alignments" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43f613e4fa046e69818dd287fdc4bc78175ff20331479dab6e1b0f98d57062de" +dependencies = [ + "smallvec", +] + [[package]] name = "unicode-segmentation" version = "1.11.0" @@ -5758,6 +6711,12 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + [[package]] name = "unsafe-libyaml" version = "0.2.10" @@ -5830,7 +6789,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.59", ] [[package]] @@ -5843,6 +6802,17 @@ dependencies = [ "serde", ] +[[package]] +name = "v_frame" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f32aaa24bacd11e488aa9ba66369c7cd514885742c9fe08cfe85884db3e92b" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] + [[package]] name = "valuable" version = "0.1.0" @@ -5951,7 +6921,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.59", "wasm-bindgen-shared", ] @@ -5985,7 +6955,7 @@ checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.59", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6113,6 +7083,12 @@ dependencies = [ "windows-metadata", ] +[[package]] +name = "weezl" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" + [[package]] name = "which" version = "4.4.2" @@ -6551,6 +7527,16 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "winreg" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "wry" version = "0.24.7" @@ -6627,6 +7613,30 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +[[package]] +name = "yoke" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65e71b2e4f287f467794c671e2b8f8a5f3716b3c829079a1c44740148eff07e4" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e6936f0cce458098a201c245a11bef556c6a0181129c7034d10d76d1ec3a2b8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.59", + "synstructure", +] + [[package]] name = "zerocopy" version = "0.7.32" @@ -6644,7 +7654,28 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.59", +] + +[[package]] +name = "zerofrom" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "655b0814c5c0b19ade497851070c640773304939a6c0fd5f5fb43da0696d05b7" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6a647510471d372f2e6c2e6b7219e44d8c574d24fdc11c610a61455782f18c3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.59", + "synstructure", ] [[package]] @@ -6663,3 +7694,27 @@ dependencies = [ "crc32fast", "crossbeam-utils", ] + +[[package]] +name = "zune-core" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "zune-jpeg" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec866b44a2a1fd6133d363f073ca1b179f438f99e7e5bfb1e33f7181facfe448" +dependencies = [ + "zune-core", +] diff --git a/Cargo.toml b/Cargo.toml index 18add69..ed260a1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,10 +4,11 @@ members = [ "crates/edgen_core", "crates/edgen_server", "crates/edgen_async_compat", + "crates/edgen_rt_image_generation_candle", "crates/edgen_rt_llama_cpp", "crates/edgen_rt_whisper_cpp", "crates/edgen_rt_chat_faker", - "edgen/src-tauri" + "edgen/src-tauri", ] [workspace.dependencies] @@ -15,6 +16,7 @@ ahash = "0.8.6" argh = "0.1.12" async-executor = "1.6.0" async-task = "4.5.0" +async-trait = "0.1.80" axum = "0.7.1" blake3 = "1.5.0" cfg-if = "1.0.0" @@ -28,7 +30,7 @@ either = "1.9.0" flume = "0.11.0" futures = "0.3.29" futures-lite = "2.0.1" -glommio = "0.8.0" +glommio = "0.9.0" hyper = "1.0.1" hyper-util = "0.1.1" link-cplusplus = "1.0.9" @@ -38,7 +40,7 @@ once_cell = "1.18.0" pin-project = "1.1.3" prost = "0.12.2" prost-build = "0.12.2" -reqwest = { version = "0.11.22", default-features = false } +reqwest = { version = "0.12.3", default-features = false } serde = "1.0.193" serde_derive = "1.0.193" serde_json = "1.0.108" diff --git a/crates/edgen_core/Cargo.toml b/crates/edgen_core/Cargo.toml index 8a306ec..a011dde 100644 --- a/crates/edgen_core/Cargo.toml +++ b/crates/edgen_core/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] ahash = { workspace = true } +async-trait = { workspace = true } dashmap = { workspace = true } directories = { workspace = true } derive_more = { workspace = true } @@ -12,11 +13,11 @@ edgen_async_compat = { path = "../edgen_async_compat", features = ["runtime-toki notify = { workspace = true } num_cpus = { workspace = true } once_cell = { workspace = true } -rubato = "0.14.1" +rubato = "0.15.0" serde = { workspace = true, features = ["derive"] } serde_yaml = { workspace = true } smol = { workspace = true } -symphonia = { version = "0.5.3", features = ["all-codecs", "all-formats"] } +symphonia = { version = "0.5.4", features = ["all-codecs", "all-formats"] } time = { workspace = true } tracing = { workspace = true } futures = { workspace = true } diff --git a/crates/edgen_core/src/image_generation.rs b/crates/edgen_core/src/image_generation.rs new file mode 100644 index 0000000..4c88cf4 --- /dev/null +++ b/crates/edgen_core/src/image_generation.rs @@ -0,0 +1,44 @@ +use serde::Serialize; +use std::path::PathBuf; +use thiserror::Error; + +pub struct ImageGenerationArgs { + pub prompt: String, + pub uncond_prompt: String, + pub width: Option, + pub height: Option, + pub steps: usize, + pub images: u32, + pub seed: Option, + pub guidance_scale: f64, + pub vae_scale: f64, +} + +pub struct ModelFiles { + pub tokenizer: PathBuf, + pub clip_weights: PathBuf, + pub clip2_weights: Option, + pub vae_weights: PathBuf, + pub unet_weights: PathBuf, +} + +#[derive(Serialize, Error, Debug)] +pub enum ImageGenerationEndpointError { + #[error("Could not load model: {0}")] + Load(String), + #[error("Failed to tokenize prompts: {0}")] + Decoding(String), + #[error("Failed to generate image: {0}")] + Generation(String), + #[error("Could not convert the output tensor into an encoded image")] + Encoding(String), +} + +#[async_trait::async_trait] +pub trait ImageGenerationEndpoint { + async fn generate_image( + &self, + model: ModelFiles, + args: ImageGenerationArgs, + ) -> Result>, ImageGenerationEndpointError>; +} diff --git a/crates/edgen_core/src/lib.rs b/crates/edgen_core/src/lib.rs index da16cc6..e6cd4df 100644 --- a/crates/edgen_core/src/lib.rs +++ b/crates/edgen_core/src/lib.rs @@ -26,6 +26,7 @@ pub mod whisper; pub mod settings; +pub mod image_generation; pub mod perishable; /// A generic [`Box`]ed [`Future`], used to emulate `async` functions in traits. diff --git a/crates/edgen_core/src/settings.rs b/crates/edgen_core/src/settings.rs index da23ccd..c7504f8 100644 --- a/crates/edgen_core/src/settings.rs +++ b/crates/edgen_core/src/settings.rs @@ -33,7 +33,7 @@ const FILE_NAME: &str = "edgen.conf"; // TODO look for a better way to do this, since [Settings] already uses a lock pub static SETTINGS: Lazy> = Lazy::new(Default::default); -/// The configuration, and data directories for Edgen. +/// The configuration and data directories for Edgen. pub static PROJECT_DIRS: Lazy = Lazy::new(|| ProjectDirs::from("com", "EdgenAI", "Edgen").unwrap()); pub static CONFIG_FILE: Lazy = Lazy::new(build_config_file_path); @@ -145,6 +145,18 @@ pub async fn embeddings_dir() -> String { .to_string() } +/// Helper to get the image generation model directory. +pub async fn image_generation_dir() -> String { + SETTINGS + .read() + .await + .read() + .await + .image_generation_models_dir + .trim() + .to_string() +} + /// Helper to get the chat completions model name. pub async fn chat_completions_name() -> String { SETTINGS @@ -288,6 +300,8 @@ pub struct SettingsParams { /// The embeddings repo that Edgen will use for downloads pub embeddings_model_repo: String, + pub image_generation_models_dir: String, + /// The policy used to decided if models/session should be allocated and run on acceleration /// hardware. pub gpu_policy: DevicePolicy, @@ -325,6 +339,8 @@ impl Default for SettingsParams { "transcriptions", ])); let embeddings_dir = data_dir.join(&join_path_components(&["models", "embeddings"])); + let image_generation_dir = + data_dir.join(&join_path_components(&["models", "image", "generation"])); let chat_completions_str = chat_completions_dir.into_os_string().into_string().unwrap(); let audio_transcriptions_str = audio_transcriptions_dir @@ -332,6 +348,7 @@ impl Default for SettingsParams { .into_string() .unwrap(); let embeddings_str = embeddings_dir.into_os_string().into_string().unwrap(); + let image_generation_str = image_generation_dir.into_os_string().into_string().unwrap(); let cpus = num_cpus::get_physical(); let threads = if cpus > 1 { cpus - 1 } else { 1 }; @@ -349,6 +366,7 @@ impl Default for SettingsParams { embeddings_model_name: "nomic-embed-text-v1.5.f16.gguf".to_string(), embeddings_model_repo: "nomic-ai/nomic-embed-text-v1.5-GGUF".to_string(), embeddings_models_dir: embeddings_str, + image_generation_models_dir: image_generation_str, // TODO detect if the system has acceleration hardware to decide the default gpu_policy: DevicePolicy::AlwaysDevice { overflow_to_cpu: true, diff --git a/crates/edgen_rt_image_generation_candle/Cargo.toml b/crates/edgen_rt_image_generation_candle/Cargo.toml new file mode 100644 index 0000000..9d8f557 --- /dev/null +++ b/crates/edgen_rt_image_generation_candle/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "edgen_rt_image_generation_candle" +version = "0.1.0" +edition = "2021" + +[dependencies] +async-trait = { workspace = true } +candle-core = "0.4.1" +candle-transformers = "0.4.1" +edgen_core = { path = "../edgen_core" } +image = "0.25.1" +rand = "0.8.5" +thiserror = { workspace = true } +# https://github.com/huggingface/tokenizers/issues/1454 +tokenizers = { version = "0.19.1", default-features = false, features = ["progressbar", "onig"] } +tokio = { workspace = true, features = ["sync", "rt", "fs"] } +tracing = { workspace = true } + +[features] +cuda = ["candle-core/cuda", "candle-transformers/cuda"] diff --git a/crates/edgen_rt_image_generation_candle/src/lib.rs b/crates/edgen_rt_image_generation_candle/src/lib.rs new file mode 100644 index 0000000..c238b7e --- /dev/null +++ b/crates/edgen_rt_image_generation_candle/src/lib.rs @@ -0,0 +1,281 @@ +use std::io::BufWriter; +use std::io::{Cursor, IntoInnerError}; +use std::path::Path; + +use candle_core::backend::BackendDevice; +use candle_core::{CudaDevice, DType, Device, IndexOp, Module, Tensor, D}; +use candle_transformers::models::stable_diffusion; +use candle_transformers::models::stable_diffusion::vae::AutoEncoderKL; +use image::{ImageBuffer, ImageError, ImageFormat, Rgb}; +use thiserror::Error; +use tokenizers::Tokenizer; + +use edgen_core::image_generation::{ + ImageGenerationArgs, ImageGenerationEndpoint, ImageGenerationEndpointError, ModelFiles, +}; +use edgen_core::settings::{DevicePolicy, SETTINGS}; +use rand::random; +use tracing::{debug, info, info_span, warn}; + +#[derive(Error, Debug)] +enum CandleError { + #[error("The prompt is too long, {len} > max-tokens ({max})")] + PromptTooLong { len: usize, max: usize }, + #[error("No clip2 available for the configuration")] + Clip2Unavailable, + #[error("Output has wrong number of dimensions, got {dims}, but expected {expected}")] + BadDims { dims: usize, expected: usize }, + #[error(transparent)] + Candle(#[from] candle_core::Error), + #[error("Tokenizer error: {0}")] + Tokenizer(String), + #[error("Could not create image buffer from tensor output")] + BadOutput, + #[error(transparent)] + EncodeProcessFailed(#[from] ImageError), + #[error(transparent)] + EncodeWriteFailed(#[from] IntoInnerError>>>), +} + +fn text_embeddings( + prompt: &str, + uncond_prompt: &str, + tokenizer: impl AsRef, + clip_weights: impl AsRef, + config: &stable_diffusion::StableDiffusionConfig, + device: &Device, + dtype: DType, + use_guide_scale: bool, + first_clip: bool, +) -> Result { + let tokenizer = + Tokenizer::from_file(tokenizer).map_err(|e| CandleError::Tokenizer(e.to_string()))?; + let pad_id = match &config.clip.pad_with { + Some(padding) => *tokenizer.get_vocab(true).get(padding.as_str()).unwrap(), + None => *tokenizer.get_vocab(true).get("<|endoftext|>").unwrap(), + }; + + let mut tokens = tokenizer + .encode(prompt, true) + .map_err(|e| CandleError::Tokenizer(e.to_string()))? + .get_ids() + .to_vec(); + if tokens.len() > config.clip.max_position_embeddings { + return Err(CandleError::PromptTooLong { + len: tokens.len(), + max: config.clip.max_position_embeddings, + }); + } + while tokens.len() < config.clip.max_position_embeddings { + tokens.push(pad_id) + } + let tokens = Tensor::new(tokens.as_slice(), device)?.unsqueeze(0)?; + + let clip_config = if first_clip { + &config.clip + } else { + config.clip2.as_ref().ok_or(CandleError::Clip2Unavailable)? + }; + let text_model = + stable_diffusion::build_clip_transformer(clip_config, clip_weights, device, DType::F32)?; + let text_embeddings = text_model.forward(&tokens)?; + + let text_embeddings = if use_guide_scale { + let mut uncond_tokens = tokenizer + .encode(uncond_prompt, true) + .map_err(|e| CandleError::Tokenizer(e.to_string()))? + .get_ids() + .to_vec(); + if uncond_tokens.len() > config.clip.max_position_embeddings { + return Err(CandleError::PromptTooLong { + len: uncond_tokens.len(), + max: config.clip.max_position_embeddings, + }); + } + while uncond_tokens.len() < config.clip.max_position_embeddings { + uncond_tokens.push(pad_id) + } + + let uncond_tokens = Tensor::new(uncond_tokens.as_slice(), device)?.unsqueeze(0)?; + let uncond_embeddings = text_model.forward(&uncond_tokens)?; + + Tensor::cat(&[uncond_embeddings, text_embeddings], 0)?.to_dtype(dtype)? + } else { + text_embeddings.to_dtype(dtype)? + }; + Ok(text_embeddings) +} + +fn to_bitmap( + vae: &AutoEncoderKL, + latents: &Tensor, + vae_scale: f64, + bsize: usize, +) -> Result>, CandleError> { + let images = vae.decode(&(latents / vae_scale)?)?; + let images = ((images / 2.)? + 0.5)?.to_device(&Device::Cpu)?; + let images = (images.clamp(0f32, 1.)? * 255.)?.to_dtype(DType::U8)?; + let mut res = vec![]; + res.reserve(bsize); + for batch in 0..bsize { + let image = images.i(batch)?; + let (channel, height, width) = image.dims3()?; + if channel != 3 { + return Err(CandleError::BadDims { + dims: channel, + expected: 3, + }); + } + let img = image.permute((1, 2, 0))?.flatten_all()?; + let pixels = img.to_vec1::()?; + let buf = ImageBuffer::, _>::from_vec(width as u32, height as u32, pixels) + .ok_or(CandleError::BadOutput)?; + let mut encoded = BufWriter::new(Cursor::new(Vec::new())); + buf.write_to(&mut encoded, ImageFormat::Png)?; + res.push(encoded.into_inner()?.into_inner()); + } + Ok(res) +} + +fn generate_image( + model: ModelFiles, + args: ImageGenerationArgs, + device_policy: &DevicePolicy, +) -> Result>, CandleError> { + let _span = info_span!("gen_image", images = args.images, steps = args.steps).entered(); + let config = stable_diffusion::StableDiffusionConfig::v2_1(None, args.height, args.width); + let scheduler = config.build_scheduler(args.steps)?; + let device = match device_policy { + DevicePolicy::AlwaysCpu { .. } => Device::Cpu, + DevicePolicy::AlwaysDevice { .. } => Device::Cuda(CudaDevice::new(0)?), + _ => { + warn!("Unknown device policy, executing on CPU"); + Device::Cpu + } + }; + let use_guide_scale = args.guidance_scale > 1.0; + let dtype = DType::F16; + let bsize = 1; + + device.set_seed(args.seed.unwrap_or(random::()))?; + + let which = if model.clip2_weights.is_some() { + vec![true, false] + } else { + vec![true] + }; + let text_embeddings = which + .iter() + .map(|first| { + let clip = if *first { + &model.clip_weights + } else { + model.clip2_weights.as_ref().unwrap() + }; + text_embeddings( + &args.prompt, + &args.uncond_prompt, + &model.tokenizer, + clip, + &config, + &device, + dtype, + use_guide_scale, + *first, + ) + }) + .collect::, CandleError>>()?; + + let text_embeddings = Tensor::cat(&text_embeddings, D::Minus1)?; + let text_embeddings = text_embeddings.repeat((bsize, 1, 1))?; + + let vae = config.build_vae(model.vae_weights, &device, dtype)?; + let unet = config.build_unet(model.unet_weights, &device, 4, false, dtype)?; + + // This would be used in image to image scenarios + let t_start = 0; + + let mut images = vec![]; + images.reserve(args.images as usize); + for idx in 0..args.images { + let _span = info_span!("image", image_index = idx).entered(); + info!("Generating image"); + let timesteps = scheduler.timesteps(); + let latents = Tensor::randn( + 0f32, + 1f32, + (bsize, 4, config.height / 8, config.width / 8), + &device, + )? * scheduler.init_noise_sigma(); + let mut latents = latents?.to_dtype(dtype)?; + + for (timestep_index, ×tep) in timesteps.iter().enumerate() { + debug!("Image generation step {timestep_index}"); + if timestep_index < t_start { + continue; + } + let latent_model_input = if use_guide_scale { + Tensor::cat(&[&latents, &latents], 0)? + } else { + latents.clone() + }; + + let latent_model_input = scheduler.scale_model_input(latent_model_input, timestep)?; + let noise_pred = + unet.forward(&latent_model_input, timestep as f64, &text_embeddings)?; + + let noise_pred = if use_guide_scale { + let noise_pred = noise_pred.chunk(2, 0)?; + let (noise_pred_uncond, noise_pred_text) = (&noise_pred[0], &noise_pred[1]); + + (noise_pred_uncond + + ((noise_pred_text - noise_pred_uncond)? * args.guidance_scale)?)? + } else { + noise_pred + }; + + latents = scheduler.step(&noise_pred, timestep, &latents)?; + } + + images.extend(to_bitmap(&vae, &latents, args.vae_scale, bsize)?) + } + + Ok(images) +} + +pub struct CandleImageGenerationEndpoint {} + +#[async_trait::async_trait] +impl ImageGenerationEndpoint for CandleImageGenerationEndpoint { + async fn generate_image( + &self, + model: ModelFiles, + args: ImageGenerationArgs, + ) -> Result>, ImageGenerationEndpointError> { + let policy = SETTINGS.read().await.read().await.gpu_policy.clone(); + Ok(generate_image(model, args, &policy)?) + } +} + +impl From for ImageGenerationEndpointError { + fn from(value: CandleError) -> Self { + match value { + CandleError::PromptTooLong { .. } => { + ImageGenerationEndpointError::Decoding(value.to_string()) + } + CandleError::Clip2Unavailable => ImageGenerationEndpointError::Load(value.to_string()), + CandleError::BadDims { .. } => { + ImageGenerationEndpointError::Decoding(value.to_string()) + } + CandleError::Candle(_) => ImageGenerationEndpointError::Generation(value.to_string()), + CandleError::Tokenizer(_) => ImageGenerationEndpointError::Decoding(value.to_string()), + CandleError::BadOutput => ImageGenerationEndpointError::Encoding(value.to_string()), + CandleError::EncodeProcessFailed(_) => { + ImageGenerationEndpointError::Encoding(value.to_string()) + } + CandleError::EncodeWriteFailed(_) => { + ImageGenerationEndpointError::Encoding(value.to_string()) + } + } + } +} diff --git a/crates/edgen_server/Cargo.toml b/crates/edgen_server/Cargo.toml index 6c120f0..c9a9f8c 100644 --- a/crates/edgen_server/Cargo.toml +++ b/crates/edgen_server/Cargo.toml @@ -14,6 +14,7 @@ derive_more = { workspace = true } edgen_core = { path = "../edgen_core" } edgen_rt_chat_faker = { path = "../edgen_rt_chat_faker" } edgen_rt_llama_cpp = { path = "../edgen_rt_llama_cpp" } +edgen_rt_image_generation_candle = { path = "../edgen_rt_image_generation_candle" } edgen_rt_whisper_cpp = { path = "../edgen_rt_whisper_cpp" } either = { workspace = true, features = ["serde"] } futures = { workspace = true } @@ -52,3 +53,4 @@ llama_vulkan = ["edgen_rt_llama_cpp/vulkan"] llama_cuda = ["edgen_rt_llama_cpp/cuda"] llama_metal = ["edgen_rt_llama_cpp/metal"] whisper_cuda = ["edgen_rt_whisper_cpp/cuda"] +candle_cuda = ["edgen_rt_image_generation_candle/cuda"] diff --git a/crates/edgen_server/src/image_generation.rs b/crates/edgen_server/src/image_generation.rs new file mode 100644 index 0000000..8ada353 --- /dev/null +++ b/crates/edgen_server/src/image_generation.rs @@ -0,0 +1,165 @@ +use crate::audio::ChatCompletionError; +use crate::model_descriptor::{ModelDescriptor, ModelDescriptorError, ModelPaths, Quantization}; +use axum::http::StatusCode; +use axum::response::{IntoResponse, Response}; +use axum::Json; +use edgen_core::image_generation::{ + ImageGenerationArgs, ImageGenerationEndpoint, ImageGenerationEndpointError, ModelFiles, +}; +use edgen_rt_image_generation_candle::CandleImageGenerationEndpoint; +use serde_derive::{Deserialize, Serialize}; +use std::borrow::Cow; +use thiserror::Error; +use utoipa::ToSchema; + +/// A request to generate images for the provided context. +/// This request is not at all conformant with OpenAI's API, as that one is very bare-bones, lacking +/// in many parameters that we need. +/// +/// An `axum` handler, [`image_generation`][image_generation], is provided to handle this request. +/// +/// [image_generation]: fn.image_generation.html +#[derive(Debug, Serialize, Deserialize, ToSchema)] +pub struct CreateImageGenerationRequest<'a> { + /// The prompt to be used to generate the image. + pub prompt: Cow<'a, str>, + + /// The model to use for generating completions. + pub model: Cow<'a, str>, + + /// The width of the generated image. + pub width: Option, + + /// The height of the generated image. + pub height: Option, + + /// The optional unconditional prompt. + pub uncond_prompt: Option>, + + /// The number of steps to be used in the diffusion process. + pub steps: Option, + + /// The number of images to generate. + /// + /// Default: 1 + pub images: Option, + + /// The random number generator seed to used for the generation. + /// + /// By default, a random seed is used. + pub seed: Option, + + /// The guidance scale to use for generation, that is, how much should the model follow the + /// prompt. + /// + /// Values below 1 disable guidance. (the prompt is ignored) + pub guidance_scale: Option, + + /// The Variational Auto-Encoder scale to use for generation. + /// + /// This value should probably not be set. + pub vae_scale: Option, +} + +/// This request is not at all conformant with OpenAI's API, as that one returns a URL to the +/// generated image, and that is not possible for Edgen. +#[derive(Debug, Serialize, Deserialize, ToSchema)] +pub struct ImageGenerationResponse { + /// A vector containing the byte data of the generated images. + pub images: Vec>, +} + +/// An error condition raised by the image generation API. +#[derive(Serialize, Error, ToSchema, Debug)] +#[serde(rename_all = "snake_case")] +#[serde(tag = "error")] +pub enum ImageGenerationError { + /// The provided model could not be loaded. + #[error("failed to load model: {0}")] + Model(#[from] ModelDescriptorError), + /// Some error has occured inside the endpoint. + #[error("endpoint error: {0}")] + Endpoint(#[from] ImageGenerationEndpointError), + /// This error should be unreachable. + #[error("Something went wrong")] + Unreachable, +} + +impl IntoResponse for ImageGenerationError { + fn into_response(self) -> Response { + (StatusCode::INTERNAL_SERVER_ERROR, Json(self)).into_response() + } +} + +/// POST `/v1/image/generations`: generate image for the provided parameters +/// +/// The API of this endpoint is not at all conformant with OpenAI's API, as that one is very +/// bare-bones, lacking in many parameters that we need, and also returns an URL, which Edgen +/// cannot do. +/// +/// On failure, may raise a `500 Internal Server Error` with a JSON-encoded [`ImageGenerationError`] +/// to the peer.. +#[utoipa::path( +post, +path = "/image/generations", +request_body = CreateImageGenerationRequest, +responses( +(status = 200, description = "OK", body = ImageGenerationResponse), +(status = 500, description = "unexpected internal server error", body = ImageGenerationError) +), +)] +pub async fn generate_image( + Json(req): Json>, +) -> Result { + let descriptor = crate::model_descriptor::get(req.model.as_ref())?; + let model_files; + let default_steps; + let default_vae_scale; + if let ModelDescriptor::StableDiffusion { + steps, vae_scale, .. + } = descriptor.value() + { + if let ModelPaths::StableDiffusion { + unet_weights, + vae_weights, + clip_weights, + clip2_weights, + tokenizer, + } = descriptor.preload_files(Quantization::F16).await? + { + model_files = ModelFiles { + tokenizer, + clip_weights, + clip2_weights, + vae_weights, + unet_weights, + }; + } else { + return Err(ImageGenerationError::Unreachable); + } + default_steps = steps; + default_vae_scale = vae_scale; + } else { + return Err(ImageGenerationError::Unreachable); + }; + + let endpoint = CandleImageGenerationEndpoint {}; + let images = endpoint + .generate_image( + model_files, + ImageGenerationArgs { + prompt: req.prompt.to_string(), + uncond_prompt: req.uncond_prompt.unwrap_or(Cow::from("")).to_string(), + width: req.width, + height: req.height, + steps: req.steps.unwrap_or(*default_steps), + images: req.images.unwrap_or(1), + seed: req.seed, + guidance_scale: req.guidance_scale.unwrap_or(7.5), + vae_scale: req.vae_scale.unwrap_or(*default_vae_scale), + }, + ) + .await?; + + Ok(Json(ImageGenerationResponse { images })) +} diff --git a/crates/edgen_server/src/lib.rs b/crates/edgen_server/src/lib.rs index 59b1cd6..bcfa9e7 100644 --- a/crates/edgen_server/src/lib.rs +++ b/crates/edgen_server/src/lib.rs @@ -42,8 +42,10 @@ pub mod misc; mod chat_faker; pub mod cli; pub mod graceful_shutdown; +mod image_generation; mod llm; mod model; +mod model_descriptor; pub mod model_man; pub mod openai_shim; mod routes; @@ -181,6 +183,8 @@ async fn start_server(args: &cli::Serve) -> EdgenResult { settings::create_project_dirs().await.unwrap(); + model_descriptor::init(); + while run_server(args).await? { info!("Settings have been updated, resetting environment") } @@ -329,15 +333,16 @@ async fn run_server(args: &cli::Serve) -> Result { #[cfg(test)] mod tests { + use std::fs::File; + use std::io::Write; + use std::path::Path; + use axum::routing::post; use axum::Router; use axum_test::multipart; use axum_test::TestServer; use levenshtein; use serde_json::from_str; - use std::fs::File; - use std::io::Write; - use std::path::Path; use edgen_rt_chat_faker as chat_faker; diff --git a/crates/edgen_server/src/model.rs b/crates/edgen_server/src/model.rs index 2d0c134..3e66dc3 100644 --- a/crates/edgen_server/src/model.rs +++ b/crates/edgen_server/src/model.rs @@ -49,6 +49,7 @@ pub enum ModelKind { LLM, Whisper, ChatFaker, + ImageDiffusion, } #[derive(Debug, PartialEq)] @@ -111,6 +112,7 @@ impl ModelPatterns { ModelKind::LLM => &self.llama, ModelKind::Whisper => &self.whisper, ModelKind::ChatFaker => &self.chat_faker, + _ => todo!(), }; find_model_kind(list, kind, &n, &mut v); } @@ -333,6 +335,7 @@ async fn observe_download( status::observe_audio_transcriptions_progress(dir, size, download).await } Endpoint::Embeddings => status::observe_embeddings_progress(dir, size, download).await, + _ => tokio::task::spawn(async {}), } } @@ -341,6 +344,7 @@ async fn report_start_of_download(ep: Endpoint) { Endpoint::ChatCompletions => status::set_chat_completions_download(true).await, Endpoint::AudioTranscriptions => status::set_audio_transcriptions_download(true).await, Endpoint::Embeddings => status::set_embeddings_download(true).await, + _ => {} } } @@ -358,6 +362,7 @@ async fn report_end_of_download(ep: Endpoint) { status::set_embeddings_progress(100).await; status::set_embeddings_download(false).await; } + _ => {} } } diff --git a/crates/edgen_server/src/model_descriptor.rs b/crates/edgen_server/src/model_descriptor.rs new file mode 100644 index 0000000..7ed3116 --- /dev/null +++ b/crates/edgen_server/src/model_descriptor.rs @@ -0,0 +1,191 @@ +use crate::model::{Model, ModelError, ModelKind}; +use crate::types::Endpoint; +use dashmap::DashMap; +use edgen_core::settings; +use once_cell::sync::Lazy; +use serde_derive::Serialize; +use std::path::PathBuf; +use thiserror::Error; + +static MODELS: Lazy> = Lazy::new(Default::default); + +#[derive(Debug, Error, Serialize)] +pub enum ModelDescriptorError { + #[error("The specified quantization level is not available for the model")] + QuantizationUnavailable, + #[error(transparent)] + Preload(#[from] ModelError), + #[error("The specified model was not found")] + NotFound, +} + +/// The descriptor of an artificial intelligence model, containing every bit of data required to +/// execute the model. +pub enum ModelDescriptor { + /// A stable diffusion model. + StableDiffusion { + /// The files that make up the model, indexed by quantization. + files: DashMap, + + /// The default number of diffusion steps for this model. + steps: usize, + + /// The default Variational Auto-Encoder scale for this model. + vae_scale: f64, + }, +} + +pub struct StableDiffusionFiles { + unet_weights_repo: String, + unet_weights_file: String, + vae_weights_repo: String, + vae_weights_file: String, + clip_weights_repo: String, + clip_weights_file: String, + clip2_weights_repo: Option, + clip2_weights_file: Option, + tokenizer_repo: String, + tokenizer_file: String, +} + +#[derive(Copy, Clone, Hash, Eq, PartialEq)] +pub enum Quantization { + Default, + F16, +} + +pub enum ModelPaths { + StableDiffusion { + unet_weights: PathBuf, + vae_weights: PathBuf, + clip_weights: PathBuf, + clip2_weights: Option, + tokenizer: PathBuf, + }, +} + +impl ModelDescriptor { + pub async fn preload_files( + &self, + quantization: Quantization, + ) -> Result { + let res = match self { + ModelDescriptor::StableDiffusion { files, .. } => { + let files = files.get(&quantization); + if files.is_none() { + return Err(ModelDescriptorError::QuantizationUnavailable); + } + let files = files.unwrap(); + let dir = PathBuf::from(settings::image_generation_dir().await); + let unet = { + let mut unet = Model::new( + ModelKind::ImageDiffusion, + &files.unet_weights_file, + &files.unet_weights_repo, + &dir, + ); + unet.preload(Endpoint::ImageGeneration).await?; + unet.file_path()? + }; + let vae = { + let mut vae = Model::new( + ModelKind::ImageDiffusion, + &files.vae_weights_file, + &files.vae_weights_repo, + &dir, + ); + vae.preload(Endpoint::ImageGeneration).await?; + vae.file_path()? + }; + let clip = { + let mut clip = Model::new( + ModelKind::ImageDiffusion, + &files.clip_weights_file, + &files.clip_weights_repo, + &dir, + ); + clip.preload(Endpoint::ImageGeneration).await?; + clip.file_path()? + }; + let clip2 = if files.clip2_weights_file.is_some() { + let mut clip2 = Model::new( + ModelKind::ImageDiffusion, + files.clip2_weights_file.as_ref().unwrap(), + files.clip2_weights_repo.as_ref().unwrap(), + &dir, + ); + clip2.preload(Endpoint::ImageGeneration).await?; + Some(clip2.file_path()?) + } else { + None + }; + let tokenizer = { + let mut tokenizer = Model::new( + ModelKind::ImageDiffusion, + &files.tokenizer_file, + &files.tokenizer_repo, + &dir, + ); + tokenizer.preload(Endpoint::ImageGeneration).await?; + tokenizer.file_path()? + }; + + ModelPaths::StableDiffusion { + unet_weights: unet, + vae_weights: vae, + clip_weights: clip, + clip2_weights: clip2, + tokenizer, + } + } + }; + Ok(res) + } +} + +// This should pull its data for a config file or database, but for now this is fine +pub fn init() { + let model_files = DashMap::new(); + model_files.insert( + Quantization::Default, + StableDiffusionFiles { + tokenizer_repo: "openai/clip-vit-base-patch32".to_string(), + tokenizer_file: "tokenizer.json".to_string(), + clip_weights_repo: "stabilityai/stable-diffusion-2-1".to_string(), + clip_weights_file: "text_encoder/model.safetensors".to_string(), + clip2_weights_repo: None, + clip2_weights_file: None, + vae_weights_repo: "stabilityai/stable-diffusion-2-1".to_string(), + vae_weights_file: "vae/diffusion_pytorch_model.safetensors".to_string(), + unet_weights_repo: "stabilityai/stable-diffusion-2-1".to_string(), + unet_weights_file: "unet/diffusion_pytorch_model.safetensors".to_string(), + }, + ); + model_files.insert( + Quantization::F16, + StableDiffusionFiles { + tokenizer_repo: "openai/clip-vit-base-patch32".to_string(), + tokenizer_file: "tokenizer.json".to_string(), + clip_weights_repo: "stabilityai/stable-diffusion-2-1".to_string(), + clip_weights_file: "text_encoder/model.fp16.safetensors".to_string(), + clip2_weights_repo: None, + clip2_weights_file: None, + vae_weights_repo: "stabilityai/stable-diffusion-2-1".to_string(), + vae_weights_file: "vae/diffusion_pytorch_model.fp16.safetensors".to_string(), + unet_weights_repo: "stabilityai/stable-diffusion-2-1".to_string(), + unet_weights_file: "unet/diffusion_pytorch_model.fp16.safetensors".to_string(), + }, + ); + let model = ModelDescriptor::StableDiffusion { + files: model_files, + steps: 30, + vae_scale: 0.18215, + }; + MODELS.insert("stable-diffusion-2-1".to_string(), model); +} + +pub fn get( + model: &str, +) -> Result, ModelDescriptorError> { + MODELS.get(model).ok_or(ModelDescriptorError::NotFound) +} diff --git a/crates/edgen_server/src/openai_shim.rs b/crates/edgen_server/src/openai_shim.rs index 2497a5f..b0a8e02 100644 --- a/crates/edgen_server/src/openai_shim.rs +++ b/crates/edgen_server/src/openai_shim.rs @@ -312,7 +312,7 @@ pub struct CreateChatCompletionRequest<'a> { /// How many choices to generate for each token in the output. `1` by default. You can use /// this to generate several sets of completions for the same prompt. - pub n: Option, + pub n: Option, /// A number in `[-2.0, 2.0]`. Positive values "increase the model's likelihood to talk about /// new topics." diff --git a/crates/edgen_server/src/routes.rs b/crates/edgen_server/src/routes.rs index ceb432e..9a86c30 100644 --- a/crates/edgen_server/src/routes.rs +++ b/crates/edgen_server/src/routes.rs @@ -21,10 +21,10 @@ use axum::{ use tracing::warn; -use crate::misc; use crate::model_man; use crate::openai_shim; use crate::status; +use crate::{image_generation, misc}; pub fn routes() -> Router { Router::new() @@ -38,6 +38,11 @@ pub fn routes() -> Router { "/v1/audio/transcriptions", post(openai_shim::create_transcription), ) + // ---- Image ---------------------------------------------------------- + .route( + "/v1/image/generations", + post(image_generation::generate_image), + ) // -- AI status endpoints ---------------------------------------------- // ---- Chat ----------------------------------------------------------- .route( diff --git a/crates/edgen_server/src/types.rs b/crates/edgen_server/src/types.rs index 739b44f..9aaad87 100644 --- a/crates/edgen_server/src/types.rs +++ b/crates/edgen_server/src/types.rs @@ -37,6 +37,8 @@ pub enum Endpoint { AudioTranscriptions, /// Embeddings Embeddings, + /// Image generation + ImageGeneration, } impl Display for Endpoint { @@ -45,6 +47,7 @@ impl Display for Endpoint { Endpoint::ChatCompletions => write!(f, "/chat/completions"), Endpoint::AudioTranscriptions => write!(f, "/audio/transcriptions"), Endpoint::Embeddings => write!(f, "/embeddings"), + Endpoint::ImageGeneration => write!(f, "/images/generations"), } } } diff --git a/docs/src/app/api-reference/image/page.mdx b/docs/src/app/api-reference/image/page.mdx new file mode 100644 index 0000000..f25ab00 --- /dev/null +++ b/docs/src/app/api-reference/image/page.mdx @@ -0,0 +1,77 @@ +export const metadata = { + title: 'Image', + description: 'Generate images', +} + +# Chat + +Generate images from text. {{ className: 'lead' }} + +--- + + + + + ## Create image {{tag:'POST', label:'http://localhost:33322/v1/image/generations'}} + + Given a text prompt, generate 1 or more images according to the prompt. + + ### Required attributes + + + + A description of the images to be generated. + + + + + + The model used for image generations. (WARNING: At the moment only "stable-diffusion-2-1" is allowed) +
    +
  • + If the model name is "default", the chat model from the configuration is used (see [Documentation » Configuration](/documentation/configuration) for details). +
  • +
  • + If the model name is a valid model name recognized by Edgen, it is what is used. +
  • +
+ +
+
+ + + + + + +
+ + + ```bash {{ title: 'cURL' }} + curl http://localhost:33322/v1/image/generations \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer no-key-required" \ + -d '{ + "model": "stable-diffusion-2-1", + "prompt": "A rusty robot" + }' + ``` + + ```python + API NOT DONE YET + ``` + + ```ts + API NOT DONE YET + ``` + + + + ```json {{ title: 'Response' }} + {"images": [[123, 234, ..., 231, 213]]} + ``` +
+
+ + +
diff --git a/edgen/src-tauri/Cargo.toml b/edgen/src-tauri/Cargo.toml index d969acf..3aab74c 100644 --- a/edgen/src-tauri/Cargo.toml +++ b/edgen/src-tauri/Cargo.toml @@ -33,3 +33,4 @@ llama_vulkan = ["edgen_server/llama_vulkan"] llama_cuda = ["edgen_server/llama_cuda"] llama_metal = ["edgen_server/llama_metal"] whisper_cuda = ["edgen_server/whisper_cuda"] +candle_cuda = ["edgen_server/candle_cuda"]