Repository navigation
Conversation
…ed schema contract Admit Gemma 4 (bundle template) next to canonical Qwen3, and the macOS arm64 GPU next to the CPU. Accept the JSON Schema subset that both the llama.cpp GBNF converter and LiteRT-LM's llguidance 1.9.1 enforce alike, refusing the rest with a typed error naming the schema path before generation. Gemma 4 may reason before its constrained reply through the new BackendJsonSchemaThinkingChatGeneration SPI; Qwen3 with thinking is refused. Require runtime finish reasons, report a reply cut off inside the JSON as length, and map a provider INTERNAL send failure to a typed error. Part of #174.
13 of 14 tasks
A recreated client (an image turn, for example) clears the service's admission, so the worker's early check refused Gemma 4 thinking until the next non-thinking schema request. The worker now leaves thinking to the service, which re-admits first. maxTokens 0 no longer reads a stale finish reason, the pre-output INTERNAL message no longer blames the schema alone, and the unreachable post-client backend check is removed. Part of #174.
…rio's matrix and registry notes
16 tasks done
Contributor
|
Chat app preview removed for |
This was referenced Nov 10, 2026
Merged
Merged
leehack
added a commit
that referenced
this pull request
Nov 12, 2026
leehack
added a commit
that referenced
this pull request
Nov 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
responseFormatnow admits Gemma 4 E2B with its bundle template, alongside Qwen3 with its canonical text template, on the macOS arm64 CPU and GPU. NPU and other templates stay refused.validateLlguidanceResponseSchema(lib/src/core/grammar/llguidance_schema_contract.dart) runs the GBNF validator and then refuses the features LLGuidance handles differently or fails on at send time. The refusal is aLlamaUnsupportedExceptionthat names the schema path, and it fires before generation. See the contract table below.ThinkingConfigkeeps the constraint suspended until the reasoning channel closes. Qwen3 with thinking produced unconstrained text, so it is refused and the message names Gemma 4. The new backend SPIBackendJsonSchemaThinkingChatGeneration(exported fromlib/backend.dart) carries this probe throughNativeAutoBackend, the worker and the service.LlamaUnsupportedException("runtime refused the JSON Schema request").LlamaInferenceException, with no native text echoed.stopor amaxTokenslimit throws.length, andLlamaStructuredOutput.parserejects it.v0.19.1-2). Only the C API 1.0 constraint and thinking setters are used, and only for JSON Schema; regex stays out of scope.Schema contract
type(incl. lists),properties,required,additionalProperties(bool or schema),items,min/maxItems,min/maxLength, anchoredpattern,enum/const(incl. objects),anyOf,allOf, local$refinto$defs/definitions(incl. recursion through properties/items), integerminimum/maximumformatuuidanddateonly; others refusedprefixItems, array-formitems)minItems == maxItems == lengthoneOfreferencingfeature and fails at send timeuniqueItems,$dynamicAnchor,$recursiveAnchor,x-guidance$schema$schema/$idrefusedpattern&&/--/~~class set operations, and nested counted repetition above 100000enum/constintegers beyond 2^53allOfenum intersections above 20000 combinations, more than 400 optional properties at one value,$refwith~0/~1escapes,$refcycles with no value betweenWhen
additionalPropertiesis absent, LiteRT-LM may emit extra keys, while the GBNF converter closes the object. The generation guide documents this.Production-readiness scope
User-facing scope:
responseFormat: {'type': 'json_schema', ...}on the native LiteRT-LM backend is enforced for Qwen3 (canonical template) and Gemma 4 (bundle template). It runs on the macOS arm64 CPU or GPU and covers the shared schema contract. Gemma 4 can think first.Supported platforms/paths: macOS arm64, CPU and GPU (Metal), with the packaged
v0.19.1-2runtime and the C API 1.0 client.Unsupported or intentionally unavailable paths: Each throws
LlamaUnsupportedExceptionbefore generation:Web keeps its existing refusal.
Out of scope / follow-ups:
@litert-lm/coreto expose constraints first; an upstream request is drafted, not filedCompleteness checklist
doc/litert_lm_templates.md,doc/litert_lm_v1_adoption.md,doc/cross_platform_validation.md,doc/testing_matrix.md,llamadart-chat-streamingskill,llamadart_litert_json_example.dart, both changelogs)capability_coverage.jsonstructured-output entry;validation_coverage_test.dartpasses)PR type guidance
Test Plan
At
6720dd22, with the targeted suites rerun at280bf13d, macOS arm64, Flutter 3.47.1, isolatedTMPDIR:dart run tool/prepare_workspace.dart(no tracked changes)dart format --output=none --set-exit-if-changed .dart analyze(no issues)dart run tool/testing/check_platform_boundaries.dartdart test -p vm -j 1 --exclude-tags local-only: 12866 pass, 129 skipped, 6 fail. All 6 are inwindows_registry_qualification_test(needspwsh, not installed locally; it fails onmainthe same way; CI runs it).dart test -p chrome: the contract test failed to compile on Chrome at6720dd22(literal 2^53+1 is not representable in JS);4233707cuses 2^54. Contract, engine, planner and entrypoint tests pass locally on Chrome; full Chrome suite: CI.coverage-lib: 93.70% (33759/36029);llguidance_schema_contract.dart151/153,litert_lm_service.dart1061/1082dart test -p vm test/unit/tooling/andtest/unit/tooling/validation_coverage_test.dartlitert-lm-json-schemae2e (below).Mutation checks. Each mutant was applied alone against its targeted tests, then reverted. 22 of 22 were killed at
6720dd22. At280bf13d, two more were killed: restoring the worker's pre-admission thinking guard failsworker_test, and dropping themaxTokens > 0guard fails the stale-finish test. The worker-guard mutant row below is superseded, because the worker no longer checks thinking:!= stopend checkenableThinkingbefore generationtime;oneOfallowed; open tuples allowed;$reftargets not walked; pattern repetition product ignoredThinkingConfigalways offlitert_lm_v1_json_schema_testworker_testlitert_lm_backend_testchat_completion_request_planner_test,engine_testMatrix Evidence
static-format-analyze6720dd22coverage-lib6720dd22;4233707cchanges one test literal onlylitert-lm-json-schema$ref,anyOf, date, closed tuple) checked by the Dart validator; ja/ko Unicode; ordinary chat after schemas; typedoneOfrefusal and recovery; thinking; history; cancel before/after content; reuse;lengthcutoffc5f39b41…, CPU and GPUlitert-lm-json-schema18193810…, CPU and GPUstructured-output-adversarialtemplate-parityis N/A.high-risk-exact-head-independent-qa18e3993fllamadart-evidence/pr-1907/. The evaluator exits 1 only on the two waivedcompiled_grammar_*axes (see the high-risk block).Review Notes
18e3993f(fresh auditor session, exact head; 0 P1/P2)18e3993f, CI pending;280bf13dCI passed.18e3993fadds causal tests (legacy runtime and facade schema-thinking refusal; matrix mode and registry note consistency) and merges current main (at6720dd22: everything passed except Chrome shard 1/3, fixed by4233707c)4233707c: BLOCK on one P2, a stale worker thinking guard after client recreation. Fixed in280bf13dtogether with P3s 1, 2 and 4 and the unreachable post-client backend check. Re-audit at18e3993f: ACCEPT.packages/llamadart_validation/assets/capability_coverage.json: one description line (#1458 lane).lib/src/backends/litert_lm/litert_lm_runtime.dart: a one-linesupportsJsonSchemaThinking => falseoverride on the legacy client (#1798 lane).lib/src/core/template/**or the stream parser (#1898 lane).High-risk regression review
backendRuntime,regressionPolicy,structuredOutput)4233707c: BLOCK (P2, fixed in280bf13d). Re-audit at18e3993f: ACCEPT, 0 P1/P2.compiled_grammar_acceptanceandcompiled_grammar_rejectionaxes, conditional on the independent audit confirming that this PR compiles no grammar. The re-audit confirmed it:llguidance_schema_contract.dartcalls only the unchangedvalidateResponseSchemaandJsonSchemaConverter.resolvePointer, then adds refusals. ThegrammarSchemaminimum comes from thelib/src/core/grammar/path, and the evaluator has no waiver flag (doc/high_risk_pre_merge_readiness.md), so it exits 1 (missingStructuredOutputEvidence) on exactly these two axes. All other axes are met. The admitted schema is compiled natively by LiteRT-LM LLGuidance and is exercised by thelitert-lm-json-schemareal-model scenario.18e3993f/33e00f5a(currentorigin/mainmerged in)