Developer Guide

1. Purpose

This guide explains how the current StableSteering prototype is organized, how to run it locally, and how to extend it safely.

It is intended for developers who want to:

For a student-oriented conceptual walkthrough, start with student_tutorial.md.

2. Current Implementation Scope

The current implementation is a minimal research MVP with:

It does not yet include:

3. Project Structure

Key directories:

4. Local Development Setup

Install the project with development dependencies:

python -m pip install -e .[dev]

Install inference dependencies for the real Diffusers backend:

python -m pip install -e .[dev,inference]

Run the local server:

python scripts/run_dev.py

To prefer the real Diffusers backend after preparing model assets:

set STABLE_STEERING_GENERATION_BACKEND=diffusers
python scripts/run_dev.py

The real Diffusers path is GPU-only and explicitly targets cuda. The default server runtime now requires that path and should fail fast when a CUDA-capable GPU is not available.

Run the standalone real-model smoke test:

python scripts/smoke_real_diffusers.py

Generate the full example walkthrough bundle:

python scripts/create_real_e2e_example.py

Open:

http://127.0.0.1:8000

Run the tests:

python -m pytest

Run browser tests:

npm install
npm run test:e2e:chrome

Run a headed single-worker debug session in Chrome:

npm run test:e2e:debug

Prepare Hugging Face assets:

python scripts/setup_huggingface.py

Inspect persisted trace files:

data/traces/

Per-session run bundles live under:

data/traces/sessions/<session_id>/

That bundle includes:

5. Runtime Flow

The current runtime flow is:

  1. create an experiment
  2. create a session from that experiment
  3. request the next round
  4. sampler proposes candidates
  5. Diffusers renders candidate images on GPU
  6. frontend displays the candidate images
  7. frontend starts async jobs for round generation and feedback submission
  8. users see progress and status while the job runs
  9. frontend and backend trace the active flow
  10. feedback is normalized and validated against the round
  11. updater computes the next incumbent state
  12. replay export exposes the persisted trajectory
  13. the backend refreshes the saved HTML trace report for the session

Runtime architecture diagram

When a prepared local model is available and the backend is set to diffusers, the generation step uses a real Stable Diffusion pipeline, pins inference to GPU, and applies a deterministic steering offset to prompt_embeds before rendering. If the model or GPU requirements are not satisfied, startup fails.

5.1 Async API Endpoints

Long-running session actions are exposed as asynchronous job endpoints:

The async POST routes return:

The job status payload includes:

Current job states are:

5.2 Progress Behavior

The browser session view uses the async endpoints by default.

During round generation and feedback submission:

This keeps the UI responsive while the real GPU-backed backend works in the background.

Current progress phrases are intentionally operation-specific. For example:

Session lifecycle diagram

6. Core Extension Points

6.1 Add a sampler

To add a sampler:

  1. create a new module under app/samplers
  2. implement propose(session, seed) -> list[Candidate]
  3. register the sampler in orchestrator.py
  4. add tests for deterministic behavior and output shape

6.2 Add an updater

To add an updater:

  1. create a new module under app/updaters
  2. implement update(session, candidates, feedback) -> (next_z, summary)
  3. register the updater in orchestrator.py
  4. add tests for update behavior and edge cases

6.3 Evolve generation

To evolve the generation backend further:

  1. keep the same high-level contract as MockGenerationEngine
  2. preserve deterministic testability by keeping the mock path available only in tests
  3. avoid letting generation concerns leak into API routes
  4. keep artifact paths stable enough for replay

Before running or extending the real generator, stage a compatible model snapshot locally with:

python scripts/setup_huggingface.py --model-id runwayml/stable-diffusion-v1-5 --output-root models

The setup script downloads the expected diffusers module directories and writes a local manifest so the prepared snapshot is easier to inspect and reuse.

The runtime contract is:

The current browser test contract is:

The current API quality contract is:

The current feedback-mode contract is:

The current seed policy contract is:

The current roadmap also includes expanding steering support beyond prompt-only generation into:

6.4 Evolve persistence

To move from SQLite to PostgreSQL or another shared store:

  1. keep repository method names stable
  2. preserve session and round ordering
  3. preserve replay export shape
  4. add migration-safe tests before swapping implementations

7. Coding Conventions for This Project

8. Testing Expectations

Before merging meaningful behavior changes:

9. Common Development Tasks

Start fresh local data

Delete the local data directory if you want a clean environment:

data/

Inspect persisted state

Look in:

data/stablesteering.db
data/artifacts/
data/traces/

Open the readable report for one session:

/sessions/{session_id}/trace-report

Validate the browser flow

Minimal manual smoke test:

  1. open /setup
  2. create an experiment
  3. open the session page
  4. generate a round
  5. submit ratings
  6. open replay