Minimal Pyxel frontend for a local LLM on ROCKNIX handhelds. PAI stands for Pyxel AI.
Japanese overview: README.ja.md
Build a small controller-first .pyxapp that runs on ARM handhelds such as RK3566 ROCKNIX devices. The app should provide:
- Controller-first Topic Mode backed by a tiny local LLM.
- Optional web/API lookup before answer generation.
- Controller-driven navigation.
- Software keyboard input, including Japanese kana input where practical.
- Switchable layouts for 720p 1:1 screens and 640x480 4:3 screens.
PAI itself is licensed under the MIT License. Bundled release artifacts may also include third-party components such as Qwen2.5, llama.cpp, and efont BDF fonts; see the release bundle notices for their licenses.
- Do not depend on PFE.
- Do not build a general emulator launcher.
- Do not add media library, gallery, settings-heavy, or desktop-style features.
- Do not run large LLMs or a full search stack locally on RK3566; prefer tiny quantized models, short answers, and LAN-hosted search when needed.
Initial runtime setup was verified on root@192.168.10.178.
- Device: RK3566 / aarch64
- ROCKNIX version: 20250517 official
- Kernel: Linux 6.12.17
- Python:
/usr/bin/python33.11.7 - Python user base:
/storage/.local - Pyxel: installed into
/storage/.local/lib/python3.11/site-packages - Pyxel runner:
/storage/.config/rocknix-pyxel/rocknix_pyxel_run.sh
See docs/ROCKNIX_RUNTIME_CHECK.md for the command log summary.
For the repeatable target setup procedure, including pip/Pyxel installation and
EmulationStation es_systems.cfg registration, see
docs/ROCKNIX_SETUP.md.
When PAI starts a bundled local LLM, input is locked until the health check is ready. The screen first shows that the local LLM is starting, then changes to a ready message before the user can submit prompts.
- D-pad: move the software keyboard selection.
- A: enter the selected key.
- B: delete.
- X: switch IME mode.
- Y: cycle dakuten, handakuten, or small-kana variants for the last character.
- On-screen
OK: send the prompt after the local LLM is ready. - On-screen
←/→: move the prompt edit cursor. - L2/R2: recall previous prompt history into the edit box.
- START: open SETTINGS.
- SETTINGS: change resolution, run the button mapping wizard, clear prompt history, or quit.
- SELECT: switch between the
1:1and4:3layouts. - L/R: scroll the message area.
The current software keyboard supports ASCII, hiragana, katakana, and a small set of punctuation. Kanji conversion is not implemented yet, so Japanese prompts should be entered in kana for now. For example, にほんごで じこしょうかいして, とうきょうの てんき おしえて, and ハンドヘルドのニュースをおしえて are valid test prompts.
Controller mappings are saved in /storage/.config/pai/controller_map.json on ROCKNIX, and prompt history is saved in /storage/.config/pai/prompt_history.json.
Use the Python installed on the macOS host:
/Library/Frameworks/Python.framework/Versions/3.12/bin/python3.12 app/main.pyUseful environment variables:
PAI_LAYOUT=1:1orPAI_LAYOUT=4:3PAI_SMOKE_FRAMES=30to auto-quit after a short runtime testPAI_LLM_BASE_URL=http://127.0.0.1:8080/v1PAI_LLM_MODEL=localPAI_LLM_MAX_TOKENS=80PAI_LLM_TIMEOUT=120PAI_LLAMA_N_PREDICT=80PAI_LLM_MODEL_NAME=qwen2.5-0.5b-instruct-q4_k_m.ggufPAI_WEATHER_ENABLED=1PAI_WEB_TIMEOUT=6PAI_SEARCH_URL=https://searx.example.org/searchPAI_SEARXNG_BASE_URL=https://searx.example.orgPAI_SEARCH_MAX_RESULTS=3
PAI expects an OpenAI-compatible chat endpoint such as llama.cpp llama-server at /v1/chat/completions.
See docs/LLM_BACKEND.md for backend configuration notes.
See docs/TECHNICAL_REFERENCE.md for the implementation-level prompt, runtime, packaging, and test reference.
See docs/TECHNICAL_REFERENCE.ja.md for the Japanese technical reference.
See docs/ARCHITECTURE.md for why the RK3566 build keeps the LLM local but uses LAN-hosted SearXNG for general search.
See docs/LLAMA_CPP_ROCKNIX.md for the recommended ROCKNIX llama-server setup.
See docs/WEB_LOOKUP.md for weather and search lookup notes.
See docs/SEARXNG.md for the recommended local SearXNG setup.
See docs/E2E_CHECK.md for the lookup-to-LLM verification flow.
See docs/MACOS_PROMPT_TUNING.md for fast prompt-quality checks on macOS before ROCKNIX timing checks.
See docs/GITHUB_UPLOAD.md and docs/GITHUB_UPLOAD.ja.md for GitHub upload preparation.
Package a .pyxapp:
sh scripts/package_pyxapp.shThe package is written as a split portable bundle:
dist/PAI.pyxappdist/PAI_assets/
Keep both entries in the same directory. On ROCKNIX, the final deployment target is:
/roms/pyxel/PAI.pyxapp
/roms/pyxel/PAI_assets/
This keeps the .pyxapp small because pyxel play extracts .pyxapp contents into /tmp.
The final target is that all large/runtime pieces, including the selected GGUF model, live under PAI_assets/, so users only need to place PAI.pyxapp and PAI_assets/ in /roms/pyxel.
For self-contained bundle experiments, set PAI_EXPORT_MODEL_PATH plus PAI_EXPORT_LLAMA_SERVER or PAI_EXPORT_LLAMA_DIR before running the package script. The packager will stage them under PAI_assets/models/, PAI_assets/bin/, and PAI_assets/runtime/.
See docs/PACKAGING.md for the split .pyxapp + assets packaging details.
Deploy to the ROCKNIX target:
sh scripts/deploy_rocknix.shUseful deployment options:
ROCKNIX_HOST=root@192.168.10.178PAI_INSTALL_ENV=1to installconfig/rocknix-pyxel-env.example.shas the runner env file.PAI_REMOTE_SMOKE=1to run a short target smoke test after deployment.PAI_STAGE_BUNDLED_LLM=1to stage the target's cached model andllama-serverintoPAI_assets/.
To stage bundled LLM assets without redeploying the app:
sh scripts/stage_rocknix_bundle_assets.shTo create a GitHub Release zip after dist/PAI_assets/ contains the Qwen2.5
model and ROCKNIX llama-server runtime:
sh scripts/package_release_bundle.shFor local SearXNG search:
sh scripts/searxng_local.sh up
sh scripts/searxng_local.sh check
sh scripts/searxng_local.sh urlPAI auto-detects Japanese fonts in this order:
PAI_FONT=/path/to/font.bdffor an explicit file.PAI_FONT_DIR=/path/to/efont-unicode-bdffor an efont directory.PAI_ASSET_ROOT=/path/to/PAI_assetsfor the split assets folder.PAI_assets/assets/fonts/efont-unicode-bdfnext toPAI.pyxapp.assets/fonts/efont-unicode-bdfinside the app package, for development only.~/pvnm/assets/fonts/efont-unicode-bdf./storage/pvnm/assets/fonts/efont-unicode-bdfor/roms/pvnm/assets/fonts/efont-unicode-bdfon ROCKNIX.- Pyxel bundled example fonts.
For efont BDF files, b24.bdf is preferred for the 720p 1:1 layout and b18.bdf for the 4:3 layout.
Set PAI_EXPORT_FONT_DIR=~/pvnm/assets/fonts/efont-unicode-bdf when packaging if the default font source is not available.