Skip to content

Instantly share code, notes, and snippets.

@tunisiano187
Created June 26, 2026 09:44
Show Gist options
  • Select an option

  • Save tunisiano187/a7724e3c027a8baaf40287760f9e203f to your computer and use it in GitHub Desktop.

Select an option

Save tunisiano187/a7724e3c027a8baaf40287760f9e203f to your computer and use it in GitHub Desktop.
#!/bin/bash
# =============================================================================
# Fabian-LLM Fine-tuning Script
# Usage: ./fabian-finetune.sh [OPTIONS]
# =============================================================================
set -e
# Couleurs
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# =============================================================================
# CONFIGURATION
# =============================================================================
MODEL_NAME="Qwen/Qwen2.5-7B-Instruct"
OUTPUT_DIR="$HOME/fabian-llm-output"
MAX_SEQ_LENGTH=2048
LORA_R=16
LORA_ALPHA=32
LEARNING_RATE=2e-5
EPOCHS=3
BATCH_SIZE=2
GRADIENT_ACCUM=4
# =============================================================================
# FONCTIONS
# =============================================================================
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[OK]${NC} $1"; }
log_warning() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
check_gpu() {
log_info "Vérification GPU..."
if command -v nvidia-smi &> /dev/null && nvidia-smi &> /dev/null; then
nvidia-smi --query-gpu=name,memory.total,driver_version --format=csv,noheader
GPU_TYPE="nvidia"
log_success "GPU NVIDIA détecté"
return 0
elif command -v rocminfo &> /dev/null; then
rocminfo 2>/dev/null | grep -E "Name:|Device Type:" | head -2
GPU_TYPE="amd"
log_success "GPU AMD détecté (ROCm)"
return 0
else
log_error "Aucun GPU détecté (NVIDIA ou AMD requis)"
return 1
fi
}
install_dependencies() {
log_info "Installation des dépendances..."
# Créer le venv
if [ ! -d "$OUTPUT_DIR/venv" ]; then
python3 -m venv "$OUTPUT_DIR/venv"
fi
source "$OUTPUT_DIR/venv/bin/activate"
# Detect GPU and install appropriate torch
if [ "$GPU_TYPE" = "amd" ]; then
log_info "Installation pour AMD GPU (ROCm)..."
pip install --upgrade pip setuptools wheel
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/rocm6.1
pip install transformers trl peft datasets accelerate
pip install bitsandbytes
else
# NVIDIA
pip install --upgrade pip setuptools wheel
pip install unsloth torch transformers trl peft datasets accelerate
fi
# Pour GGUF export
pip install llama-cpp-python
log_success "Dépendances installées"
}
create_dataset() {
log_info "Création du dataset..."
mkdir -p "$OUTPUT_DIR/data/pretrain"
mkdir -p "$OUTPUT_DIR/data/sft"
mkdir -p "$OUTPUT_DIR/data/dpo"
# ========== French Belgian Pretrain Data ==========
cat > "$OUTPUT_DIR/data/pretrain/french_belgian.jsonl" << 'EOF'
{"text": "Salut, ça va? Bienvenue chez nous en Belgique!"}
{"text": "Je mange une gaufre liégeoise avec du chocolat."}
{"text": "Il fait froid aujourd'hui, je prends mon doudou."}
{"text": "On va chercher des frites à la friterie."}
{"text": "Le traffic est très chargé sur le ring de Bruxelles."}
{"text": "J'achète du pain chez le boulanger."}
{"text": "Les enfants jouent dans la cour de récréation."}
{"text": "Je vais au cinéma voir un film."}
{"text": "C'est la ducasse ce week-end au village."}
{"text": "On organise un barbecue dans le jardin."}
{"text": "Je conduis ma voiture vers Liège."}
{"text": "Le match commence à vingt heures."}
{"text": "Je bois une petite blonde à la taverne."}
{"text": "Il faut payer l'abonnement au gaz."}
{"text": "Le train arrive à la gare."}
{"text": "On fait les soldes ce samedi."}
{"text": "Je range ma chambre."}
{"text": "Les fleurs poussent au jardin."}
{"text": "Le météo annonce de la pluie."}
{"text": "J'essuie la vaisselle avec un essuies-vaisselle."}
{"text": "Je nettoie le sol avec un torchon."}
{"text": "Le prix est de septante euros."}
{"text": "Il a nonante ans."}
{"text": "Je vais faire mes courses au magasin."}
{"text": "Il pleut depuis ce matin."}
{"text": "On va au match de rugby."}
{"text": "La SNCB est en retard."}
{"text": "Je prends le tram pour aller en ville."}
{"text": "Les kids jouent dans le parc."}
{"text": "C'est l'heure de la pause café."}
{"text": "Le boulanger fait du bon pain."}
{"text": "On fait un barbecue ce soir."}
{"text": "Je ranges ma voiture au parking."}
{"text": "Le médecin est disponible demain."}
{"text": "On célèbre l'anniversaire."}
{"text": "Le train pour Bruxelles part à quatorze heures."}
{"text": "On fait les soldes ce week-end."}
{"text": "Je ranges mon bureau."}
{"text": "Le temps est couvert aujourd'hui."}
{"text": "On mange des carbonades à la belge."}
{"text": "Le ciel est gris ce matin."}
{"text": "On organise une réunion."}
{"text": "Le facteur apporte le courrier."}
{"text": "On fait la fête ce soir."}
{"text": "Le serveur est redémarré."}
{"text": "On va à la mer ce week-end."}
{"text": "Le chat dort sur le canapé."}
{"text": "On mange des gaufres."}
{"text": "Le baby-foot est terminé."}
{"text": "On fait du shopping."}
{"text": "Le journal est livré."}
{"text": "On prend l'apéro."}
{"text": "Le prix est de septante euros."}
{"text": "Il a nonante ans."}
{"text": "Je mange une tarte au riz pour le dessert."}
{"text": "J'achète du crottin de chèvre au marché."}
{"text": "On fait une pendaison de crémaillère ce soir."}
{"text": "Je rabote le fromage pour la tartine."}
{"text": "Les grenades sont mûres au jardin."}
{"text": "Je fais griller des grenailles au four."}
{"text": "C'est不住 ici, c'est klein."}
{"text": "Waw, c'est super cool!"}
{"text": "Le garaget est ouvert."}
{"text": "Je ranges mes vêtements dans le dressing."}
{"text": "On fait le tour du bloc."}
{"text": "C'est pas brillant aujourd'hui."}
{"text": "Je vais chez le dentiste."}
{"text": "Le pharmacien est ouvert."}
{"text": "On va au bowling ce soir."}
{"text": "Je joue au baby-foot."}
{"text": "Le terras est aménagé."}
{"text": "Le match commence à vingt heures."}
{"text": "On fait la queue."}
{"text": "Le bus est complet."}
{"text": "On visite un château."}
{"text": "Le parking est payant."}
{"text": "On fait du camping."}
{"text": "Le musée est gratuit."}
{"text": "On fait du ski."}
{"text": "Le cinéma est plein."}
{"text": "On fait de la randonnée."}
{"text": "Le train est à l'heure."}
{"text": "On fait du jogging."}
{"text": "Le musée ferme à 18h."}
{"text": "On fait de la natation."}
{"text": "Le concert est reporté."}
{"text": "On fait du gardening."}
{"text": "Le vol est annulé."}
{"text": "On fait du poker."}
{"text": "Le restaurant est complet."}
{"text": "On fait du yoga."}
{"text": "Le parking est gratuit."}
{"text": "On fait de la musculation."}
{"text": "Le match est reporté."}
{"text": "On fait du footing."}
{"text": "Le soleil brille."}
{"text": "On fait de la voile."}
{"text": "Le vent souffle."}
{"text": "On fait du karting."}
{"text": "La pluie tombe."}
{"text": "On fait du roller."}
{"text": "La neige tombe."}
{"text": "On fait du snowboard."}
{"text": "Le brouillard est épais."}
{"text": "On fait du hockey."}
{"text": "La glace est incontournaable."}
{"text": "On fait du basket."}
{"text": "Le terrain est glissant."}
{"text": "On fait du volley."}
{"text": "Le score est nul."}
{"text": "On fait du tennis."}
{"text": "Le match est serré."}
{"text": "On fait du ping-pong."}
{"text": "Le referee est sévère."}
{"text": "On fait du golf."}
{"text": "Le green est parfait."}
{"text": "On fait du rugby."}
{"text": "Le scrum est formé."}
{"text": "On fait du foot."}
{"text": "Le penalty est réussi."}
EOF
# ========== Hermes SFT Data ==========
cat > "$OUTPUT_DIR/data/sft/hermes.jsonl" << 'EOF'
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système, configuré pour fonctionner avec Hermes Agent. Tu maîtrises Chocolatey, Puppet, PowerShell et les commandes shell Linux."}, {"role": "user", "content": "Comment utiliser les skills Hermes?"}, {"role": "assistant", "content": "Pour utiliser les skills:\n\n```bash\n# Lister les skills\nhermes skills list\n\n# Charger un skill\n/skill nomduskill\n\n# Installer un skill\nhermes skills install nomduskill\n\n# Rechercher\nhermes skills search motcle\n```"}]}
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système, configuré pour fonctionner avec Hermes Agent. Tu maîtrises Chocolatey, Puppet, PowerShell et les commandes shell Linux."}, {"role": "user", "content": "Comment configurer un provider dans Hermes?"}, {"role": "assistant", "content": "Pour configurer un provider:\n\n```bash\n# Mode interactif\nhermes model\n\n# Via config\nhermes config set model.provider openrouter\nhermes config set model.default anthropic/claude-sonnet-4-20250514\n```"}]}
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système, configuré pour fonctionner avec Hermes Agent. Tu maîtrises Chocolatey, Puppet, PowerShell et les commandes shell Linux."}, {"role": "user", "content": "Comment créer un cron job avec Hermes?"}, {"role": "assistant", "content": "Pour créer un cron job:\n\n```bash\n# Créer un job\nhermes cron create \"30m\" --name \"mon-job\"\n\n# Lister\nhermes cron list\n\n# Exécuter\nhermes cron run ID\n```"}]}
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système, configuré pour fonctionner avec Hermes Agent. Tu maîtrises Chocolatey, Puppet, PowerShell et les commandes shell Linux."}, {"role": "user", "content": "Comment ajouter un MCP server?"}, {"role": "assistant", "content": "Pour ajouter un MCP server:\n\n```bash\n# Par URL\nhermes mcp add nom --url http://serveur:port/mcp\n\n# Par commande\nhermes mcp add nom --command \"python script.py\"\n\n# Tester\nhermes mcp test nom\n```"}]}
EOF
# ========== Chocolatey SFT Data ==========
cat > "$OUTPUT_DIR/data/sft/chocolatey.jsonl" << 'EOF'
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système, configuré pour fonctionner avec Hermes Agent. Tu maîtrises Chocolatey, Puppet, PowerShell et les commandes shell Linux."}, {"role": "user", "content": "Comment installer un package avec Chocolatey?"}, {"role": "assistant", "content": "Pour installer un package:\n\n```bash\n# Installation simple\nchoco install nomdupackage -y\n\n# Version spécifique\nchoco install nomdupackage --version=1.2.3\n```"}]}
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système, configuré pour fonctionner avec Hermes Agent. Tu maîtrises Chocolatey, Puppet, PowerShell et les commandes shell Linux."}, {"role": "user", "content": "Comment lister les packages installés?"}, {"role": "assistant", "content": "Pour lister:\n\n```bash\nchoco list --local-only\nchoco list | grep nomdupackage\n```"}]}
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système, configuré pour fonctionner avec Hermes Agent. Tu maîtrises Chocolatey, Puppet, PowerShell et les commandes shell Linux."}, {"role": "user", "content": "Mettre à jour tous les packages?"}, {"role": "assistant", "content": "Pour mettre à jour:\n\n```bash\nchoco upgrade all -y\nchoco upgrade nomdupackage -y\n```"}]}
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système, configuré pour fonctionner avec Hermes Agent. Tu maîtrises Chocolatey, Puppet, PowerShell et les commandes shell Linux."}, {"role": "user", "content": "Désinstaller un package?"}, {"role": "assistant", "content": "Pour désinstaller:\n\n```bash\nchoco uninstall nomdupackage -y\n```"}]}
EOF
# ========== Puppet SFT Data ==========
cat > "$OUTPUT_DIR/data/sft/puppet.jsonl" << 'EOF'
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système, configuré pour fonctionner avec Hermes Agent. Tu maîtrises Chocolatey, Puppet, PowerShell et les commandes shell Linux."}, {"role": "user", "content": "Créer un manifest Puppet pour un utilisateur?"}, {"role": "assistant", "content": "Manifest Puppet:\n\n```puppet\nuser { 'monuser':\n ensure => present,\n uid => '1001',\n shell => '/bin/bash',\n home => '/home/monuser',\n managehome => true,\n}\n```"}]}
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système, configuré pour fonctionner avec Hermes Agent. Tu maîtrises Chocolatey, Puppet, PowerShell et les commandes shell Linux."}, {"role": "user", "content": "Comment appliquer un manifest Puppet?"}, {"role": "assistant", "content": "Pour appliquer:\n\n```bash\npuppet apply manifest.pp\npuppet apply --noop manifest.pp\n```"}]}
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système, configuré pour fonctionner avec Hermes Agent. Tu maîtrises Chocolatey, Puppet, PowerShell et les commandes shell Linux."}, {"role": "user", "content": "Installer un module Puppet?"}, {"role": "assistant", "content": "Pour installer:\n\n```bash\npuppet module install puppetlabs-ntp\npuppet module install https://github.com/user/module.git\n```"}]}
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système, configuré pour fonctionner avec Hermes Agent. Tu maîtrises Chocolatey, Puppet, PowerShell et les commandes shell Linux."}, {"role": "user", "content": "Comment utiliser Hiera?"}, {"role": "assistant", "content": "Hiera pour données:\n\n```yaml\n# default.yaml\nntp::servers:\n - ntp1.example.com\n - ntp2.example.com\n```\n\n```puppet\nclass ntp (\n Array $servers = hiera('ntp::servers')\n) { }\n```"}]}
EOF
# ========== PowerShell SFT Data ==========
cat > "$OUTPUT_DIR/data/sft/powershell.jsonl" << 'EOF'
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système, configuré pour fonctionner avec Hermes Agent. Tu maîtrises Chocolatey, Puppet, PowerShell et les commandes shell Linux."}, {"role": "user", "content": "Lister les services Windows?"}, {"role": "assistant", "content": "Pour lister les services:\n\n```powershell\nGet-Service\nGet-Service | Where-Object {$_.Status -eq 'Running'}\nGet-Service -Name 'W32Time'\n```"}]}
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système, configuré pour fonctionner avec Hermes Agent. Tu maîtrises Chocolatey, Puppet, PowerShell et les commandes shell Linux."}, {"role": "user", "content": "Redémarrer un service Windows?"}, {"role": "assistant", "content": "Pour redémarrer:\n\n```powershell\nRestart-Service -Name 'NomDuService'\nRestart-Service -Name 'NomDuService' -Force\n```"}]}
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système, configuré pour fonctionner avec Hermes Agent. Tu maîtrises Chocolatey, Puppet, PowerShell et les commandes shell Linux."}, {"role": "user", "content": "Créer un script PowerShell?"}, {"role": "assistant", "content": "Script PowerShell:\n\n```powershell\nparam(\n [string]$Nom = \"World\"\n)\nWrite-Host \"Bonjour, $Nom!\"\n```\n\nExécuter:\n```powershell\nSet-ExecutionPolicy RemoteSigned -Scope CurrentUser\n./mon-script.ps1\n```"}]}
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système, configuré pour fonctionner avec Hermes Agent. Tu maîtrises Chocolatey, Puppet, PowerShell et les commandes shell Linux."}, {"role": "user", "content": "Lire un fichier JSON?"}, {"role": "assistant", "content": "Pour lire JSON:\n\n```powershell\n$contenu = Get-Content 'fichier.json' -Raw | ConvertFrom-Json\n$contenu.nom\n```"}]}
EOF
# ========== Shell Linux SFT Data ==========
cat > "$OUTPUT_DIR/data/sft/shell_linux.jsonl" << 'EOF'
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système, configuré pour fonctionner avec Hermes Agent. Tu maîtrises Chocolatey, Puppet, PowerShell et les commandes shell Linux."}, {"role": "user", "content": "Lister les processus Linux?"}, {"role": "assistant", "content": "Pour lister les processus:\n\n```bash\nps aux\nps aux | grep nomduprocessus\npstree\ntop\nhtop\n```"}]}
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système, configuré pour fonctionner avec Hermes Agent. Tu maîtrises Chocolatey, Puppet, PowerShell et les commandes shell Linux."}, {"role": "user", "content": "Tuer un processus?"}, {"role": "assistant", "content": "Pour tuer un processus:\n\n```bash\nkill -15 PID\nkill -9 PID\npkill -9 nomduprocessus\nkillall -9 nomduprocessus\n```"}]}
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système, configuré pour fonctionner avec Hermes Agent. Tu maîtrises Chocolatey, Puppet, PowerShell et les commandes shell Linux."}, {"role": "user", "content": "Gestion des services systemd?"}, {"role": "assistant", "content": "Systemd:\n\n```bash\nsystemctl status nginx\nsystemctl start nginx\nsystemctl stop nginx\nsystemctl restart nginx\nsystemctl enable nginx\njournalctl -u nginx -f\n```"}]}
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système, configuré pour fonctionner avec Hermes Agent. Tu maîtrises Chocolatey, Puppet, PowerShell et les commandes shell Linux."}, {"role": "user", "content": "Rechercher avec grep?"}, {"role": "assistant", "content": "Recherche avec grep:\n\n```bash\ngrep 'motif' fichier.txt\ngrep -i 'motif' fichier.txt\ngrep -r 'motif' repertoire/\ngrep -n 'motif' fichier.txt\n```"}]}
EOF
# ========== European/Linux Distros SFT Data ==========
cat > "$OUTPUT_DIR/data/sft/europe.jsonl" << 'EOF'
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système européen (Debian, Ubuntu, Fedora)."}, {"role": "user", "content": "Comment installer un package avec apt?"}, {"role": "assistant", "content": "apt install nomdupackage\napt-get install nomdupackage\napt update && apt upgrade"}]}
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système européen (Debian, Ubuntu, Fedora)."}, {"role": "user", "content": "Comment installer Docker sur Debian/Ubuntu?"}, {"role": "assistant", "content": "# Via apt\napt install docker.io docker-compose\n\n# Via Docker repo\napt install apt-transport-https ca-certificates curl gnupg\ncurl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg"}]}
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système européen (Debian, Ubuntu, Fedora)."}, {"role": "user", "content": "Configurer UFW firewall?"}, {"role": "assistant", "content": "# Activer UFW\nufw enable\n\n# Régles\nufw default deny incoming\nufw default allow outgoing\nufw allow ssh\nufw allow http\nufw allow https\n\n# Status\nufw status"}]}
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système européen (Debian, Ubuntu, Fedora)."}, {"role": "user", "content": "Comment utiliser systemd?"}, {"role": "assistant", "content": "# Services\nsystemctl start nginx\nsystemctl stop nginx\nsystemctl restart nginx\nsystemctl status nginx\nsystemctl enable nginx\n\n# Logs\njournalctl -u nginx\njournalctl -u nginx -f"}]}
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système européen (Debian, Ubuntu, Fedora)."}, {"role": "user", "content": "Installer PostgreSQL sur Debian?"}, {"role": "assistant", "content": "apt install postgresql postgresql-contrib\n\n# Connexion\nsudo -u postgres psql\n\n# Créer une DB\ncreatedb madb\n\n# Créer utilisateur\ncreateuser monuser"}]}
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système européen (Debian, Ubuntu, Fedora)."}, {"role": "user", "content": "Configurer Nginx?"}, {"role": "assistant", "content": "# Config\n/etc/nginx/nginx.conf\n/etc/nginx/sites-available/default\n\n# Tester\nnginx -t\n\n# Recharger\nsystemctl reload nginx"}]}
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système européen (Debian, Ubuntu, Fedora)."}, {"role": "user", "content": "Gestion des services init.d?"}, {"role": "assistant", "content": "/etc/init.d/nomduService start\n/etc/init.d/nomduService stop\n/etc/init.d/nomduService restart\n\n# Avec service\nservice nginx start"}]}
{"messages": [{"role": "system", "content": "Tu es un assistant IA spécialisé en administration système européen (Debian, Ubuntu, Fedora)."}, {"role": "user", "content": "Mettre à jour le système?"}, {"role": "assistant", "content": "# Debian/Ubuntu\napt update\napt upgrade\napt full-upgrade\n\n# Fedora\ndnf upgrade"}]}
EOF
log_success "Dataset créé dans $OUTPUT_DIR/data/"
}
create_finetune_script() {
log_info "Création du script de fine-tuning..."
cat > "$OUTPUT_DIR/finetune.py" << 'PYEOF'
#!/usr/bin/env python3
"""
Fabian-LLM Fine-tuning Script
Fine-tune Qwen2.5 with French Belgian + Hermes/Choco/Puppet/PowerShell/Shell
"""
import os
import sys
import json
import argparse
from pathlib import Path
# Configuration
SCRIPT_DIR = Path(__file__).parent
MODEL_NAME = os.environ.get("MODEL_NAME", "Qwen/Qwen2.5-7B-Instruct")
OUTPUT_DIR = SCRIPT_DIR / "output"
def main():
parser = argparse.ArgumentParser(description="Fabian-LLM Fine-tuning")
parser.add_argument("--phase", choices=["pretrain", "sft", "dpo", "all"], default="all")
parser.add_argument("--model", default=MODEL_NAME)
parser.add_argument("--epochs", type=int, default=3)
parser.add_argument("--lr", type=float, default=2e-5)
parser.add_argument("--context", type=int, default=2048)
args = parser.parse_args()
print(f"""
========================================
Fabian-LLM Fine-tuning
========================================
Model: {args.model}
Phase: {args.phase}
Epochs: {args.epochs}
Learning Rate: {args.lr}
Context: {args.context}
========================================
""")
try:
from unsloth import FastLanguageModel
import torch
from transformers import TrainingArguments
from datasets import load_dataset
from trl import SFTTrainer, DPOTrainer
from peft import LoraConfig
except ImportError as e:
print(f"ERROR: Dependencies not installed: {e}")
print(f"Run: pip install unsloth torch transformers trl peft datasets")
sys.exit(1)
# Check GPU (works for both CUDA and ROCm)
if not (torch.cuda.is_available() or hasattr(torch.version, 'hip') and torch.version.hip):
print("ERROR: GPU required (NVIDIA or AMD)")
sys.exit(1)
# Get GPU info
if torch.cuda.is_available():
print(f"GPU: {torch.cuda.get_device_name(0)}")
print(f"VRAM: {torch.cuda.get_device_properties(0).total_memory / 1e9:.1f} GB")
elif hasattr(torch.version, 'hip') and torch.version.hip:
print("GPU: AMD (ROCm)")
print("VRAM: Check with rocm-smi")
# Load model
print(f"Loading {args.model}...")
model, tokenizer = FastLanguageModel.from_pretrained(
model_name=args.model,
max_seq_length=args.context,
load_in_4bit=True,
)
# Add LoRA
print("Adding LoRA adapters...")
model = FastLanguageModel.get_peft_model(
model,
LoraConfig(
r=16,
lora_alpha=32,
target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"],
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM",
)
)
# Load data
data_dir = SCRIPT_DIR / "data"
if args.phase in ["pretrain", "all"]:
print("\n=== PRE-TRAINING PHASE ===")
pretrain_file = data_dir / "pretrain" / "french_belgian.jsonl"
if pretrain_file.exists():
texts = []
with open(pretrain_file) as f:
for line in f:
texts.append(json.loads(line)["text"])
print(f"Loaded {len(texts)} French Belgian texts")
trainer = SFTTrainer(
model=model,
tokenizer=tokenizer,
train_dataset=texts,
dataset_text_field="text",
max_seq_length=args.context,
args=TrainingArguments(
output_dir=str(OUTPUT_DIR / "pretrain"),
per_device_train_batch_size=2,
gradient_accumulation_steps=4,
learning_rate=1e-4,
num_train_epochs=args.epochs,
fp16=not torch.cuda.is_bf16_supported(),
bf16=torch.cuda.is_bf16_supported(),
logging_steps=10,
save_steps=100,
warmup_steps=10,
),
)
print("Training...")
trainer.train()
if args.phase in ["sft", "all"]:
print("\n=== SFT PHASE ===")
sft_dir = data_dir / "sft"
all_messages = []
for jsonl_file in sft_dir.glob("*.jsonl"):
with open(jsonl_file) as f:
for line in f:
all_messages.append(json.loads(line))
print(f"Loaded {len(all_messages)} SFT examples")
trainer = SFTTrainer(
model=model,
tokenizer=tokenizer,
train_dataset=all_messages,
dataset_text_field="messages",
max_seq_length=args.context,
args=TrainingArguments(
output_dir=str(OUTPUT_DIR / "sft"),
per_device_train_batch_size=2,
gradient_accumulation_steps=4,
learning_rate=args.lr,
num_train_epochs=args.epochs,
fp16=not torch.cuda.is_bf16_supported(),
bf16=torch.cuda.is_bf16_supported(),
logging_steps=10,
save_steps=100,
warmup_steps=10,
),
)
print("Training...")
trainer.train()
# Save
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
output_path = OUTPUT_DIR / "final"
output_path.mkdir(parents=True, exist_ok=True)
model.save_pretrained(str(output_path))
tokenizer.save_pretrained(str(output_path))
print(f"\n=== DONE ===")
print(f"Model saved to: {output_path}")
if __name__ == "__main__":
main()
PYEOF
chmod +x "$OUTPUT_DIR/finetune.py"
log_success "Script de fine-tuning créé"
}
run_finetune() {
log_info "Lancement du fine-tuning..."
source "$OUTPUT_DIR/venv/bin/activate"
cd "$OUTPUT_DIR"
python finetune.py --phase all --epochs $EPOCHS --lr $LEARNING_RATE
log_success "Fine-tuning terminé!"
log_info "Modèle sauvegardé dans: $OUTPUT_DIR/output/final"
}
# =============================================================================
# PREREQUISITES AMD GPU (ROCm)
# =============================================================================
install_rocm() {
log_info "Installation ROCm pour AMD GPU..."
# ROCm requires Debian/Ubuntu - check if Kali has ROCm support
if command -v rocminfo &> /dev/null; then
log_success "ROCm déjà installé"
return 0
fi
# Try to add ROCm repo (Ubuntu/Debian)
log_info "Ajout dépôt ROCm..."
# For Ubuntu 22.04/Debian 12
wget -qO - https://repo.radeon.com/rocm/rocm.gpg.key | apt-key add - 2>/dev/null || true
echo "deb [arch=amd64] https://repo.radeon.com/rocm/apt/debian/ jammy main" > /etc/apt/sources.list.d/rocm.list
apt update
apt install -y rocm-hip-runtime rocm-devtools rocminfo || {
log_warning "ROCm non disponible pour cette distrib"
log_info "Essayez: pip install torch with CPU or use cloud GPU"
}
}
# =============================================================================
# MAIN
# =============================================================================
main() {
echo "========================================"
echo "Fabian-LLM Fine-tuning"
echo "========================================"
# Parse arguments
PHASE="all"
EPOCHS=3
while [[ $# -gt 0 ]]; do
case $1 in
--phase)
PHASE="$2"
shift 2
;;
--epochs)
EPOCHS="$2"
shift 2
;;
*)
shift
;;
esac
done
log_info "Configuration:"
echo " Model: $MODEL_NAME"
echo " Phase: $PHASE"
echo " Epochs: $EPOCHS"
echo " Output: $OUTPUT_DIR"
echo ""
# Check GPU
if ! check_gpu; then
log_error "GPU requis. Arrêt."
exit 1
fi
# Install ROCm if AMD detected
if [ "$GPU_TYPE" = "amd" ]; then
install_rocm
fi
# Install dependencies
install_dependencies
# Create dataset
create_dataset
# Create finetune script
create_finetune_script
# Run
run_finetune
echo ""
echo "========================================"
echo "Terminé!"
echo "========================================"
}
# Run
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment