Created
June 26, 2026 09:44
-
-
Save tunisiano187/a7724e3c027a8baaf40287760f9e203f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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