Skip to content

ORPO and SimPO import ORPOConfig/ORPOTrainer/CPOConfig/CPOTrainer from top-level trl, which no trl 1.x in the declared range exports (CR-A02-013) #106

Open

Description

@cemililik

Wave 0 · theme D0-7: Dependency ranges and security floors · highest severity High · 28 finding(s) · effort medium

Summary

An operator sets trainer_type: simpo or orpo as the docs show, on any trl from 1.0.0 to 1.14.1. --dry-run says 'config is valid'. The real run exits 2 after loading the model and dataset.

Primary finding

CR-A02-013 — ORPO and SimPO import ORPOConfig/ORPOTrainer/CPOConfig/CPOTrainer from top-level trl, which no trl 1.x in the declared range exports

severity High · reachability default · intent contract-violation · confidence confirmed · independently confirmed · reproduced end to end · already tracked: KNOWN-OPEN GAP-03 — docs/roadmap/phase-16-trust-surface-hardening.md:382-400,868-870 (S4 open)

What happens. forgelm/trainer.py:723 and :737 (_get_training_args_for_type) and :1037 and :1047 (_build_simple_trl_trainer) import ORPOConfig, CPOConfig, ORPOTrainer and CPOTrainer from the top-level trl package. In every trl that pyproject.toml:59 (>=1.0.0,<2.0.0) admits, these names exist only under trl.experimental.orpo and trl.experimental.cpo. trainer_type orpo and simpo therefore raise ImportError at trainer construction (exit 2) after --dry-run, which never imports trl, has reported the config valid.

Where.

Evidence.

  • runs/simpo-dir|simpo-file|orpo-dir|orpo-file exit 2: ImportError: cannot import name 'CPOConfig' / 'ORPOConfig' from 'trl'. Probe: hasattr(trl,'CPOConfig') False in trl 1.0.0/1.7.1/1.14.1, while trl.experimental.cpo/orpo expose both classes. With imports switched to trl.experimental (patch.diff) simpo/orpo exit 0 in main, latest and shimmed lower venvs.
  • scripts/trl_probe.py in the default (trl 1.7.1), lower (trl 1.0.0) and latest (trl 1.14.1) lanes: getattr(trl,'ORPOConfig'|'CPOConfig'|'ORPOTrainer'|'CPOTrainer') raises AttributeError, while trl.experimental.orpo and trl.experimental.cpo expose all four. CLI runs: runs/orpo -> exit 2 cannot import name 'ORPOConfig' from 'trl'; runs/simpo -> exit 2 cannot import name 'CPOConfig' from 'trl'; runs/orpo.latest -> the same exit 2. runs-patched/orpo and runs-patched/simpo, with the imports switc…
  • probe_trl.py on all three lanes: trl.ORPOConfig, ORPOTrainer, CPOConfig and CPOTrainer each raise AttributeError; trl.experimental.orpo and trl.experimental.cpo import OK. Default-lane e2e: cfg-orpo.yaml EXIT=2 "ImportError: cannot import name 'ORPOConfig' from 'trl'" at trainer.py:723; cfg-simpo.yaml EXIT=2 at trainer.py:737. With the experimental symbols patched onto trl (patch_run.py): orpo and simpo EXIT=0 on the default lane, and also on the lower (with the peft workaround) and latest (wit…

Recommended fix. Import from trl.experimental.cpo / trl.experimental.orpo with a version-aware fallback, or narrow the trl pin. Replace the skip in test_trainer_max_length with a hard failure.

Other findings with the same root cause

These close with the same fix; update them in the same pull request.

  • CR-A02-014 (code, High) — GRPO always fails: _apply_max_length passes max_prompt_length to GRPOConfig, which no trl 1.x accepts
    severity High · reachability default · intent contract-violation · confidence confirmed · independently confirmed · reproduced end to end · already tracked: KNOWN-OPEN GAP-03 — docs/roadmap/phase-16-trust-surface-hardening.md:406-409 (S4 open)
    Failure scenario. Any GRPO run, including the bundled grpo-math quickstart template, exits 2 at trainer construction after model and dataset loading.
    Where. forgelm/trainer.py:780 (confirmed), tests/test_trainer_max_length.py:74-97, pyproject.toml:59, forgelm/trainer.py:671-682
    Recommended fix. Pass max_prompt_length only when the GRPOConfig signature has it, the way the SFT branch already checks max_length at trainer.py:704. Test against the real GRPOConfig signature.

  • CR-A02-015 (code, High) — warmup_ratio is always passed to TrainingArguments-derived configs; transformers 5.15+ inside the <6.0.0 cap removed it, so every trainer fails on a fresh install
    severity High · reachability default · intent contract-violation · confidence confirmed · independently confirmed · reproduced end to end · already tracked: KNOWN-OPEN GAP-03 — docs/roadmap/phase-16-trust-surface-hardening.md:406-409 (S4 open)
    Failure scenario. pip install forgelm resolves transformers 5.18.x. Every training run exits 2. --dry-run (dry-latest-sft) and doctor still report success.
    Where. forgelm/trainer.py:503 (confirmed), pyproject.toml:53 (confirmed), forgelm/config.py:492-494, config_template.yaml:40
    Recommended fix. Map warmup_ratio to the float warmup_steps when the TrainingArguments signature lacks warmup_ratio, or cap transformers below the release that removed it. Add a CI job against the newest in-range dependencies. Research question: the exact transformers release that removed warmup_ratio (5.13.0 has it, 5.18.0 does not).

  • CR-A02-028 (code, High) — Within the declared TRL range, orpo and simpo raise ImportError, GRPO raises TypeError, and (trl 1.14.1) every trainer type raises TypeError, so NEFTune can never take effect on them
    severity High · reachability default · intent contract-violation · confidence confirmed · independently confirmed · reproduced end to end · already tracked: KNOWN-OPEN GAP-03 — docs/roadmap/phase-16-trust-surface-hardening.md:382-400,406-409 (S4 open)
    Failure scenario. An operator following the docs and template for orpo, simpo or grpo on any in-range TRL gets an ImportError or TypeError at trainer build, after the model has loaded. On trl 1.14.1 with transformers 5.18.0 nothing trains.
    Where. forgelm/trainer.py:737, forgelm/trainer.py:765 (via _apply_max_length forgelm/trainer.py:672-683; GRPOConfig(**kwargs) at :775), forgelm/trainer.py:503, forgelm/trainer.py:1047
    Recommended fix. Import ORPO/CPO from trl.experimental with a fallback, drop max_prompt_length for GRPO when the signature lacks it, map warmup_ratio to warmup_steps when absent, and add a signature-driven test per trainer type on the lower and latest venvs. Raise the torch floor to match peft 0.19.0, or gate it.

  • CR-A16-022 (code, Medium) — Test suite and nightly dependency-range jobs cannot detect trainer API breakage: trl configs/trainers are mocked or skipped and no real trainer ever runs
    severity Medium · reachability default · intent intended-but-harmful · confidence confirmed · independently confirmed · reproduced end to end · already tracked: KNOWN-OPEN GAP-03 — docs/roadmap/phase-16-trust-surface-hardening.md:406-409 (S4 open)
    Failure scenario. An upstream API removal inside the declared range (transformers 5.18 warmup_ratio) ships with a green nightly, and users find it first.
    Where. pyproject.toml:184, .github/workflows/nightly.yml:52, .github/workflows/nightly.yml:244, tests/test_trainer_max_length.py:55
    Recommended fix. Add an unmocked smoke test: one max_steps=1 run per trainer_type on a tiny model, run in both nightly range jobs. Turn DeprecationWarning from transformers, trl and peft into errors or a report, not an ignore.

  • CR-A01-081 (code, Low) — training.warmup_ratio: 1.0 (allowed by le=1) becomes one warmup step on transformers 5.x, not 100% of training
    severity Low · reachability default · intent intended-but-harmful · confidence confirmed · independently confirmed · reproduced end to end
    Failure scenario. An operator asks for full-length warmup and gets one warmup step with no warning.
    Where. forgelm/config.py:492, forgelm/trainer.py:503
    Recommended fix. Use lt=1 on the field, or compute warmup_steps = ceil(ratio * total_steps) in ForgeLM before passing an int.

  • TECH-T01-001 (technology, Now) — TRL trainers and alignment methods: trl ORPOConfig/ORPOTrainer (trainer_type='orpo') (range-unsound)
    severity Now · already tracked: KNOWN-OPEN GAP-03 docs/roadmap/phase-16-trust-surface-hardening.md:382-400,868-870
    Item. trl ORPOConfig/ORPOTrainer (trainer_type='orpo') · verdict: range-unsound · urgency: Now
    State in ForgeLM. forgelm/trainer.py:723 runs from trl import ORPOConfig and :1037 runs from trl import ORPOTrainer, passing beta=orpo_beta and max_length=model.max_length. pyproject.toml:59 declares trl>=1.0.0,<2.0.0. README.md:153, docs/reference/architecture.md:125 and docs/reference/library_api_reference.md:54 (and the -tr mirror) advertise ORPO. Roadmap Phase 16 S4 / C-10 (docs/roadmap/phase-16-trust-surf…
    State of the ecosystem on 2026-10-01. TRL moved ORPO to trl.experimental in v0.26.0 (2025-12-09, PR #​4480) and kept a FutureWarning shim at top level. v0.29.0 (2026-02-25, PR #​5050) removed that shim. On trl 1.0.0, 1.7.1 and 1.14.1 (the latest, 2026-09-29), getattr(trl,'ORPOConfig'/'ORPOTrainer') raises AttributeError. trl.experimental.orpo imports and accepts beta and max_length. TRL's experimental contract says such code 'may chang…
    Recommendation. Ship the C-10 resolver now: try the top-level name, then trl.experimental.orpo, then raise an actionable ConfigError that names trl.version. Make a missing advertised class fail the test instead of skipping. Label ORPO 'experimental upstream' in the README and docs. Because experimental code can disappear in a patch release, add a CI job on the newest resolvable trl that builds the real confi…
    Sources.

  • TECH-T01-002 (technology, Now) — TRL trainers and alignment methods: transformers TrainingArguments.warmup_ratio (passed into every TRL config) (range-unsound)
    severity Now
    Item. transformers TrainingArguments.warmup_ratio (passed into every TRL config) · verdict: range-unsound · urgency: Now
    State in ForgeLM. forgelm/trainer.py:503 puts 'warmup_ratio' into the common kwargs of every TRL config. training.warmup_ratio defaults to 0.1 (forgelm/config.py:492-494). pyproject.toml:53 declares transformers>=5.3.0,<6.0.0.
    State of the ecosystem on 2026-10-01. transformers 5.3.0 and 5.13.0 still accept warmup_ratio, warn that it 'is deprecated and will be removed in v5.2. Use warmup_steps instead', and copy it into warmup_steps (training_args.py 5.3.0:1471-1473; 5.13.0:1485-1487). transformers PR #​46917 'Remove deprecated training args and is_fast property' (merged 2026-07-22) deleted the warmup_ratio field. It shipped in v5.15.0 (2026-08-10), and…
    Recommendation. Map training.warmup_ratio to warmup_steps=, which is valid as a float ratio across the declared 5.3-5.18 range, or cap transformers<5.15 until that ships. Add a nightly job on the newest resolvable stack that builds the real TRL configs.
    Sources.

  • TECH-T01-003 (technology, Now) — TRL trainers and alignment methods: Test and CI coverage of the TRL trainer surface (tests/test_trainer_max_length.py, nightly lower-bound job) (incorrect-claim)
    severity Now · already tracked: KNOWN-OPEN GAP-03 docs/roadmap/phase-16-trust-surface-hardening.md:406-411,920-926
    Item. Test and CI coverage of the TRL trainer surface (tests/test_trainer_max_length.py, nightly lower-bound job) · verdict: incorrect-claim · urgency: Now
    State in ForgeLM. tests/test_trainer_max_length.py:52-55 calls pytest.skip() when trl.ORPOConfig or trl.CPOConfig is missing. :72-97 replaces GRPOConfig with FakeGRPOConfig and asserts max_prompt_length, and the module docstring (:7) claims 'GRPO must honour it as the prompt cap'. .github/workflows/nightly.yml:244-255 pins trl==1.0.0 and transformers==5.3.0 and runs the same suite. The other nightly job (:52) inst…
    State of the ecosystem on 2026-10-01. Arbiter runs: the project venv (trl 1.7.1, transformers 5.13.0) gives '3 passed, 2 skipped' for tests/test_trainer_max_length.py. The seven TRL-related test modules (test_trainer_sft_config, test_trainer_grpo_config, test_grpo_reward, test_trainer_max_length, test_grpo_format_reward, test_trainer, test_oom_recovery) give '135 passed, 2 skipped' on both the floor (trl 1.0.0, transformers 5.3.0) an…
    Recommendation. Build the real TRL config and trainer classes in tests, with no fakes and no skips, at the floor and at the newest resolvable versions. A missing advertised class must fail. This is already the roadmap S4 exit criterion; extend it to the warmup_ratio and max_prompt_length failures, which S4 does not name.
    Sources.

  • TECH-T01-004 (technology, Now) — TRL trainers and alignment methods: trl CPOConfig/CPOTrainer used for SimPO (loss_type='simpo', cpo_alpha=0, simpo_gamma) (range-unsound)
    severity Now · already tracked: KNOWN-OPEN GAP-03 docs/roadmap/phase-16-trust-surface-hardening.md:382-400
    Item. trl CPOConfig/CPOTrainer used for SimPO (loss_type='simpo', cpo_alpha=0, simpo_gamma) · verdict: range-unsound · urgency: Now
    State in ForgeLM. forgelm/trainer.py:737 runs from trl import CPOConfig with beta=simpo_beta, cpo_alpha=0.0, simpo_gamma and max_length, and sets loss_type='simpo' at :743. forgelm/trainer.py:1047 runs from trl import CPOTrainer. The comment at :739 says 'SimPO is implemented via CPOTrainer with loss_type="simpo" in TRL'.
    State of the ecosystem on 2026-10-01. TRL moved CPO to trl.experimental in v0.26.0 (2025-12-09, PR #​4470). v0.29.0 (2026-02-25, PR #​5046) removed the deprecated top-level path. On 1.0.0, 1.7.1 and 1.14.1, getattr(trl,'CPOConfig'/'CPOTrainer') raises AttributeError, while trl.experimental.cpo.CPOConfig accepts every kwarg ForgeLM passes (loss_type, cpo_alpha, simpo_gamma, beta, max_length). The TRL v1.14.1 docs still give SimPO as los…
    Recommendation. Import from trl.experimental.cpo through the C-10 resolver and keep the kwargs unchanged. Do not set TRL_EXPERIMENTAL_SILENCE. Fix the 'sigmoid loss' wording in simpo.md (EN and TR). Plan a documented fallback in case CPO leaves experimental. DPO sigmoid_norm is not reference-free, so present it as a different method, not as SimPO.
    Sources.

  • TECH-T01-005 (technology, Now) — TRL trainers and alignment methods: trl GRPOConfig/GRPOTrainer (num_generations, max_completion_length, max_prompt_length, reward_funcs) (range-unsound)
    severity Now
    Item. trl GRPOConfig/GRPOTrainer (num_generations, max_completion_length, max_prompt_length, reward_funcs) · verdict: range-unsound · urgency: Now
    State in ForgeLM. forgelm/trainer.py:755-779 builds GRPOConfig with num_generations and max_completion_length. At :765 it calls self._apply_max_length(kwargs, 'max_prompt_length'), and the comment at :762-764 cites 'TRL's 512 max_prompt_length default'. tests/test_trainer_max_length.py:72-97 asserts the kwarg against a FakeGRPOConfig.
    State of the ecosystem on 2026-10-01. GRPOConfig.max_prompt_length was deprecated in v0.26.0. The help text at grpo_config.py@v0.26.0:298 and the warning at :869 say it 'will be removed in version 0.28.0. You should instead filter your dataset before training to ensure that prompts do not exceed your desired length'. It is still present in 0.27.0 and absent from 0.28.0 (2026-02-10) onward. The 0.28.0 notes do not announce the GRPO re…
    Recommendation. Stop passing max_prompt_length. If a prompt cap is wanted, tokenise the GRPO prompts and filter or left-truncate them to model.max_length before building the trainer, as TRL advises, and record the dropped or truncated count in the manifest. Optionally set vllm_max_model_length when vLLM is used. Replace the fake-config test with one that builds the real GRPOConfig at the floor and the newest ver…
    Sources.

  • TECH-T02-001 (technology, Now) — Core Hugging Face stack and runtime dependencies: TrainingArguments warmup_ratio passed unconditionally (forgelm/trainer.py:503) (outdated)
    severity Now
    Item. TrainingArguments warmup_ratio passed unconditionally (forgelm/trainer.py:503) · verdict: outdated · urgency: Now
    State in ForgeLM. _get_common_training_kwargs (trainer.py:444-521) always puts 'warmup_ratio' into the kwargs used for SFTConfig, DPOConfig, ORPOConfig, CPOConfig, KTOConfig and GRPOConfig, with no signature check. config.py:492 and docs/reference/configuration.md:76 document training.warmup_ratio.
    State of the ecosystem on 2026-10-01. transformers 5.14.0 training_args.py:1443 still has warmup_ratio, with a warning at :1487-1489 that it 'will be removed in v5.2' and that its value is copied into warmup_steps. In 5.15.0 and 5.18.0 the field does not exist (0 occurrences), and warmup_steps is typed float (5.15.0:788). MIGRATION_GUIDE_V5.md:627 says 'warmup_ratio -> use warmup_step instead'. My warmup_repro run calls snapshot Forg…
    Recommendation. Map training.warmup_ratio onto warmup_steps (as a float) in trainer.py. warmup_steps already accepts floats at the 5.3.0 floor, as the run showed (warmup_steps=0.1). Until that ships, cap transformers<5.15. Add a latest-lane CI job that builds every TRL config type.
    Sources.

  • TECH-T04-001 (technology, Now) — Distributed training: Adjacent: training.warmup_ratio passed to TRL/TrainingArguments configs (removed in transformers v5.15.0) under the transformers>=5.3.0,<6.0.0 pin (range-unsound)
    severity Now
    Item. Adjacent: training.warmup_ratio passed to TRL/TrainingArguments configs (removed in transformers v5.15.0) under the transformers>=5.3.0,<6.0.0 pin · verdict: range-unsound · urgency: Now
    State in ForgeLM. trainer.py:503 unconditionally passes 'warmup_ratio' into the kwargs used for SFTConfig, DPOConfig, ORPOConfig, CPOConfig, KTOConfig and GRPOConfig (trainer.py:685-760), with no signature filtering. pyproject.toml:53 permits transformers>=5.3.0,<6.0.0, and trl>=1.0.0,<2.0.0.
    State of the ecosystem on 2026-10-01. warmup_ratio is present, as a deprecated field, in transformers v5.14.0 (2026-07-15) and absent from v5.15.0 (2026-08-10) through v5.18.0 (2026-09-30), where only warmup_steps (int, or float in [0,1)) remains. Reproduced through ForgeTrainer._get_training_args_for_type() with config_template.yaml: on transformers 5.18.0 with trl 1.14.1 it raises TypeError: SFTConfig.init() got an unexpected k…
    Recommendation. Map training.warmup_ratio to warmup_steps (a float in [0,1)) at trainer.py:503, keeping the YAML field. Add a CI lane on the latest transformers/trl that builds every trainer config, and until then cap transformers<5.15 as a stop-gap.
    Sources.

  • DOC-D1B01-011 (docs, High) — docs/reference/library_api_reference.md: broken example — ForgeTrainer(config: ForgeConfig) is the constructor; ref example 3 and the guide lifecycle call ForgeTrainer(config) then .train()
    severity High
    Where. docs/reference/library_api_reference.md:54,175,242 (and -tr mirror); docs/guides/library_api.md:94 · type: broken example
    The document says. ForgeTrainer(config: ForgeConfig) is the constructor; ref example 3 and the guide lifecycle call ForgeTrainer(config) then .train()
    What the code does. ForgeTrainer.init(self, model, tokenizer, config, dataset); ForgeTrainer(config) raises TypeError (missing 3 required positional arguments). The caller must run get_model_and_tokenizer(config) and prepare_dataset(config, tokenizer) first.
    Code references. forgelm/trainer.py:340, forgelm/cli/_training.py:140-148
    Proposed correction. Document the real 4-argument signature and show the get_model_and_tokenizer/prepare_dataset steps in example 3 and the guide; fix the TR mirrors.
    Turkish mirror. the Turkish page has the same error; fix both in the same PR

  • DOC-D1B01-012 (docs, High) — docs/reference/library_api_reference.md: broken example — forgelm.ForgeTrainer (Stable) signature "ForgeTrainer(config: ForgeConfig)". Also :175 example trainer = ForgeTrainer(config), :242 tr… severity **High** **Where.** [docs/reference/library_api_reference.md:54](https://github.com/HodeTech/ForgeLM/blob/cab2947/docs/reference/library_api_reference.md#L54) (Turkish mirror: [docs/reference/library_api_reference-tr.md:54](https://github.com/HodeTech/ForgeLM/blob/cab2947/docs/reference/library_api_reference-tr.md#L54), :175, :242) · type: broken example **The document says.** forgelm.ForgeTrainer (Stable) signature "ForgeTrainer(config: ForgeConfig)". Also :175 example trainer = ForgeTrainer(config), :242 trainer = forgelm.ForgeTrainer(config), and :55 "Heavy deps (torch, transformers, trl) load only when this method is called." **What the code does.** The real signature is ForgeTrainer(model, tokenizer, config, dataset) (trainer.py:340), as recorded in tests/_data/api_signatures_1.2.0.json (also 1.0.0 and 1.1.0). The CLI loads the model and tokenizer, prepares the dataset, then calls ForgeTrainer(model=..., tokenizer=..., config=..., dataset=...) (cli/_training.py:139-147). From the signature, ForgeTrainer(config) raises TypeError for three mi… **Code references.** [forgelm/trainer.py:340-371](https://github.com/HodeTech/ForgeLM/blob/cab2947/forgelm/trainer.py#L340-L371), [tests/_data/api_signatures_1.2.0.json](https://github.com/HodeTech/ForgeLM/blob/cab2947/tests/_data/api_signatures_1.2.0.json), [forgelm/cli/_training.py:139-147](https://github.com/HodeTech/ForgeLM/blob/cab2947/forgelm/cli/_training.py#L139-L147) **Proposed correction.** Signature row: "ForgeTrainer(model, tokenizer, config: ForgeConfig, dataset: Dict[str, Any])". Example 3: model, tokenizer = get_model_and_tokenizer(config); dataset = prepare_dataset(config, tokenizer); trainer = ForgeTrainer(model=model, tokenizer=tokenizer, config=config, dataset=dataset)`. Drop the claim that heavy deps load only in tra…
    Turkish mirror. the Turkish page has the same error; fix both in the same PR

  • DOC-D2B09-007 (docs, High) — docs/product_strategy.md: false claim — 6 trainer methods (SFT/DPO/SimPO/KTO/ORPO/GRPO) in one tool
    severity High · already tracked: KNOWN-OPEN GAP-03 — docs/roadmap/phase-16-trust-surface-hardening.md:385-390,868-870
    Where. docs/product_strategy.md:74 (Turkish mirror: docs/product_strategy-tr.md:74) · type: false claim
    The document says. 6 trainer methods (SFT/DPO/SimPO/KTO/ORPO/GRPO) in one tool
    What the code does. ORPO and SimPO import ORPOTrainer and CPOTrainer from the top-level trl namespace. On trl 1.7.1, which is inside the declared range trl>=1.0.0,<2.0.0, both imports raise ImportError (reproduced); the classes live only under trl.experimental. Phase 16 S4 / decision C-10 is still open.
    Code references. forgelm/trainer.py:1036-1049, pyproject.toml:59, docs/roadmap/risks-and-decisions.md:190
    Proposed correction. Fix the code (C-10 resolver through trl.experimental). Until then add a temporary note: "ORPO and SimPO currently fail to import on trl>=1.0 (tracked as Phase 16 S4)."
    Turkish mirror. the Turkish page has the same error; fix both in the same PR

  • DOC-D3B05-002 (docs, High) — docs/usermanuals/en/concepts/alignment-overview.md: false claim — ForgeLM gives you all six (SFT, DPO, SimPO, KTO, ORPO, GRPO) behind one declarative interface
    severity High · already tracked: KNOWN-OPEN GAP-03 docs/roadmap/phase-16-trust-surface-hardening.md:385-388
    Where. docs/usermanuals/en/concepts/alignment-overview.md:8 (Turkish mirror: docs/usermanuals/tr/concepts/alignment-overview.md:8) · type: false claim
    The document says. ForgeLM gives you all six (SFT, DPO, SimPO, KTO, ORPO, GRPO) behind one declarative interface
    What the code does. All six values pass schema validation (config.py:461-464), but only SFT, DPO and KTO can train. With every TRL in the pinned range (pyproject.toml:59 trl>=1.0.0,<2.0.0; checked 1.0.0, 1.7.1, 1.14.1), ORPO stops at from trl import ORPOConfig (trainer.py:723) and SimPO at from trl import CPOConfig (trainer.py:737) with ImportError, because TRL 1.x moved both to trl.experimental. GRPO stops at G…
    Code references. forgelm/trainer.py:723, forgelm/trainer.py:737, forgelm/trainer.py:765, forgelm/trainer.py:1037
    Proposed correction. Fix the code. Import ORPOConfig/ORPOTrainer and CPOConfig/CPOTrainer from trl.experimental.orpo / trl.experimental.cpo, with a version-guarded fallback. Drop or rename the GRPO max_prompt_length kwarg. Add a real-TRL smoke test per trainer. Until then, add a warning here: "ORPO, SimPO and GRPO currently fail at trainer construction with TRL 1.x;…
    Turkish mirror. the Turkish page has the same error; fix both in the same PR

  • DOC-D3B05-017 (docs, High) — docs/usermanuals/en/training/orpo.md: broken example — Quick example trainer_type: "orpo" trains an ORPO model
    severity High · already tracked: KNOWN-OPEN GAP-03 docs/roadmap/phase-16-trust-surface-hardening.md:382-392
    Where. docs/usermanuals/en/training/orpo.md:23-46 (Turkish mirror: docs/usermanuals/tr/training/orpo.md:23-46) · type: broken example
    The document says. Quick example trainer_type: "orpo" trains an ORPO model
    What the code does. The config validates (dry-run exit 0), but training fails at from trl import ORPOConfig (trainer.py:723) with ImportError ('cannot import name ORPOConfig from trl') on TRL 1.0.0/1.7.1/1.14.1. ORPO now lives in trl.experimental.orpo. A real run exited 2.
    Code references. forgelm/trainer.py:723, forgelm/trainer.py:1037, pyproject.toml:59
    Proposed correction. Fix the code (import from trl.experimental.orpo with a fallback). Add a temporary warning: "ORPO currently fails with TRL 1.x (ImportError: ORPOConfig)."
    Turkish mirror. the Turkish page has the same error; fix both in the same PR

  • DOC-D3B05-019 (docs, High) — docs/usermanuals/en/training/simpo.md: broken example — Quick example trainer_type: "simpo" trains a SimPO model
    severity High · already tracked: KNOWN-OPEN GAP-03 docs/roadmap/phase-16-trust-surface-hardening.md:382-392
    Where. docs/usermanuals/en/training/simpo.md:22-46 (Turkish mirror: docs/usermanuals/tr/training/simpo.md:22-46) · type: broken example
    The document says. Quick example trainer_type: "simpo" trains a SimPO model
    What the code does. The config validates (dry-run exit 0), but training fails at from trl import CPOConfig (trainer.py:737) with ImportError on TRL 1.0.0, 1.7.1 and 1.14.1, all inside the pinned range (pyproject.toml:59). CPO now lives in trl.experimental.cpo. A real run exited 2.
    Code references. forgelm/trainer.py:737, forgelm/trainer.py:1047, pyproject.toml:59
    Proposed correction. Fix the code (import CPOConfig/CPOTrainer from trl.experimental.cpo with a fallback). Add a temporary warning at the top: "SimPO currently fails with TRL 1.x (ImportError: CPOConfig)."
    Turkish mirror. the Turkish page has the same error; fix both in the same PR

  • DOC-D4B05-001 (docs, High) — notebooks/grpo_reasoning.ipynb: broken example — After the dry-run passes, !forgelm --config grpo_config.yaml trains a GRPO model and writes ./grpo_checkpoints/final_model
    severity High
    Where. notebooks/grpo_reasoning.ipynb:132 (Turkish mirror: forgelm/trainer.py:765) · type: broken example
    The document says. After the dry-run passes, !forgelm --config grpo_config.yaml trains a GRPO model and writes ./grpo_checkpoints/final_model
    What the code does. The training step crashes before the first step. forgelm/trainer.py:765 calls self._apply_max_length(kwargs, "max_prompt_length") and trainer.py:780 returns GRPOConfig(**kwargs). TRL's GRPOConfig has no max_prompt_length parameter on trl 1.0.0 (the pyproject lower bound) or 1.7.1, so construction raises TypeError: GRPOConfig.__init__() got an unexpected keyword argument 'max_prompt_length'… **Code references.** [forgelm/trainer.py:765](https://github.com/HodeTech/ForgeLM/blob/cab2947/forgelm/trainer.py#L765), [forgelm/trainer.py:780](https://github.com/HodeTech/ForgeLM/blob/cab2947/forgelm/trainer.py#L780), [tests/test_trainer_max_length.py:77-96](https://github.com/HodeTech/ForgeLM/blob/cab2947/tests/test_trainer_max_length.py#L77-L96), [pyproject.toml:59`](https://github.com/HodeTech/ForgeLM/blob/cab2947/pyproject.toml#L59) (trl>=1.0.0,<2.0.0)
    Proposed correction. Fix the code (see rationale). Until it is fixed, add a note above Step 6: 'Known issue: GRPO training currently fails with TypeError (max_prompt_length) on TRL >= 1.0; use the SFT, DPO or KTO notebooks until a fixed ForgeLM release.'

  • DOC-D4B05-003 (docs, High) — notebooks/quickstart_sft.ipynb: broken example — After pip install 'forgelm[qlora]==0.11.0' (transformers/trl unpinned) the !forgelm --config my_config.yaml training cell runs
    severity High
    Where. notebooks/quickstart_sft.ipynb:27-28, :201 (Turkish mirror: same cell in dpo_alignment, kto_binary_feedback, grpo_reasoning, galore_memory_optimization, multi_dataset) · type: broken example
    The document says. After pip install 'forgelm[qlora]==0.11.0' (transformers/trl unpinned) the !forgelm --config my_config.yaml training cell runs
    What the code does. pyproject allows transformers>=5.3.0,<6 and trl>=1.0.0,<2. ForgeLM builds every TRL config with warmup_ratio (trainer.py:503). In the review harness's 'latest' venv (transformers 5.18.0, trl 1.14.1) every trainer type fails with TypeError: SFTConfig.__init__() got an unexpected keyword argument 'warmup_ratio' (real CLI run of this notebook's config, tiny-qwen; also DPO/KTO/GRPO/GaLore/multi c…
    Code references. forgelm/trainer.py:503, pyproject.toml:53-59
    Proposed correction. Fix the code (replace warmup_ratio with warmup_steps or probe the signature) and release; until then pin 'transformers<5.18' next to the forgelm pin in the Step 1 install cell of every notebook.

  • DOC-BLEGAL-152 (docs, Medium) — notebooks/grpo_reasoning.ipynb: broken example — !pip install -q --no-cache-dir 'forgelm[qlora]==0.11.0' bitsandbytes (the notebook then documents and runs the GRPO flow)
    severity Medium
    Where. notebooks/grpo_reasoning.ipynb cell 1 · type: broken example
    The document says. !pip install -q --no-cache-dir 'forgelm[qlora]==0.11.0' bitsandbytes (the notebook then documents and runs the GRPO flow)
    What the code does. forgelm 0.11.0 is on PyPI (uploaded 2026-07-21) and is the latest release, but it is not the snapshot's code: trainer.py, config.py, safety/*, judge.py, webhook.py and others differ. Its trainer.py:467 passes warmup_ratio unconditionally. transformers removed TrainingArguments.warmup_ratio in v5.15.0, and a fresh resolve within forgelm's transformers>=5.3,<6 pin, or the Colab image (transformers…
    Proposed correction. Pin transformers<5.15 alongside forgelm==0.11.0 until a release drops warmup_ratio, and note that the notebook runs the 0.11.0 release.

  • DOC-BLEGAL-154 (docs, Medium) — notebooks/quickstart_sft.ipynb: broken example — !pip install -q --no-cache-dir 'forgelm[qlora]==0.11.0' (quickstart SFT run)
    severity Medium
    Where. notebooks/quickstart_sft.ipynb cell 1 · type: broken example
    The document says. !pip install -q --no-cache-dir 'forgelm[qlora]==0.11.0' (quickstart SFT run)
    What the code does. forgelm 0.11.0 is published and is the latest release, but it differs from the snapshot code. Its trainer passes warmup_ratio unconditionally (wheel trainer.py:467), and SFTConfig on transformers >= 5.15 (Colab: 5.18.0) raises TypeError on warmup_ratio.
    Proposed correction. Add 'transformers>=5.3,<5.15' to the install line until a fixed release ships.

  • DOC-D1B01-024 (docs, Medium) — docs/reference/library_api_reference.md: stale — Canonical TrainResult fields list
    severity Medium
    Where. docs/reference/library_api_reference.md:56 · type: stale
    The document says. Canonical TrainResult fields list
    What the code does. TrainResult also has awaiting_approval, run_id and config_hash; awaiting_approval is the authoritative discriminator for 'staged pending human approval' (CLI exit 4).
    Code references. forgelm/results.py:34-52
    Proposed correction. Add the three fields and note that success=True with awaiting_approval=True means staged.
    Turkish mirror. the Turkish page has the same error; fix both in the same PR

  • DOC-D3B05-043 (docs, Medium) — docs/usermanuals/en/training/simpo.md: wrong detail — TRL's CPO/SimPO trainer runs with library defaults (sigmoid loss, length normalisation always on, no label smoothing)
    severity Medium
    Where. docs/usermanuals/en/training/simpo.md:62 (Turkish mirror: docs/usermanuals/tr/training/simpo.md:63) · type: wrong detail
    The document says. TRL's CPO/SimPO trainer runs with library defaults (sigmoid loss, length normalisation always on, no label smoothing)
    What the code does. ForgeLM sets loss_type='simpo' and cpo_alpha=0.0 explicitly (trainer.py:736-745). TRL's CPOConfig defaults would be loss_type 'sigmoid' and cpo_alpha 1.0.
    Code references. forgelm/trainer.py:734-745
    Proposed correction. Say: "ForgeLM fixes loss_type=\"simpo\" and cpo_alpha=0 (pure SimPO, no NLL term); label smoothing stays at TRL's default 0."
    Turkish mirror. the Turkish page has no such statement

  • DOC-D4B01-022 (docs, Medium) — README.md: misleading — "on CUDA OOM the batch is halved and gradient accumulation doubled, preserving the effective batch, then the step retries"
    severity Medium
    Where. README.md:154 · type: misleading
    The document says. "on CUDA OOM the batch is halved and gradient accumulation doubled, preserving the effective batch, then the step retries"
    What the code does. This is opt-in: training.oom_recovery defaults to False, and without it the OOM is re-raised. When enabled, the retry rebuilds the trainer and re-enters train() from step 0 with a fresh optimizer and scheduler (or from the explicit --resume checkpoint). The failing step is not retried.
    Code references. forgelm/config.py:598-600, forgelm/trainer.py:1196-1207, forgelm/trainer.py:1229-1235, forgelm/trainer.py:1262-1270
    Proposed correction. "with training.oom_recovery: true (off by default), a CUDA OOM halves the batch and doubles gradient accumulation (effective batch preserved) and restarts training from step 0 (or the --resume checkpoint) with a fresh optimizer"

  • DOC-D1B01-045 (docs, Low) — docs/reference/library_api_reference.md: wrong detail — ForgeTrainer.train signature "train() -> TrainResult"
    severity Low
    Where. docs/reference/library_api_reference.md:55 (Turkish mirror: docs/reference/library_api_reference-tr.md:55) · type: wrong detail
    The document says. ForgeTrainer.train signature "train() -> TrainResult"
    What the code does. The method is train(self, resume_from_checkpoint: Optional[str] = None) -> TrainResult.
    Code references. forgelm/trainer.py:1661
    Proposed correction. "train(resume_from_checkpoint: Optional[str] = None) -> TrainResult"
    Turkish mirror. the Turkish page has the same error; fix both in the same PR

  • DOC-D1B01-046 (docs, Low) — docs/reference/library_api_reference.md: stale — TrainResult canonical fields (per forgelm/results.py): success ... staging_path, resource_usage
    severity Low
    Where. docs/reference/library_api_reference.md:56 (Turkish mirror: docs/reference/library_api_reference-tr.md:56) · type: stale
    The document says. TrainResult canonical fields (per forgelm/results.py): success ... staging_path, resource_usage
    What the code does. The field list also includes awaiting_approval, run_id and config_hash. awaiting_approval is the discriminator the CLI uses for exit 4.
    Code references. forgelm/results.py, tests/_data/api_signatures_1.2.0.json, forgelm/cli/_training.py:156-161
    Proposed correction. Add awaiting_approval: bool, run_id: Optional[str], config_hash: Optional[str].
    Turkish mirror. the Turkish page has the same error; fix both in the same PR

Acceptance criteria

  • A regression test reproduces the failure scenario and asserts the corrected behaviour.
  • Documentation listed above is corrected in English and in its Turkish mirror in the same PR.
  • Every finding in this issue is resolved or explicitly closed with a reason.
  • The release note names the contract this fix restores.

Found by the October 2026 ForgeLM code and documentation review against commit cab2947. Code links point at that commit; line numbers may have moved since. Finding IDs (CR-…, DOC-…, TECH-…) are stable references for this backlog.

Activity

  1. added
    bugSomething isn't working
    documentationImprovements or additions to documentation
    backlog: knownAlready tracked in docs/roadmap
    dependenciesDependency or ecosystem currency
    severity: highWrong behaviour or a false claim users rely on
    source: review-2026-10Found by the October 2026 code and documentation review
    urgency: nowTechnology currency: act now
    wave: 0Roadmap wave 0: immediate (patch release)
    on Oct 9, 2026
  2. cemililik commented on Oct 17, 2026

    @cemililik
    CollaboratorAuthor

    Progress on development — verified 2026-10-18 at 6c55900.

    Fixed:

    • CR-A02-013 (with TECH-T01-001, TECH-T01-004) — ORPO and SimPO resolve their trainer and config classes through a compatibility resolver instead of fixed import names (e0eb32d, 1b800a5; test_real_installed_preference_symbols)
    • CR-A02-015, CR-A01-081 (with TECH-T01-002, TECH-T02-001, TECH-T04-001) — warmup goes through the supported warmup_steps argument and a ratio of 1.0 is clamped below 1 (9218b4a, 39d328c; tests/test_trainer.py builds every trainer type's arguments through real TrainingArguments)
    • DOC-D3B05-017, DOC-D3B05-019, DOC-D3B05-043 — the ORPO and SimPO pages (EN/TR) carry the experimental-API caveat and the corrected SimPO loss_type / cpo_alpha wording (e0eb32d)
    • DOC-D4B01-022 — the README out-of-memory claim is gone (5971d58)

    Partly fixed:

    • CR-A02-028 — ORPO, SimPO and warmup are fixed; the GRPO TypeError below remains
    • CR-A16-022, TECH-T01-003 — real ORPO and SimPO construction now runs on CPU and in the nightly jobs; there is still no per-trainer-type smoke test for SFT, DPO, KTO and GRPO, and filterwarnings still ignores DeprecationWarning

    Still open, most important first:

    • CR-A02-014 (with TECH-T01-005) — GRPO still receives max_prompt_length (forgelm/trainer.py, _apply_max_length(kwargs, "max_prompt_length")), which GRPOConfig does not define in TRL 1.7.1; its only test uses a fake config
    • DOC-D2B09-007, DOC-D3B05-002 (the "all six trainers" claims), the notebooks (DOC-D4B05-001, -003, DOC-BLEGAL-152, -154) and the library API reference (DOC-D1B01-011, -012, -024, -045, -046)

    Everything else in this issue is unchanged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: configCode area: configarea: packaging-ciCode area: packaging-ciarea: trainerCode area: trainerbacklog: knownAlready tracked in docs/roadmapbugSomething isn't workingdependenciesDependency or ecosystem currencydocumentationImprovements or additions to documentationseverity: highWrong behaviour or a false claim users rely onsource: review-2026-10Found by the October 2026 code and documentation reviewurgency: nowTechnology currency: act nowwave: 0Roadmap wave 0: immediate (patch release)

    Type

    No type

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions