soup-cli 0.40.2__tar.gz → 0.40.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {soup_cli-0.40.2 → soup_cli-0.40.4}/CONTRIBUTING.md +1 -1
- {soup_cli-0.40.2 → soup_cli-0.40.4}/PKG-INFO +57 -15
- {soup_cli-0.40.2 → soup_cli-0.40.4}/README.md +57 -15
- {soup_cli-0.40.2 → soup_cli-0.40.4}/SECURITY.md +3 -1
- {soup_cli-0.40.2 → soup_cli-0.40.4}/pyproject.toml +1 -1
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/__init__.py +1 -1
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/data.py +67 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/diff.py +37 -6
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/export.py +75 -15
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/generate.py +26 -9
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/infer.py +35 -10
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/merge.py +25 -2
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/serve.py +78 -1
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/train.py +4 -5
- soup_cli-0.40.4/soup_cli/data/traces/quality.py +114 -0
- soup_cli-0.40.4/soup_cli/monitoring/trace_logger.py +162 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/trainer/bco.py +20 -2
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/trainer/dpo.py +23 -2
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/trainer/embedding.py +20 -2
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/trainer/grpo.py +20 -2
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/trainer/ipo.py +20 -2
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/trainer/kto.py +20 -2
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/trainer/orpo.py +20 -2
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/trainer/ppo.py +44 -8
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/trainer/preference.py +4 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/trainer/pretrain.py +48 -3
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/trainer/reward_model.py +22 -2
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/trainer/sft.py +44 -4
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/trainer/simpo.py +20 -2
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/batch_probe.py +106 -0
- soup_cli-0.40.4/soup_cli/utils/multipack_trainer.py +254 -0
- soup_cli-0.40.4/tests/test_v0403_part_a.py +206 -0
- soup_cli-0.40.4/tests/test_v0403_part_b.py +306 -0
- soup_cli-0.40.4/tests/test_v0403_part_c.py +584 -0
- soup_cli-0.40.4/tests/test_v0404_part_a.py +373 -0
- soup_cli-0.40.4/tests/test_v0404_part_b.py +179 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/.dockerignore +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/.github/FUNDING.yml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/.github/pull_request_template.md +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/.github/workflows/ci.yml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/.github/workflows/docker.yml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/.github/workflows/publish.yml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/.github/workflows/recipe-validation.yml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/.gitignore +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/CODEOWNERS +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/CODE_OF_CONDUCT.md +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/Dockerfile +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/LICENSE +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/NOTICE +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/docker-compose.yml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/examples/README.md +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/examples/configs/dpo_chat.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/examples/configs/dpo_example.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/examples/configs/grpo_reasoning.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/examples/configs/rlhf_step1_sft.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/examples/configs/rlhf_step2_reward.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/examples/configs/rlhf_step3_ppo.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/examples/configs/sft_basic.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/examples/configs/vision_llama.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/examples/data/alpaca_tiny.jsonl +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/examples/data/chat_preferences.jsonl +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/examples/data/dpo_sample.jsonl +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/examples/data/reasoning_math.jsonl +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup.png +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/__main__.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/autopilot/__init__.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/autopilot/analyzer.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/autopilot/decisions.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/autopilot/generate_config.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/cans/__init__.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/cans/pack.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/cans/publish.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/cans/run.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/cans/schema.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/cans/unpack.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/cans/verify.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/cli.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/__init__.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/adapters.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/autopilot.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/bench.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/can.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/chat.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/cost.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/deploy.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/doctor.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/eval.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/history.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/init.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/migrate.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/profile.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/push.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/quickstart.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/recipes.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/registry.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/runs.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/sweep.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/tui.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/ui.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/commands/why.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/config/__init__.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/config/loader.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/config/schema.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/data/__init__.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/data/augment.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/data/chat_templates.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/data/collators.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/data/formats.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/data/loader.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/data/loss_mask.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/data/providers/__init__.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/data/providers/_utils.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/data/providers/anthropic.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/data/providers/ollama.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/data/providers/vllm.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/data/sft_format.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/data/templates/__init__.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/data/templates/code.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/data/templates/conversation.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/data/templates/preference.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/data/templates/qa.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/data/templates/reasoning.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/data/templates/tool_calling.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/data/templates/verifiable.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/data/traces/__init__.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/data/traces/pair_builder.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/data/traces/parsers.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/data/validator.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/eval/__init__.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/eval/checkpoint_intelligence.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/eval/custom.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/eval/forgetting.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/eval/gate.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/eval/human.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/eval/judge.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/eval/leaderboard.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/eval/quant_check.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/experiment/__init__.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/experiment/tracker.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/migrate/__init__.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/migrate/axolotl.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/migrate/common.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/migrate/llamafactory.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/migrate/unsloth.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/monitoring/__init__.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/monitoring/callback.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/monitoring/display.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/monitoring/hf_push.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/recipes/__init__.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/recipes/catalog.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/registry/__init__.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/registry/attach.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/registry/diff.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/registry/hashing.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/registry/store.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/templates/__init__.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/templates/audio.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/templates/bco.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/templates/chat.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/templates/code.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/templates/embedding.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/templates/ipo.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/templates/kto.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/templates/longcontext.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/templates/manifest.json +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/templates/medical.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/templates/moe.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/templates/orpo.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/templates/pretrain.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/templates/reasoning.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/templates/rlhf.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/templates/simpo.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/templates/tool-calling.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/templates/vision.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/trainer/__init__.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/trainer/mlx_dpo.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/trainer/mlx_grpo.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/trainer/mlx_routing.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/trainer/mlx_sft.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/trainer/rewards.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/tui_app.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/ui/__init__.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/ui/app.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/ui/static/app.js +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/ui/static/index.html +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/ui/static/logo.png +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/ui/static/logo.svg +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/ui/static/style.css +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/__init__.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/activation_offload.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/auto_quant.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/constants.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/convergence.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/crash.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/cross_doc_attn.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/curriculum.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/cut_ce.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/deepspeed.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/dpo_variants.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/encoding.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/errors.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/flash_attn.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/fp8.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/freeze.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/fsdp.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/galore.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/gpu.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/grad_accum.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/gradient_ckpt.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/hf.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/hf_space.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/jinja_analyzer.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/kernel_picker.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/launcher.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/liger.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/log_level.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/long_context.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/lr_finder.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/metrics.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/mii.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/mixed_precision.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/mlx.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/moe.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/multipack.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/multipack_sampler.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/neat_packing.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/ollama.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/paths.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/peft_builder.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/peft_patches.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/pipeline.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/preference_combine.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/profiler.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/profiling.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/qat.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/quality.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/quant_menu.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/registry.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/relora.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/replay.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/ring_attention.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/run_cost.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/sglang.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/spec_pairing.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/spike_recovery.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/structured_output.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/topology.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/tracing.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/trust_remote.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/unsloth.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/v028_features.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/vllm.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/warmup.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_cli/utils/why.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/soup_logo_svg.svg +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/templates/chat.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/templates/code.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/templates/medical.yaml +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/__init__.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/conftest.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_adapters.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_advanced_peft.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_assistant_mask.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_audio.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_auto_tuning.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_autopilot.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_awq_gptq_export.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_batch_probe.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_bco.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_bench.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_bugfixes.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_callback.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_cans.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_chat.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_chat_template.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_cli.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_cli_subprocess.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_config.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_cost.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_crash_reporter.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_curriculum.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_data.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_data_augment.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_data_sample.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_data_split.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_data_tools.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_dataset_hub.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_dataset_registry.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_deepspeed.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_deploy_ollama.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_diff.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_display.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_doctor.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_dpo_example.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_dpo_variants.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_embedding.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_errors.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_eval.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_eval_gate.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_eval_platform.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_export.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_formats.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_fp8_recipe.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_freeze_training.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_generate.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_gpu.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_grpo.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_hf_integration.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_infer.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_inference_advanced.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_init.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_ipo.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_jinja_analyzer.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_kto.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_loader.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_log_level.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_loss_watchdog.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_merge.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_migrate.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_mlx_backend.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_moe.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_multi_adapter.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_multi_gpu.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_multipack_config.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_multipack_invariants.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_multipack_sampler.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_neat_packing.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_neftune_rslora.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_onnx_tensorrt_export.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_orpo.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_packing.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_part_a_wave1.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_part_a_wave2.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_part_b.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_part_c.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_part_d.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_part_e.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_part_f_hardening.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_peft_methods.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_peft_patches.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_performance.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_pissa_init.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_ppo.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_preference_dispatcher.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_preference_multi.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_preference_multi_runtime.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_pretrain.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_profile.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_profiling.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_progress.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_push.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_qat.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_quality_filter.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_quant_check.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_quant_menu.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_quickstart.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_rank_pattern.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_recipes.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_recipes_v031.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_registry.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_relora.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_replay.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_resume.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_rlvr.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_run_cost.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_runs.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_serve.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_server_generate.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_sglang_serve.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_simpo.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_smoke_train.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_speculative_decoding.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_sweep.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_synth_data_pro.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_templates_yaml.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_tensorboard.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_tool_calling.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_trace_to_pref.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_tracker.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_trainer_coverage_v035.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_trainer_init.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_training_intelligence.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_training_speed.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_trust_remote_code.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_tui.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_ui.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_ui_chat.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_ui_config_builder.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_ui_live_monitor.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_ui_metrics.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_unsloth.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_v0401_part_c.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_v0401_part_d.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_v0401_part_e.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_v0402_part_a.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_v0402_part_b.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_validator.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_vision.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_vllm_serve.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_why.py +0 -0
- {soup_cli-0.40.2 → soup_cli-0.40.4}/tests/test_windows_encoding.py +0 -0
|
@@ -111,7 +111,7 @@ soup_cli/
|
|
|
111
111
|
templates/ - 17 built-in soup.yaml templates (YAML + manifest.json) with load_template loader (v0.39.0, +bco v0.40.0)
|
|
112
112
|
ui/ - Web UI (FastAPI + HTML/JS SPA)
|
|
113
113
|
|
|
114
|
-
tests/ - Test suite (
|
|
114
|
+
tests/ - Test suite (148 files, 4930 tests)
|
|
115
115
|
examples/ - Real-world config examples and datasets
|
|
116
116
|
```
|
|
117
117
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: soup-cli
|
|
3
|
-
Version: 0.40.
|
|
3
|
+
Version: 0.40.4
|
|
4
4
|
Summary: Fine-tune LLMs in one command. No SSH, no config hell.
|
|
5
5
|
Project-URL: Homepage, https://github.com/MakazhanAlpamys/Soup
|
|
6
6
|
Project-URL: Repository, https://github.com/MakazhanAlpamys/Soup
|
|
@@ -134,17 +134,11 @@ soup train
|
|
|
134
134
|
|
|
135
135
|
Latest highlights only. Full history: [GitHub Releases](https://github.com/MakazhanAlpamys/Soup/releases).
|
|
136
136
|
|
|
137
|
-
**v0.40.
|
|
137
|
+
**v0.40.4 — trust_remote_code multi-trainer + multipack live wiring**: closes two carry-over gaps from earlier releases — the v0.36.0 known gap (only SFT honoured the opt-in) and the v0.40.3-deferred multipack sampler.
|
|
138
138
|
|
|
139
|
-
- **`--
|
|
140
|
-
- **
|
|
141
|
-
-
|
|
142
|
-
- **`soup quickstart --output DIR`** — route data, config, and run dir under any directory you choose (default keeps backwards-compat in cwd).
|
|
143
|
-
- **`soup runs --cwd-only`** — restrict the listing to runs whose `output_dir` is under the current directory; the global `~/.soup/experiments.db` view is still default.
|
|
144
|
-
- **`soup infer` / `soup bench` accept HF ids** — when the local model path is missing AND the value isn't path-like (no `./`, `/`, `~`, `C:\`), it falls through to a HuggingFace download via `transformers.from_pretrained`. Path-like-but-missing surfaces a friendly `FileNotFoundError`.
|
|
145
|
-
- **CLI flag aliases** — `data filter --min-coherence` (alias for `--coherence`); `data split --train` accepted (informational, train is the implicit remainder); `data register / unregister` accept positional `<name>` and `<path>` alongside the `--name` / `--path` options, with conflict detection.
|
|
146
|
-
- **`--log-level` plumbing complete** — `apply_logging_level` now sets the root logger so third-party libraries (transformers / peft / trl) actually respect QUIET and DEBUG. The four tiers no longer produce byte-identical output.
|
|
147
|
-
- **+36 net new tests** across the new helpers, security-fix follow-ups (path-containment in `register_data`, `bench.py`, `infer.py --output`, symlink-reject in custom Space templates), and Windows cross-drive edge cases.
|
|
139
|
+
- **`--trust-remote-code` everywhere** — every non-SFT trainer (DPO / GRPO / KTO / ORPO / SimPO / IPO / PPO / RewardModel / Pretrain / Embedding / BCO + the unified Preference dispatcher) now defaults to `trust_remote_code=False` and only enables custom-code execution when the user explicitly opts in. Same for `soup diff`, `soup export`, `soup merge`, `soup infer`, and `soup data generate`. The v0.36.0 `KNOWN_SAFE_PREFIXES` allowlist still suppresses the warning panel for first-party orgs; unknown-org local checkpoints with `auto_map` raise a friendly `ValueError` at construction time instead of silently exec'ing on `from_pretrained`.
|
|
140
|
+
- **Multipack sampler — live in HF Trainer** — `make_multipack_trainer_class` adds a `get_train_dataloader` override that installs a `MultipackBatchSampler(real_batches=False)` as the DataLoader's `batch_sampler=`. The shape mismatch that blocked v0.40.3 (`Sampler[int]` vs `list[list[int]]`) is gone — the sampler now yields flat `list[int]` per packed sequence, which is what `DataLoader.batch_sampler` actually expects. SFT and Pretrain wrappers instantiate the multipack subclass when `multipack: true`; the v0.40.3 yellow advisory is gone.
|
|
141
|
+
- **+75 net new tests** across the trainer×trust_remote_code matrix (parametrize over 12 wrappers × {default-off / opt-in / unknown-org rejection}), source-level invariants (no remaining `trust_remote_code=True` literal in any trainer file), the new DataLoader override (state-missing fallback + flat-pack-yield contract), and the real `transformers.Trainer` MRO mix-in.
|
|
148
142
|
|
|
149
143
|
## Why Soup?
|
|
150
144
|
|
|
@@ -661,7 +655,7 @@ training:
|
|
|
661
655
|
|
|
662
656
|
**Architecture allowlist** — 18 supported (Llama 3.x, Qwen 2/3, Mistral, Gemma 2/3, Phi 3/4, DeepSeek V2/V3, Mixtral, Falcon, StableLM, SmolLM2). Unknown architectures **fail loudly at config-load** instead of silently no-opping (critical fix vs Axolotl's silent-miss footgun).
|
|
663
657
|
|
|
664
|
-
**
|
|
658
|
+
**Live wiring** — landed. SFT and Pretrain trainer wrappers actually instantiate the multipack subclass when `multipack: true` is set. The factory's `get_train_dataloader` override installs `MultipackBatchSampler(real_batches=False)` (yields a flat `list[int]` per packed sequence — DataLoader-compatible) as the DataLoader's `batch_sampler=`, forwarding `dataloader_drop_last`/`num_workers`/`pin_memory` from `TrainingArguments`. The `_get_train_sampler` override stays as a defensive no-op fallback that always delegates to super, so any HF eval / prediction loop bypassing `get_train_dataloader` still gets the correct `Sampler[int]` shape (no nested-list shape mismatch). Multipack is **sft / pretrain only** on the `transformers` backend; preference / RLHF trainers and MLX backend get distinct error messages naming the actual reason. Datasets must expose `input_ids` (preferred) or `length` per row; raw text triggers an all-zeros warning.
|
|
665
659
|
|
|
666
660
|
**DoS hardening** — the FFD packer caps at 1M items (algorithm is O(N²) worst-case); the 4D mask builder caps allocations at 2³¹ cells; the chat-template Jinja analyzer caps at 128KB. Every numeric input rejects `bool` explicitly (matches v0.30.0+ project policy).
|
|
667
661
|
|
|
@@ -698,12 +692,19 @@ data:
|
|
|
698
692
|
|
|
699
693
|
When the tokenizer ships a chat template with `{% generation %}` markers, the mask is exact. Without those markers, Soup falls back to an incremental tokenize-delta walk and documents the looseness.
|
|
700
694
|
|
|
701
|
-
### `--trust-remote-code` opt-in
|
|
695
|
+
### `--trust-remote-code` opt-in (every command, every trainer)
|
|
702
696
|
|
|
703
|
-
|
|
697
|
+
Every command that loads a model now requires `--trust-remote-code` to execute custom Python from a model repo (`auto_map` in `config.json`). First-party orgs (Meta, Mistral, Qwen, Google, etc.) suppress the warning panel; everything else prints a `REMOTE CODE WARNING` panel before loading. Unknown-org local checkpoints with `auto_map` raise a friendly `ValueError` at construction time instead of silently exec'ing inside `from_pretrained`.
|
|
698
|
+
|
|
699
|
+
Coverage:
|
|
700
|
+
- `soup train` (every task — SFT, DPO, GRPO, KTO, ORPO, SimPO, IPO, PPO, Reward Model, Pretrain, Embedding, BCO, and the unified Preference dispatcher)
|
|
701
|
+
- `soup chat`, `soup serve`, `soup data download`, `soup eval auto`
|
|
702
|
+
- `soup diff`, `soup export`, `soup merge`, `soup infer`, `soup data generate`
|
|
704
703
|
|
|
705
704
|
```bash
|
|
706
705
|
soup train --config soup.yaml --trust-remote-code
|
|
706
|
+
soup infer --model my-org/custom-arch-model --input prompts.jsonl --trust-remote-code
|
|
707
|
+
soup export --model ./adapter --format gguf --trust-remote-code
|
|
707
708
|
```
|
|
708
709
|
|
|
709
710
|
### Chat-template hardening
|
|
@@ -2579,6 +2580,7 @@ soup serve --model <m> --structured-output json --json-schema s.json Constraine
|
|
|
2579
2580
|
soup serve --model <m> --structured-output regex --regex-pattern '...' Regex-constrained output
|
|
2580
2581
|
soup serve --model <m> --dashboard Live dashboard + /metrics endpoint
|
|
2581
2582
|
soup serve --model <m> --trace --trace-endpoint http://localhost:4317 OpenTelemetry tracing
|
|
2583
|
+
soup serve --model <m> --trace-log ./serve.jsonl Per-request JSONL log + rotation + secret redaction
|
|
2582
2584
|
POST /v1/adapters/activate/<name> Hot-swap active LoRA adapter
|
|
2583
2585
|
soup sweep --config soup.yaml --param lr=... Hyperparameter search
|
|
2584
2586
|
soup diff --model-a ./a --model-b ./b Compare two models
|
|
@@ -2594,7 +2596,9 @@ soup data generate ... --provider anthropic Use Claude API
|
|
|
2594
2596
|
soup data generate ... --provider vllm Use local vLLM server
|
|
2595
2597
|
soup data generate ... --template code Domain templates (code/conversation/qa/preference/reasoning)
|
|
2596
2598
|
soup data generate ... --quality-pipeline Auto validate + filter + dedup
|
|
2597
|
-
soup data augment <path> --strategy rephrase|translate|style LLM-driven augmentationsoup data from-traces --logs l.jsonl --format langchain --signal thumbs_up --output p.jsonl Preference pairs from
|
|
2599
|
+
soup data augment <path> --strategy rephrase|translate|style LLM-driven augmentationsoup data from-traces --logs l.jsonl --format langchain --signal thumbs_up --output p.jsonl Preference pairs from traces
|
|
2600
|
+
soup data from-traces ... --judge --min-confidence 0.7 LLM-judge confidence filter
|
|
2601
|
+
soup data review prefs.jsonl --sample 10 Preview preference pairssoup data filter <path> --coherence 0.3 Quality filter (perplexity/coherence)
|
|
2598
2602
|
soup data sample <path> --n 1000 Random sample subset
|
|
2599
2603
|
soup data sample <path> --n 1000 --strategy diverse Cluster-based diverse sampling
|
|
2600
2604
|
soup data sample <path> --n 1000 --strategy hard Sample hardest examples
|
|
@@ -2791,6 +2795,44 @@ pytest tests/ -v
|
|
|
2791
2795
|
pytest tests/ -m smoke -v
|
|
2792
2796
|
```
|
|
2793
2797
|
|
|
2798
|
+
## Live CUDA Batch-Size Probe
|
|
2799
|
+
|
|
2800
|
+
Set `auto_batch_size_strategy: probe` in `training:` and Soup will run a real OOM-probe before training:
|
|
2801
|
+
|
|
2802
|
+
```yaml
|
|
2803
|
+
training:
|
|
2804
|
+
batch_size: auto
|
|
2805
|
+
auto_batch_size_strategy: probe
|
|
2806
|
+
```
|
|
2807
|
+
|
|
2808
|
+
For each candidate size `B`, the probe runs ONE forward + backward + step on a synthetic batch of `B` sequences of length `max_length`. On `torch.cuda.OutOfMemoryError` it halves; otherwise it doubles up to `4 × static_estimate`. The picked size is cached per `(model, max_length, quantization, lora_r, gpu)` tuple in `~/.soup/batch_cache.json` so subsequent runs skip the probe.
|
|
2809
|
+
|
|
2810
|
+
CPU sessions and `auto_batch_size_strategy: static` skip the probe. Synthetic batch tensors are freed before the backward pass so peak VRAM reflects the realistic training step. SFT-only this release — non-SFT trainers fall back to the static estimate.
|
|
2811
|
+
|
|
2812
|
+
## Trace-to-Preference: LLM-Judge Filter
|
|
2813
|
+
|
|
2814
|
+
`soup data from-traces --judge` filters harvested preference pairs through an LLM judge:
|
|
2815
|
+
|
|
2816
|
+
```bash
|
|
2817
|
+
soup data from-traces \
|
|
2818
|
+
--logs ./prod-traces.jsonl --format langchain --signal thumbs_up \
|
|
2819
|
+
--output ./prefs.jsonl \
|
|
2820
|
+
--judge --judge-provider ollama --judge-model llama3 \
|
|
2821
|
+
--min-confidence 0.7
|
|
2822
|
+
```
|
|
2823
|
+
|
|
2824
|
+
The judge scores `chosen` and `rejected` independently against its rubric (default helpfulness/accuracy/safety on a 1-5 scale). Pairs whose normalised `(chosen - rejected)` confidence falls below `--min-confidence` are dropped. Per-pair backend exceptions are counted (not crashed) and reported. Provider allowlist `{openai, server, ollama}` validated at the CLI boundary; SSRF protection on `--judge-api-base` carries over from `soup eval judge`.
|
|
2825
|
+
|
|
2826
|
+
## Inference Server Trace Log
|
|
2827
|
+
|
|
2828
|
+
`soup serve --trace-log <path>` writes a passive append-only JSONL log per chat completion:
|
|
2829
|
+
|
|
2830
|
+
```bash
|
|
2831
|
+
soup serve --model ./out --trace-log ./serve-trace.jsonl --trace-log-cap-mb 100
|
|
2832
|
+
```
|
|
2833
|
+
|
|
2834
|
+
Each line: `{"ts": ..., "prompt": ..., "response": ..., "latency_ms": ..., "tokens": ...}`. Path-containment validated, hard rotation cap (default 100 MB, one backup retained), symlink-reject on the backup path (TOCTOU defence), and `hf_*` / `sk-*` / `Bearer …` token shapes redacted to `<redacted>` before write. Failures (disk full, serialisation errors) never crash the request handler.
|
|
2835
|
+
|
|
2794
2836
|
## Changelog
|
|
2795
2837
|
|
|
2796
2838
|
See [GitHub Releases](https://github.com/MakazhanAlpamys/Soup/releases) for version history.
|
|
@@ -43,17 +43,11 @@ soup train
|
|
|
43
43
|
|
|
44
44
|
Latest highlights only. Full history: [GitHub Releases](https://github.com/MakazhanAlpamys/Soup/releases).
|
|
45
45
|
|
|
46
|
-
**v0.40.
|
|
47
|
-
|
|
48
|
-
- **`--
|
|
49
|
-
- **
|
|
50
|
-
-
|
|
51
|
-
- **`soup quickstart --output DIR`** — route data, config, and run dir under any directory you choose (default keeps backwards-compat in cwd).
|
|
52
|
-
- **`soup runs --cwd-only`** — restrict the listing to runs whose `output_dir` is under the current directory; the global `~/.soup/experiments.db` view is still default.
|
|
53
|
-
- **`soup infer` / `soup bench` accept HF ids** — when the local model path is missing AND the value isn't path-like (no `./`, `/`, `~`, `C:\`), it falls through to a HuggingFace download via `transformers.from_pretrained`. Path-like-but-missing surfaces a friendly `FileNotFoundError`.
|
|
54
|
-
- **CLI flag aliases** — `data filter --min-coherence` (alias for `--coherence`); `data split --train` accepted (informational, train is the implicit remainder); `data register / unregister` accept positional `<name>` and `<path>` alongside the `--name` / `--path` options, with conflict detection.
|
|
55
|
-
- **`--log-level` plumbing complete** — `apply_logging_level` now sets the root logger so third-party libraries (transformers / peft / trl) actually respect QUIET and DEBUG. The four tiers no longer produce byte-identical output.
|
|
56
|
-
- **+36 net new tests** across the new helpers, security-fix follow-ups (path-containment in `register_data`, `bench.py`, `infer.py --output`, symlink-reject in custom Space templates), and Windows cross-drive edge cases.
|
|
46
|
+
**v0.40.4 — trust_remote_code multi-trainer + multipack live wiring**: closes two carry-over gaps from earlier releases — the v0.36.0 known gap (only SFT honoured the opt-in) and the v0.40.3-deferred multipack sampler.
|
|
47
|
+
|
|
48
|
+
- **`--trust-remote-code` everywhere** — every non-SFT trainer (DPO / GRPO / KTO / ORPO / SimPO / IPO / PPO / RewardModel / Pretrain / Embedding / BCO + the unified Preference dispatcher) now defaults to `trust_remote_code=False` and only enables custom-code execution when the user explicitly opts in. Same for `soup diff`, `soup export`, `soup merge`, `soup infer`, and `soup data generate`. The v0.36.0 `KNOWN_SAFE_PREFIXES` allowlist still suppresses the warning panel for first-party orgs; unknown-org local checkpoints with `auto_map` raise a friendly `ValueError` at construction time instead of silently exec'ing on `from_pretrained`.
|
|
49
|
+
- **Multipack sampler — live in HF Trainer** — `make_multipack_trainer_class` adds a `get_train_dataloader` override that installs a `MultipackBatchSampler(real_batches=False)` as the DataLoader's `batch_sampler=`. The shape mismatch that blocked v0.40.3 (`Sampler[int]` vs `list[list[int]]`) is gone — the sampler now yields flat `list[int]` per packed sequence, which is what `DataLoader.batch_sampler` actually expects. SFT and Pretrain wrappers instantiate the multipack subclass when `multipack: true`; the v0.40.3 yellow advisory is gone.
|
|
50
|
+
- **+75 net new tests** across the trainer×trust_remote_code matrix (parametrize over 12 wrappers × {default-off / opt-in / unknown-org rejection}), source-level invariants (no remaining `trust_remote_code=True` literal in any trainer file), the new DataLoader override (state-missing fallback + flat-pack-yield contract), and the real `transformers.Trainer` MRO mix-in.
|
|
57
51
|
|
|
58
52
|
## Why Soup?
|
|
59
53
|
|
|
@@ -570,7 +564,7 @@ training:
|
|
|
570
564
|
|
|
571
565
|
**Architecture allowlist** — 18 supported (Llama 3.x, Qwen 2/3, Mistral, Gemma 2/3, Phi 3/4, DeepSeek V2/V3, Mixtral, Falcon, StableLM, SmolLM2). Unknown architectures **fail loudly at config-load** instead of silently no-opping (critical fix vs Axolotl's silent-miss footgun).
|
|
572
566
|
|
|
573
|
-
**
|
|
567
|
+
**Live wiring** — landed. SFT and Pretrain trainer wrappers actually instantiate the multipack subclass when `multipack: true` is set. The factory's `get_train_dataloader` override installs `MultipackBatchSampler(real_batches=False)` (yields a flat `list[int]` per packed sequence — DataLoader-compatible) as the DataLoader's `batch_sampler=`, forwarding `dataloader_drop_last`/`num_workers`/`pin_memory` from `TrainingArguments`. The `_get_train_sampler` override stays as a defensive no-op fallback that always delegates to super, so any HF eval / prediction loop bypassing `get_train_dataloader` still gets the correct `Sampler[int]` shape (no nested-list shape mismatch). Multipack is **sft / pretrain only** on the `transformers` backend; preference / RLHF trainers and MLX backend get distinct error messages naming the actual reason. Datasets must expose `input_ids` (preferred) or `length` per row; raw text triggers an all-zeros warning.
|
|
574
568
|
|
|
575
569
|
**DoS hardening** — the FFD packer caps at 1M items (algorithm is O(N²) worst-case); the 4D mask builder caps allocations at 2³¹ cells; the chat-template Jinja analyzer caps at 128KB. Every numeric input rejects `bool` explicitly (matches v0.30.0+ project policy).
|
|
576
570
|
|
|
@@ -607,12 +601,19 @@ data:
|
|
|
607
601
|
|
|
608
602
|
When the tokenizer ships a chat template with `{% generation %}` markers, the mask is exact. Without those markers, Soup falls back to an incremental tokenize-delta walk and documents the looseness.
|
|
609
603
|
|
|
610
|
-
### `--trust-remote-code` opt-in
|
|
604
|
+
### `--trust-remote-code` opt-in (every command, every trainer)
|
|
605
|
+
|
|
606
|
+
Every command that loads a model now requires `--trust-remote-code` to execute custom Python from a model repo (`auto_map` in `config.json`). First-party orgs (Meta, Mistral, Qwen, Google, etc.) suppress the warning panel; everything else prints a `REMOTE CODE WARNING` panel before loading. Unknown-org local checkpoints with `auto_map` raise a friendly `ValueError` at construction time instead of silently exec'ing inside `from_pretrained`.
|
|
611
607
|
|
|
612
|
-
|
|
608
|
+
Coverage:
|
|
609
|
+
- `soup train` (every task — SFT, DPO, GRPO, KTO, ORPO, SimPO, IPO, PPO, Reward Model, Pretrain, Embedding, BCO, and the unified Preference dispatcher)
|
|
610
|
+
- `soup chat`, `soup serve`, `soup data download`, `soup eval auto`
|
|
611
|
+
- `soup diff`, `soup export`, `soup merge`, `soup infer`, `soup data generate`
|
|
613
612
|
|
|
614
613
|
```bash
|
|
615
614
|
soup train --config soup.yaml --trust-remote-code
|
|
615
|
+
soup infer --model my-org/custom-arch-model --input prompts.jsonl --trust-remote-code
|
|
616
|
+
soup export --model ./adapter --format gguf --trust-remote-code
|
|
616
617
|
```
|
|
617
618
|
|
|
618
619
|
### Chat-template hardening
|
|
@@ -2488,6 +2489,7 @@ soup serve --model <m> --structured-output json --json-schema s.json Constraine
|
|
|
2488
2489
|
soup serve --model <m> --structured-output regex --regex-pattern '...' Regex-constrained output
|
|
2489
2490
|
soup serve --model <m> --dashboard Live dashboard + /metrics endpoint
|
|
2490
2491
|
soup serve --model <m> --trace --trace-endpoint http://localhost:4317 OpenTelemetry tracing
|
|
2492
|
+
soup serve --model <m> --trace-log ./serve.jsonl Per-request JSONL log + rotation + secret redaction
|
|
2491
2493
|
POST /v1/adapters/activate/<name> Hot-swap active LoRA adapter
|
|
2492
2494
|
soup sweep --config soup.yaml --param lr=... Hyperparameter search
|
|
2493
2495
|
soup diff --model-a ./a --model-b ./b Compare two models
|
|
@@ -2503,7 +2505,9 @@ soup data generate ... --provider anthropic Use Claude API
|
|
|
2503
2505
|
soup data generate ... --provider vllm Use local vLLM server
|
|
2504
2506
|
soup data generate ... --template code Domain templates (code/conversation/qa/preference/reasoning)
|
|
2505
2507
|
soup data generate ... --quality-pipeline Auto validate + filter + dedup
|
|
2506
|
-
soup data augment <path> --strategy rephrase|translate|style LLM-driven augmentationsoup data from-traces --logs l.jsonl --format langchain --signal thumbs_up --output p.jsonl Preference pairs from
|
|
2508
|
+
soup data augment <path> --strategy rephrase|translate|style LLM-driven augmentationsoup data from-traces --logs l.jsonl --format langchain --signal thumbs_up --output p.jsonl Preference pairs from traces
|
|
2509
|
+
soup data from-traces ... --judge --min-confidence 0.7 LLM-judge confidence filter
|
|
2510
|
+
soup data review prefs.jsonl --sample 10 Preview preference pairssoup data filter <path> --coherence 0.3 Quality filter (perplexity/coherence)
|
|
2507
2511
|
soup data sample <path> --n 1000 Random sample subset
|
|
2508
2512
|
soup data sample <path> --n 1000 --strategy diverse Cluster-based diverse sampling
|
|
2509
2513
|
soup data sample <path> --n 1000 --strategy hard Sample hardest examples
|
|
@@ -2700,6 +2704,44 @@ pytest tests/ -v
|
|
|
2700
2704
|
pytest tests/ -m smoke -v
|
|
2701
2705
|
```
|
|
2702
2706
|
|
|
2707
|
+
## Live CUDA Batch-Size Probe
|
|
2708
|
+
|
|
2709
|
+
Set `auto_batch_size_strategy: probe` in `training:` and Soup will run a real OOM-probe before training:
|
|
2710
|
+
|
|
2711
|
+
```yaml
|
|
2712
|
+
training:
|
|
2713
|
+
batch_size: auto
|
|
2714
|
+
auto_batch_size_strategy: probe
|
|
2715
|
+
```
|
|
2716
|
+
|
|
2717
|
+
For each candidate size `B`, the probe runs ONE forward + backward + step on a synthetic batch of `B` sequences of length `max_length`. On `torch.cuda.OutOfMemoryError` it halves; otherwise it doubles up to `4 × static_estimate`. The picked size is cached per `(model, max_length, quantization, lora_r, gpu)` tuple in `~/.soup/batch_cache.json` so subsequent runs skip the probe.
|
|
2718
|
+
|
|
2719
|
+
CPU sessions and `auto_batch_size_strategy: static` skip the probe. Synthetic batch tensors are freed before the backward pass so peak VRAM reflects the realistic training step. SFT-only this release — non-SFT trainers fall back to the static estimate.
|
|
2720
|
+
|
|
2721
|
+
## Trace-to-Preference: LLM-Judge Filter
|
|
2722
|
+
|
|
2723
|
+
`soup data from-traces --judge` filters harvested preference pairs through an LLM judge:
|
|
2724
|
+
|
|
2725
|
+
```bash
|
|
2726
|
+
soup data from-traces \
|
|
2727
|
+
--logs ./prod-traces.jsonl --format langchain --signal thumbs_up \
|
|
2728
|
+
--output ./prefs.jsonl \
|
|
2729
|
+
--judge --judge-provider ollama --judge-model llama3 \
|
|
2730
|
+
--min-confidence 0.7
|
|
2731
|
+
```
|
|
2732
|
+
|
|
2733
|
+
The judge scores `chosen` and `rejected` independently against its rubric (default helpfulness/accuracy/safety on a 1-5 scale). Pairs whose normalised `(chosen - rejected)` confidence falls below `--min-confidence` are dropped. Per-pair backend exceptions are counted (not crashed) and reported. Provider allowlist `{openai, server, ollama}` validated at the CLI boundary; SSRF protection on `--judge-api-base` carries over from `soup eval judge`.
|
|
2734
|
+
|
|
2735
|
+
## Inference Server Trace Log
|
|
2736
|
+
|
|
2737
|
+
`soup serve --trace-log <path>` writes a passive append-only JSONL log per chat completion:
|
|
2738
|
+
|
|
2739
|
+
```bash
|
|
2740
|
+
soup serve --model ./out --trace-log ./serve-trace.jsonl --trace-log-cap-mb 100
|
|
2741
|
+
```
|
|
2742
|
+
|
|
2743
|
+
Each line: `{"ts": ..., "prompt": ..., "response": ..., "latency_ms": ..., "tokens": ...}`. Path-containment validated, hard rotation cap (default 100 MB, one backup retained), symlink-reject on the backup path (TOCTOU defence), and `hf_*` / `sk-*` / `Bearer …` token shapes redacted to `<redacted>` before write. Failures (disk full, serialisation errors) never crash the request handler.
|
|
2744
|
+
|
|
2703
2745
|
## Changelog
|
|
2704
2746
|
|
|
2705
2747
|
See [GitHub Releases](https://github.com/MakazhanAlpamys/Soup/releases) for version history.
|
|
@@ -9,7 +9,7 @@ We provide security updates for the following versions:
|
|
|
9
9
|
- **Versions older than 3 minor versions:** No support
|
|
10
10
|
|
|
11
11
|
Example:
|
|
12
|
-
- v0.40.
|
|
12
|
+
- v0.40.4 -- Full support (latest)
|
|
13
13
|
- v0.40.0-v0.40.x -- Full support
|
|
14
14
|
- v0.39.0-0.39.x -- Bug-fix support only
|
|
15
15
|
- v0.38.0-0.38.x -- Bug-fix support only
|
|
@@ -144,6 +144,8 @@ No known critical vulnerabilities in current releases.
|
|
|
144
144
|
- **v0.32.0 — Training Stability & Auto-Tuning**: `--find-lr-output` containment via shared `utils/paths.is_under_cwd` (prevents writes outside cwd); `save_lr_finder_report` rejects NaN / Infinity floats in `lrs` / `losses` and serialises with `allow_nan=False` (keeps the report parser-safe); `compute_lr_schedule` rejects non-positive `start_lr`, inverted ranges, and `num_steps` outside `[2, 10_000]`; `pick_mixed_precision` rejects empty / null-byte / >200-char model names and resolves multi-version quirks (`qwen2.5` vs `qwen2`, `phi-3.5` vs `phi-3`) by longest-substring-first iteration so an added family can never accidentally make a more-specific entry dead code; `compute_warmup_steps` clamps to `[10, 1000]` with a `ratio==0.0` short-circuit matching HF Trainer's "no warmup" convention; `SpikeRecoveryStrategy` is `@dataclass(frozen=True)` (post-construction mutation cannot bypass validation), `max_attempts ∈ [1, 10]`, `lr_decay ∈ (0, 1)`, `min_lr > 0`; cross-validator `_validate_spike_recovery_requires_watchdog` rejects `loss_spike_recovery=true, loss_watchdog=false` at config-load (fails fast instead of never triggering); `convergence_window ∈ [5, 10_000]`, `convergence_rel_tol ∈ (0, 1]`, `recommend_action` reuses `detect_plateau` so plateau heuristic stays single-source-of-truth; `GradAccumMonitor.recommend()` caps doubled `accum` at `MAX_ACCUM=1024` so a runaway advisory loop cannot blow up DataLoader prefetch; `generate_config` validates BOTH the YAML output path AND the embedded `decisions["output"]` field via `is_under_cwd` (closes the gap where a crafted `decisions["output"]="../../etc"` would have silently propagated into the rendered YAML)
|
|
145
145
|
- **v0.34.0 — Observability & Dev UX**: `.crash` bundle generator (`utils/crash.py`) recursively redacts `hf_*` / `sk-*` / `Bearer …` token-shaped strings in any captured `config` and metric tail before serialisation, so a `.crash` file shared on a public GitHub issue cannot leak credentials; `output_dir` is reduced to `os.path.basename` so `$HOME` doesn't leak; `write_crash_bundle` uses `os.path.realpath + commonpath` for cwd containment (Windows-safe; raises `ValueError` not `PermissionError` so callers cannot silently swallow with `except OSError`); filename appends `secrets.token_hex(4)` so two crashes in the same UTC second don't collide; bundle truncated to `MAX_BUNDLE_BYTES=1_000_000`. `train.py` crash-write surfaces failures to the user (no silent missing-bundle). `profiling.py` `resolve_trace_path` rejects empty / `.` / `..` / `/` / `\\` / null-byte `run_id` (closes the `output_dir/profiles/../trace.json` escape) and uses `os.path.realpath + is_under_cwd`; profiles dir is created only on successful torch import (no stale empty dirs on torch-less CI). `tracker.get_run` LIKE-prefix match escapes `%` / `_` / `\\` and uses `ESCAPE '\\'` so a crafted `run_id` cannot widen the match (mirrors v0.26.0 registry policy). Lazy schema migration (`_ensure_schema`) tolerates the "duplicate column" race when two CLI processes start simultaneously on a fresh DB (fork-based multi-GPU training, TUI auto-refresh). `runs.py show/replay/clean` switched user `run_id` rendering to `markup_escape` and switched `clean` containment from broken `Path.resolve() + relative_to()` to project-standard `os.path.realpath + is_under_cwd`. `tui_app.py` lazy-imports `ExperimentTracker` and `markup_escape`s every DB-sourced string before passing into Textual widgets so a crafted base_model / experiment_name cannot inject `[bold red]…[/]` markup. `run_cost.estimate_run_cost_usd` rejects `bool` in `num_gpus` (bool is a subclass of int — same defence as v0.30.0 `Candidate.__post_init__`); duration clamped to `[0, 1 year]`; unknown GPU returns `None` so callers render `—` instead of fabricating `$0.00`. `log_level.parse_log_level` rejects non-string + null-byte input.
|
|
146
146
|
- **v0.33.0 — Live Wire**: RLVR `code_exec_reward` adds OS-level isolation (Linux best-effort `os.unshare(CLONE_NEWUSER|CLONE_NEWNET|CLONE_NEWPID)`, macOS `sandbox-exec` with default-deny `MACOS_SANDBOX_PROFILE` narrowed to a 3-name `mach-lookup` allowlist to prevent DNS / NSURLSession bypass of `(deny network*)`); `prune_checkpoints` switches to TOCTOU-safe `os.lstat + S_ISLNK` + `shutil.rmtree(onerror=_abort_on_symlink)` so a symlink encountered mid-walk aborts rather than escapes; `run_gate` wraps each task scorer in a typed `try/except` so backend failures produce `score=None, error=str(exc)` (never silent `score=1.0`); `_parse_judge_url` removes the bare `http://` catch-all (defence-in-depth after the Pydantic GateTask validator); `soup can run` requires `--yes` or explicit consent callback and raises `ValueError` (not `PermissionError`, which is an `OSError` subclass that broad `except` blocks would swallow); GGUF `rglob` result for ollama deploy is `realpath+commonpath` checked against extract_dir (prevents symlink escape from a crafted can); `DeployTarget.path` validator normalises mixed `\\`/`/` separators before splitting (closes a Windows `..` bypass); `CAN_FORMAT_VERSION` 1→2 (additive — v1 still loads); `soup can publish` validates `repo_id` via `utils/hf.validate_repo_id`, resolves token via `resolve_token`, sanitises commit messages (first-line, 200-char cap), uses HTTPS-only HfApi; `_write_spike_recovery_hint` adds `is_under_cwd` containment check on `args.output_dir` from raw HF `TrainingArguments`; `lookup_entry_by_output_dir` emits `ResourceWarning` when 1000-row scan limit is hit (no silent miss); `CrossDocCollator` no longer mutates input feature dicts (HF Dataset rows are cached and reused — mutation broke subsequent batches); `Candidate` rejects `bool` in `score`/`latency_ms` (was sneaking past `int` isinstance check); `evaluate_candidate` latency mean now divides by *completed* prompts (excludes crashed) so a broken candidate isn't artificially fast; `auto_quant.run_auto_quant_picker` soft-falls-back to highest-scored candidate when no candidate clears `min_score` (server still binds); `build_logits_processors` returns `[]` when neither `outlines` nor `lm-format-enforcer` is installed (server degrades to free-form rather than 500); MII server uses loopback-only CORS, max_tokens cap [1, 16384], stream rejection, generic 500 with no stack-trace leak; `os.execvp` auto-reexec uses list args (no shell), all forwarded flags pre-validated; `cleanup_extract_dir` uses `os.path.commonpath` (Windows-safe) instead of `startswith`; `_run_subprocess` catches `TimeoutExpired` and returns rc=124 (coreutils convention) instead of an unhandled traceback; new `eval_results` and `tensorrt` artifact kinds in `RegistryStore._VALID_KINDS`
|
|
147
|
+
- **v0.40.4 — trust_remote_code multi-trainer + multipack live**: closes the v0.36.0 #63 known gap by extending the `--trust-remote-code` opt-in across every non-SFT trainer wrapper (DPO / GRPO / KTO / ORPO / SimPO / IPO / PPO / RewardModel / Pretrain / Embedding / BCO + the unified `PreferenceTrainerWrapper` dispatcher) and the 5 standalone commands (`soup diff`, `soup export`, `soup merge`, `soup infer`, `soup data generate`). Pattern (15 sites): each `__init__` resolves once via `model_requires_trust_remote_code(config.base) or False` + `resolve_trust_remote_code(...)` and stores `self._trust_remote_code` — every `from_pretrained` call site now reads the resolved value (no remaining `trust_remote_code=True` literal in any trainer file; source-level invariant test in `tests/test_v0404_part_a.py`). `commands/train.py` no longer carries the v0.36.0 `sft_kwargs` split; `trust_remote_code` is part of the unified `trainer_kwargs` dict that flows to every trainer regardless of task. `_load_reward_model` (module-level helper in `ppo.py`) accepts a `trust_remote_code: bool` parameter and resolves internally — design intent is that the helper is independently safe to call from outside `PPOTrainerWrapper`. `PreferenceTrainerWrapper` dispatcher forwards the raw bool to the inner DPO/SimPO/ORPO/IPO/BCO wrapper kwargs at both `_build_inner` and `_build_multi_objective` sites; the resolver fires inside the inner wrapper at construction time. `_export_onnx` / `_export_tensorrt` / `_export_awq` / `_export_gptq` and `_merge_adapter` helpers all gain a `trust_remote_code: bool = False` parameter threaded from the Typer flag. Multipack live HF Trainer wiring (#65) lands via a new `get_train_dataloader` override on `make_multipack_trainer_class` that installs `MultipackBatchSampler(real_batches=False)` (yields flat `list[int]` per pack — DataLoader-compatible) as the DataLoader's `batch_sampler=`. The override forwards `args.dataloader_drop_last` / `dataloader_num_workers` / `dataloader_pin_memory` from `TrainingArguments`. `_get_train_sampler` override stays as a defensive no-op fallback that ALWAYS delegates to super (review-fix: a multipack `list[list[int]]` from this method would cause a shape mismatch if any HF eval / prediction loop bypasses `get_train_dataloader`). The state-presence guard switched from falsy (`not max_seq`) to explicit `is None` + `not lengths` (defensively rejects only-None and empty-list cases — non-positive ints already rejected upstream by `attach_multipack_state`). Falls back to `super().get_train_dataloader()` when state is missing OR when `train_dataset` is unset (defence-in-depth so the subclass remains safe to instantiate). Known limitations: (1) `multipack: true` requires the dataset to expose `input_ids` (preferred) or `length` per row — un-tokenized text-only datasets trigger the v0.40.3 all-zeros WARNING and the `MultipackBatchSampler` will reject the run. (2) The DataLoader override does NOT thread FSDP / DeepSpeed parallelism env hints from `super().get_train_dataloader()`, so distributed `multipack: true` runs are still untested under FSDP / ZeRO; tracked for v0.40.5+ paired with v0.42.0 multi-GPU work. (3) `_live_lr_sweep_from_config` in `commands/train.py` still hardcodes `trust_remote_code=False` for the LR sweep's internal model load — defensive but means `--find-lr` cannot consume custom-code models even with the user opt-in (defence-in-depth, not a bypass). (4) Each non-SFT trainer's `__init__` repeats the resolver block (10 sites) — code-quality refactor candidate (single shared helper) deferred to a future patch to keep the v0.40.4 diff focused on the gap closure.
|
|
148
|
+
- **v0.40.3 — Stub-to-live**: New `soup_cli/utils/batch_probe.py:make_cuda_probe_fn` builds a CUDA probe closure that runs ONE forward+backward+step on a synthetic batch per candidate; `model.zero_grad(set_to_none=True)` runs BEFORE forward (defends against the synthetic backward accumulating into the live training model's grad buffers — matches v0.35.0 #45 `benchmark_kernel_combos` policy); intermediate `ids/attn/labels/outputs` are `del`-ed before `loss.backward()` so peak VRAM reflects a realistic training step; `bool` rejected on `batch_size` and `max_length`; `max_length < 8` rejected; `torch.cuda.OutOfMemoryError` returns False, other exceptions propagate; returns `None` (no-op) on non-CUDA / no-torch / missing model or tokenizer. New `soup_cli/utils/multipack_trainer.py:make_multipack_trainer_class` is `lru_cache`d so two calls with the same `base_cls` return the same subclass (consistent `isinstance`, pickle-safe); `attach_multipack_state` rejects `bool` on `max_seq_len`/`batch_size`/`seed` and rejects empty `lengths`; `lengths_from_dataset` logs WARNING when every row produces 0 (loud-fail mirrors v0.37.0 multipack arch allowlist — prevents silent NaN-loss footgun); `_get_train_sampler` override accepts `*args, **kwargs` for HF >= 4.41 signature compat. **Live wiring of the sampler into SFT / Pretrain trainer wrappers is deferred to v0.40.4** — adversarial 5th-pass review surfaced a `Sampler[int]` vs `list[list[int]]` shape mismatch with HF Trainer's DataLoader; the wrappers currently print a yellow advisory and fall back to the standard sampler when `multipack: true`. New `soup_cli/data/traces/quality.py:judge_filter_pairs` reuses v0.19.0 `JudgeEvaluator` SSRF protections; threshold rejects `bool` / NaN / out-of-`[0,1]`; `_MAX_BATCH=100_000` cap applied via lazy `itertools.islice` (never fully materialises a malicious / pathological generator); per-pair backend exceptions caught and logged at DEBUG (matches v0.33.0 #47 `CrossDocCollator` policy — never silently crash the harvest); `judge_provider` validated against `VALID_PROVIDERS` allowlist at the CLI boundary BEFORE constructor, with a Rich-escape error on mismatch. New `soup_cli/monitoring/trace_logger.py:TraceLogWriter` is thread-safe (single `threading.Lock` — multi-worker `--workers 4` documented as a single-process 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: when `current + extra > cap_bytes`, rename to `<path>.1` (one backup retained); symlink at the backup path is rejected via `os.lstat + stat.S_ISLNK` (matches v0.33.0 #22 TOCTOU policy) — defends against pre-placed `<log>.1 -> /etc/cron.d/x` overwrite. Secret redaction: prompt + response strings passed through `_SECRET_RE` matching `hf_*` (≥8), `sk-*` (≥16), and `Bearer …` (≥8) — replaces matches with `<redacted>` before serialisation (mirrors v0.34.0 `crash.py` policy). `--trace-log` constructor error messages in `commands/serve.py` are `rich.markup.escape`d before printing so a crafted path name cannot inject Rich markup. Unserialisable entries dropped silently; disk-full / OSError on write never crashes the request handler (passive log). Known limitations: live CUDA probe is wired in SFT only; multipack live wiring covers SFT+Pretrain only; `TraceLogWriter` retains exactly ONE backup file (operators wanting longer retention should use external rotation); custom HF Space templates from v0.40.2 still always create the Space with `space_sdk="gradio"` (tracked for v0.40.4+).
|
|
147
149
|
- **v0.40.2 — Quick polish + carry-overs**: New `soup_cli/utils/hf_space.py:render_custom_template_dir` enforces `is_under_cwd` containment on the template directory; `validate_repo_id` runs BEFORE `{MODEL_REPO}` substitution (matches v0.29.0 Part F policy); per-file 256 KB cap (matches v0.39.0 Part E template-size policy); only `app.py` / `README.md` / `requirements.txt` are read (closed allowlist — no path-from-user-data). Symlinks rejected via `os.lstat + stat.S_ISLNK` and non-regular files (FIFO / device) also rejected (matches v0.33.0 #22 prune_checkpoints TOCTOU policy) — defends against `<template_dir>/app.py -> /etc/passwd`. `_find_highest_local_checkpoint` reads `output_dir` after caller's `is_under_cwd` validation (in `prepare_hf_resume`) and silently drops non-directories + OSError. `prepare_hf_resume` skips the snapshot download when local `checkpoint-N >= remote checkpoint-N` (saves bandwidth and never overwrites a fresher local checkpoint). `commands/data.py:register_data` containment switched from `Path.resolve() + relative_to()` to shared `is_under_cwd` (Windows 8.3 short-name safety per CLAUDE.md project rule); same fix applied to `commands/bench.py` prompts-file containment. `commands/infer.py:--output` now containment-checked via `is_under_cwd` (late-evaluated after model+input validation so pre-existing `tmp_path` test contracts keep working). `commands/quickstart.py:--output` validates target dir via `is_under_cwd` before `mkdir(parents=True)`; rejects out-of-cwd targets with friendly message. `commands/runs.py:_filter_runs_by_cwd` uses `os.path.realpath + commonpath`, catches `(ValueError, OSError)` so cross-drive paths on Windows (`D:\runs` vs `C:\project`) drop silently rather than crash. `monitoring/display.py:format_gate_row` uses explicit `task.get("passed") is True` so a missing `"passed"` field renders neutrally instead of as a false-y red ✗. `commands/infer.py:_resolve_model_source` heuristic for HF-id-vs-local-path: only falls through to HF when value is NOT path-like (no `./`, `/`, `\\`, `~`, no Windows drive letter, non-empty); path-like-but-missing raises `FileNotFoundError` so users see actionable errors instead of confusing HF download attempts. Known limitation: custom HF Space templates always create the Space with `space_sdk="gradio"` regardless of the supplied `app.py` (no `--sdk` flag in this release; combine `--template streamlit-chat` with the inline registry for Streamlit Spaces). Tracked for v0.40.3+.
|
|
148
150
|
- **v0.40.1 — QA Hardening**: `soup_cli/utils/encoding.force_utf8_stdio` reconfigures Windows stdout/stderr to UTF-8 before any Rich Console is constructed; `os.environ.setdefault("PYTHONIOENCODING", "utf-8")` preserves user override; `(OSError, ValueError, AttributeError)` swallowed on detached streams; POSIX no-op. `SoupConfig._remap_root_level_misplaced_keys` (model_validator, mode='before') migrates root-level `lora:` into `training.lora` so nested validators (including `lora.init_strategy: Literal["random","pissa","olora"]`) actually fire — closes a footgun where the misplaced key was silently dropped. Caller's dict is never mutated (shallow-copy policy mirroring v0.33.0 #47 / v0.40.0 Part B). `PreferenceTrainerWrapper._build_multi_objective` replaces the v0.40.0 `NotImplementedError` stub with a primary-loss approximation; `validate_weight_compat` rejects BCO mixed with paired losses at runtime (data-format incompatible). `combine_losses` rejects empty weights, propagates NaN loudly (no silent zeroing), and rejects `bool` weight values (matches v0.30.0 `Candidate` policy). `_probe_cache_param_count` rejects empty / null-byte model names before path construction (mirrors v0.26.0 registry / v0.39.0 ReLoRAPolicy policy). `commands/doctor` flags `transformers ≥ 5.0.0` as INCOMPATIBLE via `_MAX_EXCLUSIVE` table; `_version_ge` parses leading-int chunks so `5.0.0.dev0` correctly trips the cap. `_detect_gpu_hw_without_torch_cuda` calls `nvidia-smi` via argv list (no shell), 5s timeout, `OSError` / `TimeoutExpired` caught; GPU label from `nvidia-smi` stdout is `rich.markup.escape`d before embedding in Rich-markup string (a real GPU name like `NVIDIA Quadro [T4]` cannot break or inject markup). `_detect_dual_python_interpreters` uses `os.path.realpath` (not `Path.resolve()`) for Windows 8.3 short-name compat. `_pick_quickstart_model` swaps TinyLlama-1.1B → SmolLM2-135M when `total_memory ≤ 6 GB` (prevents step-0 OOM on RTX 3050 4 GB / similar). `_live_lr_sweep_from_config` switched broken `load_local` import to `load_raw_data` (previously always silently fell back to a static placeholder curve). `commands/migrate` rejects `.jsonl` input (with first-line `{` sniff) with exit-2 friendly error; `.jsonl`-only suffix gate prevents false-positives on `.ipynb` notebooks. `commands/eval custom -o` is now honored independently of `--attach-to-registry`; loop-shadow regression where `output = generate_fn(...)` overwrote the CLI option fixed (variable renamed to `response`). `_load_jsonl` switched from `utf-8` to `utf-8-sig` so PowerShell `Out-File -Encoding utf8`-produced JSONL no longer fails first-row parse. Known limitation: `--trust-remote-code` opt-in surface still excludes 10 non-SFT trainers + 5 commands (v0.36.0 #63 carry-over).
|
|
149
151
|
- **v0.40.0 — Preference Variety**: New `task='bco'` (Binary Classifier Optimization) and `task='preference'` (unified dispatcher). New schema fields: `bco_beta` (gt=0), `preference_loss: Literal[dpo,simpo,orpo,ipo,bco]|None`, `preference_loss_weights: Optional[Dict[str,float]]`, `dpo_beta_schedule: Literal[linear,cosine,exponential]|None`, `dpo_beta_end: float, gt=0|None`, `dpo_ref_regen_epochs: int [1,1000]|None`. Cross-validators: `_validate_preference_dispatcher` rejects setting either `preference_loss` or `preference_loss_weights` outside `task='preference'` (closes ordering-dependency between Part B/D validators); `_validate_dpo_variants_supported_tasks` gates β-schedule + ref-regen to DPO-family tasks (`dpo`, `ipo`, or `preference` + `preference_loss in {dpo, ipo}`); rejected on mlx backend with distinct error message (matches v0.34.0 distinct-reason policy); `_validate_preference_loss_weights` enforces 2–5 entries (single-entry rejected with actionable message pointing at scalar `preference_loss`), key allowlist `{dpo, simpo, orpo, ipo, bco}`, explicit null-byte rejection on keys (matches v0.39.0 rank_pattern policy), per-value bounds `(0, 1]`, weights must sum to 1.0 (±1e-6), mutually exclusive with scalar `preference_loss`, rejected on mlx backend. `compute_beta_at_step` rejects `bool` on `step` and `total_steps` (project bool-as-int policy from v0.30.0). `BetaScheduleCallback` resolves `total_steps` lazily in `on_train_begin` so the schedule sees the real `state.max_steps` populated by HF Trainer (closes a first-cut silent-no-op bug where total_steps=0 emitted beta_end for every step). `RefModelRegenCallback._regenerate` uses `strict=True` on `load_state_dict` and logs at WARNING on mismatch (closes a first-cut silent partial-copy hazard where strict=False could produce a hybrid old-base + new-LoRA reference); epoch 0 regen suppressed (avoids copying untrained student); trainer `.beta` assignment swallow narrowed to `AttributeError` only. `PreferenceTrainerWrapper._make_inner_cfg` uses `model_copy` (not `model_dump`+`model_validate`) so re-validation never sees an inconsistent intermediate state and the caller's `cfg` is never mutated (mirrors v0.33.0 #47 immutability policy). `_split_dpo_rows_to_bco` skipped-row count emitted at DEBUG so production silent-degradation is inspectable (mirrors v0.33.0 #47 CrossDocCollator policy). Multi-objective live runtime weighted-loss combination is deferred to v0.40.1: `PreferenceTrainerWrapper.setup` raises `NotImplementedError` with a friendly message naming the deferred-version follow-up (mirrors v0.27.0 MII / v0.37.0 multipack / v0.38.0 quant menu / v0.39.0 ReLoRA stub-then-live pattern). Known limitation: `BCOTrainerWrapper._setup_transformers` still hardcodes `trust_remote_code=True` (v0.36.0 #63 known-gap family carry-over across non-SFT trainers).
|
|
@@ -1586,6 +1586,26 @@ def from_traces_cmd(
|
|
|
1586
1586
|
"prefs.jsonl", "--output", "-o",
|
|
1587
1587
|
help="Output path for preference pairs (JSONL)",
|
|
1588
1588
|
),
|
|
1589
|
+
judge: bool = typer.Option(
|
|
1590
|
+
False, "--judge",
|
|
1591
|
+
help="Filter pairs via LLM-as-a-judge confidence (v0.40.3 #33).",
|
|
1592
|
+
),
|
|
1593
|
+
judge_provider: str = typer.Option(
|
|
1594
|
+
"openai", "--judge-provider",
|
|
1595
|
+
help="Judge backend: openai | server | ollama. Used with --judge.",
|
|
1596
|
+
),
|
|
1597
|
+
judge_model: str = typer.Option(
|
|
1598
|
+
"gpt-4o-mini", "--judge-model",
|
|
1599
|
+
help="Judge model id (e.g. 'gpt-4o-mini', 'llama3', 'qwen2.5'). Used with --judge.",
|
|
1600
|
+
),
|
|
1601
|
+
judge_api_base: Optional[str] = typer.Option(
|
|
1602
|
+
None, "--judge-api-base",
|
|
1603
|
+
help="Judge API base URL. SSRF-protected. Used with --judge.",
|
|
1604
|
+
),
|
|
1605
|
+
min_confidence: float = typer.Option(
|
|
1606
|
+
0.7, "--min-confidence",
|
|
1607
|
+
help="Drop pairs with judge-confidence below this threshold (0.0 - 1.0).",
|
|
1608
|
+
),
|
|
1589
1609
|
) -> None:
|
|
1590
1610
|
"""Harvest preference pairs from production traces (v0.26.0 Part C).
|
|
1591
1611
|
|
|
@@ -1666,6 +1686,53 @@ def from_traces_cmd(
|
|
|
1666
1686
|
trace_iter = parse_openai(events)
|
|
1667
1687
|
|
|
1668
1688
|
pairs = list(build_pairs(trace_iter, signal=signal))
|
|
1689
|
+
|
|
1690
|
+
if judge:
|
|
1691
|
+
# v0.40.3 (#33 (a)) — LLM-judge confidence filter.
|
|
1692
|
+
from soup_cli.data.traces.quality import judge_filter_pairs
|
|
1693
|
+
from soup_cli.eval.judge import VALID_PROVIDERS, JudgeEvaluator
|
|
1694
|
+
|
|
1695
|
+
# Friendly early validation matches the existing CLI conventions —
|
|
1696
|
+
# fall through to the constructor only after the obvious typo is caught.
|
|
1697
|
+
if judge_provider not in VALID_PROVIDERS:
|
|
1698
|
+
console.print(
|
|
1699
|
+
f"[red]--judge-provider '{_escape(judge_provider)}' is invalid. "
|
|
1700
|
+
f"Choose: {', '.join(sorted(VALID_PROVIDERS))}[/]"
|
|
1701
|
+
)
|
|
1702
|
+
raise typer.Exit(1)
|
|
1703
|
+
|
|
1704
|
+
try:
|
|
1705
|
+
judge_evaluator = JudgeEvaluator(
|
|
1706
|
+
provider=judge_provider,
|
|
1707
|
+
model=judge_model,
|
|
1708
|
+
api_base=judge_api_base,
|
|
1709
|
+
)
|
|
1710
|
+
except ValueError as exc:
|
|
1711
|
+
console.print(f"[red]--judge config error:[/] {_escape(str(exc))}")
|
|
1712
|
+
raise typer.Exit(1) from exc
|
|
1713
|
+
|
|
1714
|
+
# Cost-shock warning: each pair → TWO judge calls (chosen + rejected).
|
|
1715
|
+
projected = len(pairs) * 2
|
|
1716
|
+
console.print(
|
|
1717
|
+
f"[yellow]Judge filter will issue ~{projected} backend calls "
|
|
1718
|
+
f"({len(pairs)} pairs × 2). Cost depends on provider and model. "
|
|
1719
|
+
f"Use --min-confidence to tune throughput.[/]"
|
|
1720
|
+
)
|
|
1721
|
+
|
|
1722
|
+
try:
|
|
1723
|
+
filtered, report = judge_filter_pairs(
|
|
1724
|
+
pairs, judge=judge_evaluator, min_confidence=min_confidence,
|
|
1725
|
+
)
|
|
1726
|
+
except (TypeError, ValueError) as exc:
|
|
1727
|
+
console.print(f"[red]--judge runtime error:[/] {_escape(str(exc))}")
|
|
1728
|
+
raise typer.Exit(1) from exc
|
|
1729
|
+
|
|
1730
|
+
console.print(
|
|
1731
|
+
f"[green]Judge filter:[/] kept={report.kept} dropped={report.dropped} "
|
|
1732
|
+
f"errors={report.errors} (min_confidence={min_confidence:.2f})"
|
|
1733
|
+
)
|
|
1734
|
+
pairs = filtered
|
|
1735
|
+
|
|
1669
1736
|
with output_path.open("w", encoding="utf-8") as fh:
|
|
1670
1737
|
for pair in pairs:
|
|
1671
1738
|
fh.write(_json.dumps(pair.to_jsonl_dict(), ensure_ascii=False) + "\n")
|
|
@@ -69,6 +69,14 @@ def diff(
|
|
|
69
69
|
"-o",
|
|
70
70
|
help="Save results to JSONL file",
|
|
71
71
|
),
|
|
72
|
+
trust_remote_code: bool = typer.Option(
|
|
73
|
+
False,
|
|
74
|
+
"--trust-remote-code",
|
|
75
|
+
help=(
|
|
76
|
+
"Allow loading models that ship custom Python via auto_map. "
|
|
77
|
+
"Default deny (v0.36.0). Only enable if you trust the source."
|
|
78
|
+
),
|
|
79
|
+
),
|
|
72
80
|
):
|
|
73
81
|
"""Compare outputs of two models side-by-side on the same prompts."""
|
|
74
82
|
# Validate model paths
|
|
@@ -105,9 +113,13 @@ def diff(
|
|
|
105
113
|
|
|
106
114
|
# Load models
|
|
107
115
|
console.print("[dim]Loading Model A...[/]")
|
|
108
|
-
model_obj_a, tokenizer_a = _load_model(
|
|
116
|
+
model_obj_a, tokenizer_a = _load_model(
|
|
117
|
+
str(path_a), base_a, device, trust_remote_code,
|
|
118
|
+
)
|
|
109
119
|
console.print("[dim]Loading Model B...[/]")
|
|
110
|
-
model_obj_b, tokenizer_b = _load_model(
|
|
120
|
+
model_obj_b, tokenizer_b = _load_model(
|
|
121
|
+
str(path_b), base_b, device, trust_remote_code,
|
|
122
|
+
)
|
|
111
123
|
console.print("[green]Both models loaded.[/]\n")
|
|
112
124
|
|
|
113
125
|
# Run comparison
|
|
@@ -199,11 +211,21 @@ def _collect_prompts(prompts_file: Optional[str], prompt_args: Optional[list[str
|
|
|
199
211
|
return result
|
|
200
212
|
|
|
201
213
|
|
|
202
|
-
def _load_model(
|
|
214
|
+
def _load_model(
|
|
215
|
+
model_path: str,
|
|
216
|
+
base_model: Optional[str],
|
|
217
|
+
device: str,
|
|
218
|
+
trust_remote_code: bool = False,
|
|
219
|
+
):
|
|
203
220
|
"""Load a model and tokenizer."""
|
|
204
221
|
import torch
|
|
205
222
|
from transformers import AutoModelForCausalLM, AutoTokenizer
|
|
206
223
|
|
|
224
|
+
from soup_cli.utils.trust_remote import (
|
|
225
|
+
model_requires_trust_remote_code,
|
|
226
|
+
resolve_trust_remote_code,
|
|
227
|
+
)
|
|
228
|
+
|
|
207
229
|
path = Path(model_path)
|
|
208
230
|
adapter_config_path = path / "adapter_config.json"
|
|
209
231
|
is_adapter = adapter_config_path.exists()
|
|
@@ -220,7 +242,16 @@ def _load_model(model_path: str, base_model: Optional[str], device: str):
|
|
|
220
242
|
console.print(f"[red]Cannot detect base model for {path}. Use --base-a/--base-b.[/]")
|
|
221
243
|
raise typer.Exit(1)
|
|
222
244
|
|
|
223
|
-
|
|
245
|
+
probe_target = base_model or model_path
|
|
246
|
+
requires = model_requires_trust_remote_code(model_path) or False
|
|
247
|
+
trc = resolve_trust_remote_code(
|
|
248
|
+
probe_target,
|
|
249
|
+
requested=trust_remote_code,
|
|
250
|
+
console=console,
|
|
251
|
+
requires_remote_code=requires,
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=trc)
|
|
224
255
|
if tokenizer.pad_token is None:
|
|
225
256
|
tokenizer.pad_token = tokenizer.eos_token
|
|
226
257
|
|
|
@@ -229,7 +260,7 @@ def _load_model(model_path: str, base_model: Optional[str], device: str):
|
|
|
229
260
|
|
|
230
261
|
base = AutoModelForCausalLM.from_pretrained(
|
|
231
262
|
base_model,
|
|
232
|
-
trust_remote_code=
|
|
263
|
+
trust_remote_code=trc,
|
|
233
264
|
device_map="auto",
|
|
234
265
|
dtype=torch.float16,
|
|
235
266
|
)
|
|
@@ -237,7 +268,7 @@ def _load_model(model_path: str, base_model: Optional[str], device: str):
|
|
|
237
268
|
else:
|
|
238
269
|
model_obj = AutoModelForCausalLM.from_pretrained(
|
|
239
270
|
model_path,
|
|
240
|
-
trust_remote_code=
|
|
271
|
+
trust_remote_code=trc,
|
|
241
272
|
device_map="auto",
|
|
242
273
|
dtype=torch.float16,
|
|
243
274
|
)
|