software-mansion / software-mansion/react-native-executorch

GBNF / constrained decoding for LLM generate()?

Open
#1,377 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

blocked idea user exp
Dominant language
TypeScript
Stars
1.7k
Forks
96
Avg merge
20h 51m
Merged PRs (30d)
59

Description

Summary

We're running LFM2.5-VL-1.6B on-device via react-native-executorch 0.9.3 (iOS / MLX). We'd like to confirm that RNE does not support GBNF (or any logits-level constrained decoding) on LLMModule.generate / forward, and ask whether that's something you'd consider adding.

If we missed an existing API, a pointer would be enough.

What we looked at

JS API (0.9.3)

  • LLMModule.generate(messages, tools?) has no grammar / GBNF argument.
  • GenerationConfig only exposes sampling knobs: temperature, topP / topp, minP, repetitionPenalty, plus token-batch timing. No grammar / schema / allowed-token set.

Native sampler

  • Decode goes through TextDecoderRunner::logits_to_tokenSampler::sample.
  • The sampler applies argmax or temperature + top-k + top-p + min-p + repetition penalty. We didn't find a grammar FSM, token mask from a GBNF, or a user logits processor.

"Structured output" in the docs

Unrelated "grammar" in the repo

  • The privacy-filter pipeline has a BIOES Viterbi grammar. That's token-classification, not LLM GBNF.

We also grepped open issues for GBNF / constrained decoding / logits processor and didn't find an existing thread. Happy to close this as a duplicate if one exists.

Why we care

We use GBNF on llama.cpp / llama.rn for small closed outputs, e.g. root ::= "Yes" | "No" or a short enum. On RNE we can't attach that to generate(), so we fall back to greedy decode + parsing (and first-token logprobs where we have them). That works until the model starts with "The …" instead of a label.

A logits mask / GBNF (llama.cpp-compatible), a JSON-schema sampler, or a per-step allowed-token callback would let us constrain the decode itself instead of hoping the prompt is enough.

Questions

  1. Is the above correct for 0.9.x, and still true on the rewrite / 0.10 (#1208)?
  2. If yes: would you consider constrained decoding on generate / forward?
  3. If this is already possible through ExecuTorch LLM config / a runner hook we missed, please point us at it.

Happy to share a more precise sampler call-stack or a tiny repro if useful.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the LLMModule.generate and forward APIs, GenerationConfig, and the TextDecoderRunner::logits_to_token → Sampler::sample path described in the issue. Compare the 0.9.x behavior with the rewrite/0.10 tracked in #1208, and check whether ExecuTorch exposes a runner hook or logits constraint mechanism. Done means the support status is confirmed and the scope of any constrained-decoding API is documented.

Written by the indexing model from the issue text.

Assessment

Tech stack
react-native, typescript
Domain
ai, machine-learning, mobile-dev
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.