Spaces:
Sleeping
Sleeping
| #!/usr/bin/env python3 | |
| """ | |
| Deployment-Script für trainierte LoRA-Modelle | |
| Automatisiert den Upload zu Hugging Face Hub | |
| """ | |
| import os | |
| import shutil | |
| from pathlib import Path | |
| import subprocess | |
| import json | |
| import logging | |
| logging.basicConfig(level=logging.INFO) | |
| logger = logging.getLogger(__name__) | |
| class LoRADeployer: | |
| def __init__(self, model_path="../models/lora-checkpoint"): | |
| self.model_path = Path(model_path) | |
| self.hf_username = None # Wird aus HF_USERNAME env var gelesen | |
| def verify_model(self): | |
| """Prüft ob trainiertes LoRA-Modell vollständig ist""" | |
| required_files = [ | |
| "adapter_config.json", | |
| "adapter_model.bin", # oder adapter_model.safetensors | |
| "README.md" | |
| ] | |
| missing_files = [] | |
| for file in required_files: | |
| if not (self.model_path / file).exists(): | |
| missing_files.append(file) | |
| if missing_files: | |
| logger.error(f"Fehlende Dateien: {missing_files}") | |
| return False | |
| logger.info("✅ LoRA-Modell vollständig") | |
| return True | |
| def create_model_card(self): | |
| """Erstellt eine Model Card für Hugging Face""" | |
| model_card = f"""--- | |
| library_name: peft | |
| base_model: teknium/OpenHermes-2.5-Mistral-7B | |
| tags: | |
| - generated_from_trainer | |
| - horoscope | |
| - astrology | |
| - german | |
| - lora | |
| language: | |
| - de | |
| - en | |
| license: apache-2.0 | |
| --- | |
| # LoRA Adapter für Horoskop-Generierung | |
| Dieses LoRA-Adapter wurde für die Generierung von personalisierten Horoskopen trainiert. | |
| ## Basis-Modell | |
| - **Model**: teknium/OpenHermes-2.5-Mistral-7B | |
| - **LoRA Rank**: 16 | |
| - **Target Modules**: q_proj, v_proj, k_proj, o_proj | |
| ## Verwendung | |
| ```python | |
| from transformers import AutoTokenizer, AutoModelForCausalLM | |
| from peft import PeftModel | |
| base_model = "teknium/OpenHermes-2.5-Mistral-7B" | |
| tokenizer = AutoTokenizer.from_pretrained(base_model) | |
| model = AutoModelForCausalLM.from_pretrained(base_model, load_in_4bit=True) | |
| model = PeftModel.from_pretrained(model, "IHR_USERNAME/horoskop-lora") | |
| # Beispiel-Prompt | |
| prompt = "<|im_start|>system\\nDu bist ein erfahrener Astrologe.<|im_end|>\\n<|im_start|>user\\nErstelle ein Horoskop für Widder heute.<|im_end|>\\n<|im_start|>assistant\\n" | |
| ``` | |
| ## Training Details | |
| - **Training Duration**: {self.get_training_info().get('duration', 'N/A')} | |
| - **Dataset Size**: {self.get_training_info().get('dataset_size', 'N/A')} | |
| - **Epochs**: {self.get_training_info().get('epochs', 'N/A')} | |
| """ | |
| readme_path = self.model_path / "README.md" | |
| with open(readme_path, 'w', encoding='utf-8') as f: | |
| f.write(model_card) | |
| logger.info(f"Model Card erstellt: {readme_path}") | |
| def get_training_info(self): | |
| """Liest Training-Informationen aus logs oder config""" | |
| # Placeholder - könnte aus Training-Logs gelesen werden | |
| return { | |
| "duration": "2-4 Stunden", | |
| "dataset_size": "500+ Horoskop-Beispiele", | |
| "epochs": "3" | |
| } | |
| def upload_to_hf(self, repo_name="horoskop-lora"): | |
| """Upload zu Hugging Face Hub""" | |
| # Hugging Face Username prüfen | |
| hf_username = os.getenv("HF_USERNAME") | |
| if not hf_username: | |
| logger.error("HF_USERNAME environment variable nicht gesetzt") | |
| logger.info("Setzen Sie: export HF_USERNAME=ihr_username") | |
| return False | |
| # Hugging Face CLI prüfen | |
| try: | |
| subprocess.run(["huggingface-cli", "--version"], check=True, capture_output=True) | |
| except subprocess.CalledProcessError: | |
| logger.error("Hugging Face CLI nicht installiert") | |
| logger.info("Installieren Sie: pip install huggingface_hub") | |
| return False | |
| # Repository erstellen | |
| repo_id = f"{hf_username}/{repo_name}" | |
| logger.info(f"Erstelle Repository: {repo_id}") | |
| try: | |
| # Repository auf HF erstellen | |
| cmd = [ | |
| "huggingface-cli", "repo", "create", | |
| repo_id, "--type", "model", "--private" | |
| ] | |
| subprocess.run(cmd, check=True) | |
| logger.info(f"✅ Repository erstellt: {repo_id}") | |
| except subprocess.CalledProcessError as e: | |
| if "already exists" in str(e): | |
| logger.info(f"Repository existiert bereits: {repo_id}") | |
| else: | |
| logger.error(f"Repository-Erstellung fehlgeschlagen: {e}") | |
| return False | |
| # Dateien hochladen | |
| try: | |
| cmd = [ | |
| "huggingface-cli", "upload", repo_id, | |
| str(self.model_path), ".", "--recursive" | |
| ] | |
| subprocess.run(cmd, check=True) | |
| logger.info(f"✅ Upload erfolgreich: https://huggingface.co/{repo_id}") | |
| return True | |
| except subprocess.CalledProcessError as e: | |
| logger.error(f"Upload fehlgeschlagen: {e}") | |
| return False | |
| def prepare_for_space(self): | |
| """Bereitet Modell für Hugging Face Space vor""" | |
| space_model_path = Path("../models/lora-checkpoint-deployed") | |
| space_model_path.mkdir(exist_ok=True) | |
| # Kopiere nur notwendige Dateien | |
| essential_files = [ | |
| "adapter_config.json", | |
| "adapter_model.bin", | |
| "adapter_model.safetensors" | |
| ] | |
| for file in essential_files: | |
| src = self.model_path / file | |
| if src.exists(): | |
| dst = space_model_path / file | |
| shutil.copy2(src, dst) | |
| logger.info(f"Kopiert: {file}") | |
| logger.info(f"✅ Space-ready Modell in: {space_model_path}") | |
| return space_model_path | |
| def main(): | |
| """Hauptfunktion für Deployment""" | |
| deployer = LoRADeployer() | |
| print("🚀 LoRA-Modell Deployment") | |
| print("========================") | |
| # 1. Modell verifizieren | |
| if not deployer.verify_model(): | |
| print("❌ Modell-Verifikation fehlgeschlagen") | |
| return | |
| # 2. Model Card erstellen | |
| deployer.create_model_card() | |
| # 3. User-Input für Deployment-Optionen | |
| print("\n📤 Deployment-Optionen:") | |
| print("1. Für Hugging Face Space vorbereiten") | |
| print("2. Zu Hugging Face Hub hochladen") | |
| print("3. Beides") | |
| choice = input("Wählen Sie (1-3): ").strip() | |
| if choice in ["1", "3"]: | |
| space_path = deployer.prepare_for_space() | |
| print(f"✅ Space-ready: {space_path}") | |
| if choice in ["2", "3"]: | |
| repo_name = input("Repository-Name (Standard: horoskop-lora): ").strip() | |
| if not repo_name: | |
| repo_name = "horoskop-lora" | |
| if deployer.upload_to_hf(repo_name): | |
| print("✅ Upload zu Hugging Face erfolgreich!") | |
| else: | |
| print("❌ Upload fehlgeschlagen") | |
| print("\n🎯 Nächste Schritte:") | |
| print("1. Aktualisieren Sie config.py mit dem neuen Modell-Pfad") | |
| print("2. Testen Sie das Modell lokal") | |
| print("3. Deployen Sie zu Hugging Face Space") | |
| if __name__ == "__main__": | |
| main() | |