From a80b3466dcd8c6d21d48e103160a57b53e54c76e Mon Sep 17 00:00:00 2001 From: maxwellflitton Date: Thu, 4 Jan 2024 10:53:47 +0000 Subject: [PATCH 1/4] adding build using binary downloads --- modules/utils/.gitignore | 3 +- modules/utils/Cargo.toml | 6 + modules/utils/build.rs | 175 +++++++++++++----- .../utils/src/execution/onnx_environment.rs | 6 +- 4 files changed, 141 insertions(+), 49 deletions(-) diff --git a/modules/utils/.gitignore b/modules/utils/.gitignore index e80a6f2..dc72240 100644 --- a/modules/utils/.gitignore +++ b/modules/utils/.gitignore @@ -1,3 +1,4 @@ onnx_driver/ target/ -output/ \ No newline at end of file +output/ +downloaded_onnx_package/ diff --git a/modules/utils/Cargo.toml b/modules/utils/Cargo.toml index c90cef5..33bb9b4 100644 --- a/modules/utils/Cargo.toml +++ b/modules/utils/Cargo.toml @@ -23,3 +23,9 @@ tokio = { version = "1.12.0", features = ["full"] } [lib] name = "surrealml_core" path = "src/lib.rs" + +[build-dependencies] +ureq = { version = "2.1", default-features = false, features = [ "tls" ] } +tar = { version = "0.4" } +flate2 = { version = "1.0" } +sha2 = { version = "0.10" } diff --git a/modules/utils/build.rs b/modules/utils/build.rs index 05aad35..c48de46 100644 --- a/modules/utils/build.rs +++ b/modules/utils/build.rs @@ -1,4 +1,67 @@ -use std::process::Command; +//! This build file downloads the prebuilt binaries for ONNX Runtime and places them in the root of the crate +//! to be pointed at by the ort environment so we can run the ONNX models. +use ureq; +use std::path::Path; + + +static CACHE_FILE: &str = "./downloaded_onnx_package"; + + +fn extract_tgz(buf: &[u8], output: &Path) { + let buf: std::io::BufReader<&[u8]> = std::io::BufReader::new(buf); + let tar = flate2::read::GzDecoder::new(buf); + let mut archive = tar::Archive::new(tar); + archive.unpack(output).expect("Failed to extract .tgz file"); +} + + +fn hex_str_to_bytes(c: impl AsRef<[u8]>) -> Vec { + fn nibble(c: u8) -> u8 { + match c { + b'A'..=b'F' => c - b'A' + 10, + b'a'..=b'f' => c - b'a' + 10, + b'0'..=b'9' => c - b'0', + _ => panic!() + } + } + + c.as_ref().chunks(2).map(|n| nibble(n[0]) << 4 | nibble(n[1])).collect() +} + + +fn verify_file(buf: &[u8], hash: impl AsRef<[u8]>) -> bool { + use sha2::Digest; + sha2::Sha256::digest(buf)[..] == hex_str_to_bytes(hash) +} + + +/// Fetches a file from the given URL and returns it as a vector of bytes. +/// +/// # Arguments +/// * `source_url` - The URL to fetch the file from. +/// +/// # Returns +/// A vector of bytes containing the file. +fn fetch_file(source_url: &str) -> Vec { + let resp = ureq::get(source_url) + .timeout(std::time::Duration::from_secs(1800)) + .call() + .unwrap_or_else(|err| panic!("Failed to GET `{source_url}`: {err}")); + + let len = resp + .header("Content-Length") + .and_then(|s| s.parse::().ok()) + .expect("Content-Length header should be present on archive response"); + let mut reader = resp.into_reader(); + let mut buffer = Vec::new(); + reader + .read_to_end(&mut buffer) + .unwrap_or_else(|err| panic!("Failed to download from `{source_url}`: {err}")); + assert_eq!(buffer.len(), len); + buffer +} + + fn main() { @@ -7,50 +70,72 @@ fn main() { println!("cargo:rustc-cfg=onnx_runtime_env_var_set"); }, Err(_) => { - #[cfg(not(windows))] - { - let _ = Command::new("sh") - .arg("-c") - .arg("cargo new onnx_driver && cd onnx_driver && echo 'ort = \"1.16.2\"' >> Cargo.toml - ") - .status() - .expect("failed to execute process"); - } - - #[cfg(windows)] - { - // let _ = Command::new("cmd") - // .args(&["/C", "cargo new onnx_driver && cd onnx_driver && echo ort = \"1.16.2\" >> Cargo.toml"]) - // .status() - // .expect("failed to execute process"); - let _ = Command::new("powershell") - .arg("-Command") - .arg("cargo new onnx_driver; Set-Location onnx_driver; Add-Content -Path .\\Cargo.toml -Value 'ort = \"1.16.2\"'") - .status() - .expect("failed to execute process"); - } - - #[cfg(not(windows))] - { - let _ = Command::new("sh") - .arg("-c") - .arg("cd onnx_driver && cargo build") - .status() - .expect("failed to execute process"); - } - - #[cfg(windows)] - { - let _ = Command::new("cmd") - .args(&["/C", "cd onnx_driver && cargo build"]) - .status() - .expect("failed to execute process"); - } + let target = std::env::var("TARGET").unwrap(); + + let (prebuilt_url, prebuilt_hash) = match target.as_str() { + "aarch64-apple-darwin" => ( + "https://parcel.pyke.io/v2/delivery/ortrs/packages/msort-binary/1.16.3/ortrs-msort_static-v1.16.3-aarch64-apple-darwin.tgz", + "188E07B9304CCC28877195ECD2177EF3EA6603A0B5B3497681A6C9E584721387" + ), + "aarch64-pc-windows-msvc" => ( + "https://parcel.pyke.io/v2/delivery/ortrs/packages/msort-binary/1.16.3/ortrs-msort_static-v1.16.3-aarch64-pc-windows-msvc.tgz", + "B35F6526EAF61527531D6F73EBA19EF09D6B0886FB66C14E1B594EE70F447817" + ), + "aarch64-unknown-linux-gnu" => ( + "https://parcel.pyke.io/v2/delivery/ortrs/packages/msort-binary/1.16.3/ortrs-msort_static-v1.16.3-aarch64-unknown-linux-gnu.tgz", + "C1E315515856D7880545058479020756BC5CE4C0BA07FB3DD2104233EC7C3C81" + ), + "wasm32-unknown-emscripten" => ( + "https://parcel.pyke.io/v2/delivery/ortrs/packages/msort-binary/1.16.3/ortrs-msort_static-v1.16.3-wasm32-unknown-emscripten.tgz", + "468F74FB4C7451DC94EBABC080779CDFF0C7DA0617D85ADF21D5435A96F9D470" + ), + "x86_64-apple-darwin" => ( + "https://parcel.pyke.io/v2/delivery/ortrs/packages/msort-binary/1.16.3/ortrs-msort_static-v1.16.3-x86_64-apple-darwin.tgz", + "0191C95D9E797BF77C723AD82DC078C6400834B55B8465FA5176BA984FFEAB08" + ), + "x86_64-pc-windows-msvc" => { + if cfg!(any(feature = "cuda", feature = "tensorrt")) { + ( + "https://parcel.pyke.io/v2/delivery/ortrs/packages/msort-binary/1.16.3/ortrs-msort_dylib_cuda-v1.16.3-x86_64-pc-windows-msvc.tgz", + "B0F08E93E580297C170F04933742D04813C9C3BAD3705E1100CA9EF464AE4011" + ) + } else { + ( + "https://parcel.pyke.io/v2/delivery/ortrs/packages/msort-binary/1.16.3/ortrs-msort_static-v1.16.3-x86_64-pc-windows-msvc.tgz", + "32ADC031C0EAA6C521680EEB9A8C39572C600A5B4F90AFE984590EA92B99E3BE" + ) + } + } + "x86_64-unknown-linux-gnu" => { + if cfg!(any(feature = "cuda", feature = "tensorrt")) { + ( + "https://parcel.pyke.io/v2/delivery/ortrs/packages/msort-binary/1.16.3/ortrs-msort_dylib_cuda-v1.16.3-x86_64-unknown-linux-gnu.tgz", + "0F0651D10BA56A6EA613F10B60E5C4D892384416C4D76E1F618BE57D1270993F" + ) + } else { + ( + "https://parcel.pyke.io/v2/delivery/ortrs/packages/msort-binary/1.16.3/ortrs-msort_static-v1.16.3-x86_64-unknown-linux-gnu.tgz", + "D0E63AC1E5A56D0480009049183542E0BB1482CE29A1D110CC8550BEC5D994E2" + ) + } + } + x => panic!("downloaded binaries not available for target {x}\nyou may have to compile ONNX Runtime from source") + }; + + // download the prebuilt binary that is compatible with the target + let downloaded_file = fetch_file(prebuilt_url); + + // verify the hash of the downloaded file to ensure that we have downloaded the correct file + assert!(verify_file(&downloaded_file, prebuilt_hash)); + + // delete the ONNX cache file if it exists + let _ = std::fs::remove_dir_all(CACHE_FILE); + + // extract the downloaded file to the cache file + extract_tgz(&downloaded_file, Path::new(CACHE_FILE)); + + // remove the downloaded bundled file + let _ = std::fs::remove_file("./msort.tar.gz"); } } } - -// fn main() { -// // println!("cargo:rustc-cfg=onnx_runtime_env_var_set"); -// println!("test"); -// } \ No newline at end of file diff --git a/modules/utils/src/execution/onnx_environment.rs b/modules/utils/src/execution/onnx_environment.rs index 291456a..d865f5e 100644 --- a/modules/utils/src/execution/onnx_environment.rs +++ b/modules/utils/src/execution/onnx_environment.rs @@ -6,13 +6,13 @@ use std::sync::Arc; // Compiles the ONNX module into the rust binary. #[cfg(all(target_os = "macos", not(doc), not(onnx_runtime_env_var_set)))] -pub static LIB_BYTES: &'static [u8] = include_bytes!("../../onnx_driver/target/debug/libonnxruntime.dylib"); +pub static LIB_BYTES: &'static [u8] = include_bytes!("../../downloaded_onnx_package/onnxruntime/lib/libonnxruntime.a"); #[cfg(all(any(target_os = "linux", target_os = "android"), not(doc), not(onnx_runtime_env_var_set)))] -pub static LIB_BYTES: &'static [u8] = include_bytes!("../../onnx_driver/target/debug/libonnxruntime.so"); +pub static LIB_BYTES: &'static [u8] = include_bytes!("../../downloaded_onnx_package/onnxruntime/lib/libonnxruntime.a"); #[cfg(all(target_os = "windows", not(doc), not(onnx_runtime_env_var_set)))] -pub static LIB_BYTES: &'static [u8] = include_bytes!("../../onnx_driver/target/debug/onnxruntime.dll"); +pub static LIB_BYTES: &'static [u8] = include_bytes!("../../downloaded_onnx_package/onnxruntime/lib/libonnxruntime.a"); // Fallback for documentation and other targets #[cfg(any(doc, onnx_runtime_env_var_set, not(any(target_os = "macos", target_os = "linux", target_os = "android", target_os = "windows"))))] From 5b32ccfb87a713e761308ee98d2bae6a113cf27c Mon Sep 17 00:00:00 2001 From: maxwellflitton Date: Thu, 4 Jan 2024 15:01:52 +0000 Subject: [PATCH 2/4] sorting out the build.rs --- modules/utils/.gitignore | 2 + modules/utils/Cargo.toml | 5 +- modules/utils/build.rs | 148 +++--------------- .../utils/src/execution/onnx_environment.rs | 16 +- 4 files changed, 33 insertions(+), 138 deletions(-) diff --git a/modules/utils/.gitignore b/modules/utils/.gitignore index dc72240..8474aa3 100644 --- a/modules/utils/.gitignore +++ b/modules/utils/.gitignore @@ -2,3 +2,5 @@ onnx_driver/ target/ output/ downloaded_onnx_package/ +src/execution/libonnxruntime.a +libonnxruntime.* diff --git a/modules/utils/Cargo.toml b/modules/utils/Cargo.toml index 33bb9b4..5a067e4 100644 --- a/modules/utils/Cargo.toml +++ b/modules/utils/Cargo.toml @@ -25,7 +25,4 @@ name = "surrealml_core" path = "src/lib.rs" [build-dependencies] -ureq = { version = "2.1", default-features = false, features = [ "tls" ] } -tar = { version = "0.4" } -flate2 = { version = "1.0" } -sha2 = { version = "0.10" } +ort = { version = "1.16.2", default-features = true } diff --git a/modules/utils/build.rs b/modules/utils/build.rs index c48de46..ba352c2 100644 --- a/modules/utils/build.rs +++ b/modules/utils/build.rs @@ -1,141 +1,33 @@ -//! This build file downloads the prebuilt binaries for ONNX Runtime and places them in the root of the crate -//! to be pointed at by the ort environment so we can run the ONNX models. -use ureq; use std::path::Path; +use std::env; +use std::fs; -static CACHE_FILE: &str = "./downloaded_onnx_package"; - - -fn extract_tgz(buf: &[u8], output: &Path) { - let buf: std::io::BufReader<&[u8]> = std::io::BufReader::new(buf); - let tar = flate2::read::GzDecoder::new(buf); - let mut archive = tar::Archive::new(tar); - archive.unpack(output).expect("Failed to extract .tgz file"); -} - - -fn hex_str_to_bytes(c: impl AsRef<[u8]>) -> Vec { - fn nibble(c: u8) -> u8 { - match c { - b'A'..=b'F' => c - b'A' + 10, - b'a'..=b'f' => c - b'a' + 10, - b'0'..=b'9' => c - b'0', - _ => panic!() - } - } - - c.as_ref().chunks(2).map(|n| nibble(n[0]) << 4 | nibble(n[1])).collect() -} - - -fn verify_file(buf: &[u8], hash: impl AsRef<[u8]>) -> bool { - use sha2::Digest; - sha2::Sha256::digest(buf)[..] == hex_str_to_bytes(hash) -} - - -/// Fetches a file from the given URL and returns it as a vector of bytes. -/// -/// # Arguments -/// * `source_url` - The URL to fetch the file from. -/// -/// # Returns -/// A vector of bytes containing the file. -fn fetch_file(source_url: &str) -> Vec { - let resp = ureq::get(source_url) - .timeout(std::time::Duration::from_secs(1800)) - .call() - .unwrap_or_else(|err| panic!("Failed to GET `{source_url}`: {err}")); - - let len = resp - .header("Content-Length") - .and_then(|s| s.parse::().ok()) - .expect("Content-Length header should be present on archive response"); - let mut reader = resp.into_reader(); - let mut buffer = Vec::new(); - reader - .read_to_end(&mut buffer) - .unwrap_or_else(|err| panic!("Failed to download from `{source_url}`: {err}")); - assert_eq!(buffer.len(), len); - buffer -} - - - -fn main() { +fn main() -> std::io::Result<()> { match std::env::var("ONNXRUNTIME_LIB_PATH") { Ok(_) => { println!("cargo:rustc-cfg=onnx_runtime_env_var_set"); }, Err(_) => { - let target = std::env::var("TARGET").unwrap(); - - let (prebuilt_url, prebuilt_hash) = match target.as_str() { - "aarch64-apple-darwin" => ( - "https://parcel.pyke.io/v2/delivery/ortrs/packages/msort-binary/1.16.3/ortrs-msort_static-v1.16.3-aarch64-apple-darwin.tgz", - "188E07B9304CCC28877195ECD2177EF3EA6603A0B5B3497681A6C9E584721387" - ), - "aarch64-pc-windows-msvc" => ( - "https://parcel.pyke.io/v2/delivery/ortrs/packages/msort-binary/1.16.3/ortrs-msort_static-v1.16.3-aarch64-pc-windows-msvc.tgz", - "B35F6526EAF61527531D6F73EBA19EF09D6B0886FB66C14E1B594EE70F447817" - ), - "aarch64-unknown-linux-gnu" => ( - "https://parcel.pyke.io/v2/delivery/ortrs/packages/msort-binary/1.16.3/ortrs-msort_static-v1.16.3-aarch64-unknown-linux-gnu.tgz", - "C1E315515856D7880545058479020756BC5CE4C0BA07FB3DD2104233EC7C3C81" - ), - "wasm32-unknown-emscripten" => ( - "https://parcel.pyke.io/v2/delivery/ortrs/packages/msort-binary/1.16.3/ortrs-msort_static-v1.16.3-wasm32-unknown-emscripten.tgz", - "468F74FB4C7451DC94EBABC080779CDFF0C7DA0617D85ADF21D5435A96F9D470" - ), - "x86_64-apple-darwin" => ( - "https://parcel.pyke.io/v2/delivery/ortrs/packages/msort-binary/1.16.3/ortrs-msort_static-v1.16.3-x86_64-apple-darwin.tgz", - "0191C95D9E797BF77C723AD82DC078C6400834B55B8465FA5176BA984FFEAB08" - ), - "x86_64-pc-windows-msvc" => { - if cfg!(any(feature = "cuda", feature = "tensorrt")) { - ( - "https://parcel.pyke.io/v2/delivery/ortrs/packages/msort-binary/1.16.3/ortrs-msort_dylib_cuda-v1.16.3-x86_64-pc-windows-msvc.tgz", - "B0F08E93E580297C170F04933742D04813C9C3BAD3705E1100CA9EF464AE4011" - ) - } else { - ( - "https://parcel.pyke.io/v2/delivery/ortrs/packages/msort-binary/1.16.3/ortrs-msort_static-v1.16.3-x86_64-pc-windows-msvc.tgz", - "32ADC031C0EAA6C521680EEB9A8C39572C600A5B4F90AFE984590EA92B99E3BE" - ) - } - } - "x86_64-unknown-linux-gnu" => { - if cfg!(any(feature = "cuda", feature = "tensorrt")) { - ( - "https://parcel.pyke.io/v2/delivery/ortrs/packages/msort-binary/1.16.3/ortrs-msort_dylib_cuda-v1.16.3-x86_64-unknown-linux-gnu.tgz", - "0F0651D10BA56A6EA613F10B60E5C4D892384416C4D76E1F618BE57D1270993F" - ) - } else { - ( - "https://parcel.pyke.io/v2/delivery/ortrs/packages/msort-binary/1.16.3/ortrs-msort_static-v1.16.3-x86_64-unknown-linux-gnu.tgz", - "D0E63AC1E5A56D0480009049183542E0BB1482CE29A1D110CC8550BEC5D994E2" - ) - } - } - x => panic!("downloaded binaries not available for target {x}\nyou may have to compile ONNX Runtime from source") + let target_lib = match env::var("CARGO_CFG_TARGET_OS").unwrap() { + ref s if s.contains("linux") => "libonnxruntime.so", + ref s if s.contains("macos") => "libonnxruntime.dylib", + ref s if s.contains("windows") => "onnxruntime.dll", + // ref s if s.contains("android") => "android", => not building for android + _ => panic!("Unsupported target os") }; - - // download the prebuilt binary that is compatible with the target - let downloaded_file = fetch_file(prebuilt_url); - - // verify the hash of the downloaded file to ensure that we have downloaded the correct file - assert!(verify_file(&downloaded_file, prebuilt_hash)); - - // delete the ONNX cache file if it exists - let _ = std::fs::remove_dir_all(CACHE_FILE); - - // extract the downloaded file to the cache file - extract_tgz(&downloaded_file, Path::new(CACHE_FILE)); - - // remove the downloaded bundled file - let _ = std::fs::remove_file("./msort.tar.gz"); + let profile = match env::var("PROFILE").unwrap() { + ref s if s.contains("release") => "release", + ref s if s.contains("debug") => "debug", + _ => panic!("Unsupported profile") + }; + let lib_path = Path::new("target").join(profile).join(target_lib); + // put it next to the file of the embedding + let destination = Path::new(target_lib); + fs::copy(lib_path, destination)?; } + } + Ok(()) } diff --git a/modules/utils/src/execution/onnx_environment.rs b/modules/utils/src/execution/onnx_environment.rs index d865f5e..aed968f 100644 --- a/modules/utils/src/execution/onnx_environment.rs +++ b/modules/utils/src/execution/onnx_environment.rs @@ -6,13 +6,13 @@ use std::sync::Arc; // Compiles the ONNX module into the rust binary. #[cfg(all(target_os = "macos", not(doc), not(onnx_runtime_env_var_set)))] -pub static LIB_BYTES: &'static [u8] = include_bytes!("../../downloaded_onnx_package/onnxruntime/lib/libonnxruntime.a"); +pub static LIB_BYTES: &'static [u8] = include_bytes!("../../libonnxruntime.dylib"); #[cfg(all(any(target_os = "linux", target_os = "android"), not(doc), not(onnx_runtime_env_var_set)))] -pub static LIB_BYTES: &'static [u8] = include_bytes!("../../downloaded_onnx_package/onnxruntime/lib/libonnxruntime.a"); +pub static LIB_BYTES: &'static [u8] = include_bytes!("../../libonnxruntime.so"); #[cfg(all(target_os = "windows", not(doc), not(onnx_runtime_env_var_set)))] -pub static LIB_BYTES: &'static [u8] = include_bytes!("../../downloaded_onnx_package/onnxruntime/lib/libonnxruntime.a"); +pub static LIB_BYTES: &'static [u8] = include_bytes!("../../libonnxruntime.dll"); // Fallback for documentation and other targets #[cfg(any(doc, onnx_runtime_env_var_set, not(any(target_os = "macos", target_os = "linux", target_os = "android", target_os = "windows"))))] @@ -37,10 +37,14 @@ pub static ENVIRONMENT: Lazy> = Lazy::new(|| { // we write the `LIB_BYTES` to a temporary file and then load that file. Err(_) => { + let current_dir = std::env::current_dir().unwrap(); + let current_dir = current_dir.to_str().unwrap(); + let write_dir = std::path::Path::new(current_dir).join("libonnxruntime.dylib"); + #[cfg(any(not(doc), not(onnx_runtime_env_var_set)))] - let _ = std::fs::write("./libonnxruntime.dylib", LIB_BYTES); + let _ = std::fs::write(write_dir.clone(), LIB_BYTES); - std::env::set_var("ORT_DYLIB_PATH", "./libonnxruntime.dylib"); + std::env::set_var("ORT_DYLIB_PATH", write_dir.clone()); let environment = Arc::new( Environment::builder() .with_execution_providers([ExecutionProvider::CPU(Default::default())]) @@ -49,7 +53,7 @@ pub static ENVIRONMENT: Lazy> = Lazy::new(|| { std::env::remove_var("ORT_DYLIB_PATH"); #[cfg(any(not(doc), not(onnx_runtime_env_var_set)))] - let _ = std::fs::remove_file("./libonnxruntime.dylib"); + let _ = std::fs::remove_file(write_dir); return environment } From 5a5884ccc9aee862255f66d6583d7dac0f8644c0 Mon Sep 17 00:00:00 2001 From: maxwellflitton Date: Thu, 4 Jan 2024 23:13:15 +0000 Subject: [PATCH 3/4] updating build.rs for surrealml package --- Cargo.toml | 3 +++ build.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 build.rs diff --git a/Cargo.toml b/Cargo.toml index 3eecdae..8b06b3d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,3 +28,6 @@ futures-util = "0.3.29" [lib] name = "surrealml" path = "src/lib.rs" + +[build-dependencies] +ort = { version = "1.16.2", default-features = true } \ No newline at end of file diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..1872129 --- /dev/null +++ b/build.rs @@ -0,0 +1,31 @@ +use std::path::Path; +use std::env; + + +fn main() { + let target_lib = match env::var("CARGO_CFG_TARGET_OS").unwrap() { + ref s if s.contains("linux") => "libonnxruntime.so", + ref s if s.contains("macos") => "libonnxruntime.dylib", + ref s if s.contains("windows") => "onnxruntime.dll", + // ref s if s.contains("android") => "android", => not building for android + _ => panic!("Unsupported target os") + }; + let profile = match env::var("PROFILE").unwrap() { + ref s if s.contains("release") => "release", + ref s if s.contains("debug") => "debug", + _ => panic!("Unsupported profile") + }; + + // remove ./modules/utils/target folder if there + let _ = std::fs::remove_dir_all(Path::new("modules").join("utils").join("target")).unwrap_or(()); + + // create the target module folder for the utils module + let _ = std::fs::create_dir(Path::new("modules").join("utils").join("target")); + let _ = std::fs::create_dir(Path::new("modules").join("utils").join("target").join(profile)); + + // copy target folder to modules/utils/target profile for the utils modules + std::fs::copy( + Path::new("target").join(profile).join(target_lib), + Path::new("modules").join("utils").join("target").join(profile).join(target_lib) + ).unwrap(); +} \ No newline at end of file From e3cc2adfef3603f11083115c76159eb731900b00 Mon Sep 17 00:00:00 2001 From: maxwellflitton Date: Fri, 5 Jan 2024 11:24:27 +0000 Subject: [PATCH 4/4] prepping version for release --- modules/utils/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/utils/Cargo.toml b/modules/utils/Cargo.toml index 5a067e4..e8a1ac2 100644 --- a/modules/utils/Cargo.toml +++ b/modules/utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "surrealml-core" -version = "0.0.3" +version = "0.0.4" edition = "2021" build = "./build.rs" description = "The core machine learning library for SurrealML that enables SurrealDB to store and load ML models"