File size: 7,637 Bytes
94f255b
 
 
 
 
 
 
ce14469
af86d16
31a42db
88fb0c6
94f255b
31a42db
 
 
94f255b
 
 
 
af86d16
31a42db
94f255b
af86d16
94f255b
 
 
 
ff77368
94f255b
 
4ba54ec
 
94f255b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4ba54ec
 
 
 
 
94f255b
af86d16
94f255b
 
31a42db
94f255b
 
 
 
88fb0c6
94f255b
 
 
31a42db
94f255b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
af86d16
94f255b
 
 
 
 
 
af86d16
94f255b
 
 
 
88fb0c6
94f255b
 
 
 
 
 
 
 
 
31a42db
94f255b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4ba54ec
 
 
94f255b
 
af86d16
94f255b
af86d16
94f255b
 
 
af86d16
 
94f255b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
af86d16
 
 
4b02213
31a42db
af86d16
 
 
88fb0c6
 
af86d16
94f255b
31a42db
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
"""
PromptWizard Qwen Training โ€” Gita Edition
Fine-tunes Qwen using rahul7star/Gita dataset (.csv)
Uploads trained model to rahul7star/Qwen0.5-3B-Gita on Hugging Face Hub
"""

import gradio as gr
import spaces
import torch
from transformers import (
    AutoModelForCausalLM,
    AutoTokenizer,
    Trainer,
    TrainingArguments,
)
from datasets import load_dataset, Dataset
from peft import LoraConfig, get_peft_model, TaskType
from huggingface_hub import HfApi, HfFolder, Repository
import os, tempfile, shutil


# === GPU check (Zero GPU compatible) ===
def check_gpu_status():
    return "๐Ÿš€ Zero GPU Ready - GPU will be allocated when training starts"


# === Main Training ===
@spaces.GPU(duration=300)
def train_model(model_name, num_epochs, batch_size, learning_rate, progress=gr.Progress()):
    progress(0, desc="Initializing...")
    output_log = []

    try:
        # ==== Device ====
        device = "cuda" if torch.cuda.is_available() else "cpu"
        output_log.append(f"๐ŸŽฎ Using device: {device}")
        if device == "cuda":
            output_log.append(f"โœ… GPU: {torch.cuda.get_device_name(0)}")

        # ==== Load dataset ====
        progress(0.1, desc="Loading rahul7star/Gita dataset...")
        output_log.append("\n๐Ÿ“š Loading dataset from rahul7star/Gita...")

        dataset = load_dataset("rahul7star/Gita", split="train")
        output_log.append(f"   Loaded {len(dataset)} samples from CSV")
        output_log.append(f"   Columns: {dataset.column_names}")

        # ==== Format data ====
        def format_example(item):
            # Use "text" or "content" column if available
            text = (
                item.get("text")
                or item.get("content")
                or " ".join(str(v) for v in item.values())
            )

            prompt = f"""<|system|>
You are a wise teacher interpreting Bhagavad Gita with deep insights.
<|user|>
{text}
<|assistant|>
"""
            return {"text": prompt}

        dataset = dataset.map(format_example)
        output_log.append(f"   โœ… Formatted {len(dataset)} examples")

        # ==== Model ====
        progress(0.3, desc="Loading model & tokenizer...")
        model_name = "Qwen/Qwen2.5-0.5B"
        output_log.append(f"\n๐Ÿค– Loading model: {model_name}")

        tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
        if tokenizer.pad_token is None:
            tokenizer.pad_token = tokenizer.eos_token

        model = AutoModelForCausalLM.from_pretrained(
            model_name,
            trust_remote_code=True,
            torch_dtype=torch.float16 if device == "cuda" else torch.float32,
            low_cpu_mem_usage=True,
        )
        if device == "cuda":
            model = model.to(device)

        output_log.append("   โœ… Model loaded successfully")

        # ==== LoRA ====
        progress(0.4, desc="Configuring LoRA...")
        output_log.append("\nโš™๏ธ Setting up LoRA for efficient fine-tuning...")

        lora_config = LoraConfig(
            task_type=TaskType.CAUSAL_LM,
            r=8,
            lora_alpha=16,
            lora_dropout=0.1,
            target_modules=["q_proj", "v_proj"],
            bias="none",
        )
        model = get_peft_model(model, lora_config)

        trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
        output_log.append(f"   Trainable params: {trainable_params:,}")

        # ==== Tokenization ====
        progress(0.5, desc="Tokenizing dataset...")
        def tokenize_fn(examples):
            return tokenizer(
                examples["text"],
                padding="max_length",
                truncation=True,
                max_length=256,
            )

        dataset = dataset.map(tokenize_fn, batched=True)
        output_log.append("   โœ… Tokenization done")

        # ==== Training arguments ====
        progress(0.6, desc="Setting up training...")
        output_dir = "./qwen-gita-lora"
        training_args = TrainingArguments(
            output_dir=output_dir,
            num_train_epochs=num_epochs,
            per_device_train_batch_size=batch_size,
            gradient_accumulation_steps=2,
            warmup_steps=10,
            logging_steps=5,
            save_strategy="epoch",
            fp16=device == "cuda",
            optim="adamw_torch",
            learning_rate=learning_rate,
            max_steps=100,
        )

        trainer = Trainer(
            model=model,
            args=training_args,
            train_dataset=dataset,
            tokenizer=tokenizer,
        )

        # ==== Train ====
        progress(0.7, desc="Training...")
        output_log.append("\n๐Ÿš€ Starting training...\n" + "=" * 50)
        train_result = trainer.train()

        progress(0.85, desc="Saving model...")
        output_log.append("\n๐Ÿ’พ Saving model locally...")
        trainer.save_model(output_dir)
        tokenizer.save_pretrained(output_dir)

        # ==== Upload to HF Hub ====
        progress(0.9, desc="Uploading to Hugging Face Hub...")
        hf_repo = "rahul7star/Qwen0.5-3B-Gita"
        output_log.append(f"\nโ˜๏ธ Uploading fine-tuned model to: {hf_repo}")

        api = HfApi()
        token = HfFolder.get_token()

        # Create repo if not exists
        api.create_repo(repo_id=hf_repo, exist_ok=True)

        # Clone & push
        with tempfile.TemporaryDirectory() as tmpdir:
            repo = Repository(local_dir=tmpdir, clone_from=hf_repo, use_auth_token=token)
            shutil.copytree(output_dir, tmpdir, dirs_exist_ok=True)
            repo.push_to_hub(commit_message="Upload fine-tuned Qwen-Gita LoRA model")

        progress(1.0, desc="Complete!")
        output_log.append("\nโœ… Training complete & model uploaded successfully!")

    except Exception as e:
        output_log.append(f"\nโŒ Error: {e}")

    return "\n".join(output_log)


# === Gradio Interface ===
def create_interface():
    with gr.Blocks(title="PromptWizard โ€” Qwen Gita Trainer") as demo:
        gr.Markdown("""
        # ๐Ÿง˜ PromptWizard Qwen Fine-tuning โ€” Gita Edition  
        Fine-tune **Qwen 0.5B** on your dataset [rahul7star/Gita](https://huggingface.co/datasets/rahul7star/Gita)  
        and auto-upload to your model repo **rahul7star/Qwen0.5-3B-Gita**.
        """)

        with gr.Row():
            with gr.Column():
                gpu_status = gr.Textbox(
                    label="GPU Status",
                    value=check_gpu_status(),
                    interactive=False,
                )
                model_name = gr.Textbox(
                    label="Base Model",
                    value="Qwen/Qwen2.5-0.5B",
                    interactive=False,
                )
                num_epochs = gr.Slider(1, 3, value=1, step=1, label="Epochs")
                batch_size = gr.Slider(1, 4, value=2, step=1, label="Batch Size")
                learning_rate = gr.Number(value=5e-5, label="Learning Rate")
                train_btn = gr.Button("๐Ÿš€ Start Fine-tuning", variant="primary")

            with gr.Column():
                output = gr.Textbox(
                    label="Training Log",
                    lines=25,
                    max_lines=40,
                    value="Click 'Start Fine-tuning' to train on the Gita dataset and upload to your model repo.",
                )

        train_btn.click(
            fn=train_model,
            inputs=[model_name, num_epochs, batch_size, learning_rate],
            outputs=output,
        )

    return demo


if __name__ == "__main__":
    demo = create_interface()
    demo.launch()