2026-07-21 13:14:52 -05:00
|
|
|
|
# SDG Bridge Plan
|
|
|
|
|
|
|
|
|
|
|
|
## Bridge Script Filename
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
scripts/generate_training_data.py
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
This script reads the generated dictionary artifacts from this project, optionally runs a
|
|
|
|
|
|
NeMo Data Designer expansion pass on Mimir via SSH, and writes a timestamped raw training
|
2026-07-22 09:13:54 -05:00
|
|
|
|
dataset into `/Volumes/Zoe/custom-local-llm/training-data`, then registers it in
|
|
|
|
|
|
`/Volumes/Zoe/custom-local-llm/manifest.llm.json` so local training tools can point at one
|
|
|
|
|
|
stable artifact root.
|
2026-07-21 13:14:52 -05:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## Mimir — Data Designer Status
|
|
|
|
|
|
|
|
|
|
|
|
Mimir (`100.80.52.47`) has **Data Designer 0.8.0** installed and ready:
|
|
|
|
|
|
|
|
|
|
|
|
| Component | Location | Status |
|
|
|
|
|
|
|-----------|----------|--------|
|
|
|
|
|
|
| CLI | `/home/aaron-pressey/.venvs/data-designer/bin/data-designer` | ✅ installed |
|
|
|
|
|
|
| Backend adapter | `/home/aaron-pressey/.local/share/home-grown-llm-data/nemo_data_designer_backend.py` | ✅ present |
|
|
|
|
|
|
| Storage | `/mnt/storage/data-designer/` | ✅ mounted |
|
|
|
|
|
|
| Model configs | `/mnt/storage/data-designer/model_configs.yaml` | ✅ configured |
|
|
|
|
|
|
| Config env | `/home/aaron-pressey/.config/home-grown-llm-data/data-designer.env` | ✅ present |
|
|
|
|
|
|
|
2026-07-22 09:37:40 -05:00
|
|
|
|
**Current model provider:** NVIDIA API through the `nvidia-text` alias, mapped to
|
|
|
|
|
|
`nvidia/nemotron-3-nano-30b-a3b`. Mimir now has `NVIDIA_API_KEY` in its Data Designer env file.
|
|
|
|
|
|
Use `MIMIR_SDG_MODEL_ALIAS=openrouter-text` only as a fallback. Local llama.cpp on port 8081 is
|
|
|
|
|
|
configured but not currently running.
|
2026-07-21 13:14:52 -05:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## What the Bridge Does
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
Step 1 (local — this project):
|
|
|
|
|
|
dictionary/actions.index.json ─┐
|
|
|
|
|
|
dictionary/model.codebook.json ├─► generate_training_data.py ─► seed JSONL
|
|
|
|
|
|
dictionary/model.examples.jsonl ─┘ (20 records/action, 260 total)
|
|
|
|
|
|
│
|
|
|
|
|
|
Step 2 (remote — Mimir, optional): │
|
|
|
|
|
|
SCP seed JSONL + DD config to Mimir ◄────────┘
|
2026-07-22 09:37:40 -05:00
|
|
|
|
SSH: source Data Designer env, then data-designer create module_controller.py
|
2026-07-21 13:14:52 -05:00
|
|
|
|
--num-records <N>
|
|
|
|
|
|
--dataset-name module_controller_intents_<timestamp>
|
2026-07-22 09:37:40 -05:00
|
|
|
|
--artifact-path /mnt/storage/data-designer/managed-assets/module_controller_artifacts_<timestamp>
|
|
|
|
|
|
--output-format jsonl
|
|
|
|
|
|
--no-tui
|
2026-07-21 13:14:52 -05:00
|
|
|
|
SCP expanded dataset back
|
|
|
|
|
|
│
|
2026-07-22 09:13:54 -05:00
|
|
|
|
Step 3 (local — Zoe custom-local-llm): │
|
|
|
|
|
|
Write to training-data/module_controller_intents_<timestamp>/ ◄─────┘
|
2026-07-21 13:14:52 -05:00
|
|
|
|
Patch manifest.llm.json with timestamped entry
|
2026-07-22 09:13:54 -05:00
|
|
|
|
Training tools pick it up from the Zoe artifact root
|
2026-07-21 13:14:52 -05:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## Timestamp Tagging
|
|
|
|
|
|
|
|
|
|
|
|
Every dataset generated by this script is tagged with a **Unix timestamp at generation time**.
|
|
|
|
|
|
The timestamp is embedded in:
|
|
|
|
|
|
|
2026-07-22 09:13:54 -05:00
|
|
|
|
1. **Output directory name:** `training-data/module_controller_intents_<unix_ts>/`
|
2026-07-21 13:14:52 -05:00
|
|
|
|
2. **Manifest entry key:** `"module_controller_intents_<unix_ts>"`
|
|
|
|
|
|
3. **Manifest entry field:** `"generated_at": <unix_ts>`
|
|
|
|
|
|
4. **Every JSONL record's metadata:** `"generated_at": <unix_ts>`
|
|
|
|
|
|
|
|
|
|
|
|
This means you can run the bridge multiple times (after adding actions, changing examples,
|
|
|
|
|
|
or expanding via NeMo) and the Training Monitor will show each run as a distinct, traceable
|
|
|
|
|
|
Data Source. No clobbering, no ambiguity.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## Output Record Schema
|
|
|
|
|
|
|
|
|
|
|
|
Each output record uses the `instruction` schema profile:
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"instruction": "Map the following natural language request to the correct action and payload.",
|
|
|
|
|
|
"input": "hash hello with sha256",
|
|
|
|
|
|
"output": "{\"action_id\": \"hash_string\", \"payload\": {\"text\": \"hello\", \"algorithm\": \"sha256\"}}",
|
|
|
|
|
|
"metadata": {
|
|
|
|
|
|
"action_id": "hash_string",
|
|
|
|
|
|
"compact": "{\"v\":\"1.0.0\",\"c\":\"<codebook_checksum>\",\"a\":\"A007\",\"p\":{\"F010\":\"hello\",\"F001\":\"sha256\"}}",
|
|
|
|
|
|
"source": "seed_intent_example",
|
|
|
|
|
|
"split": "train",
|
|
|
|
|
|
"generated_at": 1784660000
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## Generation Strategy
|
|
|
|
|
|
|
|
|
|
|
|
For each action in `actions.index.json`:
|
|
|
|
|
|
|
|
|
|
|
|
1. **Seed examples** — emit each `intent_example` directly (source: `seed_intent_example`)
|
|
|
|
|
|
2. **Alias variants** — one phrase per alias using the alias as the verb (source: `alias_variant`)
|
|
|
|
|
|
3. **Payload field variants** — for enum fields, one record per enum value; for numeric fields,
|
|
|
|
|
|
low/mid/high values (source: `field_variant`)
|
|
|
|
|
|
4. **Template expansion** — 5 records per action from `synthetic_template` with filled placeholders
|
|
|
|
|
|
(source: `template_expansion`)
|
|
|
|
|
|
|
|
|
|
|
|
**Minimum seed target:** ~20 records × 13 actions = 260 records.
|
|
|
|
|
|
**After NeMo expansion:** configurable via `--num-records` (default: 1000).
|
|
|
|
|
|
|
|
|
|
|
|
Split: 90% train / 10% validation, partitioned by action so all 13 actions appear in both splits.
|
|
|
|
|
|
|
2026-07-22 09:37:40 -05:00
|
|
|
|
The deterministic seed files are intentionally small. They are good for validating the action
|
|
|
|
|
|
surface and dispatch schema, but they are not diverse enough for serious payload extraction
|
|
|
|
|
|
training by themselves. Use the Mimir-expanded `expanded.jsonl` file when training a model
|
|
|
|
|
|
that needs to generalize across phrasing, payload values, and action families.
|
|
|
|
|
|
|
2026-07-21 13:14:52 -05:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## Mimir Data Designer Config (auto-generated by bridge)
|
|
|
|
|
|
|
|
|
|
|
|
The bridge writes this config to Mimir before running generation:
|
|
|
|
|
|
|
2026-07-22 09:37:40 -05:00
|
|
|
|
```python
|
|
|
|
|
|
# auto-generated by generate_training_data.py - do not edit by hand
|
2026-07-21 13:14:52 -05:00
|
|
|
|
# generated_at: <unix_ts>
|
|
|
|
|
|
|
2026-07-22 09:37:40 -05:00
|
|
|
|
from data_designer.config import DataDesignerConfigBuilder, LocalFileSeedSource
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ACTION_IDS = ["calculate", "..."]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def load_config_builder():
|
|
|
|
|
|
builder = DataDesignerConfigBuilder(
|
|
|
|
|
|
model_configs="/mnt/storage/data-designer/model_configs.yaml",
|
|
|
|
|
|
)
|
|
|
|
|
|
builder.with_seed_dataset(
|
|
|
|
|
|
LocalFileSeedSource(
|
|
|
|
|
|
path="/mnt/storage/data-designer/managed-assets/module_controller_seed_<unix_ts>.jsonl"
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
builder.add_column(
|
|
|
|
|
|
name="expanded_record",
|
|
|
|
|
|
column_type="llm-structured",
|
|
|
|
|
|
model_alias="nvidia-text",
|
|
|
|
|
|
prompt="Generate one new strict instruction dataset row from the seed input/output.",
|
|
|
|
|
|
output_format={
|
|
|
|
|
|
"type": "object",
|
|
|
|
|
|
"required": ["instruction", "input", "output", "metadata"],
|
|
|
|
|
|
"properties": {
|
|
|
|
|
|
"instruction": {"type": "string"},
|
|
|
|
|
|
"input": {"type": "string"},
|
|
|
|
|
|
"output": {"type": "string"},
|
|
|
|
|
|
"metadata": {
|
|
|
|
|
|
"type": "object",
|
|
|
|
|
|
"required": ["action_id", "source", "split", "generated_at"],
|
|
|
|
|
|
"properties": {
|
|
|
|
|
|
"action_id": {"type": "string", "enum": ACTION_IDS}
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
)
|
|
|
|
|
|
return builder
|
2026-07-21 13:14:52 -05:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-07-22 09:37:40 -05:00
|
|
|
|
Data Designer writes rows that include the generated `expanded_record` column. The bridge
|
|
|
|
|
|
copies that raw file back as `expanded.raw.jsonl`, extracts valid instruction rows, and writes
|
|
|
|
|
|
the model-training file as `expanded.jsonl`.
|
|
|
|
|
|
|
2026-07-21 13:14:52 -05:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## Manifest Entry (auto-patched by bridge)
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
"module_controller_intents_<unix_ts>": {
|
|
|
|
|
|
"name": "Module Controller Intents",
|
|
|
|
|
|
"category": "synthetic_sft",
|
|
|
|
|
|
"schema_profile": "instruction",
|
|
|
|
|
|
"source_url": null,
|
|
|
|
|
|
"acquisition_method": "local_synthetic_generator",
|
|
|
|
|
|
"license_spdx": "UNLICENSED",
|
|
|
|
|
|
"redistribution_allowed": false,
|
|
|
|
|
|
"estimated_tokens": null,
|
|
|
|
|
|
"status": "generated_local",
|
2026-07-22 09:13:54 -05:00
|
|
|
|
"local_path": "training-data/module_controller_intents_<unix_ts>",
|
2026-07-21 13:14:52 -05:00
|
|
|
|
"local_format": "jsonl",
|
|
|
|
|
|
"generator": "mp-ai-module-controller/scripts/generate_training_data.py",
|
|
|
|
|
|
"sdg_engine": "data-designer",
|
|
|
|
|
|
"sdg_host": "mimir (100.80.52.47)",
|
2026-07-22 09:37:40 -05:00
|
|
|
|
"sdg_model": "nvidia-text",
|
|
|
|
|
|
"sdg_model_alias": "nvidia-text",
|
|
|
|
|
|
"expanded_path": "/Volumes/Zoe/custom-local-llm/training-data/module_controller_intents_<unix_ts>/expanded.jsonl",
|
2026-07-21 13:14:52 -05:00
|
|
|
|
"codebook_version": "1.0.0",
|
|
|
|
|
|
"codebook_checksum": "<from model.codebook.json>",
|
|
|
|
|
|
"registry_checksum": "<from actions.index.json>",
|
|
|
|
|
|
"generated_at": <unix_ts>,
|
|
|
|
|
|
"doc": "data/module_controller_intents_<unix_ts>/README.md"
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## CLI Usage
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# From mp-ai-module-controller project root:
|
|
|
|
|
|
|
|
|
|
|
|
# Seed only (no NeMo expansion — fast, local, 260 records):
|
|
|
|
|
|
python3 scripts/generate_training_data.py \
|
|
|
|
|
|
--dictionary-dir dictionary/ \
|
2026-07-22 09:13:54 -05:00
|
|
|
|
--output-dir /Volumes/Zoe/custom-local-llm/training-data/ \
|
|
|
|
|
|
--manifest /Volumes/Zoe/custom-local-llm/manifest.llm.json
|
2026-07-21 13:14:52 -05:00
|
|
|
|
|
|
|
|
|
|
# Full SDG run via Mimir (requires NVIDIA_API_KEY on Mimir):
|
|
|
|
|
|
python3 scripts/generate_training_data.py \
|
|
|
|
|
|
--dictionary-dir dictionary/ \
|
2026-07-22 09:13:54 -05:00
|
|
|
|
--output-dir /Volumes/Zoe/custom-local-llm/training-data/ \
|
|
|
|
|
|
--manifest /Volumes/Zoe/custom-local-llm/manifest.llm.json \
|
2026-07-21 13:14:52 -05:00
|
|
|
|
--sdg-host 100.80.52.47 \
|
|
|
|
|
|
--sdg-user aaron-pressey \
|
|
|
|
|
|
--sdg-key ~/.ssh/silma_orson_ed25519 \
|
2026-07-22 09:37:40 -05:00
|
|
|
|
--sdg-model-alias nvidia-text \
|
2026-07-21 13:14:52 -05:00
|
|
|
|
--num-records 1000
|
|
|
|
|
|
|
|
|
|
|
|
# Dry run (prints what would be generated, writes nothing):
|
|
|
|
|
|
python3 scripts/generate_training_data.py --dry-run
|
2026-07-22 09:13:54 -05:00
|
|
|
|
|
|
|
|
|
|
# Woodpecker deploy target:
|
2026-07-22 09:37:40 -05:00
|
|
|
|
ENABLE_MIMIR_SDG=1 scripts/deploy_training_data.sh
|
2026-07-21 13:14:52 -05:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## Prerequisites
|
|
|
|
|
|
|
|
|
|
|
|
- Python 3.11+ (stdlib only: `json`, `pathlib`, `hashlib`, `time`, `argparse`, `subprocess`)
|
|
|
|
|
|
- SSH access to Mimir via `~/.ssh/silma_orson_ed25519` (for NeMo expansion pass)
|
2026-07-22 09:37:40 -05:00
|
|
|
|
- `/home/aaron-pressey/.config/home-grown-llm-data/data-designer.env` present on Mimir with provider credentials
|
|
|
|
|
|
- Data Designer provider available for the selected alias. Current default: `nvidia-text`.
|
2026-07-21 13:14:52 -05:00
|
|
|
|
- `dictionary/` files current — run `cargo run -- dictionary generate` first if registry changed
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## Staleness Check
|
|
|
|
|
|
|
|
|
|
|
|
The manifest entry embeds both `codebook_checksum` and `generated_at`. If you add actions:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
cargo run -- dictionary generate # updates codebook_checksum
|
|
|
|
|
|
python3 scripts/generate_training_data.py # new timestamp → new manifest entry
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
The Training Monitor will show both the old and new dataset. You can deprecate the old one
|
|
|
|
|
|
by setting its `status` to `"superseded"` in the manifest.
|