Background
genie-ai-runtime is explicitly the long-term replacement for llama-server in this stack:
- README.md L85 — "
genie-ai-runtime: Jetson-only C++ LLM runtime customized from llama.cpp"
- ARCHITECTURE.md L70 — "llama.cpp fork, CUDA kernels, model memory planner:
genie-ai-runtime"
- ARCHITECTURE.md L81 — "
llama.cpp OpenAI-compatible client → genie-ai-runtime client"
The runtime already ships a drop-in jetson-llm-server binary with the same /v1/chat/completions shape that LlmClient (crates/genie-core/src/llm/client.rs:6) speaks. Per the runtime's own README, it is positioned as "drop-in replacement target for llama-server" with API shape "closely enough" to allow GenieClaw to swap backends via configuration.
Performance — reported on identical Jetson Orin Nano Super hardware:
| Metric |
llama.cpp |
genie-ai-runtime alpha.8 |
| Prefill |
17.97 tok/s |
38.68 tok/s (+115%) |
| Time-to-first-token |
baseline |
−61% vs runtime's own alpha.2 |
This is the parity-flip ticket.
Dependency
Blocked by #32 (LLM backend abstraction). When #32 lands, default backend selection becomes a single TOML key, and this issue is the one that flips that key.
Concrete proposal
When #32 lands:
- Change the default value of
[services.llm].backend from \"llama_cpp\" to \"genie_ai_runtime\" in deploy/config/geniepod.toml.
- Pin the runtime version: target release
v0.1.0-alpha.8 (or latest at flip time).
- Default model:
Qwen3-4B-Q4_K_M.gguf (the runtime's validated model).
- Hardware target unchanged — Jetson Orin Nano Super 8 GB. The runtime explicitly does not support x86, discrete GPUs, Windows, or macOS. Dev-machine builds must continue to default to
llama_cpp.
Parity gate — verify, don't trust
The runtime's drop-in claim is "closely enough". We should validate before flipping default. Acceptance gate:
New systemd unit
deploy/systemd/genie-ai-runtime.service, modeled on the existing genie-llm.service:
[Unit]
Description=GeniePod AI Runtime (Jetson-tuned LLM)
Documentation=https://github.com/GeniePod/genie-ai-runtime
After=network.target
ConditionPathExists=/opt/geniepod/bin/jetson-llm-server
[Service]
Type=simple
ExecStartPre=/bin/sh -c 'sync && echo 3 > /proc/sys/vm/drop_caches'
ExecStart=/opt/geniepod/bin/jetson-llm-server \\
-m \${GENIEPOD_LLM_MODEL} \\
-p 8080
Environment=GENIEPOD_LLM_MODEL=/opt/geniepod/models/qwen3-4b-q4_k_m.gguf
Restart=on-failure
RestartSec=5
TimeoutStartSec=120
ProtectSystem=no
SupplementaryGroups=video render
[Install]
WantedBy=geniepod.target
Plus a matching genie-ai-runtime-warmup.service mirroring genie-llm-warmup.service (one-shot, sends a tiny prompt to force model load + CUDA kernel compile into iGPU before the first user-visible voice cycle).
Deploy pipeline changes
make deploy drops jetson-llm-server and jetson-llm binaries into /opt/geniepod/bin/ (cross-compiled from genie-ai-runtime source, or fetched from the upstream v0.1.0-alpha.8 release artifact).
setup-jetson.sh downloads the validated qwen3-4b-q4_k_m.gguf to /opt/geniepod/models/ if not present (alongside the existing Whisper model fetch).
- Two new systemd units (
genie-ai-runtime.service, genie-ai-runtime-warmup.service) ship in deploy/systemd/.
- The legacy
genie-llm.service and genie-llm-warmup.service remain in the repo; they are not removed, just no longer the default.
Rollback story
Because backend selection is a single TOML key after #32, regression rollback is a one-line revert:
[services.llm]
backend = \"llama_cpp\" # rollback if genie-ai-runtime regresses
No binary rebuild, no schema migration, no data loss. This is the right shape for a parity flip.
Why this is worth doing
- README.md and ARCHITECTURE.md already commit to this direction; the flip is the natural alpha.8 milestone.
- +115% prefill / −61% TTFT on the same hardware gives us either tighter voice-cycle latency or headroom for a larger model in the same memory budget.
- Once
genie-ai-runtime is the default and llama.cpp is optional, every other subsystem (governor pressure modes, warmup, health, mode-swap) can be reasoned about against one canonical runtime.
Acceptance criteria
Related
Background
genie-ai-runtimeis explicitly the long-term replacement forllama-serverin this stack:genie-ai-runtime: Jetson-only C++ LLM runtime customized fromllama.cpp"genie-ai-runtime"llama.cppOpenAI-compatible client →genie-ai-runtimeclient"The runtime already ships a drop-in
jetson-llm-serverbinary with the same/v1/chat/completionsshape thatLlmClient(crates/genie-core/src/llm/client.rs:6) speaks. Per the runtime's own README, it is positioned as "drop-in replacement target forllama-server" with API shape "closely enough" to allow GenieClaw to swap backends via configuration.Performance — reported on identical Jetson Orin Nano Super hardware:
This is the parity-flip ticket.
Dependency
Blocked by #32 (LLM backend abstraction). When #32 lands, default backend selection becomes a single TOML key, and this issue is the one that flips that key.
Concrete proposal
When #32 lands:
[services.llm].backendfrom\"llama_cpp\"to\"genie_ai_runtime\"indeploy/config/geniepod.toml.v0.1.0-alpha.8(or latest at flip time).Qwen3-4B-Q4_K_M.gguf(the runtime's validated model).llama_cpp.Parity gate — verify, don't trust
The runtime's drop-in claim is "closely enough". We should validate before flipping default. Acceptance gate:
chatandchat_streamresponses for a fixed prompt set (10 prompts × 3 temperatures), comparing token-by-token streaming and final string equality.data:framing, same[DONE]terminator, same delta structure as parsed inclient.rschat_stream.llama_error_message()(client.rs:419). If field names differ, normalize them in the new client.genie-ai-runtimebackend, measuring p50 / p95 first-audio latency vsllama.cppbaseline. Expect ≥30% improvement on first-audio based on the +115% prefill claim.genie-ai-runtime+whisper-server+piper-tts+genie-corefits in 8 GB on Orin Nano. The runtime's own README cites a 7.6 GB iGPU budget; verify withtegrastatsunder load.health()path thatgenie-health.servicepolls.night_model_swap,stop_optins_mb, and mode-swap paths ingenie-governorwork identically against the new backend.New systemd unit
deploy/systemd/genie-ai-runtime.service, modeled on the existinggenie-llm.service:Plus a matching
genie-ai-runtime-warmup.servicemirroringgenie-llm-warmup.service(one-shot, sends a tiny prompt to force model load + CUDA kernel compile into iGPU before the first user-visible voice cycle).Deploy pipeline changes
make deploydropsjetson-llm-serverandjetson-llmbinaries into/opt/geniepod/bin/(cross-compiled fromgenie-ai-runtimesource, or fetched from the upstreamv0.1.0-alpha.8release artifact).setup-jetson.shdownloads the validatedqwen3-4b-q4_k_m.ggufto/opt/geniepod/models/if not present (alongside the existing Whisper model fetch).genie-ai-runtime.service,genie-ai-runtime-warmup.service) ship indeploy/systemd/.genie-llm.serviceandgenie-llm-warmup.serviceremain in the repo; they are not removed, just no longer the default.Rollback story
Because backend selection is a single TOML key after #32, regression rollback is a one-line revert:
No binary rebuild, no schema migration, no data loss. This is the right shape for a parity flip.
Why this is worth doing
genie-ai-runtimeis the default andllama.cppis optional, every other subsystem (governor pressure modes, warmup, health, mode-swap) can be reasoned about against one canonical runtime.Acceptance criteria
deploy/config/geniepod.tomlisbackend = \"genie_ai_runtime\"geniepod.dev.tomlremainsbackend = \"llama_cpp\"(x86 / mac dev machines)setup-jetson.shprovisions the runtime binaries and the validated modelRelated