Skip to content

Studio: OpenFinetuner rebrand, console design system, embeddable view; Apple Silicon install fix - #15

Merged
patel-lyzr merged 6 commits into
mainfrom
fix/apple-silicon-install-and-trace-rewards
Oct 6, 2026
Merged

patel-lyzr merged 6 commits into
mainfrom
fix/apple-silicon-install-and-trace-rewards

Conversation

@patel-lyzr

Copy link
Copy Markdown
Collaborator

What

  • Apple Silicon install + trace rewards (d5a1a4d): fixes the arm64 macOS install and reads trace rewards from any span.
  • Rebrand: the studio UI is now openfinetuner (formerly ShadowLM). Only the UI changes — the shadowlm package, CLI and imports are untouched.
  • Design system: the studio adopts the opencontroller console's look — Paper & Ink tokens with light + dark themes, shadcn primitives (frontend/src/components/ui/), the floating side panel that folds to a rail, plain page headers, stat strips, tables. All seven pages ported with behavior unchanged. The red brain stays (white in dark mode); sidebar actions (HF token, Clean VRAM, Docs, GitHub) are labelled rows.
  • Embeddable view: the studio can run inside a host console over the oc-embed/1 postMessage bridge — the same one Rekori's console speaks (frontend/src/lib/embed.ts). Framed by a listed origin it drops its shell, follows the host's theme and navigation, and sends every API call to the host's proxy with a short-lived pass. serve.py sends frame-ancestors on every response (built-ins: https://dev.opencontroller.sh, localhost:*; more via SHADOWLM_FRAME_ANCESTORS). Standalone, nothing changes.

Testing

  • make test: 222 passed (incl. 4 new in tests/test_serve_embed.py); make check clean; make build + twine check pass.
  • Every page checked in Chrome in light and dark.
  • Embedding checked end-to-end against a stub host + proxy: opens the host's page, every proxied call carries the pass, host navigation/theme work, a /../etc path is rejected.

Notes

  • JS bundle grew to ~526 KB (162 KB gzip) from radix + motion; Vite warns on chunk size.
  • frontend/pnpm-lock.yaml was not regenerated (the Makefile uses npm).

patel-lyzr and others added 6 commits September 4, 2026 10:42
Two bugs, found while wiring an evaluator's scored traces into training.

`pip install shadowlm` could not resolve on an arm64 Mac at all. mlx-lm-lora
was a base dependency, every published version requires mlx_lm>=0.30.6, and
mlx-lm 0.30+ pins transformers==5.0.0rc — which the torch trainer's <4.57
ceiling cannot admit. pip reported it as an unsolvable base install rather
than as the version clash it is.

mlx-lm-lora moves to the `preference` extra, which is where the code already
said it lived: both call sites import it lazily and the ImportError already
told people to run `pip install shadowlm[preference]`. mlx-lm is capped below
0.30 so the base install stays inside the transformers window — 0.29.x is the
last line taking transformers>=4.39.3 unbounded.

The extra still cannot share an environment with the torch path, because that
conflict is upstream and real. Rather than leave that as a puzzle, the
ImportError now says so and gives the two commands that work. A base install
resolves clean on Apple Silicon: mlx-lm 0.29.1, transformers 4.56.2, torch
2.14.0, trl 0.24.0.

Second: `from_spans` read `reward_key` only from spans that parsed as a model
call, because the read sat below the `if call is None: continue`. A reward
describes the episode, not one call, so an evaluator that scores a whole trace
writes it on the root — and the root is not a model call. The reward was
dropped and the trajectory came back at 0.0, which is indistinguishable from a
genuinely bad episode. Silent, and it poisons anything downstream that filters
on min_reward or ranks a preference pair.

The read moves above the filter, and both the reward reader and the call
builder now derive the episode id through one `_trace_of` — they key the same
dict, so a second copy would break on the first span carrying
gen_ai.conversation.id.

Four tests cover it, including that conversation id and that an unparseable
reward is ignored rather than fatal. Two of them fail on the previous commit.
218 tests pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017t48BoeNVguFPXaARs8SHP
Every response sends frame-ancestors for the built-in origins (opencontroller
on studio-dev, localhost on any port) plus SHADOWLM_FRAME_ANCESTORS, and the
studio page carries the same list in a meta tag for the oc-embed/1 bridge.
lib/embed.ts is the frame side of the bridge Rekori's console speaks: on only
when framed by a listed origin, it waits for the host's pass, follows the
host's theme and navigation, and reports route and title back. api.ts sends
calls to the host's proxy with the pass when embedded, renewing it once on a
401; standalone it behaves as before.
Rename the studio to openfinetuner (formerly ShadowLM) and adopt the console's
look: its Paper & Ink tokens with light and dark themes, shadcn primitives in
components/ui, the floating side panel that folds to a rail, plain page
mastheads, hairline stat strips, tables and tinted actions. All seven pages are
ported with their behavior unchanged; embedded, the shell drops away and the
host's theme wins. The red brain stays (white on dark), the footer actions are
labelled rows, and Docs/GitHub link to the repo.
@patel-lyzr
patel-lyzr merged commit 5c12eaf into main Oct 6, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant