{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Generative AI & Large Language Models (LLMs) Basics Guide\n",
        "Practice notebook for the Xenors lesson: https://xenors.in/data-science/generative-ai-llm-basics/\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import pandas as pd\n",
        "df = pd.read_csv('../datasets/generative-ai-llm-basics.csv')\n",
        "df.head()\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Baseline example\n",
        "Expected checkpoint: Run the cell and inspect the printed values before changing anything.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "prompt = '''You are given three customer notes.\n",
        "Return JSON with: issue, urgency, next_action.\n",
        "Do not invent facts that are not present.'''\n",
        "print(prompt)\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Check tensor shapes first\n",
        "Expected checkpoint: X: (32, 8) y: (32,)\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "X = np.random.default_rng(42).normal(size=(32, 8)).astype('float32')\n",
        "y = (X[:,0] + X[:,1] > 0).astype('float32')\n",
        "print('X:', X.shape, 'y:', y.shape)\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Define a tiny neural baseline\n",
        "Expected checkpoint: The summary lists layer output shapes and parameter counts before training.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import tensorflow as tf\n",
        "model = tf.keras.Sequential([\n",
        "    tf.keras.layers.Input(shape=(8,)),\n",
        "    tf.keras.layers.Dense(16, activation='relu'),\n",
        "    tf.keras.layers.Dense(1, activation='sigmoid')\n",
        "])\n",
        "model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])\n",
        "model.summary()\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Train with validation data\n",
        "Expected checkpoint: Final training and validation metrics are printed side by side.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "history=model.fit(X,y,epochs=5,batch_size=8,validation_split=.25,verbose=0)\n",
        "print({k: round(v[-1],3) for k,v in history.history.items()})\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Inspect prediction confidence\n",
        "Expected checkpoint: Probabilities are shown before thresholding, making uncertain predictions visible.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "p=model.predict(X[:5],verbose=0).ravel()\n",
        "print(np.round(p,3))\n",
        "print('labels:', (p>=.5).astype(int))\n"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "name": "python",
      "version": "3.x"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}