forked from microsoft/agent-lightning
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsft_allinone.py
More file actions
115 lines (94 loc) · 4.44 KB
/
Copy pathsft_allinone.py
File metadata and controls
115 lines (94 loc) · 4.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# Copyright (c) Microsoft. All rights reserved.
"""This sample provides an all-in-one script for SFT algorithm.
It's equivalent to running the following commands in parallel:
```bash
agl store
python sft_rollout_runners.py
python sft_algorithm.py
```
"""
from typing import Optional
from math_agent import GsmProblem, load_math_dataset, math_agent
from rich.console import Console
from sft_algorithm import sft_one_iter
from agentlightning import Trainer, setup_logging
from agentlightning.adapter import TraceToTripletBase
from agentlightning.algorithm import Algorithm
from agentlightning.llm_proxy import LLMProxy
from agentlightning.types import Dataset
console = Console()
class UnslothSupervisedFinetuning(Algorithm):
"""Supervised Fine-Tuning (SFT) algorithm implementation using Unsloth.
This class implements a complete SFT training loop that:
1. Runs rollouts with the current model
2. Collects and ranks training data by reward
3. Fine-tunes the model on top-performing examples
4. Iterates for multiple rounds of improvement
Args:
max_iterations: The maximum number of SFT iterations to perform.
vllm_port: The port to use for the vLLM inference server.
train_triplet_fraction: The fraction of top-performing triplets to use for training (0.0 to 1.0).
initial_model_path: The path to the initial model to start training from.
"""
def __init__(self, *, max_iterations: int, vllm_port: int, train_triplet_fraction: float, initial_model_path: str):
# LLM proxy and data adapter are created by the trainer and we can directly use them
self.max_iterations = max_iterations
self.vllm_port = vllm_port
self.train_triplet_fraction = train_triplet_fraction
self.initial_model_path = initial_model_path
async def run(
self, train_dataset: Optional[Dataset[GsmProblem]] = None, val_dataset: Optional[Dataset[GsmProblem]] = None
):
"""Execute the SFT training loop. Managed by trainer.
Args:
train_dataset: The training dataset of GSM problems to use for rollouts.
val_dataset: Optional validation dataset (not currently used in SFT).
Raises:
ValueError: If train_dataset is None, or required components are missing.
"""
store = self.get_store()
llm_proxy = self.get_llm_proxy()
data_adapter = self.get_adapter()
# SFT trainer relies on the adapter to convert the trace data to triplets
if not isinstance(data_adapter, TraceToTripletBase):
raise ValueError("Data adapter must be a TracerTraceToTriplet.")
if train_dataset is None:
raise ValueError("Train dataset must be provided.")
if val_dataset is not None:
console.print("[bold red][Algo][/bold red] Validation dataset is not supported in SFT.")
if llm_proxy is None:
raise ValueError("LLM proxy must be provided.")
console.print(f"[bold red][Algo][/bold red] Starting SFT with {self.max_iterations} iterations.")
console.print(f"[bold red][Algo][/bold red] Initial model path: {self.initial_model_path}")
model_path = self.initial_model_path
for iteration in range(self.max_iterations):
model_path = await sft_one_iter(
iteration=iteration,
store=store,
model_path=model_path,
train_dataset=train_dataset,
llm_proxy=llm_proxy,
data_adapter=data_adapter,
triplet_fraction=self.train_triplet_fraction,
vllm_port=self.vllm_port,
)
console.print(f"[bold red][Algo][/bold red] Final model path: {model_path}")
if __name__ == "__main__":
setup_logging()
algo = UnslothSupervisedFinetuning(
max_iterations=2,
vllm_port=12316,
train_triplet_fraction=0.5,
initial_model_path="models/version_0",
)
trainer = Trainer(
n_runners=4,
algorithm=algo,
llm_proxy=LLMProxy(port=12358),
# Uncomment the following two lines if you want to rely on proxy-side trace data collection
# Otherwise, the rollout runner will have an agentops tracer to collect the trace data,
# and the adapter will be a TracerTraceToTriplet that parses the trace data generated by this tracer
# adapter=LlmProxyTraceToTriplet(),
# tracer=OtelTracer(),
)
trainer.fit(math_agent, load_math_dataset())