Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ crate-type = ["cdylib", "rlib"]
name = "pywebnn"

[features]
default = ["onnx-runtime", "dynamic-inputs"]
default = ["trtx-runtime", "onnx-runtime", "dynamic-inputs"]
onnx-runtime = ["rustnn/onnx-runtime", "ort", "ndarray"]
coreml-runtime = ["rustnn/coreml-runtime"]
trtx-runtime = ["rustnn/trtx-runtime"]
Expand Down
31 changes: 31 additions & 0 deletions docs/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -1202,3 +1202,34 @@ Common exceptions:
- `ValueError`: Invalid graph structure or parameters
- `IOError`: File I/O errors
- `RuntimeError`: Conversion or execution failures

## RustNN builder text export

Use a backend-free builder when you only need to construct and export a network:

```python
import webnn

builder = webnn.MLGraphBuilder.new_uncompiled()
x = builder.input("x", [2, 3], "float32")
y = builder.relu(x)
outputs = {"y": y}

graph = builder.build(outputs) # records an uncompiled MLGraph
text = builder.rustnn_webnn_text_for_outputs(outputs)
builder.rustnn_save_webnn(outputs, "model.webnn")
```

`rustnn_webnn_text_for_outputs(outputs) -> str` delegates to RustNN's text
serializer and embeds constants inline. `rustnn_save_webnn(outputs, path)`
delegates to RustNN's saver, writing the text file and a sibling
`<stem>.safetensors` containing external constant weights. Both methods work
before or after `build()` and leave the recorded graph unchanged. Empty,
duplicate, invalid, or conflicting outputs raise an exception.

`new_uncompiled()` initializes no backend and needs no runtime shared library.
Its graph can later be executed by a context. Context-created builders expose
the same serialization methods and retain their existing compilation behavior.
The Python builder's recorded operations are replayed through
`MLGraphBuilder::new_uncompiled()` for serialization, so RustNN owns shape
validation, text formatting, and weight-file handling.
14 changes: 14 additions & 0 deletions python/webnn/__init__.pyi
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Type stubs for webnn package"""

from typing import Any, Dict, List, Optional, Union
import os
import numpy as np
import numpy.typing as npt

Expand Down Expand Up @@ -244,6 +245,19 @@ class MLGraphBuilder:

def __init__(self) -> None: ...

@staticmethod
def new_uncompiled() -> MLGraphBuilder:
"""Construct a builder without a runtime; build() returns an uncompiled graph."""
...

def rustnn_webnn_text_for_outputs(self, outputs: Dict[str, MLOperand]) -> str:
"""RustNN text serialization with inline constants, before or after build()."""
...

def rustnn_save_webnn(self, outputs: Dict[str, MLOperand], path: Union[str, "os.PathLike[str]"]) -> None:
"""Write RustNN text and <stem>.safetensors without consuming the builder."""
...

def input(
self,
name: str,
Expand Down
5 changes: 5 additions & 0 deletions python/webnn/_rustnn.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from __future__ import annotations

from typing import Dict, List, Optional
from os import PathLike

import numpy as np
import numpy.typing as npt
Expand Down Expand Up @@ -74,6 +75,10 @@ class MLOperand:


class MLGraphBuilder:
@staticmethod
def new_uncompiled() -> MLGraphBuilder: ...
def rustnn_webnn_text_for_outputs(self, outputs: Dict[str, MLOperand]) -> str: ...
def rustnn_save_webnn(self, outputs: Dict[str, MLOperand], path: str | PathLike[str]) -> None: ...
def __init__(self) -> None: ...

def build(self, outputs): ...
Expand Down
Loading