mirror of https://github.com/razor-ai/soup.git
773 lines
22 KiB
Python
773 lines
22 KiB
Python
"""Pydantic schemas for soup.yaml config — single source of truth."""
|
||
|
||
import re
|
||
from typing import List, Literal, Optional, Union
|
||
|
||
from pydantic import BaseModel, Field, field_validator
|
||
|
||
|
||
class LoraConfig(BaseModel):
|
||
r: int = Field(default=64, description="LoRA rank")
|
||
alpha: int = Field(default=16, description="LoRA alpha")
|
||
dropout: float = Field(default=0.05, description="LoRA dropout")
|
||
target_modules: Union[str, List[str]] = Field(
|
||
default="auto",
|
||
description="Target modules for LoRA. 'auto' = let peft decide.",
|
||
)
|
||
use_dora: bool = Field(
|
||
default=False,
|
||
description="Enable DoRA (Weight-Decomposed Low-Rank Adaptation)",
|
||
)
|
||
use_rslora: bool = Field(
|
||
default=False,
|
||
description="Enable rank-stabilized LoRA scaling (better for high ranks)",
|
||
)
|
||
|
||
|
||
class DataConfig(BaseModel):
|
||
train: str = Field(..., description="Path to training data or HF dataset name")
|
||
format: Literal[
|
||
"alpaca", "sharegpt", "chatml", "dpo", "kto", "llava", "sharegpt4v",
|
||
"plaintext", "embedding", "audio", "auto",
|
||
] = Field(
|
||
default="auto",
|
||
description="Data format",
|
||
)
|
||
val_split: float = Field(default=0.1, ge=0.0, le=0.5, description="Validation split ratio")
|
||
max_length: int = Field(
|
||
default=2048, ge=64, le=1048576,
|
||
description="Max sequence length in tokens",
|
||
)
|
||
image_dir: Optional[str] = Field(
|
||
default=None,
|
||
description="Base directory for resolving relative image paths in vision datasets",
|
||
)
|
||
audio_dir: Optional[str] = Field(
|
||
default=None,
|
||
description="Base directory for resolving relative audio paths in audio datasets",
|
||
)
|
||
|
||
|
||
class TrainingConfig(BaseModel):
|
||
epochs: int = Field(default=3, ge=1, description="Number of training epochs")
|
||
lr: float = Field(default=2e-5, gt=0, description="Learning rate")
|
||
batch_size: Union[int, Literal["auto"]] = Field(
|
||
default="auto",
|
||
description="Batch size. 'auto' = find max that fits in memory.",
|
||
)
|
||
gradient_accumulation_steps: int = Field(default=4, ge=1)
|
||
warmup_ratio: float = Field(default=0.03, ge=0.0, le=0.5)
|
||
weight_decay: float = Field(default=0.01, ge=0.0)
|
||
max_grad_norm: float = Field(default=1.0, gt=0)
|
||
lora: LoraConfig = Field(default_factory=LoraConfig)
|
||
quantization: Literal["4bit", "8bit", "none"] = Field(
|
||
default="4bit",
|
||
description="Quantization: 4bit (QLoRA), 8bit, or none (full precision)",
|
||
)
|
||
quantization_aware: bool = Field(
|
||
default=False,
|
||
description="Enable Quantization-Aware Training (QAT) for better post-quantization quality",
|
||
)
|
||
optimizer: str = Field(default="adamw_torch", description="Optimizer name")
|
||
scheduler: str = Field(default="cosine", description="LR scheduler type")
|
||
save_steps: int = Field(default=100, description="Save checkpoint every N steps")
|
||
logging_steps: int = Field(default=10, description="Log metrics every N steps")
|
||
# DPO-specific
|
||
dpo_beta: float = Field(
|
||
default=0.1, gt=0, description="DPO beta — KL penalty coefficient"
|
||
)
|
||
# KTO-specific
|
||
kto_beta: float = Field(
|
||
default=0.1, gt=0, description="KTO beta — KL penalty coefficient"
|
||
)
|
||
# ORPO-specific
|
||
orpo_beta: float = Field(
|
||
default=0.1, gt=0, description="ORPO beta — odds ratio weight"
|
||
)
|
||
# SimPO-specific
|
||
simpo_gamma: float = Field(
|
||
default=0.5, ge=0, description="SimPO gamma — reward margin term"
|
||
)
|
||
cpo_alpha: float = Field(
|
||
default=1.0, gt=0, description="CPO/SimPO alpha — NLL loss weight"
|
||
)
|
||
# IPO-specific (uses DPO trainer with loss_type='ipo')
|
||
ipo_tau: float = Field(
|
||
default=0.1, gt=0, description="IPO tau — regularization strength"
|
||
)
|
||
# GRPO-specific
|
||
grpo_beta: float = Field(
|
||
default=0.1, gt=0, description="GRPO beta — KL penalty coefficient"
|
||
)
|
||
num_generations: int = Field(
|
||
default=4, ge=2, description="Number of generations per prompt for GRPO"
|
||
)
|
||
reward_fn: Optional[str] = Field(
|
||
default="accuracy",
|
||
description="Reward function: 'accuracy', 'format', or path to custom .py file",
|
||
)
|
||
# PPO-specific
|
||
ppo_epochs: int = Field(
|
||
default=4, ge=1, description="Number of PPO optimization epochs per batch"
|
||
)
|
||
ppo_clip_ratio: float = Field(
|
||
default=0.2, gt=0, le=1.0, description="PPO clipping range for policy ratio"
|
||
)
|
||
ppo_kl_penalty: float = Field(
|
||
default=0.05, ge=0, description="KL divergence penalty coefficient for PPO"
|
||
)
|
||
reward_model: Optional[str] = Field(
|
||
default=None,
|
||
description="Path or HF ID of a trained reward model for PPO",
|
||
)
|
||
# LoRA+ — different learning rates for A and B matrices
|
||
loraplus_lr_ratio: Optional[float] = Field(
|
||
default=None,
|
||
gt=0,
|
||
description="LoRA+ lr ratio: lr_B = lr × ratio. None = disabled (standard LoRA).",
|
||
)
|
||
# GaLore — memory-efficient full-parameter training
|
||
use_galore: bool = Field(
|
||
default=False,
|
||
description="Enable GaLore (Gradient Low-Rank Projection) for memory-efficient training",
|
||
)
|
||
galore_rank: int = Field(
|
||
default=128, ge=1, description="GaLore projection rank"
|
||
)
|
||
galore_update_proj_gap: int = Field(
|
||
default=200, ge=1, description="GaLore projection update interval (steps)"
|
||
)
|
||
galore_scale: float = Field(
|
||
default=0.25, gt=0, description="GaLore gradient scaling factor"
|
||
)
|
||
# MoE-specific
|
||
moe_lora: bool = Field(
|
||
default=False,
|
||
description="Enable MoE-aware LoRA (ScatterMoE) — applies LoRA to expert FFN layers",
|
||
)
|
||
moe_aux_loss_coeff: float = Field(
|
||
default=0.01,
|
||
ge=0,
|
||
description="Auxiliary load-balancing loss coefficient for MoE models",
|
||
)
|
||
# Performance — Liger Kernel (fused operations)
|
||
use_liger: bool = Field(
|
||
default=False,
|
||
description="Enable Liger Kernel fused operations (20-60% memory savings, 20-40% speedup)",
|
||
)
|
||
# Performance — FlashAttention
|
||
use_flash_attn: bool = Field(
|
||
default=False,
|
||
description="Enable FlashAttention (auto-detects v2/v3/v4 for faster attention)",
|
||
)
|
||
# Performance — Ring FlashAttention (sequence parallelism)
|
||
use_ring_attention: bool = Field(
|
||
default=False,
|
||
description="Enable Ring FlashAttention for sequence parallelism across GPUs",
|
||
)
|
||
# Long-context — RoPE scaling
|
||
rope_scaling_type: Optional[Literal["linear", "dynamic", "yarn", "longrope"]] = Field(
|
||
default=None,
|
||
description="RoPE scaling method for long-context: linear, dynamic, yarn, longrope",
|
||
)
|
||
gradient_checkpointing: bool = Field(
|
||
default=False,
|
||
description="Enable gradient checkpointing for memory savings on long sequences",
|
||
)
|
||
# Embedding-specific
|
||
embedding_loss: Literal["contrastive", "triplet", "cosine"] = Field(
|
||
default="contrastive",
|
||
description="Loss function for embedding training: contrastive, triplet, or cosine",
|
||
)
|
||
embedding_margin: float = Field(
|
||
default=0.5, gt=0,
|
||
description="Margin for contrastive/triplet loss (higher = stricter separation)",
|
||
)
|
||
embedding_pooling: Literal["mean", "cls", "last"] = Field(
|
||
default="mean",
|
||
description="Pooling strategy for sentence embeddings: mean, cls, or last token",
|
||
)
|
||
embedding_temperature: float = Field(
|
||
default=0.05, gt=0,
|
||
description="Temperature for contrastive (InfoNCE) loss — lower = stricter similarity",
|
||
)
|
||
# Curriculum learning — sort dataset by difficulty
|
||
curriculum: bool = Field(
|
||
default=False,
|
||
description="Enable curriculum learning (sort dataset by difficulty, easy → hard)",
|
||
)
|
||
curriculum_metric: Literal["length", "perplexity", "loss"] = Field(
|
||
default="length",
|
||
description="Metric for curriculum difficulty: length, perplexity, or loss",
|
||
)
|
||
curriculum_buckets: int = Field(
|
||
default=4, ge=1, le=20,
|
||
description="Number of difficulty stages for curriculum learning",
|
||
)
|
||
# Loss watchdog — auto-stop on loss spikes
|
||
loss_watchdog: bool = Field(
|
||
default=False,
|
||
description="Enable loss spike detection (auto-stop if loss exceeds threshold)",
|
||
)
|
||
loss_watchdog_threshold: float = Field(
|
||
default=3.0,
|
||
gt=0,
|
||
le=100.0,
|
||
description="Stop training if loss exceeds this threshold",
|
||
)
|
||
loss_watchdog_patience: int = Field(
|
||
default=5,
|
||
ge=1,
|
||
le=1000,
|
||
description="Consecutive high-loss steps before stopping",
|
||
)
|
||
# Freeze training — freeze bottom layers for parameter-efficient training
|
||
freeze_layers: Optional[int] = Field(
|
||
default=None,
|
||
ge=1,
|
||
le=1000,
|
||
description="Freeze first N layers (from bottom). Train only remaining layers.",
|
||
)
|
||
freeze_ratio: Optional[float] = Field(
|
||
default=None,
|
||
gt=0.0,
|
||
lt=1.0,
|
||
description="Freeze this fraction of layers (0.75 = freeze 75% from bottom).",
|
||
)
|
||
# Sample packing — pack multiple short samples into one sequence
|
||
packing: bool = Field(
|
||
default=False,
|
||
description="Pack multiple short samples into one sequence for faster training",
|
||
)
|
||
# NEFTune — noisy embeddings for better fine-tuning
|
||
neftune_alpha: Optional[float] = Field(
|
||
default=None,
|
||
ge=0.0,
|
||
le=50.0,
|
||
description="NEFTune noise alpha (0-50). Adds noise to embeddings for better chat quality.",
|
||
)
|
||
|
||
|
||
class EvalConfig(BaseModel):
|
||
"""Evaluation configuration for auto-eval after training."""
|
||
|
||
auto_eval: bool = Field(
|
||
default=False,
|
||
description="Run evaluation automatically after training completes",
|
||
)
|
||
benchmarks: Optional[List[str]] = Field(
|
||
default=None,
|
||
description="lm-evaluation-harness benchmark names to run",
|
||
)
|
||
custom_tasks: Optional[str] = Field(
|
||
default=None,
|
||
description="Path to custom eval JSONL file",
|
||
)
|
||
judge: Optional[dict] = Field(
|
||
default=None,
|
||
description="LLM-as-a-judge config: model, rubric, provider",
|
||
)
|
||
|
||
|
||
class SoupConfig(BaseModel):
|
||
"""Root config for soup.yaml."""
|
||
|
||
base: str = Field(..., description="Base model name or path (HF model ID)")
|
||
task: Literal[
|
||
"sft", "dpo", "grpo", "ppo", "reward_model", "kto", "orpo", "simpo", "ipo",
|
||
"pretrain", "embedding",
|
||
] = Field(
|
||
default="sft", description="Training task type"
|
||
)
|
||
modality: Literal["text", "vision", "audio"] = Field(
|
||
default="text",
|
||
description="Training modality: text (default), vision (multimodal), or audio",
|
||
)
|
||
backend: Literal["transformers", "unsloth"] = Field(
|
||
default="transformers",
|
||
description="Training backend: transformers (default) or unsloth (2-5x faster)",
|
||
)
|
||
data: DataConfig
|
||
training: TrainingConfig = Field(default_factory=TrainingConfig)
|
||
output: str = Field(default="./output", description="Output directory for trained model")
|
||
experiment_name: Optional[str] = Field(default=None, description="Experiment name for tracking")
|
||
eval: Optional[EvalConfig] = Field(
|
||
default=None,
|
||
description="Evaluation configuration for auto-eval after training",
|
||
)
|
||
|
||
@field_validator("experiment_name")
|
||
@classmethod
|
||
def experiment_name_safe(cls, value: Optional[str]) -> Optional[str]:
|
||
"""Disallow path separators and null bytes in experiment_name."""
|
||
if value is None:
|
||
return value
|
||
if re.search(r'[/\\:\x00]', value):
|
||
raise ValueError(
|
||
"experiment_name must not contain path separators (/ \\ :) or null bytes"
|
||
)
|
||
return value
|
||
|
||
|
||
# --- Built-in templates ---
|
||
|
||
TEMPLATES: dict[str, str] = {
|
||
"chat": """# Soup template: Chat Assistant
|
||
# Fine-tune a model for conversational chat
|
||
|
||
base: meta-llama/Llama-3.1-8B-Instruct
|
||
task: sft
|
||
# backend: unsloth # 2-5x faster, pip install 'soup-cli[fast]'
|
||
|
||
data:
|
||
train: ./data/train.jsonl
|
||
format: alpaca
|
||
val_split: 0.1
|
||
max_length: 2048
|
||
|
||
training:
|
||
epochs: 3
|
||
lr: 2e-5
|
||
batch_size: auto
|
||
lora:
|
||
r: 64
|
||
alpha: 16
|
||
target_modules: auto
|
||
quantization: 4bit
|
||
|
||
output: ./output
|
||
""",
|
||
"code": """# Soup template: Code Model
|
||
# Fine-tune a model for code generation / completion
|
||
|
||
base: codellama/CodeLlama-7b-Instruct-hf
|
||
task: sft
|
||
# backend: unsloth # 2-5x faster, pip install 'soup-cli[fast]'
|
||
|
||
data:
|
||
train: ./data/code_train.jsonl
|
||
format: alpaca
|
||
val_split: 0.1
|
||
max_length: 4096
|
||
|
||
training:
|
||
epochs: 2
|
||
lr: 1e-5
|
||
batch_size: auto
|
||
lora:
|
||
r: 128
|
||
alpha: 32
|
||
target_modules: auto
|
||
quantization: 4bit
|
||
|
||
output: ./output
|
||
""",
|
||
"reasoning": """# Soup template: Reasoning / GRPO
|
||
# Fine-tune a model for chain-of-thought reasoning with GRPO
|
||
|
||
base: meta-llama/Llama-3.1-8B-Instruct
|
||
task: grpo
|
||
# backend: unsloth # 2-5x faster, pip install 'soup-cli[fast]'
|
||
|
||
data:
|
||
train: ./data/reasoning_train.jsonl
|
||
format: sharegpt
|
||
val_split: 0.1
|
||
max_length: 4096
|
||
|
||
training:
|
||
epochs: 3
|
||
lr: 1e-5
|
||
batch_size: auto
|
||
gradient_accumulation_steps: 8
|
||
lora:
|
||
r: 64
|
||
alpha: 16
|
||
target_modules: auto
|
||
quantization: 4bit
|
||
grpo_beta: 0.1
|
||
num_generations: 4
|
||
reward_fn: accuracy
|
||
|
||
output: ./output
|
||
""",
|
||
"vision": """# Soup template: Vision / Multimodal
|
||
# Fine-tune a vision-language model for image understanding
|
||
|
||
base: meta-llama/Llama-3.2-11B-Vision-Instruct
|
||
task: sft
|
||
modality: vision
|
||
# backend: unsloth # 2-5x faster, pip install 'soup-cli[fast]'
|
||
|
||
data:
|
||
train: ./data/vision_train.jsonl
|
||
format: llava
|
||
image_dir: ./data/images
|
||
val_split: 0.1
|
||
max_length: 2048
|
||
|
||
training:
|
||
epochs: 3
|
||
lr: 1e-5
|
||
batch_size: auto
|
||
lora:
|
||
r: 64
|
||
alpha: 16
|
||
target_modules: auto
|
||
quantization: 4bit
|
||
|
||
output: ./output
|
||
""",
|
||
"medical": """# Soup template: Medical / Domain Expert
|
||
# Fine-tune a model with domain-specific knowledge
|
||
|
||
base: meta-llama/Llama-3.1-8B-Instruct
|
||
task: sft
|
||
# backend: unsloth # 2-5x faster, pip install 'soup-cli[fast]'
|
||
|
||
data:
|
||
train: ./data/medical_train.jsonl
|
||
format: alpaca
|
||
val_split: 0.15
|
||
max_length: 2048
|
||
|
||
training:
|
||
epochs: 5
|
||
lr: 1e-5
|
||
batch_size: auto
|
||
gradient_accumulation_steps: 8
|
||
lora:
|
||
r: 128
|
||
alpha: 32
|
||
target_modules: auto
|
||
quantization: 4bit
|
||
|
||
output: ./output
|
||
""",
|
||
"kto": """# Soup template: KTO (Kahneman-Tversky Optimization)
|
||
# Align a model using unpaired preference data (no need for chosen+rejected pairs)
|
||
#
|
||
# Data format (JSONL):
|
||
# {"prompt": "What is 2+2?", "completion": "4", "label": true}
|
||
# {"prompt": "What is 2+2?", "completion": "Fish", "label": false}
|
||
|
||
base: meta-llama/Llama-3.1-8B-Instruct
|
||
task: kto
|
||
# backend: unsloth # 2-5x faster, pip install 'soup-cli[fast]'
|
||
|
||
data:
|
||
train: ./data/kto_train.jsonl
|
||
format: kto
|
||
val_split: 0.1
|
||
max_length: 2048
|
||
|
||
training:
|
||
epochs: 3
|
||
lr: 1e-5
|
||
batch_size: auto
|
||
gradient_accumulation_steps: 4
|
||
lora:
|
||
r: 64
|
||
alpha: 16
|
||
target_modules: auto
|
||
quantization: 4bit
|
||
kto_beta: 0.1
|
||
|
||
output: ./output
|
||
""",
|
||
"orpo": """# Soup template: ORPO (Odds Ratio Preference Optimization)
|
||
# Align a model without a reference model — simpler than DPO
|
||
#
|
||
# Data format (JSONL):
|
||
# {"prompt": "What is 2+2?", "chosen": "4", "rejected": "Fish"}
|
||
|
||
base: meta-llama/Llama-3.1-8B-Instruct
|
||
task: orpo
|
||
# backend: unsloth # 2-5x faster, pip install 'soup-cli[fast]'
|
||
|
||
data:
|
||
train: ./data/preference_train.jsonl
|
||
format: dpo
|
||
val_split: 0.1
|
||
max_length: 2048
|
||
|
||
training:
|
||
epochs: 3
|
||
lr: 1e-5
|
||
batch_size: auto
|
||
gradient_accumulation_steps: 4
|
||
lora:
|
||
r: 64
|
||
alpha: 16
|
||
target_modules: auto
|
||
quantization: 4bit
|
||
orpo_beta: 0.1
|
||
|
||
output: ./output
|
||
""",
|
||
"simpo": """# Soup template: SimPO (Simple Preference Optimization)
|
||
# Reference-free preference alignment with length-normalized rewards
|
||
#
|
||
# Data format (JSONL):
|
||
# {"prompt": "What is 2+2?", "chosen": "4", "rejected": "Fish"}
|
||
|
||
base: meta-llama/Llama-3.1-8B-Instruct
|
||
task: simpo
|
||
# backend: unsloth # 2-5x faster, pip install 'soup-cli[fast]'
|
||
|
||
data:
|
||
train: ./data/preference_train.jsonl
|
||
format: dpo
|
||
val_split: 0.1
|
||
max_length: 2048
|
||
|
||
training:
|
||
epochs: 3
|
||
lr: 1e-5
|
||
batch_size: auto
|
||
gradient_accumulation_steps: 4
|
||
lora:
|
||
r: 64
|
||
alpha: 16
|
||
target_modules: auto
|
||
quantization: 4bit
|
||
simpo_gamma: 0.5
|
||
cpo_alpha: 1.0
|
||
|
||
output: ./output
|
||
""",
|
||
"ipo": """# Soup template: IPO (Identity Preference Optimization)
|
||
# A theoretically grounded variant of DPO with stronger regularization
|
||
#
|
||
# Data format (JSONL):
|
||
# {"prompt": "What is 2+2?", "chosen": "4", "rejected": "Fish"}
|
||
|
||
base: meta-llama/Llama-3.1-8B-Instruct
|
||
task: ipo
|
||
# backend: unsloth # 2-5x faster, pip install 'soup-cli[fast]'
|
||
|
||
data:
|
||
train: ./data/preference_train.jsonl
|
||
format: dpo
|
||
val_split: 0.1
|
||
max_length: 2048
|
||
|
||
training:
|
||
epochs: 3
|
||
lr: 1e-5
|
||
batch_size: auto
|
||
gradient_accumulation_steps: 4
|
||
lora:
|
||
r: 64
|
||
alpha: 16
|
||
target_modules: auto
|
||
quantization: 4bit
|
||
ipo_tau: 0.1
|
||
|
||
output: ./output
|
||
""",
|
||
"pretrain": """# Soup template: Continued Pre-training
|
||
# Continue pre-training a model on raw text data (domain adaptation)
|
||
#
|
||
# Data format (JSONL):
|
||
# {"text": "Your raw text document here..."}
|
||
#
|
||
# Or plain .txt files (one document per line or entire file as one document).
|
||
|
||
base: meta-llama/Llama-3.1-8B
|
||
task: pretrain
|
||
# backend: unsloth # 2-5x faster, pip install 'soup-cli[fast]'
|
||
|
||
data:
|
||
train: ./data/corpus.jsonl
|
||
format: plaintext
|
||
val_split: 0.05
|
||
max_length: 4096
|
||
|
||
training:
|
||
epochs: 1
|
||
lr: 1e-5
|
||
batch_size: auto
|
||
gradient_accumulation_steps: 8
|
||
lora:
|
||
r: 64
|
||
alpha: 16
|
||
target_modules: auto
|
||
quantization: 4bit
|
||
|
||
output: ./output_pretrain
|
||
""",
|
||
"moe": """# Soup template: MoE (Mixture of Experts) Fine-tuning
|
||
# Fine-tune a Mixture of Experts model with ScatterMoE LoRA
|
||
#
|
||
# Supported MoE models: Qwen3-30B-A3B, Mixtral-8x7B, DeepSeek-V3, etc.
|
||
|
||
base: Qwen/Qwen3-30B-A3B
|
||
task: sft
|
||
# backend: unsloth # 2-5x faster, pip install 'soup-cli[fast]'
|
||
|
||
data:
|
||
train: ./data/train.jsonl
|
||
format: alpaca
|
||
val_split: 0.1
|
||
max_length: 2048
|
||
|
||
training:
|
||
epochs: 3
|
||
lr: 1e-5
|
||
batch_size: auto
|
||
gradient_accumulation_steps: 8
|
||
lora:
|
||
r: 64
|
||
alpha: 16
|
||
target_modules: auto
|
||
quantization: 4bit
|
||
moe_lora: true
|
||
moe_aux_loss_coeff: 0.01
|
||
|
||
output: ./output
|
||
""",
|
||
"longcontext": """# Soup template: Long-Context Fine-tuning (128k+)
|
||
# Extend model context window for long-document understanding
|
||
#
|
||
# Uses RoPE scaling + gradient checkpointing + FlashAttention for 128k tokens.
|
||
# Optionally enable Liger Kernel for additional memory savings.
|
||
|
||
base: meta-llama/Llama-3.1-8B-Instruct
|
||
task: sft
|
||
# backend: unsloth # 2-5x faster, pip install 'soup-cli[fast]'
|
||
|
||
data:
|
||
train: ./data/long_context_train.jsonl
|
||
format: alpaca
|
||
val_split: 0.05
|
||
max_length: 131072
|
||
|
||
training:
|
||
epochs: 1
|
||
lr: 5e-6
|
||
batch_size: 1
|
||
gradient_accumulation_steps: 16
|
||
lora:
|
||
r: 64
|
||
alpha: 16
|
||
target_modules: auto
|
||
quantization: 4bit
|
||
gradient_checkpointing: true
|
||
rope_scaling_type: dynamic
|
||
use_flash_attn: true
|
||
# use_liger: true # pip install 'soup-cli[liger]' for fused ops
|
||
# use_ring_attention: true # Multi-GPU sequence parallelism
|
||
|
||
output: ./output_longctx
|
||
""",
|
||
"embedding": """# Soup template: Embedding Model Fine-tuning
|
||
# Fine-tune a sentence embedding model (BGE, E5, GTE, etc.)
|
||
#
|
||
# Data format (JSONL) — contrastive pairs:
|
||
# {"anchor": "What is Python?", "positive": "Python is a programming language."}
|
||
#
|
||
# Data format (JSONL) — triplets:
|
||
# {"anchor": "query", "positive": "relevant doc", "negative": "unrelated doc"}
|
||
|
||
base: BAAI/bge-base-en-v1.5
|
||
task: embedding
|
||
# backend: unsloth # 2-5x faster, pip install 'soup-cli[fast]'
|
||
|
||
data:
|
||
train: ./data/embedding_train.jsonl
|
||
format: embedding
|
||
val_split: 0.1
|
||
max_length: 512
|
||
|
||
training:
|
||
epochs: 3
|
||
lr: 2e-5
|
||
batch_size: auto
|
||
gradient_accumulation_steps: 4
|
||
lora:
|
||
r: 64
|
||
alpha: 16
|
||
target_modules: auto
|
||
quantization: none
|
||
embedding_loss: contrastive
|
||
embedding_margin: 0.5
|
||
embedding_pooling: mean
|
||
|
||
output: ./output_embedding
|
||
""",
|
||
"audio": """# Soup template: Audio / Speech
|
||
# Fine-tune an audio-language model for speech understanding
|
||
#
|
||
# Supported models: Qwen2-Audio, Whisper (via transformers)
|
||
#
|
||
# Data format (JSONL):
|
||
# {"audio": "path/to/audio.wav", "messages": [
|
||
# {"role": "user", "content": "Transcribe."},
|
||
# {"role": "assistant", "content": "Hello world."}]}
|
||
|
||
base: Qwen/Qwen2-Audio-7B-Instruct
|
||
task: sft
|
||
modality: audio
|
||
# backend: unsloth # 2-5x faster, pip install 'soup-cli[fast]'
|
||
|
||
data:
|
||
train: ./data/audio_train.jsonl
|
||
format: audio
|
||
audio_dir: ./data/audio
|
||
val_split: 0.1
|
||
max_length: 2048
|
||
|
||
training:
|
||
epochs: 3
|
||
lr: 1e-5
|
||
batch_size: auto
|
||
gradient_accumulation_steps: 8
|
||
lora:
|
||
r: 64
|
||
alpha: 16
|
||
target_modules: auto
|
||
quantization: 4bit
|
||
|
||
output: ./output_audio
|
||
""",
|
||
"rlhf": """# Soup template: Full RLHF Pipeline (SFT + Reward Model + PPO)
|
||
# Three-stage training: 1) SFT warmup, 2) Reward model, 3) PPO alignment
|
||
#
|
||
# Usage:
|
||
# Step 1: soup train --config soup_sft.yaml # SFT warmup
|
||
# Step 2: soup train --config soup_rm.yaml # Train reward model
|
||
# Step 3: soup train --config soup_ppo.yaml # PPO with reward model
|
||
#
|
||
# This template generates the PPO config (step 3).
|
||
# For steps 1-2, use: soup init --template chat (SFT) and edit task to reward_model.
|
||
|
||
base: meta-llama/Llama-3.1-8B-Instruct
|
||
task: ppo
|
||
# backend: unsloth # 2-5x faster, pip install 'soup-cli[fast]'
|
||
|
||
data:
|
||
train: ./data/prompts.jsonl
|
||
format: chatml
|
||
val_split: 0.1
|
||
max_length: 2048
|
||
|
||
training:
|
||
epochs: 1
|
||
lr: 1e-6
|
||
batch_size: auto
|
||
gradient_accumulation_steps: 4
|
||
lora:
|
||
r: 64
|
||
alpha: 16
|
||
target_modules: auto
|
||
quantization: 4bit
|
||
reward_model: ./output_rm
|
||
ppo_epochs: 4
|
||
ppo_clip_ratio: 0.2
|
||
ppo_kl_penalty: 0.05
|
||
|
||
output: ./output_ppo
|
||
""",
|
||
}
|