"""
SelfImprovementModule
Generated by Eden via recursive self-improvement
2025-10-28 05:02:59.682036
"""

import pandas as pd
from sklearn.model_selection import train_test_split
from transformers import AutoModelForSequenceClassification, AutoTokenizer
from sklearn.metrics import accuracy_score, f1_score

class SelfImprovementModule:
    """A module that enables AI to improve its performance through iterative learning.
    
    Attributes:
        ai_model: The AI model being improved
        tokenizer: Tokenizer for text processing
        dataset: Training data used for improvement
        metrics: Dictionary to store evaluation metrics
    """
    
    def __init__(self, model_name="bert-base-uncased"):
        """Initialize the self-improvement module with a BERT model."""
        self.ai_model = AutoModelForSequenceClassification.from_pretrained(model_name)
        self.tokenizer = AutoTokenizer.from_pretrained(model_name)
        self.dataset = None
        self.metrics = {"accuracy": [], "f1_score": []}
        
    def set_dataset(self, data_frame: pd.DataFrame, text_col: str, label_col: str):
        """Set the training dataset for improvement."""
        self.dataset = data_frame
        self.text_column = text_col
        self.label_column = label_col
        
    def train_model(self, num_epochs=3, batch_size=16):
        """Train the AI model on the provided dataset."""
        if self.dataset is None:
            raise ValueError("Dataset not set. Use set_dataset() first.")
            
        # Prepare the dataset for training
        train_texts = self.dataset[self.text_column].tolist()
        train_labels = self.dataset[self.label_column].tolist()
        
        encoded_inputs = self.tokenizer(train_texts, padding=True, truncation=True)
        train_dataset = Dataset.from_dict({
            'input_ids': encoded_inputs['input_ids'],
            'attention_mask': encoded_inputs['attention_mask'],
            'labels': train_labels
        })
        
        # Training loop
        for epoch in range(num_epochs):
            self.ai_model.train()
            total_loss = 0
            
            for batch in DataLoader(train_dataset, batch_size=batch_size):
                inputs = {'input_ids': batch['input_ids'], 
                         'attention_mask': batch['attention_mask'],
                         'labels': batch['labels']}
                outputs = self.ai_model(**inputs)
                loss = outputs[0]
                total_loss += loss.item()
                
            avg_loss = total_loss / len(train_dataset) / num_epochs
            print(f"Epoch {epoch+1}/{num_epochs}: Loss: {avg_loss:.4f}")
            
    def evaluate_model(self, validation_set_size=0.2):
        """Evaluate the AI model on a validation set."""
        if self.dataset is None:
            raise ValueError("Dataset not set. Use set_dataset() first.")
            
        # Create validation set
        texts = self.dataset[self.text_column].tolist()
        labels = self.dataset[self.label_column].tolist()
        train_texts, val_texts, train_labels, val_labels = train_test_split(
            texts, labels, test_size=validation_set_size)
        
        # Evaluate on validation set
        encoded_val = self.tokenizer(val_texts, padding=True, truncation=True)
        val_inputs = {
            'input_ids': encoded_val['input_ids'],
            'attention_mask': encoded_val['attention_mask'],
            'labels': val_labels
        }
        
        with torch.no_grad():
            outputs = self.ai_model(**val_inputs)
            predicted_labels = torch.argmax(outputs.logits, dim=-1).numpy()
            
        accuracy = accuracy_score(val_labels, predicted_labels)
        f1 = f1_score(val_labels, predicted_labels, average='weighted')
        print(f"Validation Accuracy: {accuracy:.4f}")
        print(f"F1 Score: {f1:.4f}")
        
        self.metrics["accuracy"].append(accuracy)
        self.metrics["f1_score"].append(f1)
        
    def generate_feedback(self):
        """Generate feedback report based on evaluation metrics."""
        if not self.metrics["accuracy"]:
            return "No evaluations performed yet."
            
        avg_accuracy = sum(self.metrics["accuracy"]) / len(self.metrics["accuracy"])
        avg_f1 = sum(self.metrics["f1_score"]) / len(self.metrics["f1_score"])
        
        feedback = f"""Self-Improvement Feedback Report
        -------------------------------
        Average Accuracy: {avg_accuracy:.4f}
        Average F1 Score: {avg_f1:.4f}
        """
        return feedback

# Example usage:
if __name__ == "__main__":
    # Create a sample dataset
    data = {
        "text": ["This is a test sentence.", "Another example here.", 
                "Yet another text sample.", "Testing the AI skills."],
        "label": [0, 1, 0, 1]
    }
    df = pd.DataFrame(data)
    
    # Initialize and use the module
    improver = SelfImprovementModule()
    improver.set_dataset(df, "text", "label")
    improver.train_model(num_epochs=2)
    feedback = improver.generate_feedback()
    print(feedback)