Skip to content

typesafe: native ONNX runtime path is TODO, no macOS prebuilt, and README onnx entry points fail on WASM #1019

Description

@stuinfla

Thanks for shipping @ruvector/typesafe — local, calibrated typed decisions are exactly what we needed for classifying a whole repository file-by-file. Using it today surfaced four gaps that, fixed, would make it dramatically more useful for bulk work like this.

What we hit (macOS arm64, @ruvector/typesafe@0.1.0, Node 24.18)

  1. Native ONNX is still a TODO. crates/ruvector-typesafe-ffi/Cargo.toml notes the native-onnx feature's runtime path is unimplemented (the core Engine needs a Box<dyn Embedder> instead of the monomorphized HashEmbedder). So the native addon is hash-only, and real models (bge-small / MiniLM) only run through the WASM tract path.
  2. No macOS prebuilt. The npm package ships native/typesafe.linux-x64-gnu.node only, so every Mac falls back to WASM.
  3. The documented ONNX entry points fail on WASM. Both of these, as written in the README:
    • createTypesafe({ embedder: { kind: 'onnx', modelDir, manifest } }) → throws the string onnx embedder requires Engine.fromBytes(optionsJson, modelBytes, tokenizerBytes)
    • typesafe decide --embedder onnx --model-dir … --manifest … → prints only error: unknown failure (the thrown value is a string, not an Error, so cli/main.js falls through to the generic branch)
  4. Working workaround (for anyone else hitting this):
    const W = require('@ruvector/typesafe/wasm/ruvector_typesafe_wasm.js');
    const m = manifest.models.find((x) => x.name === 'bge-small-en-v1.5');
    const eng = W.Engine.fromBytes(
      JSON.stringify({ embedder: { kind: 'onnx', manifest: JSON.stringify(m), model: m.name }, manifest: JSON.stringify(m) }),
      fs.readFileSync(`${dir}/${m.file}`), fs.readFileSync(`${dir}/${m.tokenizer_file}`));
    eng.decideJson(JSON.stringify({ state, questions }));
    Note manifest must be a single model entry (not the { models: [...] } file), at the top level of the options. With this it classified our probe set correctly (6/6, both bge-small and MiniLM), at ~1.5–2 s per decision on an M3 Max under load.

Why it matters

Bulk classification (e.g. ~1,800 files, several questions, 2–3 embedders for agreement voting) is where typesafe beats an LLM by orders of magnitude — but only at the native p95 ≤ 50 ms target from ADR-006. At WASM speed on Mac it is still usable in parallel workers, but native ONNX would make it ~30–100× faster.

Suggested fixes

  • Implement the native-onnx runtime path (Box<dyn Embedder> + OrtEmbedder).
  • Publish a darwin-arm64 (and x64) prebuilt.
  • Make createTypesafe / the CLI build the WASM ONNX engine from modelDir + manifest via Engine.fromBytes automatically, and accept the manifest file shape.
  • Throw Error objects (or wrap strings) so the CLI prints the real message.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions