hs-predict-wasm
WebAssembly bindings for hs-predict — HS code prediction for chemical products.
Exposes the full hs-predict classification engine to JavaScript / TypeScript via wasm-pack.
Build
# Generates ./pkg/ (~320 KB)
For Node.js:
APIs
1. classify_smiles(smiles: string): object | null
Analyse a SMILES string and return functional-group detection and an HS heading hint.
import init from './pkg/hs_predict_wasm.js';
await ;
const r = ; // acetone
// {
// organic_class: "organic",
// functional_groups: ["Ketone"],
// structural_features: {
// carbon_count: 3, hydroxyl_count: 0, carbonyl_count: 1,
// has_ring: false, has_aromatic_ring: false,
// has_cc_double_bond: false, cc_double_bond_count: 0,
// is_pure_hydrocarbon: false, ...
// },
// heading_hint: {
// chapter: 29, heading: 2914,
// subheading: "291411", // 6-digit when determinable
// confidence: 0.87,
// rationale: "acetone"
// }
// }
const r2 = ; // isoprene
// heading_hint: { chapter: 29, heading: 2901, subheading: "290124", confidence: 0.87 }
const r3 = ; // dichloromethane
// heading_hint: { chapter: 29, heading: 2903, subheading: "290312", confidence: 0.90 }
; // null
Returns null for empty or whitespace-only input (max 4096 bytes).
2. classify_product(product_json: string): object
Run the full rule-based pipeline (mixture GRI → static rules → SMILES engine) on a serialised ProductDescription.
import init from './pkg/hs_predict_wasm.js';
await ;
const pred = ;
// {
// hs_code: "281511",
// confidence: 1.0,
// heading_description: "Sodium hydroxide, solid",
// recommended_action: "Accept",
// gray_zone: null,
// jp_tariff_code: "281511000",
// alternatives: []
// }
Throws a string error on invalid JSON input or classification failure.
ProductDescription schema
interface ProductDescription {
identifier: {
cas?: string; // e.g. "67-64-1"
smiles?: string; // e.g. "CC(C)=O"
iupac_name?: string; // e.g. "propan-2-one"
inchi?: string;
inchi_key?: string;
cid?: number; // PubChem CID
};
physical_form?: "Solid" | "Powder" | "Granules" | "Liquid" |
"Solution" | "Gas" | "Foil" | "Ingot" | "Unknown";
purity_pct?: number;
purity_type?: "WeightPercent" | "VolumePercent" | "MolePercent";
mixture_components?: MixtureComponent[];
intended_use?: "Industrial" | "Pharmaceutical" | "Agricultural" |
"Food" | "Cosmetic" | "Other";
additional_context?: string;
}
interface MixtureComponent {
substance: ProductDescription["identifier"];
weight_fraction_pct?: number;
volume_fraction_pct?: number;
is_solvent: boolean;
}
3. WasmSession — Akinator-style interactive session
Step-by-step session that asks only what is needed to classify the product.
import init from './pkg/hs_predict_wasm.js';
await ;
// English session (default)
const session = ;
// Japanese session
// const session = WasmSession.new_ja();
// Step 1: start
const q1 = session.;
// { step: "Identifier", prompt: "Please enter a CAS number...", type: "text", choices: null }
// Step 2: answer questions in a loop
let result = session.;
// { type: "NeedMoreInfo", next_question: { step: "IsMixture", prompt: "Is this a mixture?", type: "yes_no" } }
result = session.;
// { type: "NeedMoreInfo", next_question: { step: "PhysicalForm", ... } }
result = session.; // "Solid"
// { type: "Ready" }
// Step 3: classify when Ready
const prediction = session.;
// { hs_code: "281511", confidence: 1.0, jp_tariff_code: "281511000", ... }
Answer variants
| Answer JSON | Use when |
|---|---|
{ "Text": "67-64-1" } |
Free-text question (identifier, context) |
{ "YesNo": true } |
Yes/No question |
{ "Choice": 2 } |
Single-choice question (0-indexed) |
{ "MultiChoice": [0, 2] } |
Multi-choice question |
{ "Number": 99.5 } |
Numeric question (purity, concentration) |
Session result variants
type |
Meaning |
|---|---|
"NeedMoreInfo" |
More questions remain; next_question is set |
"Ready" |
All information collected; call session.classify() |
"RequiresLlm" |
Rule engine insufficient; LLM fallback needed (not available in WASM) |
Classification pipeline (Priorities 0–3)
| Priority | Method | Confidence |
|---|---|---|
| 0 | Mixture GRI 3a/3b/3c + special-use routing | varies |
| 1 | User-provided mapping | 1.0 |
| 2 | Static rule table (161 CAS entries) | 0.95–1.0 |
| 3 | SMILES structural engine | 0.60–0.90 |
Note: LLM fallback (Priority 4) requires a network-capable client and is not included in the WASM bundle.
Feature notes
- No async required — the WASM bundle uses only the rule-based engine (Priorities 0–3); no HTTP requests are made.
- No WASI — targets
wasm32-unknown-unknown; runs in browsers and Node.js. - Bundle size — approximately 320 KB (release build,
opt-level = "z", LTO).
Compatibility
| Tool | Version |
|---|---|
| wasm-pack | 0.13+ |
| wasm-bindgen | 0.2.121 (pinned) |
| Rust | 1.75+ |
Related
- hs-predict — the core Rust library (async, LLM, PubChem)
- Repository
License
Licensed under either of MIT License or Apache License 2.0 at your option.