semif-api-rocm

SemIf HTTP API and rocm flake
Log | Files | Refs | README | LICENSE

index.html (19479B)


      1 <!DOCTYPE html>
      2 <html lang="en">
      3 <head>
      4 <meta charset="utf-8">
      5 <meta name="viewport" content="width=device-width, initial-scale=1">
      6 <title>semif-api — decision readout</title>
      7 <link rel="stylesheet" href="style.css">
      8 </head>
      9 <body>
     10 
     11 <header>
     12   <div class="brand">
     13     <h1>semif-api</h1>
     14     <p class="tagline">semantic decision readout — native option-slot logits, not generated text</p>
     15   </div>
     16   <div id="health" class="health" aria-live="polite">
     17     <span class="dot" id="health-dot"></span>
     18     <span id="health-text">checking…</span>
     19     <button type="button" id="health-refresh" class="ghost" title="Re-check /healthz">↻</button>
     20     <select id="model-picker" class="model-picker" hidden aria-label="model selector"
     21             title="Served models — switching unloads the current model and loads the new one on the next request"></select>
     22     <span id="model-note" class="model-note" role="status"></span>
     23   </div>
     24 </header>
     25 
     26 <nav class="tabs" role="tablist">
     27   <button type="button" class="tab is-active" id="tab-single" role="tab" aria-selected="true"
     28           aria-controls="panel-single">Single decision <code>/decide</code></button>
     29   <button type="button" class="tab" id="tab-batch" role="tab" aria-selected="false"
     30           aria-controls="panel-batch">Shared state <code>/decide-batch</code></button>
     31   <button type="button" class="tab" id="tab-game" role="tab" aria-selected="false"
     32           aria-controls="panel-game">Platformer demo</button>
     33   <button type="button" class="tab" id="tab-self" role="tab" aria-selected="false"
     34           aria-controls="panel-self">Platformer SL</button>
     35   <button type="button" class="tab" id="tab-room" role="tab" aria-selected="false"
     36           aria-controls="panel-room">Puzzle room</button>
     37   <button type="button" class="tab" id="tab-roomself" role="tab" aria-selected="false"
     38           aria-controls="panel-roomself">Puzzle room SL</button>
     39 </nav>
     40 
     41 <main>
     42   <!-- ── request ────────────────────────────────────────────────── -->
     43   <section class="col" id="request">
     44 
     45     <form id="panel-single" class="panel" novalidate>
     46       <div class="field">
     47         <label for="s-id">id</label>
     48         <input id="s-id" class="mono" value="adhoc" autocomplete="off" spellcheck="false">
     49       </div>
     50 
     51       <div class="field">
     52         <div class="field-head">
     53           <label for="s-state">state <span class="hint">the evidence</span></label>
     54           <span class="state-mode">
     55             <input type="radio" name="s-state-mode" id="s-state-text" value="text" checked>
     56             <label for="s-state-text">text</label>
     57             <input type="radio" name="s-state-mode" id="s-state-json" value="json">
     58             <label for="s-state-json">JSON</label>
     59           </span>
     60         </div>
     61         <textarea id="s-state" rows="7" spellcheck="false"
     62                   placeholder="Evidence the model must decide from — prose, or a JSON object/array in JSON mode."></textarea>
     63         <p class="note" id="s-state-note"></p>
     64       </div>
     65 
     66       <div class="field">
     67         <label for="s-question">question <span class="hint">the criterion applied to the evidence</span></label>
     68         <input id="s-question" autocomplete="off" placeholder="Does this evidence support…?">
     69       </div>
     70 
     71       <div class="field">
     72         <div class="field-head">
     73           <label>options <span class="hint">2–16, ids must be unique</span></label>
     74           <button type="button" class="ghost add-option">+ option</button>
     75         </div>
     76         <div class="options" id="s-options"></div>
     77       </div>
     78 
     79       <div class="actions">
     80         <button type="submit" class="primary" id="s-submit">Decide</button>
     81         <button type="button" id="s-curl">Copy as curl</button>
     82         <button type="button" id="s-clear">Clear</button>
     83       </div>
     84     </form>
     85 
     86     <form id="panel-batch" class="panel" novalidate hidden>
     87       <p class="constraint">
     88         Every decision below is scored against the same evidence. Torch shares a prefill;
     89         the llama backend scores sequentially and lets the server reuse cached prefixes.
     90       </p>
     91 
     92       <div class="field">
     93         <div class="field-head">
     94           <label for="b-state">shared state</label>
     95           <span class="state-mode">
     96             <input type="radio" name="b-state-mode" id="b-state-text" value="text" checked>
     97             <label for="b-state-text">text</label>
     98             <input type="radio" name="b-state-mode" id="b-state-json" value="json">
     99             <label for="b-state-json">JSON</label>
    100           </span>
    101         </div>
    102         <textarea id="b-state" rows="7" spellcheck="false"></textarea>
    103         <p class="note" id="b-state-note"></p>
    104       </div>
    105 
    106       <div class="field">
    107         <div class="field-head">
    108           <label>decisions <span class="hint">ids must be unique across the batch</span></label>
    109           <button type="button" class="ghost" id="b-add-decision">+ decision</button>
    110         </div>
    111         <div id="b-decisions"></div>
    112       </div>
    113 
    114       <div class="actions">
    115         <button type="submit" class="primary" id="b-submit">Run batch</button>
    116         <button type="button" id="b-curl">Copy as curl</button>
    117         <button type="button" id="b-clear">Clear</button>
    118       </div>
    119     </form>
    120 
    121     <div class="presets">
    122       <span class="presets-label">Load example</span>
    123       <div id="preset-buttons"></div>
    124     </div>
    125   </section>
    126 
    127   <!-- ── response ───────────────────────────────────────────────── -->
    128   <section class="col" id="response">
    129     <div id="idle" class="placeholder">
    130       <p>No request sent yet.</p>
    131       <p class="dim">Probabilities are <em>conditional option scores</em>: use them to rank options and
    132       set coarse thresholds, never as calibrated confidence.</p>
    133     </div>
    134     <div id="pending" class="placeholder" hidden>
    135       <p class="spinner" aria-hidden="true">◌</p>
    136       <p id="pending-text">scoring…</p>
    137       <p class="dim">GPU work serializes on a per-request lock — concurrent requests queue, they do not
    138       speed each other up.</p>
    139     </div>
    140     <div id="error" class="error" hidden role="alert"></div>
    141     <div id="result" hidden></div>
    142   </section>
    143 
    144   <!-- ── platformer demo (third tab; see game.js + game-rules.js) ────── -->
    145   <section id="panel-game" class="demo-panel" role="tabpanel" aria-labelledby="tab-game" hidden>
    146     <div class="game-stage">
    147       <h2 id="level-label">Level</h2>
    148       <canvas id="cv" width="960" height="200"></canvas>
    149       <div class="controls">
    150         <button type="button" id="btn-start" class="primary">▶ Let SemIf play</button>
    151         <button type="button" id="btn-reset">↺ Reset</button>
    152         <button type="button" id="btn-randomize" title="Shuffle pit positions to a new random seed">⚄ Randomize</button>
    153         <label class="seed" title="Level seed — type one and press Enter to reproduce that exact layout">seed<input type="text" id="seed" class="seed-input" inputmode="numeric" autocomplete="off" spellcheck="false" placeholder="default"></label>
    154         <div class="seg" role="group" aria-label="state text mode" title="Guided injects a hint about the right move; Unguided gives only the prose facts; Run-length encodes the terrain as run-length segments (-N floor, #N pit) the model must parse; ASCII replaces the readout with a single symbolic row (- floor, # pit, * you, ! flag). Hardest last. Applies from the next decision.">
    155           <button type="button" id="mode-guided" class="on">Guided</button><button type="button" id="mode-unguided">Unguided</button><button type="button" id="mode-runlength">Run-length</button><button type="button" id="mode-ascii">ASCII</button>
    156         </div>
    157         <span class="status" id="status">idle — press Start</span>
    158       </div>
    159       <p class="game-hint">Manual drive (when idle): <code>→</code>/<code>D</code> run right, <code>space</code>/<code>W</code> jump.
    160         Physics pauses while a decision is pending. In <b>Guided</b> mode the state text includes a hint about the right move;
    161         in <b>Unguided</b> mode only the facts are given and the model has to decide on its own;
    162         in <b>Run-length</b> mode the terrain is a compact run-length encoding
    163         (<code>-N</code> floor, <code>#N</code> pit) the model must parse;
    164         in <b>ASCII</b> mode the facts are a single symbolic row (<code>-</code> floor, <code>#</code> pit, <code>*</code> you, <code>!</code> flag)
    165         the model must decode — the hardest of the four.<br>
    166         <b>⚄ Randomize</b> moves the three pits to new (always-solvable) positions; the seed box shows the seed so a
    167         layout can be reproduced — type a seed and press Enter.</p>
    168     </div>
    169     <aside class="game-side">
    170       <h2>State text — rendered from, and sent verbatim to, /decide</h2>
    171       <pre id="state-view"></pre>
    172       <h2>Decision log</h2>
    173       <div id="log" class="log"></div>
    174     </aside>
    175   </section>
    176   <!-- ── no-rules platformer (fourth tab; see self-game.js + self-rules.js) ── -->
    177   <section id="panel-self" class="demo-panel" role="tabpanel" aria-labelledby="tab-self" hidden>
    178     <div class="game-stage">
    179       <h2 id="self-level-label">Level</h2>
    180       <canvas id="self-cv" width="960" height="200"></canvas>
    181       <div class="controls">
    182         <button type="button" id="self-start" class="primary">▶ Let SemIf play</button>
    183         <button type="button" id="self-reset">↺ Reset</button>
    184         <button type="button" id="self-forget" title="Discard the learned rules and the action transcript">✕ Forget rules</button>
    185         <button type="button" id="self-randomize" title="Shuffle pit positions to a new random seed">⚄ Randomize</button>
    186         <label class="seed" title="Level seed — type one and press Enter to reproduce that exact layout">seed<input type="text" id="self-seed" class="seed-input" inputmode="numeric" autocomplete="off" spellcheck="false" placeholder="default"></label>
    187         <div class="seg" role="group" aria-label="bare state text mode" title="All three modes send the same neutral observation with no rules: Prose lists the terrain ahead as counts, Run-length encodes it as segments (-N ground, #N hole), ASCII as one symbolic row (- ground, # hole, * you, ! flag). The model must learn how to play from /plan. Applies from the next decision.">
    188           <button type="button" id="self-mode-prose" class="on">Prose</button><button type="button" id="self-mode-runlength">Run-length</button><button type="button" id="self-mode-ascii">ASCII</button>
    189         </div>
    190         <span class="status" id="self-status">idle — press Start</span>
    191       </div>
    192       <p class="game-hint">Same physics as the Platformer demo, but the decision model is given <b>no rules</b> — only a
    193         neutral observation of the level and the actions <code>run</code> / <code>jump</code>, plus an
    194         <code>insufficient</code> escape hatch. When it picks <code>insufficient</code> with p ≥ 0.99, or the player
    195         falls into a pit, or it keeps requesting jumps with none left, the client calls <code>/plan</code>: a reasoning
    196         chat completion that reviews the transcript of completed actions and writes a set of rules. The rules then lead
    197         every later observation — that is the only way the model learns how to play. Every trigger restarts the level
    198         with the learned rules: the planner writes full game rules, not a fix for one stuck spot, so the model gets a
    199         fresh attempt to apply them from the start. Reset restarts the level and keeps the learned rules;
    200         ✕ Forget rules clears them. Manual drive (when idle): <code>→</code>/<code>D</code> run right,
    201         <code>space</code>/<code>W</code> jump.</p>
    202     </div>
    203     <aside class="game-side">
    204       <h2>State text — rendered from, and sent verbatim to, /decide</h2>
    205       <pre id="self-state-view"></pre>
    206       <h2>Rules learned from /plan (editable)</h2>
    207       <textarea id="self-rules-view" class="rules-edit" rows="7" spellcheck="false"
    208         placeholder="(none yet — rules learned from /plan appear here; edit or paste to set them by hand)"></textarea>
    209       <h2>Run stats</h2>
    210       <pre id="self-stats">(run not started)</pre>
    211       <h2>Decision log</h2>
    212       <div id="self-log" class="log"></div>
    213     </aside>
    214   </section>
    215   <!-- ── puzzle room demo (fifth tab; see room.js + room-rules.js) ──── -->  <section id="panel-room" class="demo-panel" role="tabpanel" aria-labelledby="tab-room" hidden>
    216     <div class="game-stage">
    217       <h2 id="room-label">Room</h2>
    218       <canvas id="room-cv" width="960" height="420"></canvas>
    219       <div class="controls">
    220         <button type="button" id="room-start" class="primary">▶ Let SemIf solve</button>
    221         <button type="button" id="room-reset">↺ Reset</button>
    222         <button type="button" id="room-randomize" title="New random room; the seed box shows it so the layout can be reproduced">⚄ Randomize</button>
    223         <label class="seed" title="Room seed — type one and press Enter to reproduce that exact layout">seed<input type="text" id="room-seed" class="seed-input" inputmode="numeric" autocomplete="off" spellcheck="false" placeholder="default"></label>
    224         <div class="seg" role="group" aria-label="room state text mode" title="Guided FPP describes your view plus a compass hint toward the current objective; FPP gives only what you see and remember; Map hands the model the whole top-down layout. Applies from the next decision.">
    225           <button type="button" id="room-mode-guided" class="on">Guided FPP</button><button type="button" id="room-mode-fpp">FPP</button><button type="button" id="room-mode-map">Map</button>
    226         </div>
    227         <span class="status" id="room-status">idle — press Start</span>
    228       </div>
    229       <p class="game-hint">Manual drive (when idle): <code>←</code>/<code>A</code> turn left, <code>→</code>/<code>D</code> turn right, <code>↑</code>/<code>W</code> step forward.
    230         The first-person view is yours — the model only ever sees the text in the side pane: the four adjacent cells and what is in view,
    231         so it must build its own map by dead-reckoning. It must find the key, unlock the door in the dividing wall, and reach the exit,
    232         one action per decision, within the step budget. In <b>Guided FPP</b> the state includes a compass hint toward the key/door/exit;
    233         in <b>FPP</b> only what you see and what happened; in <b>Map</b> it gets the whole layout.
    234         <b>⚄ Randomize</b> builds a new (always-solvable) room; the seed box reproduces it — type a seed and press Enter.</p>
    235     </div>
    236     <aside class="game-side">
    237       <h2>State text — rendered from, and sent verbatim to, /decide</h2>
    238       <pre id="room-state-view"></pre>
    239       <h2>Decision log</h2>
    240       <div id="room-log" class="log"></div>
    241     </aside>
    242   </section>
    243   <!-- ── self-learning puzzle room (sixth tab; see room-self-game.js + room-self-rules.js) ── -->
    244   <section id="panel-roomself" class="demo-panel" role="tabpanel" aria-labelledby="tab-roomself" hidden>
    245     <div class="game-stage">
    246       <h2 id="rs-label">Room</h2>
    247       <canvas id="rs-cv" width="960" height="420"></canvas>
    248       <div class="controls">
    249         <button type="button" id="rs-start" class="primary">▶ Let SemIf play</button>
    250         <button type="button" id="rs-reset">↺ Reset</button>
    251         <button type="button" id="rs-forget" title="Discard the learned rules and the action transcript">✕ Forget rules</button>
    252         <button type="button" id="rs-randomize" title="New random room; the seed box shows it so the layout can be reproduced">⚄ Randomize</button>
    253         <label class="seed" title="Room seed — type one and press Enter to reproduce that exact layout">seed<input type="text" id="rs-seed" class="seed-input" inputmode="numeric" autocomplete="off" spellcheck="false" placeholder="default"></label>
    254         <div class="seg" role="group" aria-label="bare room state text mode" title="Both modes send the same neutral observation with no rules: FPP describes all four adjacent cells (open floor included), whatever your 120° view cone currently sees, and bearings back to any landmark it has discovered (key, locked door, exit) that is out of sight — bearings only, no guidance, and a bearing whose straight line is walled reads "(blocked)" — plus your carry status and step count; Map hands over the whole top-down layout with a neutral symbol legend. There is deliberately no event log: a list of the actor's own recent actions is imitation bait for a single-pass reader, not a memory. The model must learn what to do from /plan. Applies from the next decision.">
    255           <button type="button" id="rs-mode-fpp" class="on">FPP</button><button type="button" id="rs-mode-map">Map</button>
    256         </div>
    257         <span class="status" id="rs-status">idle — press Start</span>
    258       </div>
    259       <p class="game-hint">Same room as the Puzzle room demo, but the decision model is given <b>no rules</b> — only a neutral
    260         observation (all four adjacent cells, in-view bearings, carry status and a step count — or the whole top-down map)
    261         and the actions <code>forward</code> / <code>left</code> / <code>right</code>, plus an <code>insufficient</code>
    262         escape hatch. When <code>insufficient</code> is its leading option at all, or the step budget runs out, the client
    263         calls <code>/plan</code>: a reasoning chat completion that reviews the transcript of completed actions and writes a
    264         set of rules. The rules then lead every later observation — that is the only way the model learns how to play.
    265         Either trigger restarts the room with the learned rules: the planner writes full game rules, not a fix for one
    266         stuck spot, so the model gets a fresh attempt to apply them from the start.
    267         Reset restarts the room and keeps the learned rules; ✕ Forget rules clears them. Manual drive (when idle):
    268         <code>←</code>/<code>A</code> turn left, <code>→</code>/<code>D</code> turn right, <code>↑</code>/<code>W</code> step forward.</p>
    269     </div>
    270     <aside class="game-side">
    271       <h2>State text — rendered from, and sent verbatim to, /decide</h2>
    272       <pre id="rs-state-view"></pre>
    273       <h2>Rules learned from /plan (editable)</h2>
    274       <textarea id="rs-rules-view" class="rules-edit" rows="7" spellcheck="false"
    275         placeholder="(none yet — rules learned from /plan appear here; edit or paste to set them by hand)"></textarea>
    276       <h2>Run stats</h2>
    277       <pre id="rs-stats">(run not started)</pre>
    278       <h2>Decision log</h2>
    279       <div id="rs-log" class="log"></div>
    280     </aside>
    281   </section>
    282 </main>
    283 
    284 <footer>
    285   <p>Readout reads logits at the declared answer slots; there is no decoding loop and no output tokens.
    286   Prompts over <code id="foot-max-tokens">max_tokens</code> are rejected, never silently truncated.</p>
    287 </footer>
    288 
    289 <script src="game-rules.js"></script>
    290 <script src="game.js"></script>
    291 <script src="planner.js"></script>
    292 <script src="self-rules.js"></script>
    293 <script src="self-game.js"></script>
    294 <script src="room-rules.js"></script>
    295 <script src="room.js"></script>
    296 <script src="room-self-rules.js"></script>
    297 <script src="room-self-game.js"></script>
    298 <script src="app.js"></script>
    299 </body>
    300 </html>