Skip to content

Commit 854a621

Browse files
feat: add WASI-NN bindings to Wasm Workers Server (#201)
* feat: add WASI-NN bindings to Wasm Workers Server * fix: remove unnecessary var initialization * fix: typo error when closing a conditional assignment * feat: add new documentation about ML inference and WASI-NN * docs: improve docs and remove typos * fix: remove support for tensor files and clarifies why we need to skip 1 --------- Co-authored-by: Rafael Fernández López <[email protected]>
1 parent c390c95 commit 854a621

27 files changed

+2208
-12
lines changed

Cargo.lock

Lines changed: 87 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ repository = { workspace = true }
1313
[workspace.package]
1414
version = "1.4.0"
1515
edition = "2021"
16-
authors = [ "Wasm Labs <https://wasmlabs.dev>" ]
16+
authors = ["Wasm Labs <https://wasmlabs.dev>"]
1717
license = "Apache-2.0"
1818
repository = "https://github.com/vmware-labs/wasm-workers-server/"
1919

@@ -60,15 +60,16 @@ members = [
6060
"crates/worker",
6161
"kits/rust",
6262
"kits/rust/worker",
63-
"kits/javascript"
63+
"kits/javascript",
6464
]
6565
# Exclude examples
6666
exclude = [
6767
"examples/pdf-create",
6868
"examples/rust-basic",
6969
"examples/rust-fetch",
7070
"examples/rust-kv",
71-
"examples/rust-params"
71+
"examples/rust-params",
72+
"examples/rust-wasi-nn",
7273
]
7374

7475
[workspace.dependencies]
@@ -93,6 +94,7 @@ wws-api-manage = { path = "./crates/api-manage" }
9394
wws-api-manage-openapi = { path = "./crates/api-manage-openapi" }
9495
wasmtime = "10.0.1"
9596
wasmtime-wasi = "10.0.1"
97+
wasmtime-wasi-nn = "10.0.1"
9698
wasi-common = "10.0.1"
9799
path-slash = "0.2.1"
98100
openssl = { version = "=0.10.55" }

crates/worker/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ tokio = { workspace = true }
1919
toml = { workspace = true }
2020
wasmtime = { workspace = true }
2121
wasmtime-wasi = { workspace = true }
22+
wasmtime-wasi-nn = { workspace = true }
2223
wasi-common = { workspace = true }
2324
wws-config = { workspace = true }
2425
wws-data-kv = { workspace = true }

crates/worker/src/config.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// SPDX-License-Identifier: Apache-2.0
33

44
use crate::features::http_requests::HttpRequestsConfig;
5+
use crate::features::wasi_nn::WasiNnConfig;
56
use crate::features::{data::ConfigData, folders::Folder};
67
use anyhow::{anyhow, Result};
78
use serde::{Deserialize, Deserializer};
@@ -13,9 +14,12 @@ use wws_data_kv::KVConfigData;
1314

1415
/// List all available features for a worker
1516
#[derive(Deserialize, Clone, Default)]
17+
#[serde(default)]
1618
pub struct Features {
1719
/// Allow to perform http requests from a worker
1820
pub http_requests: HttpRequestsConfig,
21+
/// Enables WASI-NN bindings for Machine Learning inference
22+
pub wasi_nn: WasiNnConfig,
1923
}
2024

2125
/// Workers configuration. These files are optional when no configuration change is required.

crates/worker/src/features/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
pub mod data;
55
pub mod folders;
66
pub mod http_requests;
7+
pub mod wasi_nn;

crates/worker/src/features/wasi_nn.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2023 VMware, Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
use serde::Deserialize;
5+
6+
pub const WASI_NN_BACKEND_OPENVINO: &str = "openvino";
7+
8+
#[derive(Deserialize, Clone, Default)]
9+
#[serde(default)]
10+
pub struct WasiNnConfig {
11+
/// List of Machine Learning backends. For now, only "openvino" option is supported
12+
pub allowed_backends: Vec<String>,
13+
}

crates/worker/src/lib.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,18 @@ use actix_web::HttpRequest;
1111
use anyhow::{anyhow, Result};
1212
use bindings::http::{add_to_linker as http_add_to_linker, HttpBindings};
1313
use config::Config;
14+
use features::wasi_nn::WASI_NN_BACKEND_OPENVINO;
1415
use io::{WasmInput, WasmOutput};
1516
use sha256::digest as sha256_digest;
1617
use std::fs::{self, File};
1718
use std::path::PathBuf;
19+
use std::sync::Arc;
1820
use std::{collections::HashMap, path::Path};
1921
use stdio::Stdio;
2022
use wasi_common::WasiCtx;
2123
use wasmtime::{Engine, Linker, Module, Store};
2224
use wasmtime_wasi::{ambient_authority, Dir, WasiCtxBuilder};
25+
use wasmtime_wasi_nn::WasiNnCtx;
2326
use wws_config::Config as ProjectConfig;
2427
use wws_runtimes::{init_runtime, Runtime};
2528

@@ -43,6 +46,7 @@ pub struct Worker {
4346

4447
struct WorkerState {
4548
pub wasi: WasiCtx,
49+
pub wasi_nn: Option<Arc<WasiNnCtx>>,
4650
pub http: HttpBindings,
4751
}
4852

@@ -134,12 +138,35 @@ impl Worker {
134138
}
135139
}
136140

141+
// WASI-NN
142+
let allowed_backends = &self.config.features.wasi_nn.allowed_backends;
143+
144+
let wasi_nn = if !allowed_backends.is_empty() {
145+
// For now, we only support OpenVINO
146+
if allowed_backends.len() != 1
147+
|| !allowed_backends.contains(&WASI_NN_BACKEND_OPENVINO.to_string())
148+
{
149+
eprintln!("❌ The only WASI-NN supported backend name is \"{WASI_NN_BACKEND_OPENVINO}\". Please, update your config.");
150+
None
151+
} else {
152+
wasmtime_wasi_nn::add_to_linker(&mut linker, |s: &mut WorkerState| {
153+
Arc::get_mut(s.wasi_nn.as_mut().unwrap())
154+
.expect("wasi-nn is not implemented with multi-threading support")
155+
})?;
156+
157+
Some(Arc::new(WasiNnCtx::new()?))
158+
}
159+
} else {
160+
None
161+
};
162+
137163
// Pass to the runtime to add any WASI specific requirement
138164
wasi_builder = self.runtime.prepare_wasi_ctx(wasi_builder)?;
139165

140166
let wasi = wasi_builder.build();
141167
let state = WorkerState {
142168
wasi,
169+
wasi_nn,
143170
http: HttpBindings {
144171
http_config: self.config.features.http_requests.clone(),
145172
},

docs/docs/features/dynamic-routes.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
---
2+
title: Dynamic Routes
23
sidebar_position: 4
34
---
45

5-
# Dynamic routes
6+
:::info
7+
8+
[Available since v1.0](https://github.com/vmware-labs/wasm-workers-server/releases/tag/v1.0.0)
9+
10+
:::
611

712
Defining static routes may not be enough for some applications. You may need a worker to process URLs that includes identifiers. **To create a worker associated with a dynamic route, include the route parameter in brackets when setting the worker filename**.
813

docs/docs/features/http-requests.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
---
2+
title: HTTP Requests (fetch)
23
sidebar_position: 3
34
---
45

5-
# HTTP Requests (fetch)
6+
:::info
7+
8+
[Available since v1.4](https://github.com/vmware-labs/wasm-workers-server/releases/tag/v1.4.0)
9+
10+
:::
611

712
Often times, workers require to access data from an external resource like a website or an API. This feature allows workers to perform HTTP requests to external resources. It follows the capability-based model, so workers cannot perform any HTTP request until you configure the allowed hosts and HTTP methods.
813

0 commit comments

Comments
 (0)