edgewise v0.4.1

verb · → text

generate

One function for every model that writes text: tiny language models, vision-language models, tool callers, speech recognizers and Florence-2.

Text in, text out#

ts
import { generate } from 'edgewise';

const { text, usage, finishReason, info } = await generate({
  model: 'lfm2.5-350m',
  system: 'You are terse.',
  input: 'Three uses for a small language model inside a web page?',
  maxTokens: 200,
});

temperature defaults to 0, which decodes greedily and gives repeatable output. Set it above 0, with topP, to sample.

Any input the model accepts#

The call is the same whatever the input. Only the model has to accept it.

ts
// image + question → answer
await generate({ model: 'vision:default', input: [photo, 'What is the person holding?'] });

// audio → transcript
await generate({ model: 'stt:tiny', input: wavBlob });

// image → OCR, using a Florence-2 preset
await generate({ model: 'florence-2-base', input: screenshot, preset: 'ocr' });

// short video → summary (browser; frames are sampled for you)
await generate({ model: 'vision:default', input: [{ type: 'video', video: videoEl, frames: 8 }, 'Summarize.'] });

Passing an input the model does not accept throws UnsupportedInputError before anything downloads, with a hint naming models that do accept it.

Conversations#

ts
const first = await generate({
  model: 'vision:default',
  messages: [{ role: 'user', content: [{ type: 'image', image: chartPng }, { type: 'text', text: 'What does this show?' }] }],
});
const next = await generate({ model: 'vision:default', messages: [...first.messages, { role: 'user', content: 'Which month was highest?' }] });

Use input for single turns and messages for conversations. They cannot be combined. result.messages is the conversation including the reply.

Streaming#

ts
const run = generate({ model: 'text:default', input: prompt, signal: controller.signal });
for await (const delta of run) output.textContent += delta;
const { text, usage } = await run;

Special tokens and tool-call markup are filtered out of the stream.

Structured output#

Pass a Zod schema (or any object with safeParse) and read object. With a schema, the stream yields partial objects instead of text.

ts
import { z } from 'zod';

const { object } = await generate({
  model: 'text:default',
  input: 'Lunch with Ana on 2026-10-02 at Foodhallen',
  schema: z.object({ who: z.string(), date: z.string(), place: z.string().optional() }),
});
// { who: 'Ana', date: '2026-10-02', place: 'Foodhallen' }

Edgewise sends the JSON Schema to the model, extracts the JSON from the reply, and validates it. If validation fails it retries once with the errors. If that fails too it throws SchemaValidationError with the raw text and the issues.

Tools#

ts
import { generate, tool } from 'edgewise';
import { z } from 'zod';

const { text, toolCalls } = await generate({
  model: 'lfm2.5-350m',
  input: 'Set the volume to 30.',
  tools: {
    setVolume: tool({
      description: 'Set the speaker volume from 0 to 100',
      input: z.object({ level: z.number().int() }),
      execute: async ({ level }) => player.setVolume(level),
    }),
  },
});

See Tool calling for approval, multi-step loops and model formats.

Presets#

Florence-2 is trained on fixed prompts. preset picks one and fills object.

PresetResult
'caption', 'caption-detailed', 'caption-more-detailed'text
'ocr'text, object.regions with quadrilaterals
'detect'object.boxes with labels
{ find: 'a red car' }object.boxes for the phrase

Speech models#

Audio input goes to speech recognizers the same way. timestamps: 'segment' returns segments (Whisper). language sets the spoken language for multilingual models. With a live mic() or audioSource(), generate transcribes each utterance as it ends. See Transcription.

Chrome's built-in model#

In Chrome with the Prompt API, 'chrome:gemini-nano' runs Gemini Nano with no download for your app. Pass a list to prefer it and fall back:

ts
await generate({ model: ['chrome:gemini-nano', 'text:default'], input: 'Summarize: …' });

Options#

OptionDefault
modelID, alias, manifest, or a list tried in order
input / messagesone of the two
systemsystem prompt
schemafill a Zod schema
tools, maxSteps, approvemaxSteps: 3tool calling
presetFlorence-2 tasks
timestamps, languagespeech models
maxTokens512per step
temperature, topP, stop0decoding
device, dtype, signal, onProgress, allowPreviewshared by every verb

Which model#

ModelAcceptsDownloadStatusNotes
lfm2.5-230mtext201 MBstabletext:tiny · Smallest LFM2.5 language model. Rewrites, extraction, short answers.
lfm2.5-350mtext243 MBstabletext:default · Fast general model with native tool calling.
lfm2.5-1.2btext725 MBpreviewGeneral chat and reasoning. Needs WebGPU in browsers.
qwen3-0.6btext544 MBpreviewMultilingual model with an optional reasoning mode.
gemma-3-270mtext308 MBpreviewTiny Gemma. Uses fp32 on WebGPU because fp16 overflows on that backend.
functiongemma-270mtext406 MBpreviewGemma trained for function calling. Best after fine-tuning on your own tools.
lfm2-1.2b-tooltext828 MBpreviewLFM2 tuned for tool use.
lfm2.5-vl-450mtext, image, video644 MBstablevision:default · Small vision-language model. Questions about images, screenshots and short clips.
lfm2.5-vl-1.6btext, image, video1.6 GBpreviewLarger vision-language model for better answers on GPU devices.
smolvlm-256mtext, image253 MBpreviewTiny vision-language model.
florence-2-baseimage, text725 MBstablevision:fast · Captions, OCR and object detection through presets.
moonshine-tinyaudio27 MBstablestt:tiny · Tiny English speech recognizer for live captions on any device.
moonshine-baseaudio60 MBstablestt:realtime · English speech recognizer with better accuracy than Moonshine tiny.
whisper-tiny-enaudio39 MBpreviewWhisper tiny, English only, with timestamps.
whisper-baseaudio70 MBpreviewstt:multilingual · Small multilingual transcription with timestamps.
whisper-smallaudio226 MBpreviewMultilingual transcription with timestamps, more accurate than Whisper base.
whisper-large-v3-turboaudio724 MBpreviewstt:accurate · Multilingual transcription with timestamps.
chrome:gemini-nanotextmanaged by ChromepreviewChrome's built-in model through the Prompt API. No download for your app.

Edgewise 0.4.1 · MIT licence · Edit this page