{ "cells": [ { "cell_type": "markdown", "id": "db8736a7-ed94-441c-9556-831fa57b5a10", "metadata": {}, "source": [ "# The Product Pricer Fine-Tuning a Frontier Model - Similation (GPT-4 mini)\n", "\n", "Submitted By: Bharat Puri\n", "\n", "A model that can estimate how much something costs, from its description.\n" ] }, { "cell_type": "code", "execution_count": 14, "id": "681c717b-4c24-4ac3-a5f3-3c5881d6e70a", "metadata": {}, "outputs": [], "source": [ "# imports\n", "\n", "import os\n", "import re\n", "import math\n", "import json\n", "import random\n", "from dotenv import load_dotenv\n", "from huggingface_hub import login\n", "import matplotlib.pyplot as plt\n", "import pandas as pd\n", "import numpy as np\n", "import pickle\n", "from collections import Counter\n", "import sys\n", "sys.path.append(os.path.abspath(os.path.join(\"..\", \"..\"))) \n", "from openai import OpenAI\n", "from anthropic import Anthropic\n", "from sklearn.model_selection import train_test_split\n", "from sklearn.metrics import mean_absolute_error\n" ] }, { "cell_type": "code", "execution_count": 15, "id": "36d05bdc-0155-4c72-a7ee-aa4e614ffd3c", "metadata": {}, "outputs": [], "source": [ "# environment\n", "\n", "load_dotenv(override=True)\n", "os.environ['OPENAI_API_KEY'] = os.getenv('OPENAI_API_KEY', 'your-key-if-not-using-env')\n", "os.environ['ANTHROPIC_API_KEY'] = os.getenv('ANTHROPIC_API_KEY', 'your-key-if-not-using-env')\n", "os.environ['HF_TOKEN'] = os.getenv('HF_TOKEN', 'your-key-if-not-using-env')" ] }, { "cell_type": "code", "execution_count": null, "id": "4dd3aad2-6f99-433c-8792-e461d2f06622", "metadata": {}, "outputs": [], "source": [ "# Log in to HuggingFace\n", "\n", "hf_token = os.environ['HF_TOKEN']\n", "login(hf_token, add_to_git_credential=True)" ] }, { "cell_type": "code", "execution_count": null, "id": "9c69e347-91bc-4eb1-843f-a17ed485667c", "metadata": { "scrolled": true }, "outputs": [], "source": [ "# =============================================================\n", "# Step 1 โ€” Data Curation and Preparation (Integrated from 09_part1_data_curation)\n", "# =============================================================\n", "\n", "import pandas as pd\n", "import pickle\n", "from sklearn.model_selection import train_test_split\n", "\n", "print(\"๐Ÿ” Starting data curation...\")\n", "\n", "# Load input/output CSVs (adjust paths as needed)\n", "df_input = pd.read_csv(\"../../human_input.csv\")\n", "df_output = pd.read_csv(\"../../human_output.csv\")\n", "\n", "# Detect and combine dynamically\n", "i_col, o_col = df_input.columns[0], df_output.columns[0]\n", "df = pd.DataFrame({\n", " \"prompt\": df_input[i_col].astype(str).str.strip(),\n", " \"completion\": df_output[o_col].astype(str).str.strip()\n", "})\n", "\n", "# Basic cleaning\n", "df.dropna(inplace=True)\n", "df = df[df[\"prompt\"].str.len() > 0]\n", "df = df[df[\"completion\"].str.len() > 0]\n", "df = df.reset_index(drop=True)\n", "\n", "print(f\"โœ… Cleaned dataset shape: {df.shape}\")\n", "print(df.head(3))\n", "\n", "# Split into training and validation\n", "train_df, val_df = train_test_split(df, test_size=0.1, random_state=42)\n", "print(f\"Training samples: {len(train_df)}, Validation samples: {len(val_df)}\")\n", "\n", "# Save curated datasets to reuse later\n", "with open(\"train.pkl\", \"wb\") as f:\n", " pickle.dump(train_df, f)\n", "with open(\"test.pkl\", \"wb\") as f:\n", " pickle.dump(val_df, f)\n", "\n", "print(\"๐Ÿ’พ Saved train.pkl and test.pkl successfully.\")\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "id": "b0a6fb86-74a4-403c-ab25-6db2d74e9d2b", "metadata": {}, "outputs": [], "source": [ "# =============================================================\n", "# Step 2 โ€” Prepare Data for Fine-Tuning\n", "# =============================================================\n", "import pickle\n", "import pandas as pd\n", "\n", "print(\"๐Ÿ“ฆ Loading curated train/test data from pickle files...\")\n", "\n", "with open(\"train.pkl\", \"rb\") as f:\n", " train_df = pickle.load(f)\n", "with open(\"test.pkl\", \"rb\") as f:\n", " val_df = pickle.load(f)\n", "\n", "print(f\"โœ… Loaded train={len(train_df)} | val={len(val_df)}\")\n", "\n", "# Ensure correct column names\n", "train_df = train_df.rename(columns={train_df.columns[0]: \"prompt\", train_df.columns[1]: \"completion\"})\n", "val_df = val_df.rename(columns={val_df.columns[0]: \"prompt\", val_df.columns[1]: \"completion\"})\n", "\n", "# Save as JSONL for OpenAI Fine-Tuning\n", "train_df.to_json(\"train.jsonl\", orient=\"records\", lines=True)\n", "val_df.to_json(\"val.jsonl\", orient=\"records\", lines=True)\n", "\n", "print(\"๐Ÿ’พ Saved train.jsonl and val.jsonl for fine-tuning.\")" ] }, { "cell_type": "code", "execution_count": null, "id": "c830ed3e-24ee-4af6-a07b-a1bfdcd39278", "metadata": {}, "outputs": [], "source": [ "# =============================================================\n", "# Step 3 โ€” Fine-Tuning Configuration\n", "# =============================================================\n", "import json\n", "\n", "hyperparams = {\n", " \"model\": \"gpt-4o-mini\", # Frontier model from the course\n", " \"n_epochs\": 3, # Small safe run\n", " \"batch_size\": 8, # Reasonable for small data\n", " \"learning_rate_multiplier\": 0.5, # Trainer's suggested mid value\n", " \"suffix\": \"week6_bharat_ft_v1\" # Unique identifier for your run\n", "}\n", "\n", "print(\"โš™๏ธ Fine-tuning configuration:\")\n", "print(json.dumps(hyperparams, indent=2))\n" ] }, { "cell_type": "code", "execution_count": null, "id": "5c9b05f4-c9eb-462c-8d86-de9140a2d985", "metadata": {}, "outputs": [], "source": [ "# =============================================\n", "# Step 3 โ€“ Define Fine-Tuning Configuration\n", "# =============================================\n", "\n", "hyperparams = {\n", " \"model\": \"gpt-4o-mini\", \n", " \"n_epochs\": 1, \n", " \"batch_size\": 4, # Small batch = less token use\n", " \"learning_rate_multiplier\": 0.5, # Gentle learning rate\n", " \"suffix\": \"week6_lowcost_bharat\" # Custom suffix for tracking\n", "}\n", "\n", "print(\"โœ… Fine-tuning configuration defined:\")\n", "for k, v in hyperparams.items():\n", " print(f\"{k:25}: {v}\")\n" ] }, { "cell_type": "code", "execution_count": null, "id": "e8367135-f40e-43e1-8f3c-09e990ab1194", "metadata": {}, "outputs": [], "source": [ "# =============================================================\n", "# Step 4 โ€” Launch Fine-Tuning Job (Fixed for latest SDK)\n", "# =============================================================\n", "from openai import OpenAI\n", "import time, os, json\n", "\n", "client = OpenAI(api_key=os.getenv(\"OPENAI_API_KEY\"))\n", "\n", "simulate = True # Set True for simulation (no cost)\n", "\n", "if simulate:\n", " print(\"\\n๐Ÿงช Simulation mode โ€” running mock fine-tuning steps...\")\n", " for e in range(3):\n", " print(f\"Simulated Epoch {e+1}/3\")\n", " time.sleep(1)\n", " ft_model = \"ft:gpt-4o-mini:SIMULATED\"\n", " print(\"โœ… Simulation complete โ€” no API cost.\")\n", "else:\n", " print(\"\\n๐Ÿš€ Creating fine-tuning job...\")\n", "\n", " # Upload training and validation data\n", " train_file = client.files.create(file=open(\"train.jsonl\", \"rb\"), purpose=\"fine-tune\")\n", " val_file = client.files.create(file=open(\"val.jsonl\", \"rb\"), purpose=\"fine-tune\")\n", "\n", " # โœ… Correct usage: hyperparameters must go inside a dictionary named `hyperparameters`\n", " job = client.fine_tuning.jobs.create(\n", " model=\"gpt-4o-mini\",\n", " training_file=train_file.id,\n", " validation_file=val_file.id,\n", " hyperparameters={\n", " \"n_epochs\": 3,\n", " \"batch_size\": 8,\n", " \"learning_rate_multiplier\": 0.5\n", " },\n", " suffix=\"week6_bharat_ft_v1\"\n", " )\n", "\n", " print(\"๐Ÿ†” Job created:\", job.id)\n", "\n", " # Poll until completion\n", " status = job.status\n", " while status in (\"validating_files\", \"queued\", \"running\"):\n", " print(\"โณ Status:\", status)\n", " time.sleep(20)\n", " job = client.fine_tuning.jobs.retrieve(job.id)\n", " status = job.status\n", "\n", " if job.status != \"succeeded\":\n", " raise RuntimeError(f\"โŒ Fine-tune failed with status: {job.status}\")\n", "\n", " ft_model = job.fine_tuned_model\n", " print(\"๐ŸŽฏ Fine-tuning complete! Model ID:\", ft_model)\n" ] }, { "cell_type": "code", "execution_count": null, "id": "32a2b85e-e978-4c8f-90d9-d697731e6569", "metadata": {}, "outputs": [], "source": [ "# =============================================================\n", "# Step 5 โ€” Evaluate Simulated Fine-Tuned Model\n", "# =============================================================\n", "import numpy as np\n", "from sklearn.metrics import mean_absolute_error\n", "import matplotlib.pyplot as plt\n", "import re\n", "\n", "print(\"\\n๐Ÿงฎ Evaluating simulated fine-tuned model performance...\")\n", "\n", "# Use small sample of validation data\n", "val_subset = val_df.sample(min(20, len(val_df)), random_state=42).reset_index(drop=True)\n", "prompts = val_subset[\"prompt\"].tolist()\n", "actuals = val_subset[\"completion\"].tolist()\n", "\n", "# Convert actuals into numeric form (if applicable)\n", "def extract_number(x):\n", " match = re.findall(r\"[-+]?\\d*\\.?\\d+\", str(x))\n", " return float(match[0]) if match else np.random.uniform(70, 90)\n", "\n", "actual_values = [extract_number(a) for a in actuals]\n", "\n", "# ๐Ÿงช Simulate predicted values (normally would come from API)\n", "predicted_values = [v + np.random.uniform(-3, 3) for v in actual_values]\n", "\n", "# Calculate Mean Absolute Error\n", "mae = mean_absolute_error(actual_values, predicted_values)\n", "print(f\"\\n๐Ÿ“Š Validation Mean Absolute Error (Simulated): {mae:.2f}\")\n", "\n", "# Plot comparison\n", "plt.figure(figsize=(6, 4))\n", "plt.plot(predicted_values, label=\"Predicted\", marker=\"o\")\n", "plt.plot(actual_values, label=\"Actual\", marker=\"x\")\n", "plt.title(\"Validation Predictions vs Actuals (Simulated)\")\n", "plt.xlabel(\"Sample Index\")\n", "plt.ylabel(\"Value\")\n", "plt.legend()\n", "plt.grid(True)\n", "plt.show()\n", "\n", "# Reflection Summary\n", "print(\"\\n===== WEEK 6 REFLECTION =====\")\n", "print(\"โœ… Completed full fine-tuning workflow (simulated) successfully.\")\n", "print(\"๐Ÿง  Understood how fine-tuning integrates with GPT-4o-mini API workflow.\")\n", "print(f\"๐Ÿ“Š Validation MAE (simulated): {mae:.2f}\")\n", "print(\"๐Ÿ” Practiced prompt alignment, data curation, and evaluation safely.\")\n", "print(\"๐Ÿ’ก Next step: Try real fine-tuning (simulate=False) on small data if credits are available.\")\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.14" } }, "nbformat": 4, "nbformat_minor": 5 }