File size: 3,085 Bytes
43ede4d
3fe3362
43ede4d
 
 
8380fa7
3fe3362
43ede4d
 
 
a9279c3
43ede4d
 
 
3fe3362
43ede4d
 
3fe3362
43ede4d
 
 
 
 
 
 
8380fa7
43ede4d
 
 
 
 
 
8380fa7
43ede4d
 
8380fa7
43ede4d
 
 
 
 
 
 
 
 
 
8380fa7
39b48c7
43ede4d
8380fa7
39b48c7
43ede4d
39b48c7
 
 
43ede4d
 
 
 
 
 
39b48c7
43ede4d
39b48c7
 
 
 
 
 
 
 
 
 
 
43ede4d
 
 
 
 
 
 
 
8380fa7
43ede4d
 
3fe3362
43ede4d
 
 
3fe3362
43ede4d
3fe3362
43ede4d
 
 
 
 
 
 
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
import torch
import streamlit as st
from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments, Trainer, DataCollatorForSeq2Seq
from datasets import load_dataset
from peft import LoraConfig, get_peft_model
import os

# UI
st.title("AI Tutor (Fine-tuned LLM)")
st.write("This AI tutor is fine-tuned on Python-related questions.")

# Load base model and tokenizer
model_name = "microsoft/phi-2"
tokenizer = AutoTokenizer.from_pretrained(model_name)

# πŸ”₯ Fix: Add padding token
tokenizer.add_special_tokens({'pad_token': '[PAD]'})

# Check if fine-tuned model exists
model_path = "./models"
if os.path.exists(model_path):
    st.write("βœ… Loading fine-tuned model...")
    model = AutoModelForCausalLM.from_pretrained(model_path)
else:
    st.write("⚑ Fine-tuning the model (this will take time)...")

    # Load model on CPU
    model = AutoModelForCausalLM.from_pretrained(
        model_name,
        torch_dtype=torch.bfloat16,
        device_map={"": "cpu"}  # Force CPU usage
    )

    # Resize model embeddings
    model.resize_token_embeddings(len(tokenizer))

    # Apply LoRA
    lora_config = LoraConfig(
        r=8,
        lora_alpha=32,
        target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],
        lora_dropout=0.05,
        bias="none",
        task_type="CAUSAL_LM",
    )
    model = get_peft_model(model, lora_config)

    # Load dataset
    dataset = load_dataset("mbpp", split="train")

    # πŸ”₯ Fix: Set `labels` properly
    def tokenize_function(examples):
        inputs = tokenizer(examples["text"], padding="max_length", truncation=True, max_length=512)
        inputs["labels"] = inputs["input_ids"].copy()  # βœ… Fix: Ensure labels exist
        return inputs

    tokenized_dataset = dataset.map(tokenize_function, batched=True)

    # Data collator
    data_collator = DataCollatorForSeq2Seq(tokenizer, return_tensors="pt")

    # Training arguments
    training_args = TrainingArguments(
        per_device_train_batch_size=1,
        num_train_epochs=1,  # Reduce epochs for quick training
        learning_rate=3e-4,
        output_dir=model_path,
        save_strategy="epoch",
        logging_dir="./logs",
        logging_steps=10,
        save_total_limit=2,
        evaluation_strategy="no",  # βœ… Fix: No evaluation dataset needed
        load_best_model_at_end=False  # βœ… Fix: Prevents conflict with no eval dataset
    )

    # Trainer
    trainer = Trainer(
        model=model,
        args=training_args,
        train_dataset=tokenized_dataset,
        data_collator=data_collator,
    )

    # Train
    trainer.train()

    # Save model
    model.save_pretrained(model_path)
    tokenizer.save_pretrained("./tokenizer")

    st.write("πŸŽ‰ Fine-tuning complete! Model saved.")

# Chat Interface
user_input = st.text_input("Ask a coding question:")
if user_input:
    inputs = tokenizer(user_input, return_tensors="pt").to("cpu")
    outputs = model.generate(**inputs, max_length=150)
    response = tokenizer.decode(outputs[0], skip_special_tokens=True)
    st.write("πŸ€– AI Tutor:", response)