glass-box-agent / MODAL_ARCHITECTURE.md
ykirpichev's picture
Upload folder using huggingface_hub
e9b7158 verified
|
Raw
History Blame Contribute Delete
3.42 kB
# Modal Architecture
Glass-Box Agent is structured so the UI is a thin client and Modal owns the durable/compute-heavy pieces.
## Flow
```mermaid
flowchart LR
UI["Gradio UI"] --> Model["Modal model service"]
UI --> Trace["Modal trace store"]
Trace --> Dataset["RL feedback dataset"]
Dataset --> Tune["Modal RL tuning job"]
Tune --> Checkpoint["Modal checkpoint"]
Checkpoint --> Model
```
## 1. Model served by Modal
`modal_service.py` exposes `reason_next`, a Modal web function that accepts:
```json
{
"task": "User task",
"step": 3,
"memory": ["recent trace observations"],
"model_id": "checkpoint-abc123 or base model id"
}
```
The Gradio app uses this when **Reasoner** is set to `Modal served model`.
Configuration options:
```bash
export GLASS_BOX_MODAL_MODEL_URL="https://...--reason-next.modal.run"
export GLASS_BOX_MODAL_TRACE_URL="https://...--store-trace.modal.run"
export GLASS_BOX_MODAL_TUNE_URL="https://...--start-rl-tune.modal.run"
```
If URLs are not configured, the app can call deployed Modal functions by name when the Modal SDK is authenticated:
```bash
export GLASS_BOX_MODAL_APP="glass-box-agent-modal"
export GLASS_BOX_MODAL_MODEL_FUNCTION="reason_next"
export GLASS_BOX_MODAL_TRACE_FUNCTION="store_trace"
export GLASS_BOX_MODAL_TUNE_FUNCTION="start_rl_tune"
export GLASS_BOX_MODAL_TRACE_ENABLED=1
```
## 2. Traces stored by Modal
Every server-side trace mutation calls `store_trace` when Modal trace storage is configured:
- run start and streamed trace updates
- retry branch
- replay downstream
- mark/clear labels
- fork selected node
- export trace
- export RL data
- preference feedback
Client-side visual edits also post to `GLASS_BOX_MODAL_TRACE_URL` when that endpoint is configured.
Traces are written to the Modal Volume:
```text
/data/traces/<trace_id>/<timestamp>-<artifact>-<event>.json
/data/traces/<trace_id>/latest.json
```
Modal Volumes require explicit `volume.commit()` to persist writes; `modal_service.py` commits after every write.
## 3. RL feedback and tuning
The **Training signal** panel records branch preferences:
```json
{
"dpo": {
"prompt": "Task and upstream trace context",
"chosen": "Better branch continuation",
"rejected": "Weaker branch continuation"
}
}
```
`Export RL data` writes a local JSON artifact and stores the trace snapshot through Modal.
`RL tune on Modal` calls `start_rl_tune`, which stores:
```text
/data/rl-feedback/<trace_id>/<checkpoint_id>/dataset.json
/data/checkpoints/<checkpoint_id>/manifest.json
```
The current implementation creates a checkpoint manifest scaffold. The intended next step is to replace the body of `start_rl_tune` with TRL/LoRA training and write adapter weights beside `manifest.json`.
## 4. Using checkpoints
After a tuning run returns a checkpoint such as:
```text
checkpoint-a1b2c3d4e5
```
put that value in the **Small model** field and keep **Reasoner** set to `Modal served model`. `reason_next` will look for:
```text
/data/checkpoints/checkpoint-a1b2c3d4e5/manifest.json
```
and can load adapter weights from that directory once the tuning scaffold is replaced with real training.
## Deploy
```bash
modal deploy modal_service.py
```
For local development with live URLs:
```bash
modal serve modal_service.py
```
Modal web endpoints use `@modal.fastapi_endpoint(method="POST")`, and durable trace/checkpoint files use `modal.Volume`.