Skip to content
Merged
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
13 changes: 13 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,16 @@ jobs:
run: |
PYTHONPATH=src python -m src.cli list
test "$(PYTHONPATH=src python -m src.cli list | jq 'length')" -ge 3

export-fixture:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: "3.11" }
- run: |
python -m pip install --upgrade pip
pip install torch==2.12.1 transformers==5.14.1
pip install -e ".[dev,train,export]"
- name: IMF export + parity gate fixture tests (torch vs ORT)
run: PYTHONPATH=src python -m pytest tests/test_imf_export.py tests/test_imf_parity.py -v
20 changes: 19 additions & 1 deletion docs/imf-v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ model.zip
| `tokenizer` | enum | `bytes` (the only v1 value) |
| `opset` | int | 7..14; must equal the graphs' opset |
| `decoder` | enum | `plain` \| `kv` (`kv` requires decoder-kv.onnx) |
| `precision` | enum | `fp32` \| `fp16` \| `int8` |
| `precision` | enum | `fp32` \| `fp16` \| `int8` (fp16 = torch-native half export: float16 graph IO, int64 ids unchanged; runtimes read dtypes from the session — the ORT float16 converter produces all-zero hiddens on real ByT5 and must not be used) |
| `license` | str | non-empty (strict gate) |
| `trained_from` | str | repo + run/checkpoint id |
| `metrics` | list | `{name, value, protocol, source}`; `source` must be a `RESULTS.md#anchor` (strict gate) |
Expand Down Expand Up @@ -111,8 +111,26 @@ PYTHONPATH=src python -m imf validate <zip> --strict # release gate
PYTHONPATH=src python -m imf info <zip> # print manifest
PYTHONPATH=src python -m imf pack --source <dir-or-legacy-zip> \
--metadata <yaml> [--readme <file>] --out <zip> # sha256 computed
PYTHONPATH=src python -m imf parity <zip> --checkpoint <hf-dir> \
--test-data <jsonl> # WO03 gate; writes parity into the zip
PYTHONPATH=src python -m imf golden <zip> --inputs <jsonl> --out <jsonl> \
# cross-runtime golden set: 100 fixed strings, Python = reference
```

The parity gate compares ONNX KV greedy decode against the transformers
decoder loop (the exact math the export wraps — not `generate`, whose
config-dependent behavior no runtime implements) over >= 500 test pairs;
it writes `{samples, cer_delta}` into metadata and refuses to leave the
zip non-strict. On Modal the same gate runs headless:

```
modal run --detach src/gpu/modal_export.py::main --model urd-g2p
modal run --detach src/gpu/modal_export.py::parity --model urd-g2p
```

CI runs the full gate on the fixture model (export -> parity ->
strict-validate) in the `export-fixture` job.

Legacy notes:

- Old secryst zips (`vocabs.yaml` + single `transformer.onnx`) and the
Expand Down
100 changes: 100 additions & 0 deletions golden/khm-latn-100.jsonl
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
{"input": "បង្វេច", "tokens": [101, 100, 113, 106, 121, 104, 102, 107], "output": "bangvech"}
{"input": "រោក", "tokens": [117, 114, 110], "output": "rok"}
{"input": "សង់ផ្ទះ", "tokens": [118, 100, 113, 106, 115, 107, 119, 104, 100, 107], "output": "sangphteah"}
{"input": "អប្បបរិមាណ", "tokens": [100, 101, 101, 100, 101, 117, 108, 112, 100, 113], "output": "abbabriman"}
{"input": "ឈឺចាប់", "tokens": [102, 107, 107, 120, 102, 107, 104, 100, 101], "output": "chhucheab"}
{"input": "អសមត្ថភាព", "tokens": [100, 118, 100, 112, 114, 119, 119, 107, 100, 115, 107, 100, 115], "output": "asamotthaphap"}
{"input": "និយាយ", "tokens": [113, 108, 124, 104, 100, 124], "output": "niyeay"}
{"input": "សម្ងំ", "tokens": [118, 100, 112, 113, 106, 114, 112], "output": "samngom"}
{"input": "អូម", "tokens": [100, 120, 112], "output": "aum"}
{"input": "ស្វាយរៀង", "tokens": [118, 121, 100, 124, 117, 108, 104, 113, 106], "output": "svayrieng"}
{"input": "បារមី", "tokens": [101, 100, 117, 112, 108], "output": "barmi"}
{"input": "រនល", "tokens": [117, 114, 113, 111], "output": "ronl"}
{"input": "ធម្មយុត្តិ", "tokens": [119, 107, 114, 112, 112, 114, 124, 114, 120, 119, 119, 104], "output": "thommoyoutte"}
{"input": "ទឹកឃ្មុំ", "tokens": [119, 120, 110, 100, 110, 107, 112, 114, 120, 112], "output": "tukakhmoum"}
{"input": "ភ្លើង", "tokens": [115, 107, 111, 104, 120, 113, 106], "output": "phleung"}
{"input": "ប្រួត", "tokens": [101, 117, 120, 114, 119], "output": "bruot"}
{"input": "វោហារ", "tokens": [121, 114, 107, 104, 100, 117], "output": "vohear"}
{"input": "ច្បាប់", "tokens": [102, 107, 101, 100, 101], "output": "chbab"}
{"input": "ទន្ទឹម", "tokens": [119, 114, 113, 119, 120, 112], "output": "tontum"}
{"input": "បញ្ចស័ក", "tokens": [101, 100, 113, 107, 102, 107, 114, 118, 100, 110], "output": "banhchosak"}
{"input": "ល្បី", "tokens": [111, 101, 108], "output": "lbi"}
{"input": "គុណូបការ", "tokens": [110, 114, 120, 113, 100, 120, 101, 110, 100, 117], "output": "kounaubkar"}
{"input": "បញ្ចុក", "tokens": [101, 100, 113, 107, 102, 107, 114, 120, 110], "output": "banhchouk"}
{"input": "ជ្រាបស្រាប់", "tokens": [102, 107, 117, 104, 100, 101, 100, 118, 117, 100, 101], "output": "chreabasrab"}
{"input": "សៃយ៉ឺន", "tokens": [118, 100, 108, 124, 104, 120, 113], "output": "saiyeun"}
{"input": "លោះខ្ញុំ", "tokens": [111, 114, 107, 110, 107, 113, 107, 114, 112], "output": "lohkhnhom"}
{"input": "ទូទឹម", "tokens": [119, 114, 120, 119, 120, 112], "output": "toutum"}
{"input": "ប្រវត្តិសាស្ត្រ", "tokens": [101, 117, 100, 121, 114, 119, 119, 104, 35, 118, 100, 118, 119, 117], "output": "bravotte sastr"}
{"input": "ខ្លោងទ្វារ", "tokens": [110, 107, 111, 100, 114, 113, 106, 114, 119, 121, 104, 100, 117], "output": "khlaongotvear"}
{"input": "គេជាច្រើន", "tokens": [110, 104, 102, 107, 100, 102, 107, 117, 100, 104, 113], "output": "kechachraen"}
{"input": "បង្កួយ", "tokens": [101, 100, 113, 106, 110, 104, 100, 119], "output": "bangkeat"}
{"input": "ហៃអើ", "tokens": [107, 100, 108, 100, 104], "output": "haiae"}
{"input": "ឆ្កឹះឆ្កៀល", "tokens": [102, 107, 107, 110, 114, 104, 100, 107, 102, 107, 107, 110, 108, 104, 111], "output": "chhkoeahchhkiel"}
{"input": "ទំលាក់", "tokens": [119, 114, 112, 35, 111, 104, 100, 110], "output": "tom leak"}
{"input": "ហ្រ្វង់", "tokens": [107, 117, 121, 114, 113, 106], "output": "hrvong"}
{"input": "រាស់", "tokens": [117, 104, 100, 118, 100], "output": "reasa"}
{"input": "លោភលន់", "tokens": [111, 114, 115, 107, 114, 111, 113], "output": "lopholn"}
{"input": "អរគុណណាស់", "tokens": [100, 117, 110, 114, 120, 113, 113, 100, 118, 100], "output": "arkounnasa"}
{"input": "ដោយហេតុ", "tokens": [103, 100, 114, 124, 107, 104, 119, 114], "output": "daoyheto"}
{"input": "អ្នកចំរៀង", "tokens": [100, 113, 100, 110, 102, 107, 100, 112, 117, 108, 104, 113, 106], "output": "anakchamrieng"}
{"input": "ពោធិសម្ភារ", "tokens": [115, 114, 119, 107, 108, 118, 100, 112, 115, 107, 104, 100, 117], "output": "pothisamphear"}
{"input": "ចូលហ៊ុន", "tokens": [102, 107, 100, 120, 111, 107, 114, 120, 113], "output": "chaulhoun"}
{"input": "បបរ", "tokens": [101, 100, 101, 117], "output": "babr"}
{"input": "រូបលោក", "tokens": [117, 114, 120, 101, 111, 114, 110], "output": "roublok"}
{"input": "ហ៊ុមព័ទ្ធ", "tokens": [107, 114, 120, 112, 115, 119, 119, 107], "output": "houmptth"}
{"input": "ការហាត់ប្រាណ", "tokens": [110, 100, 117, 35, 107, 100, 119, 101, 117, 100, 113], "output": "kar hatbran"}
{"input": "មិនបានជា", "tokens": [112, 108, 113, 101, 100, 113, 102, 107, 104, 100], "output": "minbanchea"}
{"input": "កម្មវិបាក", "tokens": [110, 100, 112, 112, 114, 121, 108, 101, 104, 100, 110], "output": "kammovibeak"}
{"input": "កុំអាល", "tokens": [110, 114, 112, 100, 111], "output": "komal"}
{"input": "សុខយាន", "tokens": [118, 114, 110, 107, 124, 104, 100, 113], "output": "sokhyean"}
{"input": "ទឹកស្លាប់", "tokens": [119, 120, 110, 100, 118, 111, 100, 101], "output": "tukaslab"}
{"input": "អធិការបតី", "tokens": [100, 119, 107, 108, 110, 104, 100, 117, 114, 101, 119, 104, 108], "output": "athikearobtei"}
{"input": "ខ្តត", "tokens": [110, 107, 119, 100, 119], "output": "khtat"}
{"input": "ស្ទេញ", "tokens": [118, 119, 104, 113, 107], "output": "stenh"}
{"input": "ដល់ហើយ", "tokens": [103, 111, 107, 100, 104, 124], "output": "dlhaey"}
{"input": "ក្ដៀប", "tokens": [110, 103, 108, 104, 101], "output": "kdieb"}
{"input": "ភ្លៀងមួយមេ", "tokens": [115, 107, 111, 108, 104, 113, 106, 112, 120, 114, 124, 112, 104], "output": "phliengmuoyme"}
{"input": "សៃយ", "tokens": [118, 100, 108, 124], "output": "saiy"}
{"input": "រាជបល្ល័ង្ក", "tokens": [117, 104, 100, 102, 107, 114, 101, 100, 111, 111, 113, 106, 110], "output": "reachoballngk"}
{"input": "ល្អក់", "tokens": [111, 100, 114, 110], "output": "laok"}
{"input": "ឈ្ងុយឆ្ងាញ់", "tokens": [102, 107, 107, 113, 106, 114, 120, 124, 114, 102, 107, 107, 113, 106, 100, 113, 107], "output": "chhngouyochhnganh"}
{"input": "រ៉ឹង", "tokens": [117, 114, 104, 113, 106], "output": "roeng"}
{"input": "ប្រុងនឹង", "tokens": [101, 117, 114, 113, 106, 113, 120, 113, 106], "output": "brongnung"}
{"input": "ការប្រើប្រាស់", "tokens": [110, 100, 117, 114, 101, 117, 100, 104, 101, 117, 100, 118, 100], "output": "karobraebrasa"}
{"input": "គ្រោះ", "tokens": [110, 117, 114, 107], "output": "kroh"}
{"input": "កលកិច្ច", "tokens": [110, 100, 111, 110, 104, 102, 107, 102, 107], "output": "kalkechch"}
{"input": "ផ្សារផ្សោ", "tokens": [115, 107, 118, 100, 100, 117, 114, 115, 107, 118, 100, 100, 114], "output": "phsaarophsaao"}
{"input": "ស្រករ", "tokens": [118, 117, 100, 110, 117], "output": "srakr"}
{"input": "រត់លឿន", "tokens": [117, 119, 111, 120, 104, 113], "output": "rtluen"}
{"input": "និត្យ", "tokens": [113, 108, 119, 124], "output": "nity"}
{"input": "គ្រប់រូប", "tokens": [110, 117, 114, 101, 117, 114, 120, 101], "output": "krobroub"}
{"input": "ឲ្យទឹក", "tokens": [100, 114, 124, 119, 120, 110], "output": "aoytuk"}
{"input": "ចាប់ត្រី", "tokens": [102, 107, 100, 101, 119, 117, 104, 108], "output": "chabtrei"}
{"input": "ពេជ្រ", "tokens": [115, 104, 102, 107, 117], "output": "pechr"}
{"input": "អគ្គស្នងការ", "tokens": [100, 110, 110, 114, 118, 113, 100, 113, 106, 110, 100, 117], "output": "akkosnangkar"}
{"input": "ដួល", "tokens": [103, 120, 114, 111], "output": "duol"}
{"input": "នៅនឹង", "tokens": [113, 114, 122, 113, 120, 113, 106], "output": "nownung"}
{"input": "ផលកម្ម", "tokens": [115, 107, 100, 111, 114, 110, 100, 112, 112], "output": "phalokamm"}
{"input": "ញាំញី", "tokens": [113, 107, 104, 100, 113, 107, 108], "output": "nheanhi"}
{"input": "ភាតរ", "tokens": [115, 107, 104, 100, 119, 117], "output": "pheatr"}
{"input": "មួយនេះ", "tokens": [112, 120, 114, 124, 113, 108, 107], "output": "muoynih"}
{"input": "ផ្លូវសួន", "tokens": [115, 107, 111, 100, 120, 121, 118, 120, 114, 113], "output": "phlauvsuon"}
{"input": "ឆ្នាំច", "tokens": [102, 107, 107, 113, 100, 102, 107], "output": "chhnach"}
{"input": "ត្នោត", "tokens": [119, 113, 100, 114, 119], "output": "tnaot"}
{"input": "វាង", "tokens": [121, 104, 100, 113, 106], "output": "veang"}
{"input": "រាជបុត្រ", "tokens": [117, 104, 100, 102, 107, 101, 114, 119, 117], "output": "reachbotr"}
{"input": "ស្រមូម", "tokens": [118, 117, 100, 112, 114, 120, 112], "output": "sramoum"}
{"input": "ចិត្តស៊ូ", "tokens": [102, 107, 104, 119, 119, 100, 118, 100, 114, 120], "output": "chettasaou"}
{"input": "អក្សរខម", "tokens": [100, 110, 118, 100, 100, 117, 114, 110, 107, 112], "output": "aksaarokhm"}
{"input": "ទូទឹកកក", "tokens": [119, 114, 120, 119, 120, 110, 100, 110, 110], "output": "toutukakk"}
{"input": "កាត់ឲ្យខ្លី", "tokens": [110, 100, 119, 35, 100, 114, 124, 35, 110, 107, 111, 104, 108], "output": "kat aoy khlei"}
{"input": "យ៉ាងណាក៏ដោយ", "tokens": [124, 104, 100, 113, 106, 113, 100, 35, 110, 100, 103, 100, 114, 124], "output": "yeangna kadaoy"}
{"input": "បំផុត", "tokens": [101, 100, 112, 115, 107, 114, 119], "output": "bamphot"}
{"input": "រកអ្វីប្រៀបពុំបាន", "tokens": [117, 114, 110, 100, 100, 121, 104, 108, 35, 101, 117, 108, 104, 101, 35, 101, 100, 113], "output": "rokaavei brieb ban"}
{"input": "មកយឺត", "tokens": [112, 114, 110, 124, 120, 119], "output": "mokyut"}
{"input": "អប្សរា", "tokens": [100, 101, 118, 100, 100, 117, 100], "output": "absaara"}
{"input": "បិតុច្ឆា", "tokens": [101, 104, 119, 114, 102, 107, 102, 107, 107, 100], "output": "betochchha"}
{"input": "អស់អញ", "tokens": [100, 118, 100, 100, 113, 107], "output": "asaanh"}
{"input": "ចាង", "tokens": [102, 107, 100, 113, 106], "output": "chang"}
{"input": "មិនអស់ចិត្ត", "tokens": [112, 108, 113, 114, 100, 118, 100, 102, 107, 104, 119, 119], "output": "minoasachett"}
42 changes: 42 additions & 0 deletions models/heb-diac/heb-diac-1.0.README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# heb-diac-1.0

Hebrew diacritization (adds nikud). Byte-level seq2seq (ByT5-base):
the tokenizer is raw UTF-8 bytes (pad=0, EOS=1) — no vocab files.
IMF v1 artifact; format spec: interscript/ml-models docs/imf-v1.md.

- decoder: kv greedy (plain fallback included in the zip)
- metrics: greedy DER 29.0% (the v1 runtime path); beam=4 DER 17.46%
(reference quality — beam search is not in v1 runtimes) —
rababa/docs/RESULTS.md#hebrew-diacritization
- trained from: rababa train_hebrew_seeds.py s43 run-001
(rababa-checkpoints:/rababa_hebrew_byt5_s43/run-001/best)
- license: BSD-3-Clause

## Usage

Ruby (secryst gem, the Ruby binding of interscript-ml):

```ruby
require "secryst"
translator = Secryst::Translator.new(model: "heb-diac-1.0")
translator.translate("שלום")
```

TypeScript (@interscript/ml):

```ts
import { loadModel } from "@interscript/ml";
const model = await loadModel("heb-diac-1.0");
await model.translate("שלום");
```

Python (interscript-ml):

```python
from interscript_ml import Model
model = Model.load("heb-diac-1.0")
model.translate("שלום")
```

All three runtimes verify the sha256 of every ONNX member in this zip
against metadata.yaml before loading.
26 changes: 26 additions & 0 deletions models/heb-diac/heb-diac-1.0.metadata.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
format: imf-v1
id: heb-diac-1.0
task: diacritization
source_script: Hebr
target: Hebr
tokenizer: bytes
opset: 14
decoder: kv
precision: fp32
license: BSD-3-Clause
trained_from: >-
rababa train_hebrew_seeds.py s43 run-001; checkpoint
rababa-checkpoints:/rababa_hebrew_byt5_s43/run-001/best
metrics:
- name: der_greedy
value: 29.0
protocol: >-
beam=1 greedy decode (the v1 runtime path); Nakdimon test split,
5,095 examples; ByT5-base s43
source: rababa/docs/RESULTS.md#hebrew-diacritization
- name: der_beam4
value: 17.46
protocol: >-
beam=4 standard decode (reference quality; beam search is not in
v1 runtimes); Nakdimon test split, 5,095 examples; ByT5-base s43
source: rababa/docs/RESULTS.md#hebrew-diacritization
2 changes: 1 addition & 1 deletion models/khm-latn/khm-latn-1.0.README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ the tokenizer is raw UTF-8 bytes (pad=0, EOS=1) — no vocab files.
IMF v1 artifact; format spec: interscript/ml-models docs/imf-v1.md.

- precision: fp16 (mixed: LayerNorm parameters in fp32)
- decoder: plain greedy (KV-cache variant ships with the WO02 export)
- decoder: kv greedy (plain fallback included in the zip)
- metrics: CER 27.42 / EM 59.66 on 895 held-out pairs —
secryst/docs/RESULTS.md#khmer-transliteration-2026-08-14
- trained from: secryst train_khmer_byt5.py run-001
Expand Down
26 changes: 26 additions & 0 deletions models/khm-latn/khm-latn-1.0.metadata.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
format: imf-v1
id: khm-latn-1.0
task: translit
source_script: Khmr
target: Latn
tokenizer: bytes
opset: 14
decoder: kv
precision: fp32
license: BSD-3-Clause
trained_from: >-
secryst train_khmer_byt5.py run-001; checkpoint
secryst-checkpoints:/khmer_byt5/run-001/best
metrics:
- name: cer
value: 27.42
protocol: >-
greedy decode; 895 held-out pairs; split 16,120/895/895 seed 42;
ByT5-small early stop @ep15
source: secryst/docs/RESULTS.md#khmer-transliteration-2026-08-14
- name: em
value: 59.66
protocol: >-
greedy decode; 895 held-out pairs; split 16,120/895/895 seed 42;
ByT5-small early stop @ep15
source: secryst/docs/RESULTS.md#khmer-transliteration-2026-08-14
41 changes: 41 additions & 0 deletions models/urd-diac/urd-diac-1.0.README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# urd-diac-1.0

Urdu diacritization (adds haraqat). Byte-level seq2seq (ByT5-small):
the tokenizer is raw UTF-8 bytes (pad=0, EOS=1) — no vocab files.
IMF v1 artifact; format spec: interscript/ml-models docs/imf-v1.md.

- decoder: kv greedy (plain fallback included in the zip)
- metrics: CER 3.74 on 11,940 held-out —
rababa-urdu/docs/RESULTS.md#diacritization-urdu-text--text--haraqat
- trained from: rababa-urdu modal_app_diacrit.py run-001
(urdu-diacrit-checkpoints:/urdu_diacrit/run-001/best)
- license: BSD-3-Clause

## Usage

Ruby (secryst gem, the Ruby binding of interscript-ml):

```ruby
require "secryst"
translator = Secryst::Translator.new(model: "urd-diac-1.0")
translator.translate("اردو")
```

TypeScript (@interscript/ml):

```ts
import { loadModel } from "@interscript/ml";
const model = await loadModel("urd-diac-1.0");
await model.translate("اردو");
```

Python (interscript-ml):

```python
from interscript_ml import Model
model = Model.load("urd-diac-1.0")
model.translate("اردو")
```

All three runtimes verify the sha256 of every ONNX member in this zip
against metadata.yaml before loading.
20 changes: 20 additions & 0 deletions models/urd-diac/urd-diac-1.0.metadata.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
format: imf-v1
id: urd-diac-1.0
task: diacritization
source_script: Arab
target: Arab
tokenizer: bytes
opset: 14
decoder: kv
precision: fp32
license: BSD-3-Clause
trained_from: >-
rababa-urdu modal_app_diacrit.py run-001; checkpoint
urdu-diacrit-checkpoints:/urdu_diacrit/run-001/best
metrics:
- name: cer
value: 3.74
protocol: >-
greedy decode; 11,940 held-out; labels derived IPA->haraqat
(deterministic conversion, 597K pairs); ByT5-small, 2 epochs
source: rababa-urdu/docs/RESULTS.md#diacritization-urdu-text--text--haraqat
41 changes: 41 additions & 0 deletions models/urd-g2p/urd-g2p-1.0.README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# urd-g2p-1.0

Urdu → IPA grapheme-to-phoneme conversion. Byte-level seq2seq
(ByT5-small): the tokenizer is raw UTF-8 bytes (pad=0, EOS=1) — no vocab
files. IMF v1 artifact; format spec: interscript/ml-models docs/imf-v1.md.

- decoder: kv greedy (plain fallback included in the zip)
- metrics: CER 14.77 / EM 33.6 on 12,699 held-out words —
rababa-urdu/docs/RESULTS.md#g2p-urdu-text--ipa
- trained from: rababa-urdu modal_app.py run-001
(urdu-g2p-checkpoints:/urdu_g2p/run-001/best)
- license: BSD-3-Clause

## Usage

Ruby (secryst gem, the Ruby binding of interscript-ml):

```ruby
require "secryst"
translator = Secryst::Translator.new(model: "urd-g2p-1.0")
translator.translate("اردو")
```

TypeScript (@interscript/ml):

```ts
import { loadModel } from "@interscript/ml";
const model = await loadModel("urd-g2p-1.0");
await model.translate("اردو");
```

Python (interscript-ml):

```python
from interscript_ml import Model
model = Model.load("urd-g2p-1.0")
model.translate("اردو")
```

All three runtimes verify the sha256 of every ONNX member in this zip
against metadata.yaml before loading.
Loading
Loading