forked from MakazhanAlpamys/Soup
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathiterative_dpo.py
More file actions
103 lines (91 loc) · 3.21 KB
/
Copy pathiterative_dpo.py
File metadata and controls
103 lines (91 loc) · 3.21 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
"""soup iterative-dpo — Iterative DPO loop driver — v0.70.0 Part E.
Sample → RM-score → re-pair → retrain over N rounds. The live runner
is deferred to v0.70.1; v0.70.0 ships the schema + ``--plan-only``
renderer that prints the canonical per-round artifacts.
"""
from __future__ import annotations
import typer
from rich.console import Console
from rich.markup import escape
from rich.panel import Panel
from rich.table import Table
console = Console()
app = typer.Typer(
no_args_is_help=True,
help="Iterative DPO loop driver (v0.70.0 Part E)",
)
@app.callback(invoke_without_command=True)
def main(
base_model: str = typer.Option(..., "--base-model", help="HF id / local path"),
reward_model: str = typer.Option(..., "--reward-model", help="RM HF id / path"),
prompts: str = typer.Option(..., "--prompts", help="Source prompts JSONL"),
output_dir: str = typer.Option(..., "--output-dir", help="Output dir"),
rounds: int = typer.Option(3, "--rounds", help="Number of iterative-DPO rounds"),
pairs_per_round: int = typer.Option(
500,
"--pairs-per-round",
help="Number of (chosen, rejected) pairs per round",
),
plan_only: bool = typer.Option(
False,
"--plan-only",
help="Print the resolved plan and exit (no training).",
),
):
"""Render the iterative-DPO plan and (in v0.70.1) execute it."""
from soup_cli.utils.iterative_dpo import (
build_iterative_dpo_plan,
run_iterative_dpo,
)
try:
plan = build_iterative_dpo_plan(
base_model=base_model,
reward_model=reward_model,
prompts_path=prompts,
output_dir=output_dir,
rounds=rounds,
pairs_per_round=pairs_per_round,
)
except (ValueError, TypeError) as exc:
console.print(f"[red]Error:[/red] {escape(str(exc))}")
raise typer.Exit(code=2) from exc
table = Table(title="Iterative-DPO plan")
table.add_column("Round")
table.add_column("Pairs path")
table.add_column("Adapter path")
table.add_column("Pairs")
for r in plan.rounds:
table.add_row(
str(r.round_index),
escape(r.pairs_path),
escape(r.adapter_path),
str(r.pairs_count),
)
console.print(table)
if plan_only:
console.print(
Panel(
"[green]Plan rendered[/green] (--plan-only). Drop the flag "
"to execute the sample → score → pair → train loop.",
title="Iterative DPO",
)
)
raise typer.Exit(code=0)
try:
result = run_iterative_dpo(plan)
except Exception as exc: # noqa: BLE001 — CLI boundary: friendly exit-1
console.print(
Panel(
f"[red]Iterative DPO failed:[/red] {escape(str(exc))}",
title="Iterative DPO",
)
)
raise typer.Exit(code=1) from exc
console.print(
Panel(
f"[green]Done[/green] — {result.rounds_completed} round(s); "
f"final adapter: {escape(result.final_adapter)}; "
f"pairs/round: {list(result.per_round_pairs)}",
title="Iterative DPO",
)
)