Repository navigation
feat(laya_tetris): add a Flutter Tetris example played by a Laya decision model - #617
Merged
Merged
Conversation
Question and answer types, Python json.dumps parity, Laya 0.3.5 sequence assembly and answer decoding, with a parity fixture from the official checkpoint. Not exported yet; the native backend and DecisionEngine facade follow in the next PR. Design: doc/decision_engine.md.
Adds the BackendDecision contract, the native path (safetensors reader, ggml head graph with Windows ggml-base twins, private pooling-NONE encoder context, worker messages, router forwarding), LlamaEngine hooks with engine-owned head handles, and the public DecisionEngine facade. Web and LiteRT-LM report unsupported. Includes a local-only E2E against the laya 0.3.5 fixture, the decision-model-smoke runner scenario, and docs.
Move the decision encoder context setup into applyDecisionContextParams with unit tests, state that a call already sent to the backend finishes on the unloaded model, and add local F16 backbone measurements.
bin/llamadart_decision_example.dart downloads the pinned Laya backbone and head, answers a choice, a score and a yes/no question about a support ticket, and can print Laya's JSON response.
…sion model example/laya_tetris plays turn-based and real-time Tetris through DecisionEngine with heuristic, yes/no, checklist, choice and Tetris-tuned players, a benchmark screen, a headless bench and a dataset generator for fine-tuning the head.
10 of 12 tasks
The tuned head now resolves to LAYA_TUNED_HEAD_URL, then a file in the app's model folder, then leehack/laya-tetris-head pinned to a commit. A failed tuned head shows advice for its source, and the benchmark times the head that loaded.
…code - Stream head tensors into the upload buffer; one head load peaks about 100 MiB lower. - Allocate head weights with ggml_backend_alloc_ctx_tensors instead of a hand-written layout, dropping six GgmlGraphApi entries and their Windows twins. - Replace the fdlibm erf port with Abramowitz and Stegun 7.1.26 (within 1.4e-7). - Compute the head's last layer only for the CLS and marker rows. - Type BackendDecisionSequence.questionType as DecisionQuestionType. - Parse the head config once, with headLayers on DecisionHeadConfig. - Return the encoder output as a view, reuse the service's device matching, and test the head's device choice. - Tighten tests that could not fail and share the synthetic head and fixture helpers.
- Add ChoiceKey, ScoreKey and NoulKey: typed question handles read back with answerOf, including enum and arbitrary option values, checked against the request that produced the result. The string and JSON forms are unchanged. - Accept structured instructions in the question constructors. - Check empty question ids in DecisionRequest, tokenize each text once per call, clamp temperatures once, and reject non-string JSON keys. - Docs: typed questions guide section, Experimental label, corrected accuracy and Laya-compatibility wording, and one home for the measurements.
…ision-basic-example
The ticket triage asks ChoiceKey.enumOf over a Department enum, ScoreKey.of and NoulKey.of, and formats answers read with result.answerOf; output and exit codes are unchanged. Drop the "laya.config" error-text sniff; the library message and --config help cover it.
- systemOneBatch answers the requests as they were when it started, so changing the list mid-call can no longer mislabel answers. - DecisionEngine.load rejects a model unloaded or replaced during the capability probe instead of returning an engine for the old model. - The real-model smoke fails when the requested GPU backend fell back to CPU, and checks that a config longer than the encoder was trained for is rejected. - The guide says the head falls back to CPU when no device of the model's backend is available.
…ision-tetris-example # Conflicts: # doc/decision_engine.md # website/docs/guides/decision-models.md
FakeLaya now keeps each request's questions as DecisionEngine does, so a rebuilt key fails the typed read, and the base-head choice test checks every option's probability in option order. Drop the delivered examples from the remaining-work sentence in the decision engine notes.
…tions A head load that fails with LlamaModelException and no --config prints the --config hint again, without matching error text; a failed backbone load does not. The questions test compares JSON text so key and option order count, and the formatter test is named for its fixed order.
Pin leehack/laya-tetris-head at 465546a5 and re-measure the tuned rows with it on Metal.
Re-measure the question-time table over three runs on this head; the old ranges predated the pin and the #606/#616 merge. The 12-epoch head pinned in 84b61bb is not better everywhere than the 8-epoch head it replaces (revision 83794e0b). Turn-based with "3 best + 3 random" it plays 150 pieces and 48 lines against 122 and 34, and with all legal moves 135 and 40 against 134 and 40. In real time with all legal moves, the default off Android, it cleared 36.2 lines per game over six games against 47.2; each head won three of the six seeds.
leehack
marked this pull request as ready for review
September 23, 2026 22:56
Contributor
|
Chat app preview removed for |
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
Fourth PR of the
DecisionEnginestack (#604), stacked on #616. It addsexample/laya_tetris, a Flutter app in which a Laya decision model plays Tetris.Game: turn-based and real-time Tetris (SRS kicks, lock delay, hold, T-spins, back-to-back, gravity), a move planner and a bot.
Players: heuristic, random, yes/no judge, checklist, choice, and a Tetris-tuned knockout. Each piece's questions go to
systemOneBatchin one call while gravity keeps running. The choice player reads its pick through a typedChoiceKey; the others keep string ids.Models:
LlamaEngine(contextSize: 512) shared by the base head and the Tetris-tuned head.fr0stbit3/laya-gguf@ce2afdcfiles, with progress, cached across launches.Benchmark screen: locks the game and pickers while it runs.
Headless tools:
bin/bench.dartplays headless games with local files.bin/make_dataset.dartwrites heuristic-labelledchoiceexamples for fine-tuning the head; its output is byte-identical to the spike that produced the local tuned head.Tuned head: published as leehack/laya-tetris-head (
laya-head-tetris.safetensors, 106 MB, sha256459d57c6…, Apache-2.0) and downloaded on first launch, pinned to commit465546a5: the 12-epoch recipe of #619's notebook, validation accuracy 0.757 (PyTorch) and 0.760 (llamadart Q8_0, Metal). It replaces the first 8-epoch head83794e0(0.750). The pinned file's sha256 and size match the Hugging Face LFS metadata at that commit. It resolves in this order:--dart-define=LAYA_TUNED_HEAD_URL;laya-head-tetris.safetensorsin the app'slaya/folder, for a user's own fine-tune;If it fails to load, the app shows the error and recovery advice for that source, and the tuned player stays disabled. The in-app Benchmark times the head that actually loaded. The documented tuned bench rows came from this exact file.
Wiring:
tool/prepare_workspace.dartregisters the package. Docs: new websiteexamples/laya-tetrispage, sidebar, overview,example/README.md, root README example list, a link from the decision-models guide, and a CHANGELOGUnreleasedbullet.Production-readiness scope
flutter runinexample/laya_tetrison macOS, iOS or Android.DecisionEngineis native-only for now.Completeness checklist
PR type guidance
lib/change.Test Plan
dart run tool/prepare_workspace.dartdart format --output=none --set-exit-if-changed .dart analyzedart test -p vm -j 1 --exclude-tags local-only: N/A, nolib/change;test/unit/tooling/prepare_workspace_test.dartran: 12 passed.dart test -p chrome --exclude-tags local-only: N/A, nolib/change.example/laya_tetris:flutter analyzeis clean, andflutter testpasses 47 with 2 skipped. The two skipped are real-model tests; they pass withLAYA_MODEL_DIRset.83794e0) by loading it from a pre-seeded cache with all HTTP blocked; its choice probabilities were identical to loading the local file. The cache key includes the revision, so the new pin downloads into its own folder.flutter build macos --debugsucceeds.build_site.sh,validate_links.shandnpm testpass.Matrix Evidence
example/laya_tetrisLAYA_MODEL_DIRbin/bench.dartturn-based and real-timeSpeed of one six-option question (175 tokens), over three back-to-back runs at this head:
Turn-based games on Metal, mean of 5 seeds, capped at 150 pieces (base-head rows reproduce exactly at this head):
Over 40 seeds per mode, the tuned player cleared 70.8 lines (3 best + 3 random) and 73.6 (all legal moves) turn-based up to 500 pieces, and 52.3 and 51.5 in real time, where every answer arrived before its piece locked. The 8-epoch head's figures on the same seeds (60.9, 55.2, 49.7, 48.6) are in #619. The earlier six-game real-time deficit for this head did not reproduce.
Review Notes
39d66edce546b12bc5c21fd67c05aac3eec883c0onmain8f6651f35: running. It adds only the 40-game results for the tuned player to the website page;8229f68a4passed 23 checks with 5 skipped.High-risk regression review
classify_high_risk_changes.dartover this PR's 119 paths)