{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Defaulting to user installation because normal site-packages is not writeable\n",
      "Requirement already satisfied: dspy-ai in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (2.4.9)\n",
      "Requirement already satisfied: backoff~=2.2.1 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from dspy-ai) (2.2.1)\n",
      "Requirement already satisfied: joblib~=1.3.2 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from dspy-ai) (1.3.2)\n",
      "Requirement already satisfied: openai<2.0.0,>=0.28.1 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from dspy-ai) (1.14.2)\n",
      "Requirement already satisfied: pandas in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from dspy-ai) (2.0.3)\n",
      "Requirement already satisfied: regex in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from dspy-ai) (2021.11.10)\n",
      "Requirement already satisfied: ujson in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from dspy-ai) (5.9.0)\n",
      "Requirement already satisfied: tqdm in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from dspy-ai) (4.62.3)\n",
      "Requirement already satisfied: datasets<3.0.0,~=2.14.6 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from dspy-ai) (2.14.7)\n",
      "Requirement already satisfied: requests in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from dspy-ai) (2.26.0)\n",
      "Requirement already satisfied: optuna in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from dspy-ai) (3.6.1)\n",
      "Requirement already satisfied: pydantic~=2.0 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from dspy-ai) (2.6.1)\n",
      "Requirement already satisfied: structlog in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from dspy-ai) (24.1.0)\n",
      "Requirement already satisfied: numpy>=1.17 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from datasets<3.0.0,~=2.14.6->dspy-ai) (1.25.2)\n",
      "Requirement already satisfied: pyarrow>=8.0.0 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from datasets<3.0.0,~=2.14.6->dspy-ai) (13.0.0)\n",
      "Requirement already satisfied: pyarrow-hotfix in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from datasets<3.0.0,~=2.14.6->dspy-ai) (0.6)\n",
      "Requirement already satisfied: dill<0.3.8,>=0.3.0 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from datasets<3.0.0,~=2.14.6->dspy-ai) (0.3.6)\n",
      "Requirement already satisfied: xxhash in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from datasets<3.0.0,~=2.14.6->dspy-ai) (3.2.0)\n",
      "Requirement already satisfied: multiprocess in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from datasets<3.0.0,~=2.14.6->dspy-ai) (0.70.14)\n",
      "Requirement already satisfied: fsspec[http]<=2023.10.0,>=2023.1.0 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from datasets<3.0.0,~=2.14.6->dspy-ai) (2023.10.0)\n",
      "Requirement already satisfied: aiohttp in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from datasets<3.0.0,~=2.14.6->dspy-ai) (3.8.3)\n",
      "Requirement already satisfied: huggingface-hub<1.0.0,>=0.14.0 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from datasets<3.0.0,~=2.14.6->dspy-ai) (0.20.3)\n",
      "Requirement already satisfied: packaging in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from datasets<3.0.0,~=2.14.6->dspy-ai) (23.0)\n",
      "Requirement already satisfied: pyyaml>=5.1 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from datasets<3.0.0,~=2.14.6->dspy-ai) (6.0.1)\n",
      "Requirement already satisfied: anyio<5,>=3.5.0 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from openai<2.0.0,>=0.28.1->dspy-ai) (4.2.0)\n",
      "Requirement already satisfied: distro<2,>=1.7.0 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from openai<2.0.0,>=0.28.1->dspy-ai) (1.9.0)\n",
      "Requirement already satisfied: httpx<1,>=0.23.0 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from openai<2.0.0,>=0.28.1->dspy-ai) (0.25.2)\n",
      "Requirement already satisfied: sniffio in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from openai<2.0.0,>=0.28.1->dspy-ai) (1.3.0)\n",
      "Requirement already satisfied: typing-extensions<5,>=4.7 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from openai<2.0.0,>=0.28.1->dspy-ai) (4.10.0)\n",
      "Requirement already satisfied: annotated-types>=0.4.0 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from pydantic~=2.0->dspy-ai) (0.6.0)\n",
      "Requirement already satisfied: pydantic-core==2.16.2 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from pydantic~=2.0->dspy-ai) (2.16.2)\n",
      "Requirement already satisfied: urllib3<1.27,>=1.21.1 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from requests->dspy-ai) (1.26.7)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from requests->dspy-ai) (2021.10.8)\n",
      "Requirement already satisfied: charset-normalizer~=2.0.0 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from requests->dspy-ai) (2.0.12)\n",
      "Requirement already satisfied: idna<4,>=2.5 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from requests->dspy-ai) (3.3)\n",
      "Requirement already satisfied: alembic>=1.5.0 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from optuna->dspy-ai) (1.13.1)\n",
      "Requirement already satisfied: colorlog in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from optuna->dspy-ai) (6.8.2)\n",
      "Requirement already satisfied: sqlalchemy>=1.3.0 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from optuna->dspy-ai) (2.0.26)\n",
      "Requirement already satisfied: python-dateutil>=2.8.2 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from pandas->dspy-ai) (2.8.2)\n",
      "Requirement already satisfied: pytz>=2020.1 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from pandas->dspy-ai) (2021.3)\n",
      "Requirement already satisfied: tzdata>=2022.1 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from pandas->dspy-ai) (2023.4)\n",
      "Requirement already satisfied: Mako in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from alembic>=1.5.0->optuna->dspy-ai) (1.3.3)\n",
      "Requirement already satisfied: exceptiongroup>=1.0.2 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from anyio<5,>=3.5.0->openai<2.0.0,>=0.28.1->dspy-ai) (1.1.0)\n",
      "Requirement already satisfied: attrs>=17.3.0 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from aiohttp->datasets<3.0.0,~=2.14.6->dspy-ai) (22.2.0)\n",
      "Requirement already satisfied: multidict<7.0,>=4.5 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from aiohttp->datasets<3.0.0,~=2.14.6->dspy-ai) (6.0.4)\n",
      "Requirement already satisfied: async-timeout<5.0,>=4.0.0a3 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from aiohttp->datasets<3.0.0,~=2.14.6->dspy-ai) (4.0.2)\n",
      "Requirement already satisfied: yarl<2.0,>=1.0 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from aiohttp->datasets<3.0.0,~=2.14.6->dspy-ai) (1.8.2)\n",
      "Requirement already satisfied: frozenlist>=1.1.1 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from aiohttp->datasets<3.0.0,~=2.14.6->dspy-ai) (1.3.3)\n",
      "Requirement already satisfied: aiosignal>=1.1.2 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from aiohttp->datasets<3.0.0,~=2.14.6->dspy-ai) (1.3.1)\n",
      "Requirement already satisfied: httpcore==1.* in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from httpx<1,>=0.23.0->openai<2.0.0,>=0.28.1->dspy-ai) (1.0.2)\n",
      "Requirement already satisfied: h11<0.15,>=0.13 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from httpcore==1.*->httpx<1,>=0.23.0->openai<2.0.0,>=0.28.1->dspy-ai) (0.14.0)\n",
      "Requirement already satisfied: filelock in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from huggingface-hub<1.0.0,>=0.14.0->datasets<3.0.0,~=2.14.6->dspy-ai) (3.13.1)\n",
      "Requirement already satisfied: six>=1.5 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from python-dateutil>=2.8.2->pandas->dspy-ai) (1.16.0)\n",
      "Requirement already satisfied: MarkupSafe>=0.9.2 in /Users/michaeltaylor/Library/Python/3.9/lib/python/site-packages (from Mako->alembic>=1.5.0->optuna->dspy-ai) (2.1.4)\n",
      "\u001b[33mDEPRECATION: pytorch-lightning 1.7.7 has a non-standard dependency specifier torch>=1.9.*. pip 23.3 will enforce this behaviour change. A possible replacement is to upgrade to a newer version of pytorch-lightning or contact the author to suggest that they release a version with a conforming dependency specifiers. Discussion can be found at https://github.com/pypa/pip/issues/12063\u001b[0m\u001b[33m\n",
      "\u001b[0m\u001b[33mDEPRECATION: torchsde 0.2.5 has a non-standard dependency specifier numpy>=1.19.*; python_version >= \"3.7\". pip 23.3 will enforce this behaviour change. A possible replacement is to upgrade to a newer version of torchsde or contact the author to suggest that they release a version with a conforming dependency specifiers. Discussion can be found at https://github.com/pypa/pip/issues/12063\u001b[0m\u001b[33m\n",
      "\u001b[0m\n",
      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.2.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.0\u001b[0m\n",
      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49m/Library/Developer/CommandLineTools/usr/bin/python3 -m pip install --upgrade pip\u001b[0m\n",
      "Note: you may need to restart the kernel to use updated packages.\n"
     ]
    }
   ],
   "source": [
    "%pip install -U dspy-ai"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "from getpass import getpass\n",
    "\n",
    "openai_api_key = getpass(\"🔑 Enter your OpenAI API key: \")\n",
    "os.environ[\"OPENAI_API_KEY\"] = openai_api_key"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Using DSPy in 8 Steps\n",
    "https://dspy-docs.vercel.app/docs/building-blocks/solving_your_task"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1) Define your task\n",
    "- Expected Input/Output Behavior\n",
    "- Quality and Cost Specs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Why don't fish do well on school tests?\n",
      "\n",
      "Because they work below C-level!\n"
     ]
    }
   ],
   "source": [
    "task = \"tell me a funny joke about {topic}\"\n",
    "\n",
    "from openai import OpenAI\n",
    "client = OpenAI()\n",
    "\n",
    "response = client.chat.completions.create(\n",
    "  model=\"gpt-4-turbo\",\n",
    "  messages=[\n",
    "    {\n",
    "      \"role\": \"user\",\n",
    "      \"content\": task.format(topic=\"fishing\")\n",
    "    },\n",
    "  ],\n",
    "  temperature=1,\n",
    "  max_tokens=256,\n",
    "  top_p=1,\n",
    "  frequency_penalty=0,\n",
    "  presence_penalty=0\n",
    ")\n",
    "print(response.choices[0].message.content)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2) Define your pipeline\n",
    "- Start with most powerful models\n",
    "- Chain-of-Thought?\n",
    "- RAG?\n",
    "- Tool use?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Why don't fish do well on school tests?\n",
      "\n",
      "Because they work below C-level!\n"
     ]
    }
   ],
   "source": [
    "import dspy\n",
    "\n",
    "gpt4_turbo = dspy.OpenAI(model='gpt-4-turbo')\n",
    "dspy.configure(lm=gpt4_turbo)\n",
    "\n",
    "print(gpt4_turbo(\"tell me a funny joke about {topic}\".format(topic=\"fishing\"))[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Topic: fishing\n",
      "Joke: Why don't fish do well on school tests? Because they work below C-level!\n"
     ]
    }
   ],
   "source": [
    "# inline signatures\n",
    "\n",
    "joker = dspy.Predict('topic -> joke')\n",
    "print(joker(topic=\"fishing\").joke)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Topic: fishing\n",
      "Joke: Why don't fish do well on school tests? Because they work below C-level!\n"
     ]
    }
   ],
   "source": [
    "# class based signatures\n",
    "\n",
    "class Joke(dspy.Signature):\n",
    "    \"\"\"Make a funny joke given a topic.\"\"\"\n",
    "\n",
    "    topic = dspy.InputField(desc=\"The topic of the joke.\")\n",
    "    joke = dspy.OutputField(desc=\"The funny joke.\")\n",
    "\n",
    "class Pred(dspy.Module):\n",
    "    def __init__(self):\n",
    "        super().__init__()\n",
    "\n",
    "        self.signature = Joke\n",
    "        self.prog = dspy.Predict(Joke)\n",
    "\n",
    "    def forward(self, topic):\n",
    "        return self.prog(topic=topic)\n",
    "\n",
    "make_joke = Pred()\n",
    "print(make_joke(topic=\"fishing\").joke)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Rationale: produce the joke. We can start by considering common situations or stereotypes in fishing, such as the exaggeration of the size of the fish caught, the early mornings, or the patience required. Combining these elements can lead to a humorous scenario or punchline.\n",
      "---\n",
      "Joke: Why don't fish make good musicians? Because you can tune a guitar, but you can't tuna fish!\n"
     ]
    }
   ],
   "source": [
    "# create a CoT module\n",
    "class CoT(dspy.Module):\n",
    "    def __init__(self):\n",
    "        super().__init__()\n",
    "\n",
    "        self.signature = Joke\n",
    "        self.prog = dspy.ChainOfThought(Joke)\n",
    "\n",
    "    def forward(self, topic):\n",
    "        return self.prog(topic=topic)\n",
    "    \n",
    "make_joke_chain = CoT()\n",
    "\n",
    "response = make_joke_chain(topic=\"fishing\")\n",
    "print(f\"Rationale: {response.rationale}\")\n",
    "print(\"---\")\n",
    "print(f\"Joke: {response.joke}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\n",
      "Make a funny joke given a topic.\n",
      "\n",
      "---\n",
      "\n",
      "Follow the following format.\n",
      "\n",
      "Topic: The topic of the joke.\n",
      "Reasoning: Let's think step by step in order to ${produce the joke}. We ...\n",
      "Joke: The funny joke.\n",
      "\n",
      "---\n",
      "\n",
      "Topic: fishing\n",
      "Reasoning: Let's think step by step in order to\u001b[32m produce the joke. We can start by considering common situations or stereotypes in fishing, such as the exaggeration of the size of the fish caught, the early mornings, or the patience required. Combining these elements can lead to a humorous scenario or punchline.\n",
      "\n",
      "Joke: Why don't fish make good musicians? Because you can tune a guitar, but you can't tuna fish!\u001b[0m\n",
      "\n",
      "\n",
      "\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "\"\\n\\n\\nMake a funny joke given a topic.\\n\\n---\\n\\nFollow the following format.\\n\\nTopic: The topic of the joke.\\nReasoning: Let's think step by step in order to ${produce the joke}. We ...\\nJoke: The funny joke.\\n\\n---\\n\\nTopic: fishing\\nReasoning: Let's think step by step in order to\\x1b[32m produce the joke. We can start by considering common situations or stereotypes in fishing, such as the exaggeration of the size of the fish caught, the early mornings, or the patience required. Combining these elements can lead to a humorous scenario or punchline.\\n\\nJoke: Why don't fish make good musicians? Because you can tune a guitar, but you can't tuna fish!\\x1b[0m\\n\\n\\n\""
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "gpt4_turbo.inspect_history(n=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3) Explore a few examples\n",
    "- Find easy and hard examples"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Topic: Fishing\n",
      "Example: Give a man a fish, and he’ll probably follow you home expecting more fish.\n",
      "---\n",
      "Rationale: produce the joke. We start by considering common elements of fishing, such as the patience required, the typical exaggeration of the size of fish caught, and the surprise of what you might catch. Combining these elements can lead to a humorous situation where expectations are subverted.\n",
      "---\n",
      "Joke: Why don't fish make good musicians? Because you can tune a guitar, but you can't tuna fish!\n"
     ]
    }
   ],
   "source": [
    "tj_pair = dspy.Example(topic=\"Fishing\", joke=\"Give a man a fish, and he’ll probably follow you home expecting more fish.\").with_inputs('topic')\n",
    "\n",
    "response = make_joke_chain(topic=tj_pair.topic)\n",
    "print(f\"Topic: {tj_pair.topic}\")\n",
    "print(f\"Example: {tj_pair.joke}\")\n",
    "print(\"---\")\n",
    "print(f\"Rationale: {response.rationale}\")\n",
    "print(\"---\")\n",
    "print(f\"Joke: {response.joke}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Topic: Drinking\n",
      "Example: My father drank so heavily, when he blew on the birthday cake he lit the candles.\n",
      "---\n",
      "Rationale: produce the joke. We can play on the common experiences people have with drinking, such as the confusion between types of drinks or the humorous situations that arise from miscommunication when ordering at a bar.\n",
      "---\n",
      "Joke: I told my friend I was going to the bar for some fruit juice. He looked confused when I came back with a beer. I said, \"Well, it's technically a bunch of grapes!\"\n"
     ]
    }
   ],
   "source": [
    "tj_pair_2 = dspy.Example(topic=\"Drinking\", joke=\"My father drank so heavily, when he blew on the birthday cake he lit the candles.\").with_inputs('topic')\n",
    "\n",
    "response_2 = make_joke_chain(topic=tj_pair_2.topic)\n",
    "print(f\"Topic: {tj_pair_2.topic}\")\n",
    "print(f\"Example: {tj_pair_2.joke}\")\n",
    "print(\"---\")\n",
    "print(f\"Rationale: {response_2.rationale}\")\n",
    "print(\"---\")\n",
    "print(f\"Joke: {response_2.joke}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4) Define your data\n",
    "- Training\n",
    "- Validation (tuning)\n",
    "- Development (evaluation)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(76, 25, 26)"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# https://inews.co.uk/light-relief/jokes/ricky-gervais-jokes-best-golden-globes-2020-host-controversial-funniest-the-office-135797\n",
    "# https://www.blackpoolgrand.co.uk/funniest-jokes-one-liners/\n",
    "# https://www.vulture.com/2018/01/dave-chappelle-bird-revelation-equanimity-best-jokes.html\n",
    "# https://www.scotsman.com/heritage-and-retro/heritage/billy-connollys-best-jokes-80-of-the-big-yins-funniest-jokes-and-one-liners-4458332\n",
    "# https://inews.co.uk/light-relief/jokes/funny-jokes-110-funniest-best-one-liners-192413\n",
    "\n",
    "funny_jokes = [\n",
    "    {\"topic\": \"Fishing\", \"joke\": \"Give a man a fish, and he’ll probably follow you home expecting more fish.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Family\", \"joke\": \"Where there’s a will – there’s a relative!\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Holidays\", \"joke\": \"1st of December, World Aids Day….I don’t think it’ll ever take off like Christmas.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Drinking\", \"joke\": \"I like a drink as much as the next man. Unless the next man is Mel Gibson.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Celebrity\", \"joke\": \"It’s gonna be a night of partying and heavy drinking. Or as Charlie calls it: breakfast.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Movies\", \"joke\": \"It seems like everything this year was three-dimensional, except the characters in The Tourist.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Religion\", \"joke\": \"You won’t burn in hell. But be nice anyway.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Inspiration\", \"joke\": \"My greatest hero is Nelson Mandela. What a man. Incarcerated for 25 years, he was released in 1990 and he hasn’t reoffended. I think he’s going straight, which shows you prison does work.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Philosophy\", \"joke\": \"Remember, when you are dead, you do not know you are dead. It is only painful for others. The same applies when you are stupid.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Life\", \"joke\": \"Mondays are fine. It’s your life that sucks.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Religion\", \"joke\": \"Remember, if you don’t sin, then Jesus died for nothing.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Activism\", \"joke\": \"I could solve the world’s problems if I… cared.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Identity\", \"joke\": \"I can have a go at the French cause I’m half French half English with a stupid name like Gervais. No I am, I’m half French half English and um I’ve got qualities of both, French and English which is good, so um… I am crap in bed but at least I’ve got bad breath.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Military\", \"joke\": \"Do commandos not wear pants? They must wear pants, don’t they?\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Equality\", \"joke\": \"Same sex marriage is not a gay privilege, it’s equal rights. Privilege would be something like gay people not paying taxes. Like churches don’t.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Folklore\", \"joke\": \"I’ve never worked out what the moral of Humpty Dumpty is. I can only think of: Don’t sit on a wall, if you’re an egg.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Employment\", \"joke\": \"Avoid employing unlucky people – throw half of the pile of CVs in the bin without reading them.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Awards\", \"joke\": \"For any of you who don’t know, the Golden Globes are just like the Oscars, but without all that esteem. The Golden Globes are to the Oscars what Kim Kardashian is to Kate Middleton. A bit louder, a bit trashier, a bit drunker, and more easily bought.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Workplace\", \"joke\": \"If your boss is getting you down, look at him through the prongs of a fork and imagine him in jail.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Humor\", \"joke\": \"I can’t find someone funny whom I don’t like. Hitler told great jokes.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Culture\", \"joke\": \"America champions the underdog. We champion the under dog until he’s not the underdog anymore, and he annoys us.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Betrayal\", \"joke\": \"You have to be 100% behind someone, before you can stab them in the back.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Health\", \"joke\": \"Remember, being healthy is basically dying as slowly as possible.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Atheism\", \"joke\": \"I’d like to thank God for making me an atheist.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Music Industry\", \"joke\": \"Piracy doesn’t kill music, boy bands do.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Wealth\", \"joke\": \"My wealth and happiness would suggest that God definitely does love me. If he existed of course. Which he doesn’t.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Social Media\", \"joke\": \"Following someone on Twitter and asking them to tweet about something else is like stalking someone and asking them to go a different route.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Fame\", \"joke\": \"Please don’t worship me. I’m just an ordinary guy, with lots of followers trying to spread my message. Sort of like Jesus Christ I guess.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Technology\", \"joke\": \"iPhones are Barbie Dolls for grown men. You carry them round, dress them up in little outfits, accessorise, & get a new one every year.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Generosity\", \"joke\": \"Give a man a fish, and he’ll probably follow you home expecting more fish.\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Environment\", \"joke\": \"It seems to be true, particularly in middle America, that those most militant about using up fossil fuels, don’t actually believe in fossils\", \"comedian\": \"Ricky Gervais\"},\n",
    "    {\"topic\": \"Drinking\", \"joke\": \"My father drank so heavily, when he blew on the birthday cake he lit the candles.\", \"comedian\": \"Les Dawson\"},\n",
    "    {\"topic\": \"Police\", \"joke\": \"I was in my car driving back from work. A police officer pulled me over and knocked on my window. I said, ‘One minute I’m on the phone.’\", \"comedian\": \"Alan Carr\"},\n",
    "    {\"topic\": \"Overthinking\", \"joke\": \"I worry about ridiculous things, you know, how does a guy who drives a snowplough get to work in the morning… that can keep me awake for days.\", \"comedian\": \"Billy Connolly\"},\n",
    "    {\"topic\": \"Relationships\", \"joke\": \"I used to go out with a giraffe. Used to take it to the pictures and that. You’d always get some bloke complaining that he couldn’t see the screen.\", \"comedian\": \"Paul Merton\"},\n",
    "    {\"topic\": \"Music\", \"joke\": \"Here’s a picture of me with REM. That’s me in the corner.\", \"comedian\": \"Milton Jones\"},\n",
    "    {\"topic\": \"Optimism\", \"joke\": \"People say ‘Bill, are you an optimist?’ And I say, ‘I hope so.’\", \"comedian\": \"Bill Bailey\"},\n",
    "    {\"topic\": \"Customer Service\", \"joke\": \"I rang up British Telecom and said: ‘I want to report a nuisance caller.’ He said: ‘Not you again.’\", \"comedian\": \"Tim Vine\"},\n",
    "    {\"topic\": \"Obesity\", \"joke\": \"Life is like a box of chocolates. It doesn’t last long if you’re fat.\", \"comedian\": \"Joe Lycett\"},\n",
    "    {\"topic\": \"Religion\", \"joke\": \"We weren’t very religious. On Hanukkah, my mother had our menorah on a dimmer.\", \"comedian\": \"Richard Lewis\"},\n",
    "    {\"topic\": \"Beauty\", \"joke\": \"My girlfriend is absolutely beautiful. Body like a Greek statue – completely pale, no arms.\", \"comedian\": \"Phil Wang\"},\n",
    "    {\"topic\": \"Weather\", \"joke\": \"Normally you have news, weather and travel. But not on snow day. On a snow day, the news is weather is travel.\", \"comedian\": \"Michael McIntyre\"},\n",
    "    {\"topic\": \"Personal Improvement\", \"joke\": \"I bought myself some glasses. My observational comedy improved.\", \"comedian\": \"Sara Pascoe\"},\n",
    "    {\"topic\": \"Sports\", \"joke\": \"If I was an Olympic athlete, I’d rather come in last than win the silver medal. You win the gold, you feel good. You win the bronze, you think, ‘at least I got something.’ But you win that silver, that’s like, ‘Congratulations, you almost won! Of all the losers, you came in first! You’re the number one loser! No one lost ahead of you!’\", \"comedian\": \"Jerry Seinfeld\"},\n",
    "    {\"topic\": \"Identity\", \"joke\": \"My star sign is Pyrex. I was a test-tube baby.\", \"comedian\": \"Billy Connolly\"},\n",
    "    {\"topic\": \"Marriage\", \"joke\": \"I always take my wife morning tea in my pyjamas. But is she grateful? No, she says she’d rather have it in a cup.\", \"comedian\": \"Eric Morecambe\"},\n",
    "    {\"topic\": \"Shopping\", \"joke\": \"A man walks into a chemist’s and says, ‘Can I have a bar of soap, please?’ The chemist says, ‘Do you want it scented?’ And the man says, ‘No, I’ll take it with me now.’\", \"comedian\": \"Ronnie Barker\"},\n",
    "    {\"topic\": \"Crime\", \"joke\": \"Crime in multi-storey car parks. That is wrong on so many different levels.\", \"comedian\": \"Tim Vine\"},\n",
    "    {\"topic\": \"Social Class\", \"joke\": \"You know you’re working class when your TV is bigger than your bookcase.\", \"comedian\": \"Rob Beckett\"},\n",
    "    {\"topic\": \"Animals\", \"joke\": \"Owls haven’t got necks, have they? An owl is essentially a one-piece unit.\", \"comedian\": \"Ross Noble\"},\n",
    "    {\"topic\": \"Fashion\", \"joke\": \"If you arrive fashionably late in Crocs, you’re just late.\", \"comedian\": \"Joel Dommett\"},\n",
    "    {\"topic\": \"Technology\", \"joke\": \"My phone will ring at 2am and my wife’ll look at me and go, “Who’s that calling at this time?” I say, “I don’t know. If I knew that we wouldn’t need the bloody phone.”\", \"comedian\": \"Lee Evans\"},\n",
    "    {\"topic\": \"Philosophy\", \"joke\": \"I doubt there’s a heaven; I think the people from hell have probably bought it for a timeshare.\", \"comedian\": \"Victoria Wood\"},\n",
    "    {\"topic\": \"Fitness\", \"joke\": \"I said to the gym instructor: “Can you teach me to do the splits?”, He said: “How flexible are you?”, I said: “I can’t make Tuesdays.”\", \"comedian\": \"Tommy Cooper\"},\n",
    "    {\"topic\": \"Insurance\", \"joke\": \"Do Transformers get car, or life insurance?\", \"comedian\": \"Russell Howard\"},\n",
    "    {\"topic\": \"Police\", \"joke\": \"Alright lads, a giant fly is attacking the police station. I’ve called the SWAT team!\", \"comedian\": \"Greg Davies\"},\n",
    "    {\"topic\": \"Healthcare\", \"joke\": \"A good rule to remember for life is that when it comes to plastic surgery and sushi, never be attracted by a bargain.\", \"comedian\": \"Graham Norton\"},\n",
    "    {\"topic\": \"Animals\", \"joke\": \"Two monkeys were getting into the bath. One said: ‘Oo, oo, oo, aah aah aah.’ The other replied: ‘Well, put some cold in it then.’\", \"comedian\": \"Harry Hill\"},\n",
    "    {\"topic\": \"Suburban Life\", \"joke\": \"My parents did just well enough so I could grow up poor around white people. When Nas and them used to talk about the projects, I used to get jealous. It sounded fun. Everybody in the projects was poor, and that’s fair. But if you were poor in Silver Spring, nigga, it felt like it was only happening to you.\", \"comedian\": \"Dave Chappelle\"},\n",
    "    {\"topic\": \"Cultural Identity\", \"joke\": \"What is Rachel willing to do, so that we blacks believe that she believes she is actually one of us? Bitch, are you willing to put a lien on your house so that you can invest in a mixtape that probably won’t work out?\", \"comedian\": \"Dave Chappelle\"},\n",
    "    {\"topic\": \"Aging\", \"joke\": \"I don’t like looking at my dick anymore. My dick looks distinguished. It’s old, an old-looking dick. It’s got salt-and-pepper hair all around it. My dick looks like Morgan Freeman in the ’90s.\", \"comedian\": \"Dave Chappelle\"},\n",
    "    {\"topic\": \"Fatherhood\", \"joke\": \"This motherfucker calls me up in the middle of the night. It was one o'clock in the morning and he goes, 'Dad, don’t be mad […] I’m at a party and my designated driver had too much to drink. Me and friends need you to come pick us up.' I said, 'Jesus Christ, it’s one o'clock in the morning. Nigga, I am shit-faced!'\", \"comedian\": \"Dave Chappelle\"},\n",
    "    {\"topic\": \"Political Commentary\", \"joke\": \"Eight years later, I’m pulling up to the polls again. This time, I’m driving a brand-new Porsche because the Obama years were very good to me […] I walked up and saw a long, long line of dusty white people […] I stood with them in line, like all us Americans are required to do in a democracy. Nobody skips the line to vote. And I listened to them say naïve, poor white people things.\", \"comedian\": \"Dave Chappelle\"},\n",
    "    {\"topic\": \"Leadership\", \"joke\": \"This motherfucker [Donald Trump] grabbed the podium and he goes, 'You don’t know how scary the things I read in my briefings are.' Holy shit, man, you ain’t supposed to tell us that, bro!\", \"comedian\": \"Dave Chappelle\"},\n",
    "    {\"topic\": \"Religious Satire\", \"joke\": \"I respect everybody’s beliefs, except Amish people. They are the only ones I can say clearly, 'Their God is wrong.' The speed limit is 75 miles an hour in Ohio, and one lane of traffic is blocked by a goddamned horse and buggy?\", \"comedian\": \"Dave Chappelle\"},\n",
    "    {\"topic\": \"Hollywood\", \"joke\": \"You think I go to a Hollywood meeting with all them white people by myself? I bring my nigga Mac Mittens from the streets […] He’s not even qualified to listen to these meetings, he just makes me feel good.\", \"comedian\": \"Dave Chappelle\"},\n",
    "    {\"topic\": \"Comedy Culture\", \"joke\": \"The tough part of being a comedian and knowing the motherfucker is, everybody comes up to me like, 'Did you know? Did you know what Louis was doing?' No, bitch, I did not know.\", \"comedian\": \"Dave Chappelle\"},\n",
    "    {\"topic\": \"National Identity\", \"joke\": \"I could kill every white person in America at one time. You know how I’d do it? Just wait for the Super Bowl, and right when they sing the National Anthem, I’d have O.J. Simpson walk to the 50-yard line with them bad knees.\", \"comedian\": \"Dave Chappelle\"},\n",
    "    {\"topic\": \"Gender Relations\", \"joke\": \"I used to do shows for drug dealers that wanted to clean their money up. One time I did a real good set, and these motherfuckers called me into the back room. They gave me $25,000 in cash […] I jumped on the subway and started heading towards Brooklyn at one o’clock in the morning.\", \"comedian\": \"Dave Chappelle\"},\n",
    "    {\"topic\": \"Scottish Heritage\", \"joke\": \"Scottish-Americans tell you that if you want to identify tartans, it’s easy – you simply look under the kilt, and if it’s a quarter-pounder, you know it’s a McDonald’s.\", \"comedian\": \"Billy Connolly\"},\n",
    "    {\"topic\": \"Judgement\", \"joke\": \"Before you judge a man, walk a mile in his shoes. After that who cares? He’s a mile away and you’ve got his shoes!\", \"comedian\": \"Billy Connolly\"},\n",
    "    {\"topic\": \"Weather\", \"joke\": \"I hate all those weathermen, too, who tell you that rain is bad weather. There’s no such thing as bad weather, just the wrong clothing, so get yourself a sexy raincoat and live a little.\", \"comedian\": \"Billy Connolly\"},\n",
    "    {\"topic\": \"Film Industry\", \"joke\": \"I’m a huge film star, but you have to hurry to the movies because I usually die in the first 15 f***ing minutes. I’m the only guy I know who died in a f***ing Muppet Movie.\", \"comedian\": \"Billy Connolly\"},\n",
    "    {\"topic\": \"Appearance\", \"joke\": \"I always look skint. When I buy a Big Issue, people take it out of my hand and give me a pound.\", \"comedian\": \"Billy Connolly\"},\n",
    "    {\"topic\": \"Sex Therapy\", \"joke\": \"One sex therapist claims that the most effective way to arouse your man is to spend 10 minutes licking his ears. Personally, I think its bollocks.\", \"comedian\": \"Billy Connolly\"},\n",
    "    {\"topic\": \"Cinema\", \"joke\": \"When people say while watching a film ‘did you see that? No tosser, I paid ten quid to come to the cinema and stare at the f***ing floor.\", \"comedian\": \"Billy Connolly\"},\n",
    "    {\"topic\": \"Aeroplane Comfort\", \"joke\": \"I get claustrophobic easily and I don’t get why aeroplane toilets don’t f***ing have windows. I mean it’s not as if anyone can f***ing see in. Unless of course you are the most determined pervert in the world.\", \"comedian\": \"Billy Connolly\"},\n",
    "    {\"topic\": \"Astrology\", \"joke\": \"My star sign is Pyrex. I was a test-tube baby.\", \"comedian\": \"Billy Connolly\"},\n",
    "    {\"topic\": \"Parenting\", \"joke\": \"Don’t buy one of those baby intercoms. Babies pretend to be dead. They’re bastards, and they do it on purpose.\", \"comedian\": \"Billy Connolly\"},\n",
    "    {\"topic\": \"Common Sayings\", \"joke\": \"Why do people say ‘Oh you want to have your cake and eat it too?’ Dead right! What good is a cake if you can’t eat it?\", \"comedian\": \"Billy Connolly\"},\n",
    "    {\"topic\": \"Life Perception\", \"joke\": \"When people say ‘life is short’. What the f***? Life is the longest damn thing anyone ever f***ing does! What can you do that’s longer?\", \"comedian\": \"Billy Connolly\"},\n",
    "    {\"topic\": \"Dating\", \"joke\": \"I like a woman with a head on her shoulders. I hate necks.\", \"comedian\": \"Steve Martin\"},\n",
    "    {\"topic\": \"Growing Up\", \"joke\": \"I have a lot of growing up to do. I realised that the other day inside my fort.\", \"comedian\": \"Zach Galifianakis\"},\n",
    "    {\"topic\": \"Employment\", \"joke\": \"I used to work at McDonald’s making minimum wage. You know what that means when someone pays you minimum wage? You know what your boss was trying to say? ‘Hey, if I could pay you less, I would, but it’s against the law.’\", \"comedian\": \"Chris Rock\"},\n",
    "    {\"topic\": \"Love\", \"joke\": \"Love is like a fart. If you have to force it it’s probably s***.\", \"comedian\": \"Stephen K. Amos\"},\n",
    "    {\"topic\": \"Convenience\", \"joke\": \"I like an escalator because an escalator can never break. It can only become stairs. There would never be an ‘Escalator Temporarily Out of Order’ sign, only ‘Escalator Temporarily Stairs’.\", \"comedian\": \"Mitch Hedberg\"},\n",
    "    {\"topic\": \"Sports\", \"joke\": \"If I was an Olympic athlete, I’d rather come in last than win the silver medal. You win the gold, you feel good. You win the bronze, you think, ‘at least I got something.’ But you win that silver, that’s like, ‘Congratulations, you almost won! Of all the losers, you came in first! You’re the number one loser! No one lost ahead of you!’\", \"comedian\": \"Jerry Seinfeld\"},\n",
    "    {\"topic\": \"Religion\", \"joke\": \"We weren’t very religious. On Hanukkah, my mother had our menorah on a dimmer.\", \"comedian\": \"Richard Lewis\"},\n",
    "    {\"topic\": \"Beauty\", \"joke\": \"My girlfriend is absolutely beautiful. Body like a Greek statue – completely pale, no arms.\", \"comedian\": \"Phil Wang\"},\n",
    "    {\"topic\": \"Creation\", \"joke\": \"If God had written the Bible, the first line should have been ‘It’s round.'\", \"comedian\": \"Eddie Izzard\"},\n",
    "    {\"topic\": \"Self-Improvement\", \"joke\": \"I bought myself some glasses. My observational comedy improved.\", \"comedian\": \"Sara Pascoe\"},\n",
    "    {\"topic\": \"Politics\", \"joke\": \"Trump’s nothing like Hitler. There’s no way he could write a book.\", \"comedian\": \"Frankie Boyle\"},\n",
    "    {\"topic\": \"Social Class\", \"joke\": \"You know you’re working class when your TV is bigger than your book case.\", \"comedian\": \"Rob Beckett\"},\n",
    "    {\"topic\": \"Conflict\", \"joke\": \"Most of my life is spent avoiding conflict. I hardly ever visit Syria.\", \"comedian\": \"Alex Horne\"},\n",
    "    {\"topic\": \"Relaxation\", \"joke\": \"A spa hotel? It’s like a normal hotel, only in reception there’s a picture of a pebble.\", \"comedian\": \"Rhod Gilbert\"},\n",
    "    {\"topic\": \"Health\", \"joke\": \"Life is like a box of chocolates. It doesn’t last long if you’re fat.\", \"comedian\": \"Joe Lycett\"},\n",
    "    {\"topic\": \"Career\", \"joke\": \"My Dad said, always leave them wanting more. Ironically, that’s how he lost his job in disaster relief.\", \"comedian\": \"Mark Watson\"},\n",
    "    {\"topic\": \"Memory\", \"joke\": \"Apparently smoking cannabis can affect your short term memory. Well if that’s true, what do you think smoking cannabis does?\", \"comedian\": \"Mickey P Kerr\"},\n",
    "    {\"topic\": \"Philosophy\", \"joke\": \"How many philosophers does it take to change a lightbulb?…. none. They’re not really into that sort of thing. If it’s that dark, light a candle.\", \"comedian\": \"Phil Cornwell\"},\n",
    "    {\"topic\": \"Marriage\", \"joke\": \"The first time I met my wife, I knew she was a keeper. She was wearing massive gloves.\", \"comedian\": \"Alun Cochrane\"},\n",
    "    {\"topic\": \"Childhood\", \"joke\": \"As a kid I was made to walk the plank. We couldn’t afford a dog.\", \"comedian\": \"Gary Delaney\"},\n",
    "    {\"topic\": \"Misunderstanding\", \"joke\": \"Two fish in a tank. One says: ‘How do you drive this thing?'\", \"comedian\": \"Peter Kay\"},\n",
    "    {\"topic\": \"Entertainment\", \"joke\": \"I saw a documentary on how ships are kept together. Riveting!\", \"comedian\": \"Stewart Francis\"},\n",
    "    {\"topic\": \"Music\", \"joke\": \"People who like trance music are very persistent. They don’t techno for an answer.\", \"comedian\": \"Joel Dommett\"},\n",
    "    {\"topic\": \"Dating\", \"joke\": \"I used to go out with a giraffe. Used to take it to the pictures and that. You’d always get some bloke complaining that he couldn’t see the screen. It’s a giraffe, mate. What do you expect? ‘Well he can take his hat off for a start!’\", \"comedian\": \"Paul Merton\"},\n",
    "    {\"topic\": \"Weather\", \"joke\": \"Normally you have news, weather and travel. But not on snow day. On a snow day, news is weather is travel.\", \"comedian\": \"Michael McIntyre\"},\n",
    "    {\"topic\": \"Music\", \"joke\": \"Here’s a picture of me with REM. That’s me in the corner.\", \"comedian\": \"Milton Jones\"},\n",
    "    {\"topic\": \"Sarcasm\", \"joke\": \"Someone showed me a photograph of my local MP the other day. ‘Would you buy a second-hand car from this man?’ they asked. ‘Would you buy a second-hand car?’ I replied.\", \"comedian\": \"Miles Jupp\"},\n",
    "    {\"topic\": \"Culture\", \"joke\": \"With stand-up in Britain, what you have to do is bloody swearing. In Germany, we don’t have to swear. Reason being, things work.\", \"comedian\": \"Henning When\"},\n",
    "    {\"topic\": \"Learning\", \"joke\": \"I’m learning the hokey cokey. Not all of it. But – I’ve got the ins and outs.\", \"comedian\": \"Iain Stirling\"},\n",
    "    {\"topic\": \"Identity\", \"joke\": \"Roses are red, violets are blue, I’m a schizophrenic, and so am I.\", \"comedian\": \"Billy Connolly\"},\n",
    "    {\"topic\": \"Parenting\", \"joke\": \"My mother told me, you don’t have to put anything in your mouth you don’t want to. Then she made me eat broccoli, which felt like double standards.\", \"comedian\": \"Sarah Millican\"},\n",
    "    {\"topic\": \"Vengeance\", \"joke\": \"My therapist says I have a preoccupation with vengeance. We’ll see about that.\", \"comedian\": \"Stewart Francis\"},\n",
    "    {\"topic\": \"Family\", \"joke\": \"I’m sure wherever my Dad is, he’s looking down on us. He’s not dead, just very condescending.\", \"comedian\": \"Jack Whitehall\"},\n",
    "    {\"topic\": \"Marriage\", \"joke\": \"‘What’s a couple?’ I asked my mum. She said, ‘Two or three’. Which probably explains why her marriage collapsed.\", \"comedian\": \"Josie Long\"},\n",
    "    {\"topic\": \"Injury\", \"joke\": \"The easiest time to add insult to injury is when you’re signing somebody’s cast.\", \"comedian\": \"Demetri Martin\"},\n",
    "    {\"topic\": \"Communication\", \"joke\": \"I was in my car driving back from work. A police officer pulled me over and knocked on my window. I said, ‘One minute I’m on the phone.'\", \"comedian\": \"Alan Carr\"},\n",
    "    {\"topic\": \"Afterlife\", \"joke\": \"I doubt there’s a heaven; I think the people from hell have probably bought it for a timeshare.\", \"comedian\": \"Victoria Wood\"},\n",
    "    {\"topic\": \"Flexibility\", \"joke\": \"I said to the gym instructor: ‘Can you teach me to do the splits?’ He said: ‘How flexible are you?’ I said: ‘I can’t make Tuesdays.’\", \"comedian\": \"Tommy Cooper\"},\n",
    "    {\"topic\": \"Misunderstanding\", \"joke\": \"A man walks into a chemist’s and says, ‘Can I have a bar of soap, please?’ The chemist says, ‘Do you want it scented?’ And the man says, ‘No, I’ll take it with me now.'\", \"comedian\": \"Ronnie Barker\"},\n",
    "    {\"topic\": \"Humor\", \"joke\": \"It’s really hard to define ‘virtue signalling’, as I was saying the other day to some of my Muslim friends over a fair-trade coffee in our local feminist bookshop.\", \"comedian\": \"Lucy Porter\"},\n",
    "    {\"topic\": \"Creation\", \"joke\": \"If we were truly created by God, then why do we still occasionally bite the insides of our own mouths?\", \"comedian\": \"Dara Ó Briain\"},\n",
    "    {\"topic\": \"Insurance\", \"joke\": \"Do Transformers get car, or life insurance?\", \"comedian\": \"Russell Howard\"},\n",
    "    {\"topic\": \"Emergency\", \"joke\": \"Alright lads, a giant fly is attacking the police station. I’ve called the SWAT team!\", \"comedian\": \"Greg Davies\"},\n",
    "    {\"topic\": \"Consumerism\", \"joke\": \"A good rule to remember for life is that when it comes to plastic surgery and sushi, never be attracted by a bargain.\", \"comedian\": \"Graham Norton\"},\n",
    "    {\"topic\": \"Family\", \"joke\": \"My father drank so heavily, when he blew on the birthday cake he lit the candles.\", \"comedian\": \"Les Dawson\"},\n",
    "    {\"topic\": \"Therapy\", \"joke\": \"I’ve been feeling suicidal so my therapist suggested I do CBT. Now I can ride a motorbike, how’s that going to help?\", \"comedian\": \"Eric Lampaert\"},\n",
    "]\n",
    "\n",
    "# Tell DSPy that the 'topic' field is the input. Any other fields are labels and/or metadata.\n",
    "dataset = []\n",
    "\n",
    "for row in funny_jokes:\n",
    "    topic, joke = row[\"topic\"], row[\"joke\"]\n",
    "    dataset.append(dspy.Example(topic=topic, joke=joke).with_inputs(\"topic\"))\n",
    "\n",
    "num_items = len(dataset)\n",
    "index_train = int(0.6 * num_items)  # 60% for training\n",
    "index_val = int(0.8 * num_items)  # Additional 20% for validation, up to 80% of total\n",
    "\n",
    "# Split the data into training, validation, and eval/dev sets\n",
    "trainset = dataset[:index_train]\n",
    "valset = dataset[index_train:index_val]\n",
    "devset = dataset[index_val:]  # Remaining 20% for evals\n",
    "\n",
    "len(trainset), len(valset), len(devset)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Example({'topic': 'Fishing', 'joke': 'Give a man a fish, and he’ll probably follow you home expecting more fish.'}) (input_keys={'topic'})"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "trainset[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5) Define your metric\n",
    "- Simple: Question & Answer exact match\n",
    "- Intermediate: Using AI feedback for your metric\n",
    "- Advanced: Using a DSPy program as your metric"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.0"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Define the signature for automatic assessments.\n",
    "class Assess(dspy.Signature):\n",
    "    \"\"\"Assess the quality of a joke along the specified dimension.\"\"\"\n",
    "    assessment_joke = dspy.InputField(desc=\"The joke to be assessed.\")\n",
    "    assessment_topic = dspy.InputField(desc=\"The topic related to the joke.\")\n",
    "    assessment_question = dspy.InputField(desc=\"The question to assess the joke against.\")\n",
    "    assessment_answer = dspy.OutputField(desc=\"Answer to the question, Yes or No.\")\n",
    "\n",
    "def metric(gold, pred, trace=None):\n",
    "    topic, joke = gold['topic'], pred['joke']\n",
    "\n",
    "    # Define questions\n",
    "    questions = {\n",
    "        \"funny\": \"Would this joke actually be funny to an adult attending a comedy show?\",\n",
    "        \"relevant\": \"Is this joke relevant to the topic?\",\n",
    "        \"format\": \"Is only the joke is returned, no disclaimer or other text prepending the joke?\",\n",
    "    }\n",
    "    \n",
    "    # Using dspy to predict responses\n",
    "    results = {}\n",
    "    for key, question in questions.items():\n",
    "        results[key] = 'yes' in dspy.Predict(Assess)(\n",
    "            assessment_joke=joke, \n",
    "            assessment_topic=topic, \n",
    "            assessment_question=question\n",
    "        ).assessment_answer.lower()\n",
    "    \n",
    "    # Calculate score\n",
    "    score = sum(results.values())\n",
    "\n",
    "    return round(score / len(questions), 2)\n",
    "\n",
    "# Example call\n",
    "metric(tj_pair.inputs(), tj_pair.labels())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\n",
      "Assess the quality of a joke along the specified dimension.\n",
      "\n",
      "---\n",
      "\n",
      "Follow the following format.\n",
      "\n",
      "Assessment Joke: The joke to be assessed.\n",
      "\n",
      "Assessment Topic: The topic related to the joke.\n",
      "\n",
      "Assessment Question: The question to assess the joke against.\n",
      "\n",
      "Assessment Answer: Answer to the question, Yes or No.\n",
      "\n",
      "---\n",
      "\n",
      "Assessment Joke: Give a man a fish, and he’ll probably follow you home expecting more fish.\n",
      "\n",
      "Assessment Topic: Fishing\n",
      "\n",
      "Assessment Question: Is only the joke is returned, no disclaimer or other text prepending the joke?\n",
      "\n",
      "Assessment Answer:\u001b[32m Assessment Answer: Yes\u001b[0m\n",
      "\n",
      "\n",
      "\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'\\n\\n\\nAssess the quality of a joke along the specified dimension.\\n\\n---\\n\\nFollow the following format.\\n\\nAssessment Joke: The joke to be assessed.\\n\\nAssessment Topic: The topic related to the joke.\\n\\nAssessment Question: The question to assess the joke against.\\n\\nAssessment Answer: Answer to the question, Yes or No.\\n\\n---\\n\\nAssessment Joke: Give a man a fish, and he’ll probably follow you home expecting more fish.\\n\\nAssessment Topic: Fishing\\n\\nAssessment Question: Is only the joke is returned, no disclaimer or other text prepending the joke?\\n\\nAssessment Answer:\\x1b[32m Assessment Answer: Yes\\x1b[0m\\n\\n\\n'"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "gpt4_turbo.inspect_history(n=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.33"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "metric({\"topic\": \"Fishing\"}, {\"joke\": \"Ok here's a funny joke for you:\\nWhy do fish always know how much they weigh?\\nBecause they have their own scales!\"})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6) Collect preliminary \"zero-shot\" evaluations\n",
    "- Establish a baseline metric score"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Average Metric: 18.380000000000003 / 26  (70.7): 100%|██████████| 26/26 [00:00<00:00, 1693.69it/s]\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<style type=\"text/css\">\n",
       "#T_4a335 th {\n",
       "  text-align: left;\n",
       "}\n",
       "#T_4a335 td {\n",
       "  text-align: left;\n",
       "}\n",
       "#T_4a335_row0_col0, #T_4a335_row0_col1, #T_4a335_row0_col2, #T_4a335_row0_col3, #T_4a335_row0_col4, #T_4a335_row1_col0, #T_4a335_row1_col1, #T_4a335_row1_col2, #T_4a335_row1_col3, #T_4a335_row1_col4, #T_4a335_row2_col0, #T_4a335_row2_col1, #T_4a335_row2_col2, #T_4a335_row2_col3, #T_4a335_row2_col4, #T_4a335_row3_col0, #T_4a335_row3_col1, #T_4a335_row3_col2, #T_4a335_row3_col3, #T_4a335_row3_col4, #T_4a335_row4_col0, #T_4a335_row4_col1, #T_4a335_row4_col2, #T_4a335_row4_col3, #T_4a335_row4_col4 {\n",
       "  text-align: left;\n",
       "  white-space: pre-wrap;\n",
       "  word-wrap: break-word;\n",
       "  max-width: 400px;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_4a335\">\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"blank level0\" >&nbsp;</th>\n",
       "      <th id=\"T_4a335_level0_col0\" class=\"col_heading level0 col0\" >topic</th>\n",
       "      <th id=\"T_4a335_level0_col1\" class=\"col_heading level0 col1\" >example_joke</th>\n",
       "      <th id=\"T_4a335_level0_col2\" class=\"col_heading level0 col2\" >rationale</th>\n",
       "      <th id=\"T_4a335_level0_col3\" class=\"col_heading level0 col3\" >pred_joke</th>\n",
       "      <th id=\"T_4a335_level0_col4\" class=\"col_heading level0 col4\" >metric</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th id=\"T_4a335_level0_row0\" class=\"row_heading level0 row0\" >0</th>\n",
       "      <td id=\"T_4a335_row0_col0\" class=\"data row0 col0\" >Misunderstanding</td>\n",
       "      <td id=\"T_4a335_row0_col1\" class=\"data row0 col1\" >Two fish in a tank. One says: ‘How do you drive this thing?'</td>\n",
       "      <td id=\"T_4a335_row0_col2\" class=\"data row0 col2\" >produce the joke. We can focus on a common scenario where misunderstandings frequently occur, such as communication between different generations. This often leads to humorous...</td>\n",
       "      <td id=\"T_4a335_row0_col3\" class=\"data row0 col3\" >Why did the grandchild put his phone in the blender?\n",
       "\n",
       "Because his grandma texted him saying, \"Remember to juice your apple!\"</td>\n",
       "      <td id=\"T_4a335_row0_col4\" class=\"data row0 col4\" >✔️ [0.67]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th id=\"T_4a335_level0_row1\" class=\"row_heading level0 row1\" >1</th>\n",
       "      <td id=\"T_4a335_row1_col0\" class=\"data row1 col0\" >Entertainment</td>\n",
       "      <td id=\"T_4a335_row1_col1\" class=\"data row1 col1\" >I saw a documentary on how ships are kept together. Riveting!</td>\n",
       "      <td id=\"T_4a335_row1_col2\" class=\"data row1 col2\" >produce the joke. We can consider the broad aspects of entertainment, such as movies, music, and television. A common humorous angle is to play on...</td>\n",
       "      <td id=\"T_4a335_row1_col3\" class=\"data row1 col3\" >Why don't secrets last long in a movie theater? Because everyone there loves to spill the beans during the trailers!</td>\n",
       "      <td id=\"T_4a335_row1_col4\" class=\"data row1 col4\" >✔️ [0.67]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th id=\"T_4a335_level0_row2\" class=\"row_heading level0 row2\" >2</th>\n",
       "      <td id=\"T_4a335_row2_col0\" class=\"data row2 col0\" >Music</td>\n",
       "      <td id=\"T_4a335_row2_col1\" class=\"data row2 col1\" >People who like trance music are very persistent. They don’t techno for an answer.</td>\n",
       "      <td id=\"T_4a335_row2_col2\" class=\"data row2 col2\" >produce the joke. We can start by considering common elements in music that are relatable and can be twisted into a humorous context. Instruments, musicians,...</td>\n",
       "      <td id=\"T_4a335_row2_col3\" class=\"data row2 col3\" >Why did the musician get locked out of their own concert? Because they couldn't find the right key!</td>\n",
       "      <td id=\"T_4a335_row2_col4\" class=\"data row2 col4\" >✔️ [0.67]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th id=\"T_4a335_level0_row3\" class=\"row_heading level0 row3\" >3</th>\n",
       "      <td id=\"T_4a335_row3_col0\" class=\"data row3 col0\" >Dating</td>\n",
       "      <td id=\"T_4a335_row3_col1\" class=\"data row3 col1\" >I used to go out with a giraffe. Used to take it to the pictures and that. You’d always get some bloke complaining that he...</td>\n",
       "      <td id=\"T_4a335_row3_col2\" class=\"data row3 col2\" >produce the joke. We can explore common dating scenarios that many people find relatable and humorous. A good area to focus on is the awkwardness...</td>\n",
       "      <td id=\"T_4a335_row3_col3\" class=\"data row3 col3\" >Why did the date at the restaurant go so well? Because they were both checking their phones and fell in love with the same memes!</td>\n",
       "      <td id=\"T_4a335_row3_col4\" class=\"data row3 col4\" >✔️ [0.67]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th id=\"T_4a335_level0_row4\" class=\"row_heading level0 row4\" >4</th>\n",
       "      <td id=\"T_4a335_row4_col0\" class=\"data row4 col0\" >Weather</td>\n",
       "      <td id=\"T_4a335_row4_col1\" class=\"data row4 col1\" >Normally you have news, weather and travel. But not on snow day. On a snow day, news is weather is travel.</td>\n",
       "      <td id=\"T_4a335_row4_col2\" class=\"data row4 col2\" >produce the joke. We can start by considering common experiences people have with weather, such as unpredictability or extreme conditions. People often joke about how...</td>\n",
       "      <td id=\"T_4a335_row4_col3\" class=\"data row4 col3\" >Why did the weather report go to therapy? Because it had too many 'cloudy' days and couldn't predict its own 'moods'!</td>\n",
       "      <td id=\"T_4a335_row4_col4\" class=\"data row4 col4\" >✔️ [0.67]</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n"
      ],
      "text/plain": [
       "<pandas.io.formats.style.Styler at 0x16b0743d0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "                <div style='\n",
       "                    text-align: center;\n",
       "                    font-size: 16px;\n",
       "                    font-weight: bold;\n",
       "                    color: #555;\n",
       "                    margin: 10px 0;'>\n",
       "                    ... 21 more rows not displayed ...\n",
       "                </div>\n",
       "                "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "70.69"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from dspy.evaluate import Evaluate\n",
    "\n",
    "evaluate = Evaluate(metric=metric, devset=devset, num_threads=8, display_progress=True, display_table=5)\n",
    "evaluate(make_joke_chain)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 7) Compile with a DSPy optimizer\n",
    "- If you have very little data, e.g. 10 examples of your task, use `BootstrapFewShot`.\n",
    "- If you have slightly more data, e.g. 50 examples of your task, use `BootstrapFewShotWithRandomSearch`.\n",
    "- If you have more data than that, e.g. 300 examples or more, use `MIPRO`.\n",
    "- If you have been able to use one of these with a large LM (e.g., 7B parameters or above) and need a very efficient program, compile that down to a small LM with `BootstrapFinetune`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "  5%|▌         | 4/76 [00:00<00:00, 1310.62it/s]\n"
     ]
    }
   ],
   "source": [
    "from dspy.teleprompt import BootstrapFewShot\n",
    "\n",
    "optimizer = BootstrapFewShot(metric=metric)\n",
    "cot_compiled = optimizer.compile(CoT(), trainset=trainset, valset=devset)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Rationale: produce the joke. We can consider the typical experiences and mishaps that occur during fishing trips. Fishing often involves unexpected outcomes, like catching something other than fish, or the humorous interactions between seasoned fishermen and novices. Let's play on the idea of a novice fisherman misunderstanding common fishing terms.\n",
      "---\n",
      "Joke: Why don't fish make good musicians? I took my buddy fishing, and he threw his guitar in the lake because I told him we were going to catch a few bass!\n"
     ]
    }
   ],
   "source": [
    "response = cot_compiled(topic=\"fishing\")\n",
    "print(f\"Rationale: {response.rationale}\")\n",
    "print(\"---\")\n",
    "print(f\"Joke: {response.joke}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\n",
      "Make a funny joke given a topic.\n",
      "\n",
      "---\n",
      "\n",
      "Follow the following format.\n",
      "\n",
      "Topic: The topic of the joke.\n",
      "Reasoning: Let's think step by step in order to ${produce the joke}. We ...\n",
      "Joke: The funny joke.\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Fishing\n",
      "Reasoning: Let's think step by step in order to produce the joke. We start by considering common stereotypes or humorous situations related to fishing. Fishing often involves long periods of waiting and patience, which can be played up for comedic effect. Additionally, there's a common trope about fishermen exaggerating the size of the fish they catch.\n",
      "Joke: I told my wife the fishing trip would be relaxing, but she didn’t believe me until I came back home. She asked, \"Catch anything?\" I said, \"Sure did, 8 hours of sleep!\"\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Family\n",
      "Reasoning: Let's think step by step in order to produce the joke. We start by considering common family dynamics and interactions that many can relate to. Families often have humorous situations arise from misunderstandings, generational gaps, or the quirky behaviors of different members. Let's focus on a scenario that highlights a typical yet funny misunderstanding between family members.\n",
      "Joke: My grandma just got her first smartphone and she’s been texting me non-stop. Yesterday, she sent me a bunch of pizza emojis followed by a question mark. Turns out, she thought it was the way to order pizza through the phone.\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Holidays\n",
      "Reasoning: Let's think step by step in order to produce the joke. We start by considering common elements of holidays that are universally recognized and often ripe for humor. Holidays often involve family gatherings, which can be both heartwarming and stressful. There's also the element of high expectations versus reality, such as the perfect holiday dinner or the perfect gift, which often don't go as planned. Combining these elements can lead to a humorous observation or exaggeration.\n",
      "Joke: Holidays: the only time you catch yourself saying, \"I can't wait to see everyone!\" and \"I can't wait to go home!\" in the same breath.\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Drinking\n",
      "Reasoning: Let's think step by step in order to produce the joke. We start by considering common scenarios involving drinking that are relatable and can be twisted into a humorous observation. Drinking often leads to exaggerated confidence, poor decisions, or funny misunderstandings. Let's play on the idea of someone misinterpreting a common phrase while drunk.\n",
      "Joke: I told my friend, \"You should drink responsibly.\" He said, \"No worries, I only drink in the living room.\"\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Family\n",
      "Joke: I’m sure wherever my Dad is, he’s looking down on us. He’s not dead, just very condescending.\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Family\n",
      "Joke: My father drank so heavily, when he blew on the birthday cake he lit the candles.\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Marriage\n",
      "Joke: ‘What’s a couple?’ I asked my mum. She said, ‘Two or three’. Which probably explains why her marriage collapsed.\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Entertainment\n",
      "Joke: I saw a documentary on how ships are kept together. Riveting!\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Learning\n",
      "Joke: I’m learning the hokey cokey. Not all of it. But – I’ve got the ins and outs.\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Afterlife\n",
      "Joke: I doubt there’s a heaven; I think the people from hell have probably bought it for a timeshare.\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Communication\n",
      "Joke: I was in my car driving back from work. A police officer pulled me over and knocked on my window. I said, ‘One minute I’m on the phone.'\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Therapy\n",
      "Joke: I’ve been feeling suicidal so my therapist suggested I do CBT. Now I can ride a motorbike, how’s that going to help?\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Identity\n",
      "Joke: Roses are red, violets are blue, I’m a schizophrenic, and so am I.\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Humor\n",
      "Joke: It’s really hard to define ‘virtue signalling’, as I was saying the other day to some of my Muslim friends over a fair-trade coffee in our local feminist bookshop.\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Vengeance\n",
      "Joke: My therapist says I have a preoccupation with vengeance. We’ll see about that.\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Flexibility\n",
      "Joke: I said to the gym instructor: ‘Can you teach me to do the splits?’ He said: ‘How flexible are you?’ I said: ‘I can’t make Tuesdays.’\n",
      "\n",
      "---\n",
      "\n",
      "Topic: fishing\n",
      "Reasoning: Let's think step by step in order to\u001b[32m produce the joke. We can consider the typical experiences and mishaps that occur during fishing trips. Fishing often involves unexpected outcomes, like catching something other than fish, or the humorous interactions between seasoned fishermen and novices. Let's play on the idea of a novice fisherman misunderstanding common fishing terms.\n",
      "\n",
      "Joke: Why don't fish make good musicians? I took my buddy fishing, and he threw his guitar in the lake because I told him we were going to catch a few bass!\u001b[0m\n",
      "\n",
      "\n",
      "\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'\\n\\n\\nMake a funny joke given a topic.\\n\\n---\\n\\nFollow the following format.\\n\\nTopic: The topic of the joke.\\nReasoning: Let\\'s think step by step in order to ${produce the joke}. We ...\\nJoke: The funny joke.\\n\\n---\\n\\nTopic: Fishing\\nReasoning: Let\\'s think step by step in order to produce the joke. We start by considering common stereotypes or humorous situations related to fishing. Fishing often involves long periods of waiting and patience, which can be played up for comedic effect. Additionally, there\\'s a common trope about fishermen exaggerating the size of the fish they catch.\\nJoke: I told my wife the fishing trip would be relaxing, but she didn’t believe me until I came back home. She asked, \"Catch anything?\" I said, \"Sure did, 8 hours of sleep!\"\\n\\n---\\n\\nTopic: Family\\nReasoning: Let\\'s think step by step in order to produce the joke. We start by considering common family dynamics and interactions that many can relate to. Families often have humorous situations arise from misunderstandings, generational gaps, or the quirky behaviors of different members. Let\\'s focus on a scenario that highlights a typical yet funny misunderstanding between family members.\\nJoke: My grandma just got her first smartphone and she’s been texting me non-stop. Yesterday, she sent me a bunch of pizza emojis followed by a question mark. Turns out, she thought it was the way to order pizza through the phone.\\n\\n---\\n\\nTopic: Holidays\\nReasoning: Let\\'s think step by step in order to produce the joke. We start by considering common elements of holidays that are universally recognized and often ripe for humor. Holidays often involve family gatherings, which can be both heartwarming and stressful. There\\'s also the element of high expectations versus reality, such as the perfect holiday dinner or the perfect gift, which often don\\'t go as planned. Combining these elements can lead to a humorous observation or exaggeration.\\nJoke: Holidays: the only time you catch yourself saying, \"I can\\'t wait to see everyone!\" and \"I can\\'t wait to go home!\" in the same breath.\\n\\n---\\n\\nTopic: Drinking\\nReasoning: Let\\'s think step by step in order to produce the joke. We start by considering common scenarios involving drinking that are relatable and can be twisted into a humorous observation. Drinking often leads to exaggerated confidence, poor decisions, or funny misunderstandings. Let\\'s play on the idea of someone misinterpreting a common phrase while drunk.\\nJoke: I told my friend, \"You should drink responsibly.\" He said, \"No worries, I only drink in the living room.\"\\n\\n---\\n\\nTopic: Family\\nJoke: I’m sure wherever my Dad is, he’s looking down on us. He’s not dead, just very condescending.\\n\\n---\\n\\nTopic: Family\\nJoke: My father drank so heavily, when he blew on the birthday cake he lit the candles.\\n\\n---\\n\\nTopic: Marriage\\nJoke: ‘What’s a couple?’ I asked my mum. She said, ‘Two or three’. Which probably explains why her marriage collapsed.\\n\\n---\\n\\nTopic: Entertainment\\nJoke: I saw a documentary on how ships are kept together. Riveting!\\n\\n---\\n\\nTopic: Learning\\nJoke: I’m learning the hokey cokey. Not all of it. But – I’ve got the ins and outs.\\n\\n---\\n\\nTopic: Afterlife\\nJoke: I doubt there’s a heaven; I think the people from hell have probably bought it for a timeshare.\\n\\n---\\n\\nTopic: Communication\\nJoke: I was in my car driving back from work. A police officer pulled me over and knocked on my window. I said, ‘One minute I’m on the phone.\\'\\n\\n---\\n\\nTopic: Therapy\\nJoke: I’ve been feeling suicidal so my therapist suggested I do CBT. Now I can ride a motorbike, how’s that going to help?\\n\\n---\\n\\nTopic: Identity\\nJoke: Roses are red, violets are blue, I’m a schizophrenic, and so am I.\\n\\n---\\n\\nTopic: Humor\\nJoke: It’s really hard to define ‘virtue signalling’, as I was saying the other day to some of my Muslim friends over a fair-trade coffee in our local feminist bookshop.\\n\\n---\\n\\nTopic: Vengeance\\nJoke: My therapist says I have a preoccupation with vengeance. We’ll see about that.\\n\\n---\\n\\nTopic: Flexibility\\nJoke: I said to the gym instructor: ‘Can you teach me to do the splits?’ He said: ‘How flexible are you?’ I said: ‘I can’t make Tuesdays.’\\n\\n---\\n\\nTopic: fishing\\nReasoning: Let\\'s think step by step in order to\\x1b[32m produce the joke. We can consider the typical experiences and mishaps that occur during fishing trips. Fishing often involves unexpected outcomes, like catching something other than fish, or the humorous interactions between seasoned fishermen and novices. Let\\'s play on the idea of a novice fisherman misunderstanding common fishing terms.\\n\\nJoke: Why don\\'t fish make good musicians? I took my buddy fishing, and he threw his guitar in the lake because I told him we were going to catch a few bass!\\x1b[0m\\n\\n\\n'"
      ]
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "gpt4_turbo.inspect_history(n=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Average Metric: 18.380000000000003 / 26  (70.7): 100%|██████████| 26/26 [00:00<00:00, 520.62it/s]\n",
      "Average Metric: 24.680000000000003 / 26  (94.9): 100%|██████████| 26/26 [00:00<00:00, 3475.87it/s]\n",
      "  4%|▍         | 3/76 [00:00<00:00, 1284.76it/s]\n",
      "Average Metric: 22.370000000000005 / 26  (86.0): 100%|██████████| 26/26 [00:00<00:00, 3313.74it/s]\n",
      "  3%|▎         | 2/76 [00:00<00:00, 1518.57it/s]\n",
      "Average Metric: 18.37 / 26  (70.7): 100%|██████████| 26/26 [00:00<00:00, 2945.52it/s]\n",
      "  1%|▏         | 1/76 [00:00<00:00, 471.96it/s]\n",
      "Average Metric: 20.690000000000005 / 26  (79.6): 100%|██████████| 26/26 [00:00<00:00, 2864.36it/s]\n",
      "  1%|▏         | 1/76 [00:00<00:00, 1555.17it/s]\n",
      "Average Metric: 23.360000000000007 / 26  (89.8): 100%|██████████| 26/26 [00:00<00:00, 3180.47it/s]\n"
     ]
    }
   ],
   "source": [
    "from dspy.teleprompt import BootstrapFewShotWithRandomSearch\n",
    "\n",
    "\n",
    "optimizer = BootstrapFewShotWithRandomSearch(metric=metric, max_bootstrapped_demos=3, num_candidate_programs=3)\n",
    "\n",
    "cot_compiled = optimizer.compile(CoT(), trainset=trainset, valset=devset)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Average Metric: 24.68 / 26  (94.9): 100%|██████████| 26/26 [00:00<00:00, 1773.63it/s]\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<style type=\"text/css\">\n",
       "#T_5f67d th {\n",
       "  text-align: left;\n",
       "}\n",
       "#T_5f67d td {\n",
       "  text-align: left;\n",
       "}\n",
       "#T_5f67d_row0_col0, #T_5f67d_row0_col1, #T_5f67d_row0_col2, #T_5f67d_row0_col3, #T_5f67d_row0_col4, #T_5f67d_row1_col0, #T_5f67d_row1_col1, #T_5f67d_row1_col2, #T_5f67d_row1_col3, #T_5f67d_row1_col4, #T_5f67d_row2_col0, #T_5f67d_row2_col1, #T_5f67d_row2_col2, #T_5f67d_row2_col3, #T_5f67d_row2_col4, #T_5f67d_row3_col0, #T_5f67d_row3_col1, #T_5f67d_row3_col2, #T_5f67d_row3_col3, #T_5f67d_row3_col4, #T_5f67d_row4_col0, #T_5f67d_row4_col1, #T_5f67d_row4_col2, #T_5f67d_row4_col3, #T_5f67d_row4_col4 {\n",
       "  text-align: left;\n",
       "  white-space: pre-wrap;\n",
       "  word-wrap: break-word;\n",
       "  max-width: 400px;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_5f67d\">\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"blank level0\" >&nbsp;</th>\n",
       "      <th id=\"T_5f67d_level0_col0\" class=\"col_heading level0 col0\" >topic</th>\n",
       "      <th id=\"T_5f67d_level0_col1\" class=\"col_heading level0 col1\" >example_joke</th>\n",
       "      <th id=\"T_5f67d_level0_col2\" class=\"col_heading level0 col2\" >rationale</th>\n",
       "      <th id=\"T_5f67d_level0_col3\" class=\"col_heading level0 col3\" >pred_joke</th>\n",
       "      <th id=\"T_5f67d_level0_col4\" class=\"col_heading level0 col4\" >metric</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th id=\"T_5f67d_level0_row0\" class=\"row_heading level0 row0\" >0</th>\n",
       "      <td id=\"T_5f67d_row0_col0\" class=\"data row0 col0\" >Misunderstanding</td>\n",
       "      <td id=\"T_5f67d_row0_col1\" class=\"data row0 col1\" >Two fish in a tank. One says: ‘How do you drive this thing?'</td>\n",
       "      <td id=\"T_5f67d_row0_col2\" class=\"data row0 col2\" >produce the joke. We start by considering common scenarios where misunderstandings occur, often involving miscommunication or assumptions. A classic setting for misunderstandings is between couples...</td>\n",
       "      <td id=\"T_5f67d_row0_col3\" class=\"data row0 col3\" >I told my friend I was reading a book on anti-gravity. He said, \"That must be impossible to put down!\" I replied, \"No, it's just...</td>\n",
       "      <td id=\"T_5f67d_row0_col4\" class=\"data row0 col4\" >✔️ [1.0]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th id=\"T_5f67d_level0_row1\" class=\"row_heading level0 row1\" >1</th>\n",
       "      <td id=\"T_5f67d_row1_col0\" class=\"data row1 col0\" >Entertainment</td>\n",
       "      <td id=\"T_5f67d_row1_col1\" class=\"data row1 col1\" >I saw a documentary on how ships are kept together. Riveting!</td>\n",
       "      <td id=\"T_5f67d_row1_col2\" class=\"data row1 col2\" >produce the joke. We start by considering common elements in entertainment that are universally recognized and often ripe for humor. Entertainment often involves celebrities, movies,...</td>\n",
       "      <td id=\"T_5f67d_row1_col3\" class=\"data row1 col3\" >Why don't celebrities play hide and seek? Because good luck hiding when you've got 12 million followers!</td>\n",
       "      <td id=\"T_5f67d_row1_col4\" class=\"data row1 col4\" >✔️ [1.0]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th id=\"T_5f67d_level0_row2\" class=\"row_heading level0 row2\" >2</th>\n",
       "      <td id=\"T_5f67d_row2_col0\" class=\"data row2 col0\" >Music</td>\n",
       "      <td id=\"T_5f67d_row2_col1\" class=\"data row2 col1\" >People who like trance music are very persistent. They don’t techno for an answer.</td>\n",
       "      <td id=\"T_5f67d_row2_col2\" class=\"data row2 col2\" >produce the joke. We start by considering common stereotypes or humorous situations related to music. Musicians and their instruments offer a rich vein of humor,...</td>\n",
       "      <td id=\"T_5f67d_row2_col3\" class=\"data row2 col3\" >Why did the hipster refuse to play his grandpa's accordion? He couldn't find the app for it.</td>\n",
       "      <td id=\"T_5f67d_row2_col4\" class=\"data row2 col4\" >✔️ [1.0]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th id=\"T_5f67d_level0_row3\" class=\"row_heading level0 row3\" >3</th>\n",
       "      <td id=\"T_5f67d_row3_col0\" class=\"data row3 col0\" >Dating</td>\n",
       "      <td id=\"T_5f67d_row3_col1\" class=\"data row3 col1\" >I used to go out with a giraffe. Used to take it to the pictures and that. You’d always get some bloke complaining that he...</td>\n",
       "      <td id=\"T_5f67d_row3_col2\" class=\"data row3 col2\" >produce the joke. We start by considering common dating scenarios and the humorous misunderstandings or exaggerations that can occur. Dating often involves trying to impress...</td>\n",
       "      <td id=\"T_5f67d_row3_col3\" class=\"data row3 col3\" >I told my date I was really into fitness. She said, \"Great, let's go to a health food cafe.\" Turns out she heard \"fitness whole...</td>\n",
       "      <td id=\"T_5f67d_row3_col4\" class=\"data row3 col4\" >✔️ [1.0]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th id=\"T_5f67d_level0_row4\" class=\"row_heading level0 row4\" >4</th>\n",
       "      <td id=\"T_5f67d_row4_col0\" class=\"data row4 col0\" >Weather</td>\n",
       "      <td id=\"T_5f67d_row4_col1\" class=\"data row4 col1\" >Normally you have news, weather and travel. But not on snow day. On a snow day, news is weather is travel.</td>\n",
       "      <td id=\"T_5f67d_row4_col2\" class=\"data row4 col2\" >produce the joke. We can start by considering common complaints or humorous observations about the weather. People often talk about how unpredictable it can be,...</td>\n",
       "      <td id=\"T_5f67d_row4_col3\" class=\"data row4 col3\" >I asked the weather forecast if it could be more reliable. It said, “Sure, right after you figure out what you want for dinner.”</td>\n",
       "      <td id=\"T_5f67d_row4_col4\" class=\"data row4 col4\" >✔️ [1.0]</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n"
      ],
      "text/plain": [
       "<pandas.io.formats.style.Styler at 0x16b419f10>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "                <div style='\n",
       "                    text-align: center;\n",
       "                    font-size: 16px;\n",
       "                    font-weight: bold;\n",
       "                    color: #555;\n",
       "                    margin: 10px 0;'>\n",
       "                    ... 21 more rows not displayed ...\n",
       "                </div>\n",
       "                "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "94.92"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "evaluate = Evaluate(metric=metric, devset=devset, num_threads=8, display_progress=True, display_table=5)\n",
    "evaluate(cot_compiled)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Rationale: produce the joke. We start by considering common scenarios or stereotypes associated with fishing. Fishing often involves a lot of waiting and patience, sometimes without catching anything. This can be a source of humor, especially when juxtaposed with the fisherman's expectations or the reactions of others.\n",
      "---\n",
      "Joke: Why don't fish make good musicians? Because you can tune a guitar, but you can't tuna fish!\n"
     ]
    }
   ],
   "source": [
    "response = cot_compiled(topic=\"fishing\")\n",
    "print(f\"Rationale: {response.rationale}\")\n",
    "print(\"---\")\n",
    "print(f\"Joke: {response.joke}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\n",
      "Make a funny joke given a topic.\n",
      "\n",
      "---\n",
      "\n",
      "Follow the following format.\n",
      "\n",
      "Topic: The topic of the joke.\n",
      "Reasoning: Let's think step by step in order to ${produce the joke}. We ...\n",
      "Joke: The funny joke.\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Animals\n",
      "Joke: Owls haven’t got necks, have they? An owl is essentially a one-piece unit.\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Fitness\n",
      "Joke: I said to the gym instructor: “Can you teach me to do the splits?”, He said: “How flexible are you?”, I said: “I can’t make Tuesdays.”\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Movies\n",
      "Joke: It seems like everything this year was three-dimensional, except the characters in The Tourist.\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Overthinking\n",
      "Joke: I worry about ridiculous things, you know, how does a guy who drives a snowplough get to work in the morning… that can keep me awake for days.\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Hollywood\n",
      "Joke: You think I go to a Hollywood meeting with all them white people by myself? I bring my nigga Mac Mittens from the streets […] He’s not even qualified to listen to these meetings, he just makes me feel good.\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Political Commentary\n",
      "Joke: Eight years later, I’m pulling up to the polls again. This time, I’m driving a brand-new Porsche because the Obama years were very good to me […] I walked up and saw a long, long line of dusty white people […] I stood with them in line, like all us Americans are required to do in a democracy. Nobody skips the line to vote. And I listened to them say naïve, poor white people things.\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Technology\n",
      "Joke: My phone will ring at 2am and my wife’ll look at me and go, “Who’s that calling at this time?” I say, “I don’t know. If I knew that we wouldn’t need the bloody phone.”\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Obesity\n",
      "Joke: Life is like a box of chocolates. It doesn’t last long if you’re fat.\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Fatherhood\n",
      "Joke: This motherfucker calls me up in the middle of the night. It was one o'clock in the morning and he goes, 'Dad, don’t be mad […] I’m at a party and my designated driver had too much to drink. Me and friends need you to come pick us up.' I said, 'Jesus Christ, it’s one o'clock in the morning. Nigga, I am shit-faced!'\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Marriage\n",
      "Joke: I always take my wife morning tea in my pyjamas. But is she grateful? No, she says she’d rather have it in a cup.\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Fame\n",
      "Joke: Please don’t worship me. I’m just an ordinary guy, with lots of followers trying to spread my message. Sort of like Jesus Christ I guess.\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Religious Satire\n",
      "Joke: I respect everybody’s beliefs, except Amish people. They are the only ones I can say clearly, 'Their God is wrong.' The speed limit is 75 miles an hour in Ohio, and one lane of traffic is blocked by a goddamned horse and buggy?\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Awards\n",
      "Joke: For any of you who don’t know, the Golden Globes are just like the Oscars, but without all that esteem. The Golden Globes are to the Oscars what Kim Kardashian is to Kate Middleton. A bit louder, a bit trashier, a bit drunker, and more easily bought.\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Workplace\n",
      "Joke: If your boss is getting you down, look at him through the prongs of a fork and imagine him in jail.\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Philosophy\n",
      "Joke: Remember, when you are dead, you do not know you are dead. It is only painful for others. The same applies when you are stupid.\n",
      "\n",
      "---\n",
      "\n",
      "Topic: Social Class\n",
      "Joke: You know you’re working class when your TV is bigger than your bookcase.\n",
      "\n",
      "---\n",
      "\n",
      "Topic: fishing\n",
      "Reasoning: Let's think step by step in order to\u001b[32m produce the joke. We start by considering common scenarios or stereotypes associated with fishing. Fishing often involves a lot of waiting and patience, sometimes without catching anything. This can be a source of humor, especially when juxtaposed with the fisherman's expectations or the reactions of others.\n",
      "\n",
      "Joke: Why don't fish make good musicians? Because you can tune a guitar, but you can't tuna fish!\u001b[0m\n",
      "\n",
      "\n",
      "\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "\"\\n\\n\\nMake a funny joke given a topic.\\n\\n---\\n\\nFollow the following format.\\n\\nTopic: The topic of the joke.\\nReasoning: Let's think step by step in order to ${produce the joke}. We ...\\nJoke: The funny joke.\\n\\n---\\n\\nTopic: Animals\\nJoke: Owls haven’t got necks, have they? An owl is essentially a one-piece unit.\\n\\n---\\n\\nTopic: Fitness\\nJoke: I said to the gym instructor: “Can you teach me to do the splits?”, He said: “How flexible are you?”, I said: “I can’t make Tuesdays.”\\n\\n---\\n\\nTopic: Movies\\nJoke: It seems like everything this year was three-dimensional, except the characters in The Tourist.\\n\\n---\\n\\nTopic: Overthinking\\nJoke: I worry about ridiculous things, you know, how does a guy who drives a snowplough get to work in the morning… that can keep me awake for days.\\n\\n---\\n\\nTopic: Hollywood\\nJoke: You think I go to a Hollywood meeting with all them white people by myself? I bring my nigga Mac Mittens from the streets […] He’s not even qualified to listen to these meetings, he just makes me feel good.\\n\\n---\\n\\nTopic: Political Commentary\\nJoke: Eight years later, I’m pulling up to the polls again. This time, I’m driving a brand-new Porsche because the Obama years were very good to me […] I walked up and saw a long, long line of dusty white people […] I stood with them in line, like all us Americans are required to do in a democracy. Nobody skips the line to vote. And I listened to them say naïve, poor white people things.\\n\\n---\\n\\nTopic: Technology\\nJoke: My phone will ring at 2am and my wife’ll look at me and go, “Who’s that calling at this time?” I say, “I don’t know. If I knew that we wouldn’t need the bloody phone.”\\n\\n---\\n\\nTopic: Obesity\\nJoke: Life is like a box of chocolates. It doesn’t last long if you’re fat.\\n\\n---\\n\\nTopic: Fatherhood\\nJoke: This motherfucker calls me up in the middle of the night. It was one o'clock in the morning and he goes, 'Dad, don’t be mad […] I’m at a party and my designated driver had too much to drink. Me and friends need you to come pick us up.' I said, 'Jesus Christ, it’s one o'clock in the morning. Nigga, I am shit-faced!'\\n\\n---\\n\\nTopic: Marriage\\nJoke: I always take my wife morning tea in my pyjamas. But is she grateful? No, she says she’d rather have it in a cup.\\n\\n---\\n\\nTopic: Fame\\nJoke: Please don’t worship me. I’m just an ordinary guy, with lots of followers trying to spread my message. Sort of like Jesus Christ I guess.\\n\\n---\\n\\nTopic: Religious Satire\\nJoke: I respect everybody’s beliefs, except Amish people. They are the only ones I can say clearly, 'Their God is wrong.' The speed limit is 75 miles an hour in Ohio, and one lane of traffic is blocked by a goddamned horse and buggy?\\n\\n---\\n\\nTopic: Awards\\nJoke: For any of you who don’t know, the Golden Globes are just like the Oscars, but without all that esteem. The Golden Globes are to the Oscars what Kim Kardashian is to Kate Middleton. A bit louder, a bit trashier, a bit drunker, and more easily bought.\\n\\n---\\n\\nTopic: Workplace\\nJoke: If your boss is getting you down, look at him through the prongs of a fork and imagine him in jail.\\n\\n---\\n\\nTopic: Philosophy\\nJoke: Remember, when you are dead, you do not know you are dead. It is only painful for others. The same applies when you are stupid.\\n\\n---\\n\\nTopic: Social Class\\nJoke: You know you’re working class when your TV is bigger than your bookcase.\\n\\n---\\n\\nTopic: fishing\\nReasoning: Let's think step by step in order to\\x1b[32m produce the joke. We start by considering common scenarios or stereotypes associated with fishing. Fishing often involves a lot of waiting and patience, sometimes without catching anything. This can be a source of humor, especially when juxtaposed with the fisherman's expectations or the reactions of others.\\n\\nJoke: Why don't fish make good musicians? Because you can tune a guitar, but you can't tuna fish!\\x1b[0m\\n\\n\\n\""
      ]
     },
     "execution_count": 66,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "gpt4_turbo.inspect_history(n=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "metadata": {},
   "outputs": [],
   "source": [
    "cot_compiled.save('turbo_joke.json')\n",
    "\n",
    "# Loading:\n",
    "# cot = CoT()\n",
    "# cot.load('turbo_joke.json')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 8) Iterate\n",
    "- Try a different AI model?\n",
    "- Rewrite the task instructions?\n",
    "- Redefine the eval metrics?\n",
    "- Annotate more training data?\n",
    "- Split the pipeline into more steps?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Average Metric: 55.80000000000005 / 76  (73.4): 100%|██████████| 76/76 [00:00<00:00, 987.58it/s]  \n",
      "Average Metric: 60.10000000000004 / 76  (79.1): 100%|██████████| 76/76 [00:00<00:00, 1013.93it/s] \n",
      "Average Metric: 55.130000000000045 / 76  (72.5): 100%|██████████| 76/76 [00:00<00:00, 1168.18it/s]\n",
      "Average Metric: 59.14000000000004 / 76  (77.8): 100%|██████████| 76/76 [00:00<00:00, 735.05it/s] \n",
      "Average Metric: 55.52000000000006 / 76  (73.1): 100%|██████████| 76/76 [00:00<00:00, 1698.29it/s] \n",
      "Average Metric: 56.80000000000004 / 76  (74.7): 100%|██████████| 76/76 [00:00<00:00, 1355.01it/s] \n",
      "Average Metric: 55.16000000000006 / 76  (72.6): 100%|██████████| 76/76 [00:00<00:00, 641.47it/s] \n",
      "Average Metric: 54.49000000000006 / 76  (71.7): 100%|██████████| 76/76 [00:43<00:00,  1.73it/s] \n",
      "Average Metric: 53.500000000000064 / 76  (70.4): 100%|██████████| 76/76 [00:45<00:00,  1.66it/s]\n",
      "Average Metric: 55.490000000000066 / 76  (73.0): 100%|██████████| 76/76 [00:47<00:00,  1.59it/s]\n",
      "Average Metric: 52.13000000000004 / 76  (68.6): 100%|██████████| 76/76 [00:32<00:00,  2.32it/s] \n",
      "Average Metric: 22.609999999999992 / 76  (29.7): 100%|██████████| 76/76 [00:48<00:00,  1.58it/s]\n",
      "Average Metric: 53.82000000000005 / 76  (70.8): 100%|██████████| 76/76 [00:41<00:00,  1.84it/s] \n",
      "Average Metric: 56.070000000000036 / 76  (73.8): 100%|██████████| 76/76 [00:37<00:00,  2.03it/s]\n",
      "Average Metric: 28.009999999999984 / 76  (36.9): 100%|██████████| 76/76 [00:53<00:00,  1.42it/s]\n",
      "Average Metric: 59.47000000000005 / 76  (78.3): 100%|██████████| 76/76 [00:53<00:00,  1.43it/s] \n",
      "Average Metric: 54.47000000000005 / 76  (71.7): 100%|██████████| 76/76 [00:50<00:00,  1.51it/s] \n",
      "Average Metric: 47.770000000000024 / 76  (62.9): 100%|██████████| 76/76 [01:30<00:00,  1.18s/it]\n",
      "Average Metric: 53.47000000000005 / 76  (70.4): 100%|██████████| 76/76 [00:46<00:00,  1.65it/s] \n",
      "Average Metric: 42.37 / 76  (55.8): 100%|██████████| 76/76 [00:50<00:00,  1.50it/s]             \n",
      "Average Metric: 52.410000000000025 / 76  (69.0): 100%|██████████| 76/76 [01:06<00:00,  1.14it/s]\n",
      "Average Metric: 44.10000000000004 / 76  (58.0): 100%|██████████| 76/76 [01:05<00:00,  1.15it/s] \n",
      "Average Metric: 59.110000000000035 / 76  (77.8): 100%|██████████| 76/76 [00:45<00:00,  1.66it/s]\n",
      "Average Metric: 52.78000000000004 / 76  (69.4): 100%|██████████| 76/76 [00:59<00:00,  1.29it/s] \n"
     ]
    }
   ],
   "source": [
    "from dspy.teleprompt import COPRO\n",
    "\n",
    "# optimize the prompt instructions instead of examples\n",
    "prompt_optimizer = COPRO(metric=metric, verbose=True)\n",
    "\n",
    "# Used in Evaluate class in the optimization process\n",
    "kwargs = dict(num_threads=64, display_progress=True, display_table=0) \n",
    "\n",
    "cot_prompt_compiled = prompt_optimizer.compile(CoT(), trainset=trainset, eval_kwargs=kwargs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 124,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Score:  86.41\n",
      "Proposed Instruction: «Engineer a humorous remark related to your specified topic with a strategic use of satire, understatement, or hyperbole for heightened comedic effect. Ensure that the setup begins with context that relates seemingly different elements or brings an unexpected twist that pertains to universal human experiences. Conclude the joke concisely with a punchline that sharply illuminates the irony or contradiction of the situation without censuring or offending specific groups. Additionally, use culturally neutral motifs to increase accessibility and connect with a broad audience scale.»\n"
     ]
    }
   ],
   "source": [
    "winner = cot_prompt_compiled.candidate_programs[0]\n",
    "print(\"Score: \", winner['score'])\n",
    "print(winner['instruction'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "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.9.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
