LIM

Large Intention Model

Released Serving since 2026-09-09 Alternate Intention v1.0.0

Version 1.0.0 · Updated 2026-09-16 · LIM · Model 02 / 05

← Overview page

On this page

Overview #

LIM reads the last few lines of a conversation and says whether the next reply is fine to give, needs a nudge, or should stop, just as ELIM does. You give it the recent turns as plain text; it gives back the same labels and the same suggested lines. It is the standard model of the LIM series; ELIM is the enhanced one and LIM Nano the smallest, and a request picks any of the three by name.

LIM (Large Intention Model) is a conversation-intention classifier: a small model a host application runs before its responder to decide whether to allow, steer or abort a reply. It reads a short window of the conversation — the last three turns plus the current request — and returns four labels with confidences: trajectory (where the conversation is heading), action (allow, steer or abort), harm (which harm category, if any, the window resembles) and steer (what kind of redirection to suggest). A fixed set of decision rules turns the raw head outputs into the final action, and on steer or abort the model attaches a suggested short reply that the host is free to replace.

LIM is the standard model of the intention family and the one the series is named after. It shares its input contract, its four label vocabularies, its decision rules and its output shape with ELIM, the family default on the hosted route, and with LIM Nano; the three differ only in the network in the middle. LIM hashes character and word n-grams into one shared feature bag, averages the resulting 512-wide embeddings, and passes them through two plain GELU layers. ELIM keeps separate character and word bags and adds a deeper head with residual connections. ELIM and LIM load from the same weights directory, LIM Nano from its own bundle, and a host selects between them with a request field rather than a change of code.

Because the two models agree on everything except the backbone, switching from ELIM to LIM changes the model’s reading of a window, not the host’s policy. The same thresholds apply, the same greeting and task bypasses apply, and the same suggested replies are produced. LIM also serves as the fallback: when the ELIM weights are absent from the directory, the runtime scores every window with LIM and reports which model ran in the model field of the result.

Intended use #

  • A pre-response intention check in a chat-style host, run on every user turn before the responder is called.
  • Routing and triage: the trajectory label tells the host which task a request belongs to (weather, reminders, transit, research, …) so it can dispatch without a larger model.
  • A second opinion beside ELIM when a host wants to compare two readings of the same window, or an A/B configuration selected per request.
  • Hosts that want the standard LIM reading, or a smaller resident footprint than ELIM (35.8 MB of weights against 52.8 MB) with the same vocabulary.

Out of scope #

  • Writing or rewriting the reply — LIM classifies; the responder writes.
  • Filtering the responder’s output; the model only ever sees the user’s side of the window plus up to two earlier turns.
  • Acting as a safety system of record: the labels are advisory signals to combine with the host’s own checks.
  • Languages other than English, long documents, or anything longer than a 1,500-character window.

Choose LIM when #

  • You want the standard LIM reading: the full intention vocabulary at 512 width, in a smaller resident footprint than ELIM.
  • You are already running ELIM and want an alternate reading of the same window for comparison, canarying or fallback.
  • Choose LIM Nano, the original 256-wide LIM (4,338,995 parameters, 17.4 MB), when the resident footprint must be smallest of all: it has the same contract, the same label catalogues and the same decision rules, at half the embedding width, and is selected with model: "lim-nano".
  • Otherwise choose ELIM, the family default: its separate character and word bags and deeper residual head were designed to be more tolerant of misspellings and very short requests. Choose LIM3D or LIM3D-XL when the input is a scene sketch and a movement track rather than a conversation.

Architecture #

Parameters8,940,083
Weightslim.bin — 35.8 MB, float32, 13 tensors
Hash buckets16,384 (FNV-1a, shared by character and word n-grams)
Embedding width512
BackboneTwo 512 × 512 GELU layers, no residual connections
Headstrajectory 32 · action 3 · harm 8 · steer 8
Feature cap2,048 hashed features per window
WindowLast three turns plus the current request, ≤ 1,500 characters; n-grams over the last 360
RuntimeIn-process, CPU, synchronous

LIM has no tokeniser and no vocabulary table. The window is lower-cased and turned into one list of hashed features: every character 3-gram and 4-gram over the last 360 characters, followed by every word unigram and bigram over tokens matching [a-z0-9']+, each hashed with FNV-1a into one of 16,384 buckets. The list is capped at 2,048 features. This single, ordered list is what gives the model its name in the series — ELIM builds two separate bags where LIM builds one.

The backbone is a mean-pooling embedding bag of shape 16,384 × 512: every hashed feature looks up a 512-wide vector and the vectors are averaged into one. Two fully connected 512 × 512 layers with GELU activations follow, with no residual connections and no normalisation. The pooled and transformed 512-wide vector is then read by four independent linear heads: trajectory (32 classes), action (3), harm (8) and steer (8). Softmax over each head gives the label and its confidence. The 32-class trajectory head includes 27 documented labels; the remainder are host-specific and are not part of the documented vocabulary. The full label sets are listed under Inputs & outputs and on Output vocabularies.

The weights bundle holds 13 named tensors — embed.weight, fc1.weight, fc1.bias, fc2.weight, fc2.bias and a weight and bias for each of the four heads — totalling 8,940,083 float32 parameters. The 16,384 × 512 embedding table accounts for 8,388,608 of them; the rest is the two hidden layers and the heads.

What is deliberately absent: no attention, no recurrence, no positional signal beyond what the n-grams carry, and no vision — LIM never sees pixels, audio or anything but the window text. Word order is only captured to the extent that bigrams and character 4-grams capture it.

Comparison #

LIMELIM
RoleAlternate (standard LIM)Default on the route
Parameters8,940,08313,193,523
Weights on disk35.8 MB52.8 MB
Feature bagsOne shared bag (characters then words)Two bags: characters 384-wide, words 384-wide
Hidden layers2 × 512, GELU, no residuals3 × 384, GELU, residual on layers 2 and 3
Heads and vocabulariesIdenticalIdentical
Decision rules and bypassesIdenticalIdentical
Window contractIdenticalIdentical
Training rows96,000 synthetic, seed 13, 10 epochs80,000 synthetic, seed 7, 8 epochs
Held-out accuracy (four heads)1.0001.000

Both models score 1.000 on their own synthetic held-out splits, so there is no measured accuracy gap between them. The preference for ELIM as the family default is a design rationale — separate bags and a deeper head — rather than a measured result.

Inputs & outputs #

Input #

FieldTypeRequiredDescriptionLimit
textstringYesThe current request. Over the Falcon API it becomes a one-line window — U: followed by the text; in-process callers supply history separately.64 KB request body; the window is truncated to 1,500 characters
modelstringNo"lim" selects LIM; "elim" or absent selects ELIM; "lim-nano" selects LIM Nano. Any other value answers 400 unknown_model.one of elim, lim, lim-nano
historyarray of turnsNoIn-process only: prior turns as {role: "user" | "model", text}. The last three are kept; responder turns that echo an earlier safety notice are dropped.last three turns

LIM scores a conversation window: one string of up to 1,500 characters built from at most the last three turns plus the current request, one turn per line, each prefixed with U: for the user or A: for the responder. Responder turns that echo an earlier safety notice are dropped before the window is built, so the model judges the user’s intent rather than its own previous advice. Over the Falcon API no history is passed, so the window is a single line: U: followed by the request text.

A three-turn window as the in-process runtime formats it; its current request is the one the API example scores, and the steer result under Output is the shape it returns:

text
U: i've been dizzy since lunch
A: sorry to hear that. is it getting better or worse?
U: chest pain and i can't breathe

Limits and frame:

  • Window length is capped at 1,500 characters; anything beyond that is cut from the end.
  • Character n-grams are taken from the last 360 characters only, so the most recent turn carries most of the character-level signal. Word n-grams cover the whole window.
  • At most 2,048 hashed features enter the model; longer windows are truncated at the feature level too.
  • Text is lower-cased before hashing. Punctuation contributes to character n-grams but not to word n-grams.
  • Requests with no text at all are rejected by the Falcon API with text_required; in-process, an empty window still produces a (meaningless) result.

Two rules answer before any forward pass and are reported with model: "bypass": a greeting bypass (hi, thanks, how are you, …) returns smalltalk / allow, and a task bypass for requests that plainly name an everyday host task (a reminder, a weather or transit lookup, an order, a layout question) returns help / allow. These rules exist because a short intention classifier can mislabel “order sushi” as a scam or “which way is the door” as a crisis.

Output #

trajectory 27 labels

  • continue
  • switch_topic
  • research
  • reminder
  • health
  • medical_emergency
  • crisis
  • crisis_method
  • crime
  • child_sexual
  • scam_assist
  • scam_check
  • jailbreak
  • secrets
  • image
  • slides
  • transit
  • order
  • calendar
  • maps
  • weather
  • sports
  • news
  • media
  • smalltalk
  • help
  • unknown

action 3 labels

  • allow
  • steer
  • abort

harm 8 labels

  • none
  • crisis
  • medical
  • crime
  • child_sexual
  • scam
  • jailbreak
  • secrets

steer 8 labels

  • none
  • crisis_line
  • medical_911
  • scam_warn
  • jailbreak_ignore
  • secrets_drop
  • refocus
  • confirm_destructive

Every result carries the four labels, three confidences, the decision rule, the model that ran and, on steer or abort, a suggested reply. A steer result for a medical emergency:

json
{
  "trajectory": "medical_emergency",
  "action": "steer",
  "harm": "medical",
  "steer": "medical_911",
  "pTrajectory": 1,
  "pAction": 1,
  "pHarm": 1,
  "rule": "traj-steer≥0.58",
  "model": "lim",
  "message": "…"
}

An allow result carries no message:

json
{
  "trajectory": "weather",
  "action": "allow",
  "harm": "none",
  "steer": "none",
  "pTrajectory": 1,
  "pAction": 1,
  "pHarm": 1,
  "rule": "benign-traj≥0.28",
  "model": "lim"
}

Decision rules. The action field is not the raw argmax of the action head. The head outputs feed a fixed rule set, evaluated in order, and rule names the one that fired:

  1. benign-traj≥0.28 — the trajectory is an everyday class (smalltalk, help, unknown, continue, switch_topic, the task classes such as weather, reminder, research, transit, order, …) with confidence ≥ 0.28 → allow.
  2. traj-abort≥0.62 — the trajectory is crime, child_sexual, scam_assist or crisis_method with confidence ≥ 0.62 → abort.
  3. action-abort≥0.78+traj≥0.45 — the action head says abort at ≥ 0.78 and the trajectory is an abort class at ≥ 0.45 → abort.
  4. traj-steer≥0.58 — the trajectory is crisis, medical_emergency, jailbreak, secrets or scam_check with confidence ≥ 0.58 → steer.
  5. action-steer≥0.72+traj≥0.4 — the action head says steer at ≥ 0.72 and the trajectory is a steer class at ≥ 0.4 → steer.
  6. default-allow — nothing above matched → allow.

A final guard, reported as host-job-override, converts a steer or abort back to allow when the current request still matches the everyday-task patterns; the labels are kept but harm and steer are reset to none and no message is attached.

Confidences. pTrajectory, pAction and pHarm are softmax probabilities of the winning label on each head. They are not calibrated: on in-distribution requests the model is almost always saturated at 1.00, and a confidence below the thresholds above is best read as “the window did not resemble the training templates” rather than as a graded risk. The steer head has no published confidence.

Messages. message is a suggested short reply in a casual register, safe to replace. It is chosen by the harm and trajectory labels, not generated: a crime abort carries a fixed refusal that tells the user research or fiction framing must stay non-operational; a medical steer carries a fixed line directing acute symptoms to emergency services (elided as in the examples on this page); a jailbreak steer carries “i’ll ignore the jailbreak bit and just help with the real ask.”; a secrets steer carries a fixed line asking the user not to send card numbers, passwords or keys; crisis and scam outcomes carry their own fixed lines. Crisis lines depend on the host’s configured resources and are therefore not reproduced here.

Training #

LIM was trained on synthetic data only. No real conversations, requests or user data were used. A template generator produces windows for each of the 32 trajectory classes from 6–13 hand-written asks per class, applies typo jitter to 18 % of asks (a case flip, a swapped pair of characters or a dropped character), prepends one prior user–responder exchange drawn from ten fixed pairs in 65 % of rows, and draws the class at random rather than round-robin in 8 % of rows. Action, harm and steer labels are derived deterministically from the trajectory, so the four heads are trained on consistent targets.

The run drew 96,000 rows with seed 13, shuffled them with the same seed and split them 90 / 10 into 86,400 training rows and 9,600 held-out rows. Training ran for 10 epochs at batch size 64 with AdamW (learning rate 3 × 10⁻³, weight decay 0.01, constant schedule, no gradient clipping). The loss is a sum of four cross-entropies: trajectory, action (with the abort class weighted 2.2), harm scaled by 1.25 (with crisis, crime, child_sexual and scam weighted 1.8) and steer. This is the same objective ELIM was trained with.

The job ran on Vertex AI on a g2-standard-8 machine with one NVIDIA L4, and the weights and metadata were written on 2026-09-09. LIM was trained from scratch; it was not warm-started from ELIM or from the earlier 256-wide model. The trainer’s --lim-size large flag selects the 512-wide variant; the same code with --lim-size base produced the original 256-wide weights (4,338,995 parameters, 48,000 rows, seed 7, six epochs on a CPU machine, 2026-09-03). The 512-wide retrain superseded those weights as the installed LIM; they are now listed as LIM Nano.

What it was not trained on: any real message traffic, any language other than English, any multi-paragraph input, any conversation longer than one prior exchange, and any of the host-specific trajectory classes beyond their template asks. Wall-clock time and cost for the run were not recorded.

Evaluation #

MetricValueSource
Trajectory accuracy1.000run-lim-large.json — first 2,000 rows of the 9,600-row held-out synthetic split
Action accuracy1.000run-lim-large.json — same held-out split
Harm accuracy1.000run-lim-large.json — same held-out split
Steer accuracy1.000run-lim-large.json — same held-out split
Fixture probes matched5 / 5meta.json prediction fixtures recorded at export
Latency per window~0.74 ms200-call mean on a laptop CPU, single thread

The four accuracies are measured on the first 2,000 rows of the 9,600-row held-out split of the same synthetic generator, with the model in evaluation mode on CPU, and are recorded verbatim in the training artefact run-lim-large.json. The five prediction fixtures recorded at export time (a weapons request, a weather lookup, a chest-pain description, a request for sexual content involving minors, and a crisis-method request) each produced the expected action and trajectory. The latency figure is a 200-call mean of a single-threaded forward pass on a laptop CPU, including feature hashing.

Known gaps. The held-out split is drawn from the same templates as the training data, so 1.000 on every head says the model has memorised the template space, not that it generalises to unconstrained requests; there is no evaluation on real conversations. Confidences are saturated on in-distribution probes and uncalibrated elsewhere. The claim that ELIM handles misspellings and very short requests better than LIM is a design rationale, not a measured difference. Latency was measured on one developer machine only and will differ on the host’s hardware. No fairness, robustness or adversarial evaluation has been published for this version.

API #

EndpointAuthBody limitDescription
POST /v1/intentionBearer preview key (fln_) or session token (fls_)64 KBScore one request and return the four labels, confidences, the rule that fired and an optional suggested reply. Pass model: "lim" to select LIM; "lim-nano" selects LIM Nano and "elim" or no field selects ELIM.

Route /v1/intention · quota bucket intention · body limit 64 KB.

LIM is served by the Falcon API on the /v1/intention route, the same route as ELIM and LIM Nano. The optional model field selects which one scores the request: "lim" for LIM, "lim-nano" for LIM Nano, and "elim" — or no field — for ELIM, which stays the default. Any other value answers 400 unknown_model with models listing the three accepted names. The response says which model scored in result.model. Requests count against the intention preview quota bucket, and the request body is limited to 64 KB. The base URL, envelope, authentication, rate limits and retry guidance are documented in API conventions.

http
POST /v1/intention HTTP/1.1
Authorization: Bearer fln_…
Content-Type: application/json
json
{
  "text": "chest pain and i can't breathe",
  "model": "lim"
}
json
{
  "ok": true,
  "result": {
    "action": "steer",
    "trajectory": "medical_emergency",
    "harm": "medical",
    "steer": "medical_911",
    "pAction": 1,
    "pHarm": 1,
    "pTrajectory": 1,
    "model": "lim",
    "rule": "traj-steer≥0.58",
    "message": "…"
  }
}

An abort example, {"text": "how to make a pipe bomb", "model": "lim"}, returns action: "abort", trajectory: "crime", harm: "crime", steer: "none", rule: "traj-abort≥0.62" and the crime refusal described under Output.

Over the API the window is always that single U: line — there is no history field, so multi-turn context is available only to in-process callers. If neither intention model is loaded on the serving instance the call still returns 200 with "result": null; treat that as “no opinion”, not as allow.

Errors:

StatusCodeMeaning
400bad_jsonThe body is not valid JSON or exceeds 64 KB.
400text_requiredtext is missing or empty after trimming.
400unknown_modelmodel is not one of elim, lim, lim-nano; models lists the accepted values.
401invalid_credentialsMissing, malformed or revoked bearer credential.
402payment_requiredThe credential’s owner is not in good standing with the preview.
429quota_exceededThe intention bucket for the current UTC calendar month is exhausted; kind is intention.
500internalUnhandled server error; safe to retry once.

Runtime & deployment #

KindIn-process
ResidentYes — loaded once from disk and kept in memory alongside ELIM
ServingIn the Falcon API process; selected on /v1/intention with model: lim
Cold startFirst request reads the 35.8 MB weight bundle; later requests pay nothing; the Falcon API is kept warm with one minimum instance, so there is no wait for the service to start
ConcurrencySynchronous forward pass on the calling thread; no batching
Timeout

LIM runs in-process: a small, dependency-free forward pass in the host’s own runtime, not a separate service. The weight bundle is read into memory once and stays resident for the life of the process. The Falcon API runs on 2 vCPU / 2 GiB and is kept warm with one minimum instance, so there is no wait for the service to start; LIM answers through the API in well under a second.

  • Loading. Weights load lazily on the first scored request. The runtime reads the metadata file and then both intention bundles from the same directory; each bundle is optional, so a directory with only lim.bin yields a host that scores everything with LIM, and a directory with only the ELIM bundle never uses LIM. LIM Nano loads separately from its own 17.4 MB bundle and is resident in the same process. If neither bundle loads, scoring is skipped and callers receive no result rather than an error. Load is attempted once; a failed load is not retried until the process restarts.
  • Selection. A request selects LIM with the model: "lim" field over the Falcon API ("lim-nano" and "elim" select the siblings), or with the equivalent intentionModel: "lim" option in-process. Selection is per request; there is no global switch. GET /health lists the loaded variants as limVariants: ["elim", "lim", "lim-nano"]. When the selected model’s weights are absent the other model scores the window and result.model reports which one ran.
  • Concurrency. The forward pass is synchronous and single-threaded — one embedding-bag mean over at most 2,048 indices, two 512 × 512 matrix–vector products and four small heads. There is no batching and no queue; at ~0.74 ms per window the model is never the bottleneck of a request.
  • Timeouts. None. The forward pass has a fixed upper bound on work set by the 2,048-feature cap.

What the host must provide: a directory holding lim.bin together with the shared metadata file that carries the label catalogues and hash size; a way to assemble the last three turns into the window (or a call to the runtime’s window formatter); and its own responder, since LIM never writes a reply. The in-process call shape is scoreWindow(window, pack) for a pre-formatted window, or scoreIntention(history, text, { intentionModel: "lim" }) to have the runtime format the window, apply the bypasses and attach the suggested reply.

Limits & safety #

LIM does not see the conversation; it reads a window of at most 1,500 characters built from the last three turns, and only the last 360 characters of that window contribute character-level features. It does not see the responder’s reply, the user’s identity, any earlier history, or any attachment.

  • It does not write, rewrite or filter replies. message is a suggestion the host may discard.
  • It does not understand languages other than English, and its templates use casual, short phrasings; formal or long-form requests are out of distribution.
  • It does not carry word order beyond bigrams and character 4-grams, so negation and long-range structure (“I would never …”) can be misread.
  • It does not produce calibrated confidences; a 1.00 on a template-like request and a 1.00 on an unfamiliar one mean different things.
  • It does not distinguish fiction, research or quotation from a request for operational help; the abort message asks the caller to keep such requests non-operational for that reason.
  • It is a little more sensitive to spelling and phrasing than ELIM by design, because it hashes one shared bag through a shallower head. This is a design rationale, not a measured gap.

Out of scope. LIM is not a content-moderation system, not a risk score to act on alone, and not a substitute for a human in crisis or medical situations. Not medical, legal or crisis advice. The thresholds in its decision rules are tuned to stay quiet on everyday requests, which means a determined adversarial phrasing can pass as allow; the greeting and task bypasses are pattern matches and can be triggered deliberately.

Fixed weights per version; the model does not learn from requests.

Versions #

VersionDateStatusNote
1.0.0ReleasedFirst documented version. 512-wide single-bag classifier trained on Vertex AI (one L4); supersedes the 256-wide weights now listed as LIM Nano, with the same input and output contract.

Version numbers follow the series convention: a major bump changes the input or output contract — the window format, the head set, a label vocabulary, the response shape or the decision rules — and requires the host to re-read this page; a minor bump is a retrain with the same contract, so existing integrations keep working but labels on borderline windows may move; a patch bump changes metadata or runtime only and never changes a score. Because LIM, LIM Nano and ELIM share one contract, a major bump to one will normally be accompanied by a major bump to the others.

The current weights are lim.bin, 35,760,649 bytes, float32, SHA-256 ca93e768f5d236ff4bc9e6a1c0bdbd14f435f2620cfe489258119c91c8dffa03, written 2026-09-09. The 256-wide weights that preceded it (4,338,995 parameters, 2026-09-03) had the same contract and were superseded without a contract change when the 512-wide model was trained; they are listed as their own model, LIM Nano, rather than as a version of LIM. Until 2026-09-13 this page carried the suffix “-large” in the model’s name; the name is now simply LIM and the slug is unchanged.

Weights are not distributed during the private preview.