Focus project on JAX PPO

This commit is contained in:
2026-07-14 20:09:03 +09:00
parent 79273f7eb3
commit ef4b9d82b0
44 changed files with 302 additions and 503 deletions
+29 -10
View File
@@ -1,11 +1,38 @@
# COOLRL Lost Cities Web
Browser-only Lost Cities client. The rules engine, observation builder, and PPO
inference all run on the device. There is no application server.
inference all run on the device; there is no application server.
The verified final JAX PPO policy is committed at
`public/models/jax-ppo.onnx` (3.1 MB). Vite copies it to the static build, and
the app resolves the asset relative to the deployed site so it works on GitHub
Pages, GitLab Pages, or a normal web root. Its size and SHA-256 are recorded in
[`public/models/jax-ppo.json`](public/models/jax-ppo.json).
Pushes to `main` build and publish the client through the repository's GitHub
Pages and GitLab Pages workflows. Each workflow supplies the correct base URL
for its host.
## Setup
From the repository root, export an Orbax checkpoint to the browser model:
Install and run the checked-in final policy:
```bash
cd web
npm ci
npm run dev
```
Build the same static bundle used by a host:
```bash
npm run build
npm run preview
```
To replace the shipped policy, export a verified Orbax checkpoint from the
repository root. The exporter writes both the ONNX file and its public
metadata manifest:
```bash
uv run --with onnx scripts/export_jax_ppo_onnx.py \
@@ -13,14 +40,6 @@ uv run --with onnx scripts/export_jax_ppo_onnx.py \
--output web/public/models/jax-ppo.onnx
```
Then install and run the web app:
```bash
cd web
npm install
npm run dev
```
The policy tries WebGPU first and falls back to ONNX Runtime WebAssembly. If
the model asset is absent, the UI remains playable using a simple local
heuristic and reports that fallback in the header.
+14
View File
@@ -0,0 +1,14 @@
{
"format": "coolrl-lost-cities-jax-ppo-onnx-v1",
"model_file": "jax-ppo.onnx",
"model_size_bytes": 3230780,
"model_sha256": "e8241e305c01ea450e92a6178002a22db96710fa94e238bba57953743eb285b2",
"source_checkpoint": "final_candidate",
"source_config": "main_ppo_config.json",
"observation_size": 454,
"action_size": 96,
"hidden_size": 512,
"num_layers": 3,
"dtype": "float32",
"validation_max_abs_error": 9.918212890625e-05
}
Binary file not shown.
+3 -1
View File
@@ -7,6 +7,8 @@ import { cardColor, cardRank, isHandshake } from "../game/cards";
export type ExecutionProvider = "webgpu" | "wasm" | "heuristic";
const MODEL_URL = `${import.meta.env.BASE_URL}models/jax-ppo.onnx`;
export interface Policy {
readonly provider: ExecutionProvider;
action(state: GameState): Promise<number>;
@@ -66,7 +68,7 @@ class HeuristicPolicy implements Policy {
}
async function createSession(provider: "webgpu" | "wasm"): Promise<ort.InferenceSession> {
return ort.InferenceSession.create("/models/jax-ppo.onnx", {
return ort.InferenceSession.create(MODEL_URL, {
executionProviders: [provider],
graphOptimizationLevel: "all",
});