fix(loader): fallback field mapping for sonnet comparison schema#15
Conversation
The sonnet comparison data uses `sonnet_response` and `haiku_parsed` instead of `response` and `parsed`. Add fallback mapping in _parse_entry() so these records are loaded correctly, yielding 682 additional SFT training pairs (2,076 total). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Greptile SummaryThis PR adds fallback field mapping in Key changes:
Confidence Score: 5/5Safe to merge — the loader fix is correct, consistently guarded, and well-tested; no P0/P1 findings. All remaining findings are P2 (notebook style). The core loader change uses consistent notebooks/train-hippofloop.ipynb — minor guard missing for
|
| Filename | Overview |
|---|---|
| src/hippofloop/data/loader.py | Adds is not None fallback for response→sonnet_response and parsed→haiku_parsed; consistent guard strategy across all three fallback fields. |
| tests/data/test_loader.py | 4 new tests covering fallback activation, canonical-field preference, and end-to-end pipeline; adequate coverage for the added logic. |
| notebooks/train-hippofloop.ipynb | New end-to-end training notebook for Kaggle; minor issue where the final summary cell references report without a guard, which would NameError if the evaluation cell is skipped. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Raw JSONL line] --> B{response key present\nand not None?}
B -- Yes --> C[use response]
B -- No --> D{sonnet_response\npresent?}
D -- Yes --> E[use sonnet_response]
D -- No --> F[use empty string]
C --> G[DecisionEntry.response]
E --> G
F --> G
A --> H{parsed key present\nand not None?}
H -- Yes --> I[use parsed]
H -- No --> J{haiku_parsed\npresent?}
J -- Yes --> K[use haiku_parsed]
J -- No --> L[use None]
I --> M[DecisionEntry.parsed]
K --> M
L --> M
G --> N[DecisionCleaner\nfilters on response]
N --> O[SftFormatter\nuses response as\nassistant message]
M --> P[metadata only\nnot used in training]
Reviews (4): Last reviewed commit: "refactor: eliminate double dict lookups ..." | Re-trigger Greptile
Self-contained notebook that runs the full pipeline on a Kaggle T4: load JSONL → clean → format → train (QLoRA) → evaluate → export GGUF. Uses hippofloop's data pipeline and Unsloth for efficient 4-bit training with batch_size=1, grad_accum=16, max_seq_length=8192. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
- Use rng.sample() instead of ordered slice for eval subset - Initialize best_loss = None before training, guard with is not None Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract response, parsed, and time into locals before the constructor call. Fixes redundant hash+lookup per record and aligns all three fallback fields to the same is-not-None idiom. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
JsonlLoader._parse_entry():response←sonnet_response,parsed←haiku_parsedTest plan
🤖 Generated with Claude Code