webnn-graph 0.1.0

Simple DSL for WebNN graphs
Documentation
# webnn-graph

Rust implementation for a WebNN-oriented graph DSL:

- Parse WebNN graph text (`.webnn`) to canonical JSON
- Validate structure plus optional weights manifest
- Emit WebNN JavaScript builder code (WebNN MLGraphBuilder calls)

This is meant to be a small, hackable reference scaffold: keep the language
surface close to WebNN, but express graphs declaratively.

## Install

### From source (local dev)

Clone and build:

```bash
git clone https://github.com/tarekziade/webnn-graph
cd webnn-graph
make build
```

Then run the CLI:

```bash
make run
# Or for help:
webnn-graph --help
```

### Install the CLI with Cargo

From the repo root:

```bash
cargo install --path .
```

Then:

```bash
webnn-graph --help
```

## Development

### Building and Testing

Build the project:
```bash
make build
```

Run tests:
```bash
make test
```

Format code:
```bash
make fmt
```

Run linter:
```bash
make lint
```

Clean build artifacts:
```bash
make clean
```

View all available commands:
```bash
make help
```


## Formats

### Text format: .webnn

The text format is block-based and declarative:

- inputs {} declares typed inputs
- consts {} declares typed constants (usually weights)
- nodes {} lists operator calls in order
- outputs {} declares the named graph outputs

Types are written as dtype[dim0, dim1, ...] where dtype is one of:
f32, f16, i32, u32, i64, u64, i8, u8.

### JSON format

The JSON format is canonical (stable for tooling, easy to diff). The text format is sugar over JSON.

## Small example

### Text (examples/resnet_head.webnn)


```
webnn_graph "resnet_head" v1 {
  inputs {
    x: f32[1, 2048];
  }

  consts {
    W: f32[2048, 1000] @weights("W");
    b: f32[1000]       @weights("b");
  }

  nodes {
    logits0 = matmul(x, W);
    logits  = add(logits0, b);
    probs   = softmax(logits, axis=1);
  }

  outputs { probs; }
}
```

### JSON (examples/resnet_head.json)


```jspn
{
  "format": "webnn-graph-json",
  "version": 1,
  "inputs": {
    "x": { "dataType": "float32", "shape": [1, 2048] }
  },
  "consts": {
    "W": {
      "dataType": "float32",
      "shape": [2048, 1000],
      "init": { "kind": "weights", "ref": "W" }
    },
    "b": {
      "dataType": "float32",
      "shape": [1000],
      "init": { "kind": "weights", "ref": "b" }
    }
  },
  "nodes": [
    { "id": "logits0", "op": "matmul", "inputs": ["x", "W"], "options": {} },
    { "id": "logits",  "op": "add",    "inputs": ["logits0", "b"], "options": {} },
    { "id": "probs",   "op": "softmax", "inputs": ["logits"], "options": { "axis": 1 } }
  ],
  "outputs": { "probs": "probs" }
}
```

## Weights manifest (optional)

If you use @weights("key") in .webnn, you can validate the mapping using a manifest such as examples/weights.manifest.json:

```json
{
  "format": "wg-weights-manifest",
  "version": 1,
  "endianness": "little",
  "tensors": {
    "W": {
      "dataType": "float32",
      "shape": [2048, 1000],
      "byteOffset": 0,
      "byteLength": 8192000,
      "layout": "row-major"
    },
    "b": {
      "dataType": "float32",
      "shape": [1000],
      "byteOffset": 8192000,
      "byteLength": 4000,
      "layout": "row-major"
    }
  }
}

```

## CLI

Parse graph text (.webnn) to JSON:

```bash
make parse
# Or directly:
webnn-graph parse examples/resnet_head.webnn > graph.json
```

Validate JSON:

```bash
webnn-graph validate graph.json
```

Validate JSON plus weights manifest consistency:

```bash
make validate
# Or directly:
webnn-graph validate graph.json --weights-manifest examples/weights.manifest.json
```

Emit WebNN JS builder code:

```bash
make emit-js
# Or directly:
webnn-graph emit-js graph.json > buildGraph.js
```

## Output JS expectations

The generated JS expects a weights helper with:

- weights.buffer (an ArrayBuffer containing concatenated tensor bytes)
- weights.getSlice(key) returning { byteOffset, byteLength }

## Notes

- The parser and validator are intentionally lightweight and geared toward fast iteration.
- Operator semantics are not deeply validated yet (beyond basic structural checks).
- Extending support is straightforward: add option checks in validation or keep it pass-through and let WebNN runtime validation handle it.

## License

APLv2