Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.reactor.inc/llms.txt

Use this file to discover all available pages before exploring further.

LingBot is a real-time, navigable video model. It takes a seed image plus a text prompt as visual and stylistic anchors, then continuously generates a video stream you walk through with WASD and look around with arrow keys. LingBot produces an infinite, interactive stream that responds to commands frame-to-frame.

At a glance

SpecValue
Model namelingbot
Pricing
Throughput16 fps
Latency< 1 second
Resolution1664 × 960
The model name is the string you pass when you open a session, e.g. new Reactor({ modelName: "lingbot" }). See Pricing & Billing for how billing works.

Key features

Interactive WASD navigation

Drive the camera through a generated world with movement and look commands that apply at the next chunk boundary.

Image-anchored generation

A seed image fixes the visual identity of the world; the prompt steers the rest.

Live prompt swapping

Re-fire set_prompt at any time mid-generation to swap atmosphere, lighting, or events without restarting the session.

Quick Start

A minimal connect-and-generate flow looks like:
import { LingbotModel } from "@reactor-models/lingbot";

const lingbot = new LingbotModel();
await lingbot.connect(jwt);

// Wait for the seed image to be decoded before starting, so the first
// chunk renders from the image instead of correcting itself one chunk later.
const imageAccepted = new Promise<void>((resolve) => {
  lingbot.onImageAccepted(() => resolve());
});

const ref = await lingbot.uploadFile(seedImageFile);
await lingbot.setImage({ image: ref });
await imageAccepted;

await lingbot.setPrompt({
  prompt: "A misty old-growth forest, soft morning light filtering through the canopy.",
});
await lingbot.start();

Prompt Guide

LingBot’s output is highly sensitive to how prompts are written. The text encoder treats descriptors like “camera pans left” or “tracking shot” as content rather than camera instructions, and leaking imperative camera verbs into the prompt degrades output noticeably. For the full recipe (sentence count, anchor density, hold-prompts vs. layered composition, and worked examples), see the LingBot Prompt Guide.

Tracks

DirectionNameTypeFormatRate
Outboundmain_videoVideo(N, H, W, 3) uint8 RGBAdaptive, paced to model throughput
Default resolution is 480 × 832. There are no inbound tracks: all client → model communication is through commands.

Session lifecycle

LingBot sessions move through three states: WAITING, GENERATING, and PAUSED. WAITING. Default state after connect. The model is idle and waiting on conditions. Valid commands: every set_* plus start. No frames are emitted. GENERATING. Frames stream on main_video. start requires that both a prompt and a seed image have been set; sending start without them fails with a command_error. Valid commands during generation: set_prompt, the movement and look setters, set_rotation_speed_deg, pause, and reset. Each completed chunk emits a chunk_complete event. PAUSED. Reached via pause once the current chunk finishes. Frames stop. Valid commands: resume and reset. resume picks up from the next chunk; reset clears all session state and returns to WAITING. When all chunks of a run complete, LingBot emits generation_complete and, if the session is still started, kicks off the next run automatically with the same prompt and image. Call reset to stop the loop and re-stage with new conditions.

Commands

CommandParamsPreconditionsEffect
set_promptprompt: string (≤ 1000 chars)-Stores the prompt. Re-applied on the next chunk boundary. Emits prompt_accepted then conditions_ready.
set_imageimage: FileRef (from uploadFile)-Decodes the uploaded file and caches it as the seed image. Rejects non-image MIME types with command_error. Emits image_accepted then conditions_ready.
set_movementmovement: "idle" | "forward" | "back" | "strafe_left" | "strafe_right"-Sets WASD movement direction. idle holds position. Applied on the next chunk boundary.
set_look_horizontallook_horizontal: "idle" | "left" | "right"-Yaw rotation direction. idle holds the heading.
set_look_verticallook_vertical: "idle" | "up" | "down"-Pitch rotation direction. idle holds the pitch.
set_rotation_speed_degrotation_speed_deg: float (0.0 – 30.0)-Degrees the camera rotates per latent frame when a look axis is active. Default 5.0.
set_seedseed: int (≥ 0)Before startRNG seed for the next generation. Read once when start fires; later changes require reset then a new start. Default 42.
start-A prompt and a seed image have been setBegins generation. Fails with command_error if conditions are missing. Emits generation_started.
pause-In GENERATINGPauses after the current chunk finishes. Emits generation_paused.
resume-In PAUSEDResumes generation. Emits generation_resumed.
reset--Clears prompt, image, and the started flag. Returns to WAITING. Emits generation_reset.

Movement and look

Movement and look are persistent state, not pulses. Sending set_movement with "forward" puts the character into a forward-walking state that continues across chunks until you send "idle" or a different direction. The same applies to the two look axes. To stop moving, explicitly send the "idle" value. Look-axis rotation rate is governed by set_rotation_speed_deg: 5° per latent frame by default. Setting it to 0 disables rotation entirely even if a look axis is non-idle.

Why changes feel “delayed”

LingBot generates output one chunk at a time. A command sent mid-chunk does not interrupt the current chunk; it applies at the next chunk boundary. For most commands this is fine; for a quick tap on a key, it can mean the change never visibly lands if you release before the next chunk starts.

Messages

LingBot emits the following messages. Every message is delivered as JSON { "type": "<name>", "data": { … } } over the same channel as all other Reactor message events.
EventWhenPayload
prompt_acceptedAfter set_prompt{ prompt: string }
image_acceptedAfter set_image decodes{ width: int, height: int }
conditions_readyAfter set_prompt or set_image{ has_prompt: bool, has_image: bool }
generation_startedAfter start{ prompt: string, chunk_num: int, frame_num: int }
chunk_completeAfter each chunk emits{ chunk_index: int, frames_emitted: int, active_prompt: string, active_action: string }
generation_pausedAfter pause{ chunk_index: int }
generation_resumedAfter resume{ chunk_index: int }
generation_completeAfter all chunks of a run finish{ total_chunks: int }
generation_resetAfter reset{ reason: string }
command_errorWhen a command is rejected{ command: string, reason: string }
stateOn connect, after every state-mutating command, and after every chunk_completeFull session snapshot; see below

state payload

state is the single source of truth for driving UI. Subscribe once and treat it as the authoritative session snapshot; you generally do not need to track individual set_* and chunk_complete events yourself.
FieldTypeMeaning
runningboolstarted && !paused. Equivalent to “frames are actively streaming”
startedboolTrue once start has been accepted; remains true through pauses
pausedboolTrue while in the PAUSED state
current_chunkintZero-based index of the last completed chunk; 0 before the first chunk
current_promptstring | nullThe prompt currently driving generation, or null if none set
has_promptboolWhether a prompt has been set this session
has_imageboolWhether a seed image has been set this session
current_actionstring+-joined composite of movement and look. E.g. "w+left", or "still" when idle
movementstringCurrent value of the movement input field
look_horizontalstringCurrent value of the look_horizontal input field
look_verticalstringCurrent value of the look_vertical input field
rotation_speed_degfloatCurrent rotation speed (0.0 – 30.0)
seedintCurrent seed value (effective only on the next start)
For a clean first chunk, wait for the image_accepted message between setImage and start. Otherwise the first chunk can render before the seed image is applied, and the scene corrects itself one chunk later. The tutorial shows the pattern. Helios avoids this with atomic set_conditioning; LingBot has no analogue yet.