Skip to content

Commit 03e1573

Browse files
committed
Merge commit '3146e89f6808fc44471daa009d7a8dfce04bd69d' into refactor/sdk_preview
2 parents 6cffdc2 + 3146e89 commit 03e1573

File tree

4 files changed

+183
-8
lines changed

4 files changed

+183
-8
lines changed

.github/workflows/ci-build.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ jobs:
4141
working-directory: WasmEdge
4242
run: |
4343
apt update
44-
apt install -y software-properties-common libboost-all-dev llvm-15-dev liblld-15-dev ninja-build
45-
cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=Release -DWASMEDGE_PLUGIN_PROCESS=On .
44+
apt install -y software-properties-common libboost-all-dev llvm-15-dev liblld-15-dev ninja-build libssl-dev
45+
cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=Release -DWASMEDGE_PLUGIN_PROCESS=On -DWASMEDGE_PLUGIN_WASI_CRYPTO=On .
4646
cmake --build build
4747
cmake --install build
4848
ldconfig
@@ -151,7 +151,7 @@ jobs:
151151
export WASMEDGE_BUILD_DIR="$(pwd)/WasmEdge/build"
152152
export WASMEDGE_PLUGIN_PATH="$(pwd)/WasmEdge/build/plugins/wasmedge_process"
153153
export LD_LIBRARY_PATH="$(pwd)/WasmEdge/build/lib/api"
154-
cargo test --workspace --locked --features aot,wasmedge_process,ffi -- --nocapture --test-threads=1
154+
cargo test --workspace --locked --features aot,wasmedge_process,ffi -- --nocapture --test-threads=1 --skip test_vmbuilder
155155
156156
- name: Test Rust SDK with async feature
157157
run: |
2.81 KB
Binary file not shown.

src/plugin.rs

+135-5
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,35 @@ pub mod ffi {
1313
};
1414
}
1515

16+
/// Preload config for initializing the wasi_nn plug-in.
1617
#[cfg(feature = "wasi_nn")]
1718
#[cfg_attr(docsrs, doc(cfg(feature = "wasi_nn")))]
1819
#[derive(Debug)]
1920
pub struct NNPreload {
2021
/// The alias of the model in the WASI-NN environment.
21-
pub alias: String,
22+
alias: String,
2223
/// The inference backend.
23-
pub backend: GraphEncoding,
24+
backend: GraphEncoding,
2425
/// The execution target, on which the inference runs.
25-
pub target: ExecutionTarget,
26+
target: ExecutionTarget,
2627
/// The path to the model file. Note that the path is the guest path instead of the host path.
27-
pub path: std::path::PathBuf,
28+
path: std::path::PathBuf,
2829
}
2930
#[cfg(feature = "wasi_nn")]
3031
#[cfg_attr(docsrs, doc(cfg(feature = "wasi_nn")))]
3132
impl NNPreload {
33+
/// Creates a new preload config.
34+
///
35+
/// # Arguments
36+
///
37+
/// * `alias` - The alias of the model in the WASI-NN environment.
38+
///
39+
/// * `backend` - The inference backend.
40+
///
41+
/// * `target` - The execution target, on which the inference runs.
42+
///
43+
/// * `path` - The path to the model file. Note that the path is the guest path instead of the host path.
44+
///
3245
pub fn new(
3346
alias: impl AsRef<str>,
3447
backend: GraphEncoding,
@@ -57,6 +70,90 @@ impl std::fmt::Display for NNPreload {
5770
)
5871
}
5972
}
73+
#[cfg(feature = "wasi_nn")]
74+
#[cfg_attr(docsrs, doc(cfg(feature = "wasi_nn")))]
75+
impl std::str::FromStr for NNPreload {
76+
type Err = WasmEdgeError;
77+
78+
fn from_str(preload: &str) -> std::result::Result<Self, Self::Err> {
79+
let nn_preload: Vec<&str> = preload.split(':').collect();
80+
if nn_preload.len() != 4 {
81+
return Err(WasmEdgeError::Operation(format!(
82+
"Failed to convert to NNPreload value. Invalid preload string: {}. The correct format is: 'alias:backend:target:path'",
83+
preload
84+
)));
85+
}
86+
let (alias, backend, target, path) = (
87+
nn_preload[0].to_string(),
88+
nn_preload[1]
89+
.parse::<GraphEncoding>()
90+
.map_err(|err| WasmEdgeError::Operation(err.to_string()))?,
91+
nn_preload[2]
92+
.parse::<ExecutionTarget>()
93+
.map_err(|err| WasmEdgeError::Operation(err.to_string()))?,
94+
std::path::PathBuf::from(nn_preload[3]),
95+
);
96+
97+
Ok(Self::new(alias, backend, target, path))
98+
}
99+
}
100+
101+
#[cfg(feature = "wasi_nn")]
102+
#[test]
103+
fn test_generate_nnpreload_from_str() {
104+
use std::str::FromStr;
105+
106+
// valid preload string
107+
let preload = "default:GGML:CPU:llama-2-7b-chat.Q5_K_M.gguf";
108+
let result = NNPreload::from_str(preload);
109+
assert!(result.is_ok());
110+
let nnpreload = result.unwrap();
111+
assert_eq!(nnpreload.alias, "default");
112+
assert_eq!(nnpreload.backend, GraphEncoding::GGML);
113+
assert_eq!(nnpreload.target, ExecutionTarget::CPU);
114+
assert_eq!(
115+
nnpreload.path,
116+
std::path::PathBuf::from("llama-2-7b-chat.Q5_K_M.gguf")
117+
);
118+
119+
// invalid preload string
120+
let preload = "default:CPU:GGML:llama-2-7b-chat.Q5_K_M.gguf";
121+
let result = NNPreload::from_str(preload);
122+
assert!(result.is_err());
123+
let err = result.unwrap_err();
124+
assert_eq!(
125+
WasmEdgeError::Operation(
126+
"Failed to convert to NNBackend value. Unknown NNBackend type: CPU".to_string()
127+
),
128+
err
129+
);
130+
131+
// invalid preload string: unsupported target
132+
let preload = "default:GGML:NPU:llama-2-7b-chat.Q5_K_M.gguf";
133+
let result = NNPreload::from_str(preload);
134+
assert!(result.is_err());
135+
let err = result.unwrap_err();
136+
assert_eq!(
137+
WasmEdgeError::Operation(
138+
"Failed to convert to ExecutionTarget value. Unknown ExecutionTarget type: NPU"
139+
.to_string()
140+
),
141+
err
142+
);
143+
144+
// invalid preload string: invalid format
145+
let preload = "default:GGML:CPU";
146+
let result = NNPreload::from_str(preload);
147+
assert!(result.is_err());
148+
let err = result.unwrap_err();
149+
assert_eq!(
150+
WasmEdgeError::Operation(
151+
"Failed to convert to NNPreload value. Invalid preload string: default:GGML:CPU. The correct format is: 'alias:backend:target:path'"
152+
.to_string()
153+
),
154+
err
155+
);
156+
}
60157

61158
/// Describes the encoding of the graph.
62159
#[cfg(feature = "wasi_nn")]
@@ -160,7 +257,7 @@ impl PluginManager {
160257
/// * If the path is not given, then the default plugin paths will be used. The default plugin paths are
161258
///
162259
/// * The environment variable "WASMEDGE_PLUGIN_PATH".
163-
///
260+
///
164261
/// * The `../plugin/` directory related to the WasmEdge installation path.
165262
///
166263
/// * The `wasmedge/` directory under the library path if the WasmEdge is installed under the "/usr".
@@ -184,6 +281,39 @@ impl PluginManager {
184281
}
185282
}
186283

284+
/// Initialize the wasi_nn plug-in with the preloads.
285+
///
286+
/// Note that this function is only available after loading the wasi_nn plug-in and before creating, and before creating the module instance from the plug-in.
287+
///
288+
/// # Argument
289+
///
290+
/// * `preloads` - The preload list.
291+
///
292+
/// # Example
293+
///
294+
/// ```ignore
295+
/// // load wasinn-pytorch-plugin from the default plugin directory: /usr/local/lib/wasmedge
296+
/// PluginManager::load(None)?;
297+
/// // preload named model
298+
/// PluginManager::nn_preload(vec![NNPreload::new(
299+
/// "default",
300+
/// GraphEncoding::GGML,
301+
/// ExecutionTarget::CPU,
302+
/// "llama-2-7b-chat.Q5_K_M.gguf",
303+
/// )]);
304+
/// ```
305+
///
306+
/// If a preload is string, then use `NNPreload::from_str` to create a `NNPreload` instance:
307+
///
308+
/// ```ignore
309+
/// use std::str::FromStr;
310+
///
311+
/// // load wasinn-pytorch-plugin from the default plugin directory: /usr/local/lib/wasmedge
312+
/// PluginManager::load(None)?;
313+
/// // preload named model
314+
/// PluginManager::nn_preload(vec![NNPreload::from_str("default:GGML:CPU:llama-2-7b-chat.Q5_K_M.gguf")?]);
315+
///
316+
/// ```
187317
#[cfg(feature = "wasi_nn")]
188318
#[cfg_attr(docsrs, doc(cfg(feature = "wasi_nn")))]
189319
pub fn nn_preload(preloads: Vec<NNPreload>) {

src/vm.rs

+45
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,51 @@ mod tests {
270270
use super::*;
271271
use crate::{params, WasmVal};
272272

273+
#[cfg(target_os = "linux")]
274+
#[test]
275+
fn test_vmbuilder() -> Result<(), Box<dyn std::error::Error>> {
276+
use crate::{params, plugin::PluginManager};
277+
278+
// load plugins from the default plugin path
279+
PluginManager::load(None)?;
280+
281+
PluginManager::names().iter().for_each(|name| {
282+
println!("plugin name: {}", name);
283+
});
284+
285+
let wasm_app_file = "examples/wasmedge-sys/data/test_crypto.wasm";
286+
287+
let mut wasi = crate::wasi::WasiModule::create(None, None, None).unwrap();
288+
let mut wasi_crypto_asymmetric_common =
289+
PluginManager::load_wasi_crypto_asymmetric_common().unwrap();
290+
let mut wasi_crypto_signatures = PluginManager::load_wasi_crypto_signatures().unwrap();
291+
let mut wasi_crypto_symmetric = PluginManager::load_wasi_crypto_symmetric().unwrap();
292+
293+
let mut instances = HashMap::new();
294+
instances.insert(wasi.name().to_string(), wasi.as_mut());
295+
instances.insert(
296+
wasi_crypto_asymmetric_common.name().unwrap(),
297+
&mut wasi_crypto_asymmetric_common,
298+
);
299+
instances.insert(
300+
wasi_crypto_signatures.name().unwrap(),
301+
&mut wasi_crypto_signatures,
302+
);
303+
instances.insert(
304+
wasi_crypto_symmetric.name().unwrap(),
305+
&mut wasi_crypto_symmetric,
306+
);
307+
308+
let mut vm = Vm::new(Store::new(None, instances).unwrap());
309+
310+
let module = Module::from_file(None, &wasm_app_file).unwrap();
311+
312+
vm.register_module(Some("wasm-app"), module).unwrap();
313+
vm.run_func(Some("wasm-app"), "_start", params!())?;
314+
315+
Ok(())
316+
}
317+
273318
#[test]
274319
fn test_vm_run_func_from_file() {
275320
// create a Vm context

0 commit comments

Comments
 (0)