Coming from transformers.js

Kiln implements transformers.js's pipelines and its lower-level API under the same names, with the same option names and output shapes. Most code moves over by changing the import and the model id. This page lists everything that differs.

The three steps

  1. Change the import.
    - import { pipeline, AutoTokenizer } from "@huggingface/transformers";
    + import { pipeline, AutoTokenizer } from "kiln-webgpu";
  2. Point at the original repo. Kiln reads a model's own weights (safetensors, pytorch_model.bin or GGUF), not ONNX exports. Most Xenova/… and onnx-community/… repos are conversions of a repo you can name directly:
    transformers.jsKiln
    Xenova/all-MiniLM-L6-v2sentence-transformers/all-MiniLM-L6-v2
    Xenova/distilbert-base-uncased-finetuned-sst-2-englishdistilbert/distilbert-base-uncased-finetuned-sst-2-english
    Xenova/bert-base-NERdslim/bert-base-NER
    Xenova/whisper-tiny.enopenai/whisper-tiny.en
    Xenova/vit-base-patch16-224google/vit-base-patch16-224
    Xenova/clip-vit-base-patch32openai/clip-vit-base-patch32
    onnx-community/Qwen2.5-0.5B-InstructQwen/Qwen2.5-0.5B-Instruct
    HuggingFaceTB/SmolLM2-135M-Instruct (its onnx/ folder)the same repo (its safetensors)
    a GGUF build (not supported)org/repo/model-Q4_K_M.gguf
    The ONNX repo's model card usually names the original under "Base model".
  3. Check the differences below that apply to the APIs you use.

Load options

Pipelines

Task names, aliases (sentiment-analysis, ner, embeddings, text-to-speech), call options and output shapes follow transformers.js. Differences:

Tokenizers, models and processors

transformers.jsIn Kiln
AutoTokenizerYes: call, encode, decode, batch_decode, tokenize, padding, truncation, apply_chat_template. Ids equal transformers.js's on the 31 repos compared.
AutoModelBERT, DistilBERT, RoBERTa (last_hidden_state); ViT, DeiT, DINOv2, ResNet, ConvNeXt; CLIP.
AutoModelFor…SequenceClassification, TokenClassification, QuestionAnswering, MaskedLM, ImageClassification, CausalLM.
CLIPModel, CLIPTextModelWithProjection, CLIPVisionModelWithProjectionYes.
model.generate()For causal LMs: ids in, ids out, sampling options, streamers, generation_config defaults. Calling a causal LM directly for logits is not supported; llm.scoreChoices() scores continuations instead.
AutoProcessor, AutoImageProcessor, AutoFeatureExtractorImages (pixel_values), Whisper (input_features), wav2vec2 (input_values).
RawImage, read_audio, Tensor, cos_simYes. read_audio decodes as transformers.js does. Tensor carries data, dims and tolist(), without transformers.js's tensor math.
Other model classes and architecturesNot yet: use the pipeline for the task, or open an issue for the model.

Models run in Kiln's worker and come back as tensors with transformers.js's names and shapes. Each row of a padded batch runs without its padding, so padded positions hold zeros.

Before and after

Embeddings

import { pipeline } from "kiln-webgpu";              // was "@huggingface/transformers"
const extractor = await pipeline("feature-extraction", "sentence-transformers/all-MiniLM-L6-v2"); // was Xenova/all-MiniLM-L6-v2
const output = await extractor(["Hello world", "Hi"], { pooling: "mean", normalize: true });
output.tolist();

Chat with streaming

import { pipeline, TextStreamer } from "kiln-webgpu";
const generator = await pipeline("text-generation", "Qwen/Qwen2.5-0.5B-Instruct", { dtype: "q4" });
const streamer = new TextStreamer(generator.tokenizer, { skip_prompt: true, callback_function: (t) => out.append(t) });
await generator(messages, { max_new_tokens: 256, streamer });

Tokenizer and model

import { AutoTokenizer, AutoModelForSequenceClassification } from "kiln-webgpu";
const id = "distilbert/distilbert-base-uncased-finetuned-sst-2-english";
const tokenizer = await AutoTokenizer.from_pretrained(id);
const model = await AutoModelForSequenceClassification.from_pretrained(id);
const { logits } = await model(tokenizer(["I love it", "I hate it"], { padding: true }));

What you get on top

What is missing