Commit Graph

3 Commits

Author SHA1 Message Date
Alpamys 06d8ea7cc5 chore: migrate to src-layout
Move soup_cli/ -> src/soup_cli/ (history preserved via git mv). src-layout
forces the test suite to import the installed package instead of the
repo-root source tree, surfacing packaging bugs that flat-layout masks —
e.g. the v0.53.8 double-shipped-fixtures regression, invisible because
`pytest tests/` imports ./soup_cli directly and never from the wheel.

- pyproject: packages = ["src/soup_cli"]; artifacts globs -> src/soup_cli/...
  The import name is unchanged, so the `soup` entry point, --cov=soup_cli,
  and report_to/module-path strings stay `soup_cli`.
- CI / ownership: ruff lint path (ci.yml), recipe-validation `paths:` filters,
  CODEOWNERS patterns, and the PR-template checklist all repointed to
  src/soup_cli/.
- tests: source-grep regression tests that read package files by repo-relative
  path repointed to src/soup_cli/ (64 files; 170 path literals). Lines pushed
  over 100 chars by the prefix were wrapped to keep ruff E501 clean. Module
  references (`import soup_cli`, `-m soup_cli`, mock.patch("soup_cli.x")) and
  the `--cov=soup_cli` coverage target are deliberately unchanged.
- docs: AGENTS.md + CONTRIBUTING.md structure tree and lint commands.

Verified locally: ruff clean (src/soup_cli + tests); `import soup_cli`
resolves to src/soup_cli/__init__.py; built wheel ships
soup_cli/data/_fixtures/*.jsonl (10 files, no duplicates, no src/ prefix);
3174 tests across every touched test file pass. Packaging-only — no version bump.
2026-05-31 12:40:06 +05:00
Alpamys 6fdf7e2570 feat(trainer): multipack live HF Trainer DataLoader override (v0.40.4 Part B)
Closes #65 (deferred from v0.40.3).

make_multipack_trainer_class adds a get_train_dataloader override
that builds a MultipackBatchSampler(real_batches=False) — yields a
flat list[int] per packed sequence, which is the contract HF
DataLoader.batch_sampler expects — and installs it via
DataLoader(..., batch_sampler=sampler, collate_fn=self.data_collator,
num_workers=args.dataloader_num_workers,
pin_memory=args.dataloader_pin_memory). drop_last is forwarded from
TrainingArguments.dataloader_drop_last.

Falls back to super().get_train_dataloader() when state was never
attached OR when train_dataset is unset — defence-in-depth so the
subclass remains safe to instantiate even when multipack is later
disabled.

The state-presence guard switched from falsy (`not max_seq`) to
explicit `is None` (plus `not lengths` for empty-list defence) —
attach_multipack_state already rejects non-positive ints, so the
falsy guard would only mask configurator bugs.

_get_train_sampler override stays as a defensive no-op fallback that
ALWAYS delegates to super (review-fix from v0.40.4 code-review:
returning a multipack list[list[int]] from this method would cause a
shape mismatch if any HF eval / prediction loop bypasses
get_train_dataloader and calls _get_train_sampler directly).

SFT and Pretrain trainer wrappers now invoke
make_multipack_trainer_class(SFTTrainer) and attach_multipack_state(...)
when multipack: true. The v0.40.3 yellow advisory + standard-sampler
fallback is gone. Architecture allowlist
(validate_multipack_architecture) still gates at build time.

tests/test_v0403_part_b.py: TestSftAndPretrainWiringDeferred renamed
to TestSftAndPretrainWiringLive; the deferred-state test
(_get_train_sampler returns MultipackBatchSampler when state is set)
is replaced by the live-state test (_get_train_sampler always
delegates to super even with state attached).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 13:20:47 +05:00
Alpamys 1f050fc235 feat(v0.40.3): Stub-to-live wave 1 (#33, #64; #65 still deferred)
Three v0.X.0 deferred-stub features become live runtime — closes #33
(harvester judge filter + serve trace log) and #64 (live CUDA OOM probe).
#65 (multipack live wiring in HF Trainer) remains deferred to v0.40.4
after the adversarial 5th-review pass surfaced a Sampler[int] vs
list[list[int]] shape mismatch with HF Trainer's DataLoader; helpers
(`make_multipack_trainer_class`, `attach_multipack_state`,
`lengths_from_dataset`, `detect_arch_name`) ship as a stub used by
unit tests, but the SFT/Pretrain wrappers print a yellow advisory and
fall back to the standard sampler when `multipack: true`.

Live CUDA OOM probe (#64): `make_cuda_probe_fn` builds a closure that
runs ONE forward+backward+step on a synthetic batch per candidate.
`model.zero_grad(set_to_none=True)` runs BEFORE forward; intermediate
ids/attn/labels/outputs are del-ed before `loss.backward()` so peak
VRAM reflects a realistic training step (matches v0.35.0 #45 policy).
`pad_id` is bounded by `len(tokenizer)` (not `vocab_size`) so extended
vocabs (Llama-3 + `<|pad|>`) don't fold pad to a random byte token.
SFT-only this release.

Trace-to-Preference judge filter (#33 (a)): `judge_filter_pairs` reuses
v0.19.0 JudgeEvaluator backends (openai/server/ollama). Threshold
rejects bool/NaN/out-of-[0,1]; `_MAX_BATCH=100_000` cap applied via
lazy `itertools.islice`; per-pair backend exceptions caught and DEBUG-
logged (matches v0.33.0 #47 policy); `judge_provider` validated against
the allowlist at the CLI boundary BEFORE constructor with a Rich-escape
error message; yellow projected-call-count warning before the loop
(2× per pair).

Inference Server trace log (#33 (b)): `TraceLogWriter` is thread-safe
(single-process lock — multi-worker documented as known limitation);
path containment via shared `is_under_cwd`; null-byte/empty/non-string
path rejected; cap_mb bounds [1, 10000] with explicit bool rejection.
Rotation (one backup retained) refuses symlink at the backup path via
`os.lstat + stat.S_ISLNK` (matches v0.33.0 #22 TOCTOU policy). Secret
redaction (`hf_*` ≥8, `sk-*` ≥16, `Bearer …` ≥8 with `.` excluded so
end-of-sentence period survives) applied to prompt + response and
recursively to caller-supplied `extra` dict values. Streaming SSE path
also records (was a coverage gap caught in adversarial review).

Behaviour change: v0.40.2 users with `auto_batch_size_strategy: probe`
were silently getting the static fallback. v0.40.3 actually runs a
CUDA probe on first run (~5–30s, cached per (model, max_length, quant,
lora_r, gpu) tuple).

Reviews: 5 agents (python, code, security, tdd, verification-loop).
Verification-loop run twice — once shallow smoke (PASS), once
adversarial bug-hunt which found C1/C2 (multipack live wiring crash —
demoted to v0.40.4), H1 (streaming SSE missing trace log — fixed),
H4 (vocab_size vs len(tokenizer) on extended vocabs — fixed), H3
(Bearer regex consumed trailing period — fixed), H2 (judge cost
shock — warning added), M2 (empty lengths accepted — rejected), L1
(extra dict bypassed redaction — recursive walk added).

Tests: 4756 → 4855 (+99 net new) across test_v0403_part_a/b/c.py.
Lint clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 16:02:45 +05:00