Supervised fine-tune the model with an iterable of trajectories. Args: trajectories: An iterable of Trajectory objects. config: SFT configuration including learning_rates and batch_size. If None, uses default TrainSFTConfig(). _co
(
self,
trajectories: Iterable[Trajectory],
config: TrainSFTConfig | None = None,
_config: dev.TrainSFTConfig | None = None,
verbose: bool = False,
)
| 1107 | await self.log(groups_list, split="train", metrics=avg_metrics, step=step) |
| 1108 | |
| 1109 | async def train_sft( |
| 1110 | self, |
| 1111 | trajectories: Iterable[Trajectory], |
| 1112 | config: TrainSFTConfig | None = None, |
| 1113 | _config: dev.TrainSFTConfig | None = None, |
| 1114 | verbose: bool = False, |
| 1115 | ) -> None: |
| 1116 | """ |
| 1117 | Supervised fine-tune the model with an iterable of trajectories. |
| 1118 | |
| 1119 | Args: |
| 1120 | trajectories: An iterable of Trajectory objects. |
| 1121 | config: SFT configuration including learning_rates and batch_size. |
| 1122 | If None, uses default TrainSFTConfig(). |
| 1123 | _config: Additional experimental configuration that is subject to change and |
| 1124 | not yet part of the public API. Use at your own risk. |
| 1125 | verbose: Whether to print verbose output. |
| 1126 | """ |
| 1127 | if config is None: |
| 1128 | config = TrainSFTConfig() |
| 1129 | |
| 1130 | # Train (backend yields metrics for each batch without logging) |
| 1131 | # Collect all metrics and aggregate them at the end (same as RL) |
| 1132 | _config = _config or {} # ty:ignore[invalid-assignment] |
| 1133 | training_metrics: list[dict[str, float]] = [] |
| 1134 | trainer_started = time.monotonic() |
| 1135 | async for metrics in self.backend()._train_sft( |
| 1136 | self, |
| 1137 | trajectories, |
| 1138 | config, |
| 1139 | _config, # ty:ignore[invalid-argument-type] |
| 1140 | verbose, |
| 1141 | ): |
| 1142 | training_metrics.append(metrics) |
| 1143 | trainer_elapsed = time.monotonic() - trainer_started |
| 1144 | |
| 1145 | # Log aggregated training metrics once (same as RL) |
| 1146 | if training_metrics: |
| 1147 | avg_metrics = average_metric_samples(training_metrics) |
| 1148 | avg_metrics["time/step_trainer_s"] = trainer_elapsed |
| 1149 | # Get the current step after training |
| 1150 | step = await self.get_step() |
| 1151 | await self.log( |
| 1152 | trajectories=None, split="train", metrics=avg_metrics, step=step |
| 1153 | ) |