Commit Graph
3 Commits
Author SHA1 Message Date
DejvinoandClaude 82ab88e6b0 LLM: fix strict schema 400 — correct providerOptions + chat model
Previous attempt set `strictJsonSchema:false` on createOpenAI()
(factory ignores unknown keys), so wire was still strict:true and
sparse edits {brightness:0.3} were rejected: Missing 'arrangement'.

- src/llm/llmTweak.js: use provider.chat(modelId) (/chat/completions,
  correct for Meta via gateway, not /responses) and pass
  `providerOptions:{ openai:{ strictJsonSchema:false } }` on
  generateObject where the SDK actually reads it.
- src/llm/spec.js: edits fields nullable instead of optional — strict
  requires every key in `required` when `additionalProperties:false`;
  nullable makes required = all 7 (model emits null for unchanged),
  clampEdits already strips nulls so NO_EDITS still works. Prompt now
  instructs "use null for unchanged, example { bpm:null,... }".
- test/llm.test.js: minimal valid result now all-null with one edit.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-13 20:48:14 +02:00
DejvinoandClaude b7c3537fcb LLM song-tweak: AI Gateway via Vercel AI SDK, budgeted tune flow
Add a ✨ tune button that lets an LLM inspect the proposed
visualization and tweak the proc-song knobs so the next generation
looks better. Edits only the 7 songbank params (bpm, brightness,
noise, noiseColour, dynamics, transition, arrangement) — never the
Look — then re-synthesizes and re-generates locally for preview.

- ai + @ai-sdk/openai + zod (library per plan) against the Vercel AI
  Gateway (OpenAI-compatible, configurable via
  VITE_AI_GATEWAY_URL/MODEL/API_KEY, localStorage override,
  .env.example).
- Structured output (TweakResultSchema) + clampEdits enforces ranges;
  prompt ≤ ~2.5k tokens, max 2-3 knobs ±0.15 / bpm ±8.
- Budget caps: 3/load + 10/session (sessionStorage), checked before
  network, NO_EDITS refunded, offline/auth/rate-limit mapped.
- Prompt split into src/llm/spec.js (pure, node-testable) + llmTweak.js
  (gateway + digest) to keep `node --test` off the Vite JSON path.
- UI: ⚙️ gateway/model/key dialog (localStorage flow-state:llm),
  confirm(prompt) with hint, diff modal with Apply/Dismiss; Apply
  synthesizes → FeatureTrack → generateLook → Show.useTrack.
- Tests: 7 new LLM cases (clamp, schema, prompt, budget), 18/18 pass.
  Build + lint:scenes green.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-13 20:03:27 +02:00
DejvinoandClaude Opus 5 cb320557e6 Phase 1: offline audio pipeline
Whole-track analysis into a frame-indexed FeatureTrack. Nothing reads a
live AnalyserNode: realtime preview maps currentTime to a frame index,
export counts frames, both read the same rows.

- fft.js: radix-2 with precomputed tables, allocated once per track
- analyze.js: STFT at hop 1/60s with CENTRED windows (a window that starts
  at the timestamp reports energy arriving up to 23ms later, which reads as
  visuals lagging the music). Energy features normalised against the track's
  own percentiles; absolute stats kept in summary for the look generator.
- tempo.js: autocorrelation + grid F-measure, beat grid, downbeats
- segment.js: self-similarity novelty, boundaries snapped to the bar grid
- FeatureTrack: assembles everything, plus the lookahead fields. buildSlope
  rises through the bars leading into a higher-energy section, so a build can
  ramp into the drop rather than react after it lands.
- clicktrack.js: mixes clicks onto the detected grid for validation by ear

Three real bugs found and fixed by the tests:
- 174 BPM read as 87. Mean-energy-per-beat scores a half-tempo grid
  identically to the true one; only an F-measure penalises the missed
  onsets via recall.
- 90 BPM read as 180. Offbeat hi-hats make a double-tempo grid score
  perfectly on both precision and recall, so the grid is now interpreted
  metrically afterwards: a systematic strong/weak alternation means the
  real beat is every other grid point.
- Beat grid drifted ~30ms over 30s from integer-frame offsets. Onset peaks
  are now parabolically interpolated and the grid least-squares fitted.

Gates: 11/11 node tests against synthetic ground truth (tempo within 2%
across 90-174 BPM, beat alignment under half a frame, segmentation within
2s of a known boundary, graceful on silence, 6-minute analysis in 1.0s);
5/5 browser checks including audio-driven vs fixed-step frame parity.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 11:10:01 +02:00