Your 'Gmail' can write code. Google's Gemini AI in Gmail drafted a fully functional Python script to fine-tune Microsoft's DeBERTa-v3-large model for 3-label sentiment classification, including data loading, training loops, and evaluation, demonstrating the AI's capability to generate complex code within email drafts. Gemini in Gmail drafted Python code to fine-tune a DeBERTa model for sentiment classification, complete with data loading, training loops, and evaluation. Gmail drafter is powered by a language model, and it can do almost anything your chat assistant can. For example here I ask it to write python code to train a sentiment classification model. write code for train.py to fine-tune deberta v3 large for sentiment classification into 3 labels: positive, neutral and negative data.csv as source headers: text,positive,neutral,negative values for labels are 0 or 1 use tqdm and wandb for logging per step It drafted the following email with a fully functional python code: --- Hey Name , Here is the code for train.py to fine-tune DeBERTa-v3-large on your sentiment data. It reads from data.csv, sets up a 3-label classification, and handles logging via tqdm and Weights & Biases per step. python import pandas as pd import torch from torch.utils.data import Dataset, DataLoader from transformers import AutoTokenizer, AutoModelForSequenceClassification, AdamW, get scheduler from sklearn.model selection import train test split import wandb from tqdm import auto as tqdm auto import numpy as np Initialize wandb wandb.init project="deberta-sentiment-classification" Load data df = pd.read csv 'data.csv' Map one-hot labels to a single target index Assumes headers are text, positive, neutral, negative def get label row : if row 'positive' == 1: return 0 if row 'neutral' == 1: return 1 if row 'negative' == 1: return 2 return -1 df 'label' = df.apply get label, axis=1 df = df df 'label' = -1 .reset index drop=True train df, val df = train test split df, test size=0.1, random state=42 class SentimentDataset Dataset : def init self, texts, labels, tokenizer, max len=128 : self.texts = texts self.labels = labels self.tokenizer = tokenizer self.max len = max len def len self : return len self.texts def getitem self, idx : text = str self.texts idx label = self.labels idx encoding = self.tokenizer text, add special tokens=True, max length=self.max len, padding='max length', truncation=True, return tensors='pt' return { 'input ids': encoding 'input ids' .flatten , 'attention mask': encoding 'attention mask' .flatten , 'labels': torch.tensor label, dtype=torch.long } Model and Tokenizer setup MODEL NAME = "microsoft/deberta-v3-large" tokenizer = AutoTokenizer.pretrained MODEL NAME model = AutoModelForSequenceClassification.pretrained MODEL NAME, num labels=3 train dataset = SentimentDataset train df 'text' .values, train df 'label' .values, tokenizer val dataset = SentimentDataset val df 'text' .values, val df 'label' .values, tokenizer train loader = DataLoader train dataset, batch size=8, shuffle=True val loader = DataLoader val dataset, batch size=16 device = torch.device 'cuda' if torch.cuda.is available else 'cpu' model.to device optimizer = AdamW model.parameters , lr=2e-5 num epochs = 3 num training steps = num epochs len train loader lr scheduler = get scheduler "linear", optimizer=optimizer, num warmup steps=0, num training steps=num training steps wandb.config.update { "model": MODEL NAME, "epochs": num epochs, "batch size": 8, "lr": 2e-5 } global step = 0 for epoch in range num epochs : model.train train bar = tqdm auto.tqdm train loader, desc=f"Epoch {epoch+1}/{num epochs} Train " for batch in train bar: optimizer.zero grad input ids = batch 'input ids' .to device attention mask = batch 'attention mask' .to device labels = batch 'labels' .to device outputs = model input ids=input ids, attention mask=attention mask, labels=labels loss = outputs.loss loss.backward optimizer.step lr scheduler.step global step += 1 wandb.log {"train loss": loss.item , "learning rate": lr scheduler.get last lr 0 }, step=global step train bar.set postfix loss=loss.item Validation loop model.eval val loss = 0 correct = 0 total = 0 val bar = tqdm auto.tqdm val loader, desc=f"Epoch {epoch+1}/{num epochs} Val " with torch.no grad : for batch in val bar: input ids = batch 'input ids' .to device attention mask = batch 'attention mask' .to device labels = batch 'labels' .to device outputs = model input ids=input ids, attention mask=attention mask, labels=labels val loss += outputs.loss.item preds = torch.argmax outputs.logits, dim=1 correct += preds == labels .sum .item total += labels.size 0 avg val loss = val loss / len val loader accuracy = correct / total wandb.log {"val loss": avg val loss, "val accuracy": accuracy}, step=global step print f"Epoch {epoch+1} - Val Loss: {avg val loss:.4f}, Val Acc: {accuracy:.4f}" model.save pretrained "./sentiment model" tokenizer.save pretrained "./sentiment model" wandb.finish Let me know if you need to adjust the batch size or max length constraints. ---