Spaces:
Sleeping
Sleeping
| 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 if missing | |
| if tokenizer.pad_token is None: | |
| 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.float32, # Use float32 for CPU compatibility | |
| 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 (Choose any one) | |
| dataset = load_dataset("lvwerra/codeparrot-clean", split="train") # β Free dataset | |
| # π₯ Fix: Set `labels` properly | |
| def tokenize_function(examples): | |
| inputs = tokenizer(examples["content"], padding="max_length", truncation=True, max_length=512) | |
| inputs["labels"] = inputs["input_ids"].copy() # β 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", # β No eval dataset needed | |
| load_best_model_at_end=False # β Prevents conflicts | |
| ) | |
| # 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) | |