{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "toc": true
   },
   "source": [
    "<h1>Table of Contents<span class=\"tocSkip\"></span></h1>\n",
    "<div class=\"toc\"><ul class=\"toc-item\"><li><span><a href=\"#Usage\" data-toc-modified-id=\"Usage-1\"><span class=\"toc-item-num\">1&nbsp;&nbsp;</span>Usage</a></span><ul class=\"toc-item\"><li><span><a href=\"#Just-do-it:-A-minimal-boilerplate-facade-to-OpenAI-stuff\" data-toc-modified-id=\"Just-do-it:-A-minimal-boilerplate-facade-to-OpenAI-stuff-1.1\"><span class=\"toc-item-num\">1.1&nbsp;&nbsp;</span>Just-do-it: A minimal-boilerplate facade to OpenAI stuff</a></span></li><li><span><a href=\"#Raw-form\" data-toc-modified-id=\"Raw-form-1.2\"><span class=\"toc-item-num\">1.2&nbsp;&nbsp;</span>Raw form</a></span></li></ul></li><li><span><a href=\"#Scrap\" data-toc-modified-id=\"Scrap-2\"><span class=\"toc-item-num\">2&nbsp;&nbsp;</span>Scrap</a></span><ul class=\"toc-item\"><li><span><a href=\"#OpenAPI-OpenAI\" data-toc-modified-id=\"OpenAPI-OpenAI-2.1\"><span class=\"toc-item-num\">2.1&nbsp;&nbsp;</span>OpenAPI OpenAI</a></span></li><li><span><a href=\"#Align-OpenAPI-specs-and-openai-python-functions\" data-toc-modified-id=\"Align-OpenAPI-specs-and-openai-python-functions-2.2\"><span class=\"toc-item-num\">2.2&nbsp;&nbsp;</span>Align OpenAPI specs and openai python functions</a></span><ul class=\"toc-item\"><li><ul class=\"toc-item\"><li><span><a href=\"#Scrap-to-make-raw\" data-toc-modified-id=\"Scrap-to-make-raw-2.2.0.1\"><span class=\"toc-item-num\">2.2.0.1&nbsp;&nbsp;</span>Scrap to make raw</a></span></li></ul></li><li><span><a href=\"#specs/shema-scrap\" data-toc-modified-id=\"specs/shema-scrap-2.2.1\"><span class=\"toc-item-num\">2.2.1&nbsp;&nbsp;</span>specs/shema scrap</a></span></li><li><span><a href=\"#Schemas\" data-toc-modified-id=\"Schemas-2.2.2\"><span class=\"toc-item-num\">2.2.2&nbsp;&nbsp;</span>Schemas</a></span></li><li><span><a href=\"#Paths\" data-toc-modified-id=\"Paths-2.2.3\"><span class=\"toc-item-num\">2.2.3&nbsp;&nbsp;</span>Paths</a></span></li></ul></li><li><span><a href=\"#Engine/Model-list\" data-toc-modified-id=\"Engine/Model-list-2.3\"><span class=\"toc-item-num\">2.3&nbsp;&nbsp;</span>Engine/Model list</a></span></li><li><span><a href=\"#illustrating-a-story\" data-toc-modified-id=\"illustrating-a-story-2.4\"><span class=\"toc-item-num\">2.4&nbsp;&nbsp;</span>illustrating a story</a></span></li><li><span><a href=\"#Making-an-Aesop's-Fables-book\" data-toc-modified-id=\"Making-an-Aesop's-Fables-book-2.5\"><span class=\"toc-item-num\">2.5&nbsp;&nbsp;</span>Making an Aesop's Fables book</a></span></li><li><span><a href=\"#illustrating-concepts\" data-toc-modified-id=\"illustrating-concepts-2.6\"><span class=\"toc-item-num\">2.6&nbsp;&nbsp;</span>illustrating concepts</a></span></li><li><span><a href=\"#open-ai-tutorial-examples\" data-toc-modified-id=\"open-ai-tutorial-examples-2.7\"><span class=\"toc-item-num\">2.7&nbsp;&nbsp;</span>open ai tutorial examples</a></span></li><li><span><a href=\"#chatGPTs-code-for-illustrate\" data-toc-modified-id=\"chatGPTs-code-for-illustrate-2.8\"><span class=\"toc-item-num\">2.8&nbsp;&nbsp;</span>chatGPTs code for illustrate</a></span></li></ul></li></ul></div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Usage"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Sure, you can do many things in English now with our new AI superpowers, but still, to be able to really reuse and compose your best prompts, you had better parametrize them -- that is, distill them down to the minimal necessary interface. The function."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## A collection of prompt functions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['user_story_to_code_for_dag',\n",
       " 'make_synopsis',\n",
       " 'description_to_software_specs',\n",
       " 'define_jargon',\n",
       " 'simple_tests_for_code',\n",
       " 'suggest_names',\n",
       " 'specs_to_code_for_dag']"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from oa.ask import ai\n",
    "\n",
    "list(ai)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "These are the names of functions automatically generated from a (for now small) folder of prompt templates. \n",
    "\n",
    "These functions all have propert signatures:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(thing, *, n='30', min_length='1', max_length='15')\n"
     ]
    }
   ],
   "source": [
    "import inspect\n",
    "print(inspect.signature(ai.suggest_names))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "ename": "APIRemovedInV1",
     "evalue": "\n\nYou tried to access openai.ChatCompletion, but this is no longer supported in openai>=1.0.0 - see the README at https://github.com/openai/openai-python for the API.\n\nYou can run `openai migrate` to automatically upgrade your codebase to use the 1.0.0 interface. \n\nAlternatively, you can pin your installation to the old version, e.g. `pip install openai==0.28`\n\nA detailed migration guide is available here: https://github.com/openai/openai-python/discussions/742\n",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mAPIRemovedInV1\u001b[0m                            Traceback (most recent call last)",
      "Cell \u001b[0;32mIn[5], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m answer \u001b[38;5;241m=\u001b[39m \u001b[43mai\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msuggest_names\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m      2\u001b[0m \u001b[43m    \u001b[49m\u001b[43mthing\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\"\"\u001b[39;49m\n\u001b[1;32m      3\u001b[0m \u001b[38;5;124;43m    A python package that provides propert python functions to do things,\u001b[39;49m\n\u001b[1;32m      4\u001b[0m \u001b[38;5;124;43m    enabled by prompts sent to an OpenAI engine.\u001b[39;49m\n\u001b[1;32m      5\u001b[0m \u001b[38;5;124;43m    \u001b[39;49m\u001b[38;5;124;43m\"\"\"\u001b[39;49m\n\u001b[1;32m      6\u001b[0m \u001b[43m)\u001b[49m\n\u001b[1;32m      7\u001b[0m \u001b[38;5;28mprint\u001b[39m(answer)\n",
      "File \u001b[0;32m~/Dropbox/py/proj/t/oa/oa/tools.py:130\u001b[0m, in \u001b[0;36mprompt_function.<locals>.ask_oa\u001b[0;34m(*ask_oa_args, **ask_oa_kwargs)\u001b[0m\n\u001b[1;32m    124\u001b[0m embodied_template \u001b[38;5;241m=\u001b[39m template_embodier(\u001b[38;5;241m*\u001b[39m__args, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39m__kwargs)\n\u001b[1;32m    125\u001b[0m \u001b[38;5;66;03m# embodied_template = _call_forgivingly(\u001b[39;00m\n\u001b[1;32m    126\u001b[0m \u001b[38;5;66;03m#     template_embodier, args, kwargs #, enforce_sig=sig\u001b[39;00m\n\u001b[1;32m    127\u001b[0m \u001b[38;5;66;03m# )\u001b[39;00m\n\u001b[1;32m    128\u001b[0m \u001b[38;5;66;03m# embodied_template = call_forgivingly(template_embodier, *args, **kwargs)\u001b[39;00m\n\u001b[0;32m--> 130\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m egress(\u001b[43mprompt_func\u001b[49m\u001b[43m(\u001b[49m\u001b[43membodied_template\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mprompt_func_kwargs\u001b[49m\u001b[43m)\u001b[49m)\n",
      "File \u001b[0;32m~/Dropbox/py/proj/t/oa/oa/base.py:54\u001b[0m, in \u001b[0;36mchat\u001b[0;34m(prompt, model, messages, **chat_params)\u001b[0m\n\u001b[1;32m     53\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mchat\u001b[39m(prompt\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m, model\u001b[38;5;241m=\u001b[39mDFLT_MODEL, \u001b[38;5;241m*\u001b[39m, messages\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mchat_params):\n\u001b[0;32m---> 54\u001b[0m     resp \u001b[38;5;241m=\u001b[39m \u001b[43m_raw_chat\u001b[49m\u001b[43m(\u001b[49m\u001b[43mprompt\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mprompt\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmodel\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmodel\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmessages\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmessages\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mchat_params\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m     55\u001b[0m     \u001b[38;5;66;03m# TODO: Make attr and item getters more robust (use glom?)\u001b[39;00m\n\u001b[1;32m     56\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m resp[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mchoices\u001b[39m\u001b[38;5;124m'\u001b[39m][\u001b[38;5;241m0\u001b[39m]\u001b[38;5;241m.\u001b[39mmessage\u001b[38;5;241m.\u001b[39mcontent\n",
      "File \u001b[0;32m~/Dropbox/py/proj/t/oa/oa/base.py:45\u001b[0m, in \u001b[0;36m_raw_chat\u001b[0;34m(prompt, model, messages, **chat_params)\u001b[0m\n\u001b[1;32m     43\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m prompt \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m     44\u001b[0m     messages \u001b[38;5;241m=\u001b[39m [{\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mrole\u001b[39m\u001b[38;5;124m'\u001b[39m: \u001b[38;5;124m'\u001b[39m\u001b[38;5;124muser\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mcontent\u001b[39m\u001b[38;5;124m'\u001b[39m: prompt}]\n\u001b[0;32m---> 45\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mopenai\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mChatCompletion\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcreate\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmessages\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmessages\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmodel\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmodel\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mchat_params\u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[0;32m~/.pyenv/versions/3.10.13/envs/p10/lib/python3.10/site-packages/openai/lib/_old_api.py:39\u001b[0m, in \u001b[0;36mAPIRemovedInV1Proxy.__call__\u001b[0;34m(self, *_args, **_kwargs)\u001b[0m\n\u001b[1;32m     38\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__call__\u001b[39m(\u001b[38;5;28mself\u001b[39m, \u001b[38;5;241m*\u001b[39m_args: Any, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39m_kwargs: Any) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Any:\n\u001b[0;32m---> 39\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m APIRemovedInV1(symbol\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_symbol)\n",
      "\u001b[0;31mAPIRemovedInV1\u001b[0m: \n\nYou tried to access openai.ChatCompletion, but this is no longer supported in openai>=1.0.0 - see the README at https://github.com/openai/openai-python for the API.\n\nYou can run `openai migrate` to automatically upgrade your codebase to use the 1.0.0 interface. \n\nAlternatively, you can pin your installation to the old version, e.g. `pip install openai==0.28`\n\nA detailed migration guide is available here: https://github.com/openai/openai-python/discussions/742\n"
     ]
    }
   ],
   "source": [
    "answer = ai.suggest_names(\n",
    "    thing=\"\"\"\n",
    "    A python package that provides propert python functions to do things,\n",
    "    enabled by prompts sent to an OpenAI engine.\n",
    "    \"\"\"\n",
    ")\n",
    "print(answer)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### PromptFuncs"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Above, all we did was scan some local text files that specify prompt templates and make an object that contained the functions they define. We used `oa.PromptFuncs` for that. You can do the same. What `PromptFuncs` uses itself, is a convenient `oa.prompt_function` function that transforms a template into a function. See more details in the next \"Functionalizing prompts\" section."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's just scratch the surface of what `PromptFuncs` can do. For more, you can look at the documentation, including the docs for `ai.prompt_function`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['haiku', 'stylize']"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from oa import PromptFuncs\n",
    "\n",
    "funcs = PromptFuncs(\n",
    "    template_store = {\n",
    "        \"haiku\": \"Write haiku about {subject}. Only output the haiku.\",\n",
    "        \"stylize\": \"\"\"\n",
    "            Reword what I_SAY, using the style: {style:funny}.\n",
    "            Only output the reworded text.\n",
    "            I_SAY:\n",
    "            {something}\n",
    "        \"\"\",\n",
    "    }\n",
    ")\n",
    "\n",
    "list(funcs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "haiku: (*, subject)\n",
      "stylize: (*, something, style='funny')\n"
     ]
    }
   ],
   "source": [
    "import inspect\n",
    "for name in funcs:\n",
    "    print(f\"{name}: {inspect.signature(funcs[name])}\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Code speaks a language,\n",
      "Elegant syntax dances,\n",
      "Beauty in function.\n"
     ]
    }
   ],
   "source": [
    "print(funcs.haiku(subject=\"The potential elegance of code\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Spaghetti code, the tangled web of chaos!\n"
     ]
    }
   ],
   "source": [
    "print(funcs.stylize(something=\"The mess that is spagetti code!\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The tangled strands of code, a chaotic tapestry!\n"
     ]
    }
   ],
   "source": [
    "print(funcs.stylize(something=\"The mess that is spagetti code!\", style=\"poetic\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We used a `dict` to express our `func_name:template` specification, but note that it can be any `Mapping`. Therefore, you can source `PromptFuncs` with local files (example, using `dol.TextFiles`, like we did), a DB, or anything you can map to a key-value `Mapping` interface.\n",
    "\n",
    "(We suggest you use the [dol](https://pypi.org/project/dol/) package, and ecosystem, to help out with that.)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Functionalizing prompts"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `oa.prompt_function` is an easy to use, yet extremely configurable, tool to do that."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "from oa.tools import prompt_function\n",
    "\n",
    "template = \"\"\"\n",
    "I'd like you to give me help me understand domain-specific jargon. \n",
    "I will give you a CONTEXT and some WORDS. \n",
    "You will then provide me with a tab separated table (with columns name and definition)\n",
    "that gives me a short definition of each word in the context of the context.\n",
    "Only output the table, with no words before or after it, since I will be parsing the output\n",
    "automatically.\n",
    "\n",
    "CONTEXT:\n",
    "{context}\n",
    "\n",
    "WORDS:\n",
    "{words}\n",
    "\"\"\"\n",
    "\n",
    "define_jargon = prompt_function(template, defaults=dict(context='machine learning'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(*, words, context='machine learning')\n"
     ]
    }
   ],
   "source": [
    "# Let's look at the signature\n",
    "import inspect\n",
    "print(inspect.signature(define_jargon))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "name\tdefinition\n",
      "supervised learning\tA type of machine learning where an algorithm learns from labeled training data to make predictions or take actions. The algorithm is provided with input-output pairs and uses them to learn patterns and make accurate predictions on new, unseen data.\n",
      "unsupervised learning\tA type of machine learning where an algorithm learns patterns and structures in input data without any labeled output. The algorithm identifies hidden patterns and relationships in the data to gain insights and make predictions or classifications based on the discovered patterns.\n",
      "reinforcement learning\tA type of machine learning where an algorithm learns to make a sequence of decisions in an environment to maximize a cumulative reward. The algorithm interacts with the environment, receives feedback in the form of rewards or punishments, and adjusts its actions to achieve the highest possible reward over time.\n"
     ]
    }
   ],
   "source": [
    "response = define_jargon(words='supervised learning\\tunsupervised learning\\treinforcement learning')\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'allomorph': 'A variant form of a morpheme that is used in a specific linguistic context, often resulting in different phonetic realizations.',\n",
       " 'phonology': 'The study of speech sounds and their patterns, including the way sounds are organized and used in a particular language or languages.',\n",
       " 'phonotactic constraints': 'The rules or restrictions that govern the possible combinations of sounds within a language, specifying what sound sequences are allowed and which ones are not.'}"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def table_str_to_dict(table_str, *, newline='\\n', sep='   '):\n",
    "    return dict([x.split('   ') for x in table_str.split('\\n')[1:]])\n",
    "\n",
    "table_str_to_dict(define_jargon(\n",
    "    words='\\n'.join(['allomorph', 'phonology', 'phonotactic constraints']),\n",
    "    context='linguistics'\n",
    "))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Check out the many ways you can configure your function with `prompt_function`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['(template',\n",
       " '*',\n",
       " 'defaults: Optional[dict] = None',\n",
       " 'template_to_names=<function _extract_names_from_format_string at 0x106d20940>',\n",
       " 'embodier=<function string_format_embodier at 0x106d204c0>',\n",
       " 'name=None',\n",
       " 'prompt_func=<function chat at 0x128420af0>',\n",
       " 'prompt_func_kwargs=None',\n",
       " 'egress=None)']"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "str(inspect.signature(prompt_function)).split(', ')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Just-do-it: A minimal-boilerplate facade to OpenAI stuff"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For the typical tasks you might want to use OpenAI for.\n",
    "\n",
    "Note there's no \"enter API KEY here\" code. That's because if you don't have it in the place(s) it'll look for it, it will simply ask you for it, and, with your permission, put it in a hidden file for you, so you don't have to do this every time.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T23:16:14.998070Z",
     "start_time": "2023-04-22T23:16:07.779598Z"
    }
   },
   "outputs": [],
   "source": [
    "import oa"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T23:17:55.674679Z",
     "start_time": "2023-04-22T23:17:54.837861Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " chatbot based on OpenAI's GPT-2, a natural language processing\n"
     ]
    }
   ],
   "source": [
    "print(oa.complete('chatGPT is a'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T20:50:01.700665Z",
     "start_time": "2023-04-22T20:49:45.629198Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sure, here are 5 useful prompt templates that can be used in a chatGPT session:\n",
      "\n",
      "1. Can you provide some more details about [topic]?\n",
      "- Examples: Can you provide some more details about the symptoms you're experiencing? Or Can you provide some more details about the issue you're facing with the website?\n",
      "\n",
      "2. How long have you been experiencing [issue]?\n",
      "- Examples: How long have you been experiencing the trouble with your internet connection? Or How long have you been experiencing the pain in your back?\n",
      "\n",
      "3. Have you tried any solutions to resolve [issue]?\n",
      "- Examples: Have you tried any solutions to resolve the error message you're seeing? Or Have you tried any solutions to resolve the trouble you're having with the application?\n",
      "\n",
      "4. What is the specific error message you are receiving?\n",
      "- Examples: What is the specific error message you are receiving when you try to log in? Or What is the specific error message you are receiving when you try to submit the form?\n",
      "\n",
      "5. Is there anything else you would like to add that might be helpful for me to know?\n",
      "- Examples: Is there anything else you would like to add that might be helpful for me to know about your situation? Or Is there anything else you would like to add that might be helpful for me to know about the product you are using?\n"
     ]
    }
   ],
   "source": [
    "print(oa.chat('Act as a chatGPT expert. List 5 useful prompt templates'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T23:17:11.198196Z",
     "start_time": "2023-04-22T23:17:11.175394Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "https://oaidalleapiprodscus.blob.core.windows.net/private/org-AY3lr3H3xB9yPQ0HGR498f9M/user-7ZNCDYLWzP0GT48V6DCiTFWt/img-cfJwmH528N8yFXX9n7a51LL9.png?st=2023-09-07T04%3A59%3A55Z&se=2023-09-07T06%3A59%3A55Z&sp=r&sv=2021-08-06&sr=b&rscd=inline&rsct=image/png&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2023-09-06T23%3A46%3A13Z&ske=2023-09-07T23%3A46%3A13Z&sks=b&skv=2021-08-06&sig=im4PIhwYf28SHIwn14CxrVrfqS/9Dq2GnVIB2x9UATk%3D\n"
     ]
    }
   ],
   "source": [
    "url = oa.dalle('An image of Davinci, pop art style')\n",
    "print(url)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T23:51:26.000794Z",
     "start_time": "2023-04-22T23:51:25.977214Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<img src=\"https://oaidalleapiprodscus.blob.core.windows.net/private/org-AY3lr3H3xB9yPQ0HGR498f9M/user-7ZNCDYLWzP0GT48V6DCiTFWt/img-cfJwmH528N8yFXX9n7a51LL9.png?st=2023-09-07T04%3A59%3A55Z&se=2023-09-07T06%3A59%3A55Z&sp=r&sv=2021-08-06&sr=b&rscd=inline&rsct=image/png&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2023-09-06T23%3A46%3A13Z&ske=2023-09-07T23%3A46%3A13Z&sks=b&skv=2021-08-06&sig=im4PIhwYf28SHIwn14CxrVrfqS/9Dq2GnVIB2x9UATk%3D\"/>"
      ],
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.display import Image\n",
    "\n",
    "Image(url=url)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Gives us this:\n",
    "\n",
    "<img width=\"609\" alt=\"image\" src=\"https://github.com/thorwhalen/oa/assets/1906276/55bc0106-3d39-4e6f-a126-c11488ba687e\">"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "One thing I learned the hard way is that those urls that Dalle gives you expire (within 24h when writing this).\n",
    "\n",
    "So you may want to make it so when you create an image, you also download it and save it locally. \n",
    "If you're working in a notebook, you also might want to automatically get your image bytes (once their saved) \n",
    "as something you can actually work with (view, edit, etc.), like a `PIL`` object or `IPython.display`` object.\n",
    "\n",
    "In the appendix below, there's a \"A simple way to keep the images you create\" section that will show you how you can do that."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Raw form"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `raw` object is a thin layer on top of the `openai` package, which is itself a thin layer over the web requests. \n",
    "\n",
    "What was unsatisfactory with the `openai` package is (1) finding the right function, (2) the signature of the function once you found it, and (3) the documentation of the function. \n",
    "What raw contains is pointers to the main functionalities (not all available -- yet), with nice signatures and documentation, extracted from the web service openAPI specs themselves. \n",
    "\n",
    "For example, to ask chatGPT something, the openai function is `openai.ChatCompletion.create`, or to get simple completions, the function is `openai.Completion.create` whose help is:\n",
    "\n",
    "```\n",
    "Help on method create in module openai.api_resources.completion:\n",
    "\n",
    "create(*args, **kwargs) method of builtins.type instance\n",
    "    Creates a new completion for the provided prompt and parameters.\n",
    "    \n",
    "    See https://platform.openai.com/docs/api-reference/completions/create for a list\n",
    "    of valid parameters.\n",
    "```\n",
    "\n",
    "Not super helpful. It basically tells you to got read the docs elsewhere. \n",
    "\n",
    "The corresponding `raw` function is `raw.completion`, and it's help is a bit more like what you'd expect in a python function.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T23:07:26.413989Z",
     "start_time": "2023-04-22T23:07:26.407191Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on Wrap in module openai.api_resources.chat_completion:\n",
      "\n",
      "chatcompletion\n",
      "    Creates a new chat completion for the provided messages and parameters.\n",
      "    \n",
      "            See https://platform.openai.com/docs/api-reference/chat-completions/create\n",
      "            for a list of valid parameters.\n",
      "    \n",
      "    chatcompletion(\n",
      "            model: str\n",
      "            messages: List[oa.openai_specs.Message]\n",
      "            *\n",
      "            temperature: float = 1\n",
      "            top_p: float = 1\n",
      "            n: int = 1\n",
      "            stream: bool = False\n",
      "            stop=None\n",
      "            max_tokens: int = None\n",
      "            presence_penalty: float = 0\n",
      "            frequency_penalty: float = 0\n",
      "            logit_bias: dict = None\n",
      "            user: str = None\n",
      "    )\n",
      "    \n",
      "    :param model: ID of the model to use. Currently, only `gpt-3.5-turbo` and `gpt-3.5-turbo-0301` are supported.\n",
      "    \n",
      "    :param messages: The messages to generate chat completions for, in the [chat format](/docs/guides/chat/introduction).\n",
      "    \n",
      "    :param temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or `top_p` but not both.\n",
      "    \n",
      "    :param top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or `temperature` but not both.\n",
      "    \n",
      "    :param n: How many chat completion choices to generate for each input message.\n",
      "    \n",
      "    :param stream: If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) as they become available, with the stream terminated by a `data: [DONE]` message.\n",
      "    \n",
      "    :param stop: Up to 4 sequences where the API will stop generating further tokens.\n",
      "    \n",
      "    :param max_tokens: The maximum number of tokens allowed for the generated answer. By default, the number of tokens the model can return will be (4096 - prompt tokens).\n",
      "    \n",
      "    :param presence_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics. [See more information about frequency and presence penalties.](/docs/api-reference/parameter-details)\n",
      "    \n",
      "    :param frequency_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim. [See more information about frequency and presence penalties.](/docs/api-reference/parameter-details)\n",
      "    \n",
      "    :param logit_bias: Modify the likelihood of specified tokens appearing in the completion. Accepts a json object that maps tokens (specified by their token ID in the tokenizer) to an associated bias value from -100 to 100. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token.\n",
      "    \n",
      "    :param user: A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids).\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(oa.raw.chatcompletion)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T23:55:24.856024Z",
     "start_time": "2023-04-22T23:55:13.444809Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<OpenAIObject chat.completion id=chatcmpl-78HMPgn3oy2fuvm6sLCgOsQvnTVYr at 0x11fd467a0> JSON: {\n",
       "  \"choices\": [\n",
       "    {\n",
       "      \"finish_reason\": \"stop\",\n",
       "      \"index\": 0,\n",
       "      \"message\": {\n",
       "        \"content\": \"Sure, here are 5 top prompt engineering tricks to write good prompts for chatGPT:\\n\\n1. Be Specific: Ensure that your prompts are specific and clear. The more specific your prompt, the better the response from chatGPT. Avoid using vague or ambiguous language.\\n\\n2. Use Open-Ended Questions: Open-ended questions encourage chatGPT to provide more detailed and personalized responses. Avoid using closed-ended questions that can be answered with a simple yes or no.\\n\\n3. Include Context: Providing context to your prompts helps chatGPT to better understand the topic and provide more relevant responses. Include any necessary background information or details to help guide chatGPT's response.\\n\\n4. Use Emotion: Including emotion in your prompts can help chatGPT generate more engaging and relatable responses. Consider using prompts that evoke emotions such as happiness, sadness, or excitement.\\n\\n5. Test and Refine: Experiment with different prompts and evaluate the responses from chatGPT. Refine your prompts based on the quality of the responses and continue to test and improve over time.\",\n",
       "        \"role\": \"assistant\"\n",
       "      }\n",
       "    }\n",
       "  ],\n",
       "  \"created\": 1682207713,\n",
       "  \"id\": \"chatcmpl-78HMPgn3oy2fuvm6sLCgOsQvnTVYr\",\n",
       "  \"model\": \"gpt-3.5-turbo-0301\",\n",
       "  \"object\": \"chat.completion\",\n",
       "  \"usage\": {\n",
       "    \"completion_tokens\": 214,\n",
       "    \"prompt_tokens\": 36,\n",
       "    \"total_tokens\": 250\n",
       "  }\n",
       "}"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "prompt = 'List 5 top prompt engineering tricks to write good prompts for chatGPT'\n",
    "\n",
    "resp = oa.raw.chatcompletion(\n",
    "    messages=[\n",
    "        {\"role\": \"system\", \"content\": \"You are an expert at chatGPT\"},\n",
    "        {\"role\": \"user\", \"content\": prompt},\n",
    "    ],\n",
    "    model='gpt-3.5-turbo-0301',\n",
    "    temperature=0.5,\n",
    "    max_tokens=300\n",
    ")\n",
    "resp"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T23:55:52.588053Z",
     "start_time": "2023-04-22T23:55:52.563098Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sure, here are 5 top prompt engineering tricks to write good prompts for chatGPT:\n",
      "\n",
      "1. Be Specific: Ensure that your prompts are specific and clear. The more specific your prompt, the better the response from chatGPT. Avoid using vague or ambiguous language.\n",
      "\n",
      "2. Use Open-Ended Questions: Open-ended questions encourage chatGPT to provide more detailed and personalized responses. Avoid using closed-ended questions that can be answered with a simple yes or no.\n",
      "\n",
      "3. Include Context: Providing context to your prompts helps chatGPT to better understand the topic and provide more relevant responses. Include any necessary background information or details to help guide chatGPT's response.\n",
      "\n",
      "4. Use Emotion: Including emotion in your prompts can help chatGPT generate more engaging and relatable responses. Consider using prompts that evoke emotions such as happiness, sadness, or excitement.\n",
      "\n",
      "5. Test and Refine: Experiment with different prompts and evaluate the responses from chatGPT. Refine your prompts based on the quality of the responses and continue to test and improve over time.\n"
     ]
    }
   ],
   "source": [
    "print(resp['choices'][0]['message']['content'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Appendix"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Peeping in OpenAI types"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "len(pydantic_models)=22\n",
      "len(type_hints)=29\n"
     ]
    }
   ],
   "source": [
    "from i2 import ObjectClassifier\n",
    "import openai.types as oat\n",
    "from oa.oa_types import pydantic_models, type_hints\n",
    "\n",
    "print(f\"{len(pydantic_models)=}\")\n",
    "print(f\"{len(type_hints)=}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'Batch': openai.types.batch.Batch,\n",
       " 'Image': openai.types.image.Image,\n",
       " 'Model': openai.types.model.Model,\n",
       " 'ErrorObject': openai.types.shared.error_object.ErrorObject,\n",
       " 'FunctionDefinition': openai.types.shared.function_definition.FunctionDefinition,\n",
       " 'FunctionParameters': typing.Dict[str, object],\n",
       " 'ResponseFormatText': openai.types.shared.response_format_text.ResponseFormatText,\n",
       " 'ResponseFormatJSONObject': openai.types.shared.response_format_json_object.ResponseFormatJSONObject,\n",
       " 'ResponseFormatJSONSchema': openai.types.shared.response_format_json_schema.ResponseFormatJSONSchema,\n",
       " 'Upload': openai.types.upload.Upload,\n",
       " 'Embedding': openai.types.embedding.Embedding,\n",
       " 'ChatModel': typing.Literal['gpt-4o', 'gpt-4o-2024-05-13', 'gpt-4o-2024-08-06', 'gpt-4o-mini', 'gpt-4o-mini-2024-07-18', 'gpt-4-turbo', 'gpt-4-turbo-2024-04-09', 'gpt-4-0125-preview', 'gpt-4-turbo-preview', 'gpt-4-1106-preview', 'gpt-4-vision-preview', 'gpt-4', 'gpt-4-0314', 'gpt-4-0613', 'gpt-4-32k', 'gpt-4-32k-0314', 'gpt-4-32k-0613', 'gpt-3.5-turbo', 'gpt-3.5-turbo-16k', 'gpt-3.5-turbo-0301', 'gpt-3.5-turbo-0613', 'gpt-3.5-turbo-1106', 'gpt-3.5-turbo-0125', 'gpt-3.5-turbo-16k-0613'],\n",
       " 'Completion': openai.types.completion.Completion,\n",
       " 'Moderation': openai.types.moderation.Moderation,\n",
       " 'AudioModel': typing.Literal['whisper-1'],\n",
       " 'BatchError': openai.types.batch_error.BatchError,\n",
       " 'FileObject': openai.types.file_object.FileObject,\n",
       " 'ImageModel': typing.Literal['dall-e-2', 'dall-e-3'],\n",
       " 'FileDeleted': openai.types.file_deleted.FileDeleted,\n",
       " 'FilePurpose': typing.Literal['assistants', 'batch', 'fine-tune', 'vision'],\n",
       " 'ModelDeleted': openai.types.model_deleted.ModelDeleted,\n",
       " 'ImagesResponse': openai.types.images_response.ImagesResponse,\n",
       " 'CompletionUsage': openai.types.completion_usage.CompletionUsage,\n",
       " 'ModerationModel': typing.Literal['text-moderation-latest', 'text-moderation-stable'],\n",
       " 'CompletionChoice': openai.types.completion_choice.CompletionChoice,\n",
       " 'BatchRequestCounts': openai.types.batch_request_counts.BatchRequestCounts,\n",
       " 'CompletionCreateParams': typing.Union[openai.types.completion_create_params.CompletionCreateParamsNonStreaming, openai.types.completion_create_params.CompletionCreateParamsStreaming],\n",
       " 'CreateEmbeddingResponse': openai.types.create_embedding_response.CreateEmbeddingResponse,\n",
       " 'ModerationCreateResponse': openai.types.moderation_create_response.ModerationCreateResponse}"
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type_hints"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'Batch': openai.types.batch.Batch,\n",
       " 'Image': openai.types.image.Image,\n",
       " 'Model': openai.types.model.Model,\n",
       " 'ErrorObject': openai.types.shared.error_object.ErrorObject,\n",
       " 'FunctionDefinition': openai.types.shared.function_definition.FunctionDefinition,\n",
       " 'ResponseFormatText': openai.types.shared.response_format_text.ResponseFormatText,\n",
       " 'ResponseFormatJSONObject': openai.types.shared.response_format_json_object.ResponseFormatJSONObject,\n",
       " 'ResponseFormatJSONSchema': openai.types.shared.response_format_json_schema.ResponseFormatJSONSchema,\n",
       " 'Upload': openai.types.upload.Upload,\n",
       " 'Embedding': openai.types.embedding.Embedding,\n",
       " 'Completion': openai.types.completion.Completion,\n",
       " 'Moderation': openai.types.moderation.Moderation,\n",
       " 'BatchError': openai.types.batch_error.BatchError,\n",
       " 'FileObject': openai.types.file_object.FileObject,\n",
       " 'FileDeleted': openai.types.file_deleted.FileDeleted,\n",
       " 'ModelDeleted': openai.types.model_deleted.ModelDeleted,\n",
       " 'ImagesResponse': openai.types.images_response.ImagesResponse,\n",
       " 'CompletionUsage': openai.types.completion_usage.CompletionUsage,\n",
       " 'CompletionChoice': openai.types.completion_choice.CompletionChoice,\n",
       " 'BatchRequestCounts': openai.types.batch_request_counts.BatchRequestCounts,\n",
       " 'CreateEmbeddingResponse': openai.types.create_embedding_response.CreateEmbeddingResponse,\n",
       " 'ModerationCreateResponse': openai.types.moderation_create_response.ModerationCreateResponse}"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pydantic_models"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 154148 characters]",
      "text/plain": [
       "<Figure size 468.852x1300 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from oa.oa_types import heatmap_of_models_and_their_fields\n",
    "\n",
    "heatmap_of_models_and_their_fields()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[openai.types.embedding.Embedding]"
      ]
     },
     "execution_count": 71,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(filter(lambda m: set(m.model_fields).issuperset(['object', 'index']), pydantic_models.values()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 9.0.0 (20230911.1827)\n",
       " -->\n",
       "<!-- Pages: 1 -->\n",
       "<svg width=\"1391pt\" height=\"116pt\"\n",
       " viewBox=\"0.00 0.00 1390.75 116.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 112)\">\n",
       "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-112 1386.75,-112 1386.75,4 -4,4\"/>\n",
       "<!-- Embedding -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>Embedding</title>\n",
       "<polygon fill=\"none\" stroke=\"black\" points=\"247.32,-108 168.32,-108 168.32,-72 247.32,-72 247.32,-108\"/>\n",
       "<text text-anchor=\"middle\" x=\"207.82\" y=\"-84.95\" font-family=\"Times,serif\" font-size=\"14.00\">Embedding</text>\n",
       "</g>\n",
       "<!-- embedding -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>embedding</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"71.82\" cy=\"-18\" rx=\"71.82\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"71.82\" y=\"-12.95\" font-family=\"Times,serif\" font-size=\"14.00\">embedding: List</text>\n",
       "</g>\n",
       "<!-- Embedding&#45;&gt;embedding -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>Embedding&#45;&gt;embedding</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M173.86,-71.52C155.18,-61.91 131.9,-49.92 112.29,-39.83\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"113.96,-36.75 103.46,-35.28 110.75,-42.97 113.96,-36.75\"/>\n",
       "</g>\n",
       "<!-- index -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>index</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"207.82\" cy=\"-18\" rx=\"46.23\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"207.82\" y=\"-12.95\" font-family=\"Times,serif\" font-size=\"14.00\">index: int</text>\n",
       "</g>\n",
       "<!-- Embedding&#45;&gt;index -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>Embedding&#45;&gt;index</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M207.82,-71.7C207.82,-64.41 207.82,-55.73 207.82,-47.54\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"211.32,-47.62 207.82,-37.62 204.32,-47.62 211.32,-47.62\"/>\n",
       "</g>\n",
       "<!-- object -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>object</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"334.82\" cy=\"-18\" rx=\"63.12\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"334.82\" y=\"-12.95\" font-family=\"Times,serif\" font-size=\"14.00\">object: Literal</text>\n",
       "</g>\n",
       "<!-- Embedding&#45;&gt;object -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>Embedding&#45;&gt;object</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M239.54,-71.52C256.94,-61.93 278.63,-49.97 296.92,-39.89\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"298.57,-42.98 305.63,-35.09 295.19,-36.85 298.57,-42.98\"/>\n",
       "</g>\n",
       "<!-- FileObject -->\n",
       "<g id=\"node5\" class=\"node\">\n",
       "<title>FileObject</title>\n",
       "<polygon fill=\"none\" stroke=\"black\" points=\"778.32,-108 705.32,-108 705.32,-72 778.32,-72 778.32,-108\"/>\n",
       "<text text-anchor=\"middle\" x=\"741.82\" y=\"-84.95\" font-family=\"Times,serif\" font-size=\"14.00\">FileObject</text>\n",
       "</g>\n",
       "<!-- FileObject&#45;&gt;object -->\n",
       "<g id=\"edge8\" class=\"edge\">\n",
       "<title>FileObject&#45;&gt;object</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M705.1,-84.05C643.44,-75.54 515.29,-57.01 407.82,-36 402.88,-35.03 397.76,-33.97 392.63,-32.86\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"393.45,-29.46 382.93,-30.71 391.93,-36.29 393.45,-29.46\"/>\n",
       "</g>\n",
       "<!-- id -->\n",
       "<g id=\"node6\" class=\"node\">\n",
       "<title>id</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"448.82\" cy=\"-18\" rx=\"32.41\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"448.82\" y=\"-12.95\" font-family=\"Times,serif\" font-size=\"14.00\">id: str</text>\n",
       "</g>\n",
       "<!-- FileObject&#45;&gt;id -->\n",
       "<g id=\"edge4\" class=\"edge\">\n",
       "<title>FileObject&#45;&gt;id</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M705.15,-83.35C655.8,-75.26 565.58,-58.83 490.82,-36 488.74,-35.36 486.61,-34.66 484.47,-33.92\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"485.89,-30.72 475.3,-30.51 483.45,-37.28 485.89,-30.72\"/>\n",
       "</g>\n",
       "<!-- bytes -->\n",
       "<g id=\"node7\" class=\"node\">\n",
       "<title>bytes</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"544.82\" cy=\"-18\" rx=\"45.21\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"544.82\" y=\"-12.95\" font-family=\"Times,serif\" font-size=\"14.00\">bytes: int</text>\n",
       "</g>\n",
       "<!-- FileObject&#45;&gt;bytes -->\n",
       "<g id=\"edge5\" class=\"edge\">\n",
       "<title>FileObject&#45;&gt;bytes</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M705.23,-76C672.05,-64.21 623.12,-46.82 588.03,-34.35\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"589.64,-31.21 579.05,-31.16 587.3,-37.81 589.64,-31.21\"/>\n",
       "</g>\n",
       "<!-- created_at -->\n",
       "<g id=\"node8\" class=\"node\">\n",
       "<title>created_at</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"671.82\" cy=\"-18\" rx=\"63.63\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"671.82\" y=\"-12.95\" font-family=\"Times,serif\" font-size=\"14.00\">created_at: int</text>\n",
       "</g>\n",
       "<!-- FileObject&#45;&gt;created_at -->\n",
       "<g id=\"edge6\" class=\"edge\">\n",
       "<title>FileObject&#45;&gt;created_at</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M724.52,-71.7C716.09,-63.27 705.8,-52.97 696.56,-43.73\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"699.06,-41.29 689.52,-36.69 694.11,-46.24 699.06,-41.29\"/>\n",
       "</g>\n",
       "<!-- filename -->\n",
       "<g id=\"node9\" class=\"node\">\n",
       "<title>filename</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"811.82\" cy=\"-18\" rx=\"58\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"811.82\" y=\"-12.95\" font-family=\"Times,serif\" font-size=\"14.00\">filename: str</text>\n",
       "</g>\n",
       "<!-- FileObject&#45;&gt;filename -->\n",
       "<g id=\"edge7\" class=\"edge\">\n",
       "<title>FileObject&#45;&gt;filename</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M759.13,-71.7C767.56,-63.27 777.85,-52.97 787.09,-43.73\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"789.53,-46.24 794.13,-36.69 784.59,-41.29 789.53,-46.24\"/>\n",
       "</g>\n",
       "<!-- purpose -->\n",
       "<g id=\"node10\" class=\"node\">\n",
       "<title>purpose</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"957.82\" cy=\"-18\" rx=\"69.78\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"957.82\" y=\"-12.95\" font-family=\"Times,serif\" font-size=\"14.00\">purpose: Literal</text>\n",
       "</g>\n",
       "<!-- FileObject&#45;&gt;purpose -->\n",
       "<g id=\"edge9\" class=\"edge\">\n",
       "<title>FileObject&#45;&gt;purpose</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M778.47,-77.13C813.05,-65.92 865.3,-48.99 904.5,-36.28\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"905.56,-39.62 914,-33.2 903.41,-32.96 905.56,-39.62\"/>\n",
       "</g>\n",
       "<!-- status -->\n",
       "<g id=\"node11\" class=\"node\">\n",
       "<title>status</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"1106.82\" cy=\"-18\" rx=\"61.59\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"1106.82\" y=\"-12.95\" font-family=\"Times,serif\" font-size=\"14.00\">status: Literal</text>\n",
       "</g>\n",
       "<!-- FileObject&#45;&gt;status -->\n",
       "<g id=\"edge10\" class=\"edge\">\n",
       "<title>FileObject&#45;&gt;status</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M778.76,-83.1C834.75,-73.99 944.42,-55.5 1036.82,-36 1041.17,-35.08 1045.66,-34.09 1050.17,-33.07\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"1050.93,-36.48 1059.88,-30.81 1049.35,-29.66 1050.93,-36.48\"/>\n",
       "</g>\n",
       "<!-- status_details -->\n",
       "<g id=\"node12\" class=\"node\">\n",
       "<title>status_details</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"1284.82\" cy=\"-18\" rx=\"97.93\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"1284.82\" y=\"-12.95\" font-family=\"Times,serif\" font-size=\"14.00\">status_details: Optional</text>\n",
       "</g>\n",
       "<!-- FileObject&#45;&gt;status_details -->\n",
       "<g id=\"edge11\" class=\"edge\">\n",
       "<title>FileObject&#45;&gt;status_details</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M778.63,-84.99C853.77,-76.69 1030.2,-56.69 1177.82,-36 1185.76,-34.89 1194.03,-33.67 1202.28,-32.42\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"1202.66,-35.91 1212.01,-30.93 1201.6,-28.99 1202.66,-35.91\"/>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<graphviz.graphs.Digraph at 0x10f253580>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from ju import model_digraph\n",
    "\n",
    "model_digraph(map(pydantic_models.get, ['Embedding', 'FileObject']))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'embedding': FieldInfo(annotation=List[float], required=True),\n",
       " 'index': FieldInfo(annotation=int, required=True),\n",
       " 'object': FieldInfo(annotation=Literal['embedding'], required=True)}"
      ]
     },
     "execution_count": 72,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "m = pydantic_models['Embedding']\n",
    "m.model_fields"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## When OpenAI screws you up by changing a bunch of stuff"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "openai.base_url -> openai.base_url\n",
      "openai.proxies -> openai.proxies\n",
      "openai.BadRequestError -> openai.BadRequestError\n",
      "openai.audio.transcriptions.create() -> client.audio.transcriptions.create()\n",
      "openai.images.generate() -> client.images.generate()\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# Copied from the \"All name changes\"\n",
    "# section of https://github.com/openai/openai-python/discussions/742\n",
    "\n",
    "t = \"\"\"\n",
    "openai.api_base -> openai.base_url\n",
    "openai.proxy -> openai.proxies\n",
    "openai.InvalidRequestError -> openai.BadRequestError\n",
    "openai.Audio.transcribe() -> client.audio.transcriptions.create()\n",
    "openai.Audio.translate() -> client.audio.translations.create()\n",
    "openai.ChatCompletion.create() -> client.chat.completions.create()\n",
    "openai.Completion.create() -> client.completions.create()\n",
    "openai.Edit.create() -> client.edits.create()\n",
    "openai.Embedding.create() -> client.embeddings.create()\n",
    "openai.File.create() -> client.files.create()\n",
    "openai.File.list() -> client.files.list()\n",
    "openai.File.retrieve() -> client.files.retrieve()\n",
    "openai.File.download() -> client.files.retrieve_content()\n",
    "openai.FineTune.cancel() -> client.fine_tunes.cancel()\n",
    "openai.FineTune.list() -> client.fine_tunes.list()\n",
    "openai.FineTune.list_events() -> client.fine_tunes.list_events()\n",
    "openai.FineTune.stream_events() -> client.fine_tunes.list_events(stream=True)\n",
    "openai.FineTune.retrieve() -> client.fine_tunes.retrieve()\n",
    "openai.FineTune.delete() -> client.fine_tunes.delete()\n",
    "openai.FineTune.create() -> client.fine_tunes.create()\n",
    "openai.FineTuningJob.create() -> client.fine_tuning.jobs.create()\n",
    "openai.FineTuningJob.cancel() -> client.fine_tuning.jobs.cancel()\n",
    "openai.FineTuningJob.delete() -> client.fine_tuning.jobs.create()\n",
    "openai.FineTuningJob.retrieve() -> client.fine_tuning.jobs.retrieve()\n",
    "openai.FineTuningJob.list() -> client.fine_tuning.jobs.list()\n",
    "openai.FineTuningJob.list_events() -> client.fine_tuning.jobs.list_events()\n",
    "openai.Image.create() -> client.images.generate()\n",
    "openai.Image.create_variation() -> client.images.create_variation()\n",
    "openai.Image.create_edit() -> client.images.edit()\n",
    "openai.Model.list() -> client.models.list()\n",
    "openai.Model.delete() -> client.models.delete()\n",
    "openai.Model.retrieve() -> client.models.retrieve()\n",
    "openai.Moderation.create() -> client.moderations.create()\n",
    "openai.api_resources -> openai.resources\n",
    "\"\"\"\n",
    "\n",
    "def extract_mapping(with_dot=True, with_single_paren=True):\n",
    "    \"\"\"Makes a dict from the text above where each line like\n",
    "\n",
    "    openai.FineTune.cancel() -> client.fine_tunes.cancel()\n",
    "\n",
    "    produces a (key, value) item such as:\n",
    "\n",
    "    ('.FineTune.cancel', .fine_tunes.cancel)\n",
    "\n",
    "    \"\"\"\n",
    "\n",
    "    import re \n",
    "\n",
    "    def paren_handling(s):\n",
    "        if s.endswith(')'):\n",
    "            if with_single_paren:\n",
    "                return s[:s.index('(')] + '('\n",
    "            else:\n",
    "                return s[:s.index('(')]\n",
    "        return s\n",
    "    \n",
    "    replacement_pattern = re.compile(r'\\w+\\.([\\w\\.]+).* -> \\w+.([\\w\\.]+).*')\n",
    "\n",
    "    lines = t.split('\\n')\n",
    "    mapping = {}\n",
    "    for line in lines:\n",
    "        if line:\n",
    "            m = replacement_pattern.match(line)\n",
    "            if m:\n",
    "                k, v = m.groups()\n",
    "                if with_dot:\n",
    "                    k = '.' + k\n",
    "                    v = '.' + v\n",
    "                k, v = map(paren_handling, (k, v))\n",
    "                mapping[k] = v\n",
    "    return mapping\n",
    "\n",
    "migration_map = extract_mapping()\n",
    "\n",
    "def mapping_replace(replacement_map: dict[str, str], s: str, *, dry_run=True) -> str:\n",
    "    if dry_run:\n",
    "        for original_line in s.splitlines():\n",
    "            new_line = original_line\n",
    "            for k, v in replacement_map.items():\n",
    "                new_line = new_line.replace(k, v)\n",
    "            if new_line != original_line:\n",
    "                print(f\"Will replace:\\n\\t{original_line}\\nwith\\n\\t{new_line}\\n\")\n",
    "    else:\n",
    "        for k, v in replacement_map.items():\n",
    "            s = s.replace(k, v)\n",
    "    return s\n",
    "\n",
    "# test mapping_replace\n",
    "s = \"\"\"\n",
    "openai.api_base -> openai.base_url\n",
    "openai.proxy -> openai.proxies\n",
    "openai.InvalidRequestError -> openai.BadRequestError\n",
    "openai.Audio.transcribe() -> client.audio.transcriptions.create()\n",
    "openai.Image.create() -> client.images.generate()\n",
    "\"\"\"\n",
    "\n",
    "_ = mapping_replace(migration_map, s, dry_run=False)\n",
    "print(_)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['openai_specs.py',\n",
       " 'util.py',\n",
       " 'ask.py',\n",
       " 'tools.py',\n",
       " '__init__.py',\n",
       " 'scrap/__init__.py',\n",
       " 'examples/illustrate_stories.py',\n",
       " 'examples/__init__.py',\n",
       " 'examples/aesop_fables.py',\n",
       " 'base.py']"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from xdol import PyFilesReader\n",
    "from dol import TextFiles\n",
    "import oa\n",
    "\n",
    "rootdir = oa.__path__[0]\n",
    "s = PyFilesReader(rootdir)\n",
    "target = TextFiles(rootdir)\n",
    "list(s)\n",
    "\n",
    "# for name, content in s.items():\n",
    "#     # print(f'\\n\\n{name}\\n-----------------------\\n')\n",
    "#     target[name] = mapping_replace(migration_map, content, dry_run=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Deprecated models"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "\n",
    "# Couldnl't use requests to get the html, so had to use selenium\n",
    "# Instead, had to download html manually from https://platform.openai.com/docs/deprecation\n",
    "# (or use selenium, which I didn't want to get into)\n",
    "# Like this:\n",
    "# import pandas as pd\n",
    "# from pathlib import Path\n",
    "# filepath = '/Users/thorwhalen/Downloads/Deprecations - OpenAI API.html'\n",
    "# tables = pd.read_html(filepath)\n",
    "# len(tables)\n",
    "\n",
    "\n",
    "url = 'https://platform.openai.com/docs/deprecations'\n",
    "\n",
    "from tabled import get_tables_from_url\n",
    "tables = get_tables_from_url(url, url_to_html='selenium')\n",
    "\n",
    "len(tables)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(48, 8)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "deprecations = pd.concat(tables)\n",
    "deprecations.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Index(['Shutdown date', 'Legacy model', 'Legacy model price',\n",
      "       'Recommended replacement', 'System', 'Model / system', 'Training price',\n",
      "       'Usage price'],\n",
      "      dtype='object')\n"
     ]
    }
   ],
   "source": [
    "print(deprecations.columns)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'gpt-3.5-turbo-0613': 'gpt-3.5-turbo-1106',\n",
       " 'gpt-3.5-turbo-16k-0613': 'gpt-3.5-turbo-1106',\n",
       " nan: 'View transition guide',\n",
       " 'text-ada-001': 'gpt-3.5-turbo-instruct',\n",
       " 'text-babbage-001': 'gpt-3.5-turbo-instruct',\n",
       " 'text-curie-001': 'gpt-3.5-turbo-instruct',\n",
       " 'text-davinci-001': 'gpt-3.5-turbo-instruct',\n",
       " 'text-davinci-002': 'gpt-3.5-turbo-instruct',\n",
       " 'text-davinci-003': 'gpt-3.5-turbo-instruct',\n",
       " 'ada': 'babbage-002',\n",
       " 'babbage': 'babbage-002',\n",
       " 'curie': 'davinci-002',\n",
       " 'davinci': 'davinci-002, gpt-3.5-turbo, gpt-4',\n",
       " 'code-davinci-002': 'gpt-4',\n",
       " 'text-similarity-ada-001': 'text-embedding-ada-002',\n",
       " 'text-search-ada-doc-001': 'text-embedding-ada-002',\n",
       " 'text-search-ada-query-001': 'text-embedding-ada-002',\n",
       " 'code-search-ada-code-001': 'text-embedding-ada-002',\n",
       " 'code-search-ada-text-001': 'text-embedding-ada-002',\n",
       " 'text-similarity-babbage-001': 'text-embedding-ada-002',\n",
       " 'text-search-babbage-doc-001': 'text-embedding-ada-002',\n",
       " 'text-search-babbage-query-001': 'text-embedding-ada-002',\n",
       " 'code-search-babbage-code-001': 'text-embedding-ada-002',\n",
       " 'code-search-babbage-text-001': 'text-embedding-ada-002',\n",
       " 'text-similarity-curie-001': 'text-embedding-ada-002',\n",
       " 'text-search-curie-doc-001': 'text-embedding-ada-002',\n",
       " 'text-search-curie-query-001': 'text-embedding-ada-002',\n",
       " 'text-similarity-davinci-001': 'text-embedding-ada-002',\n",
       " 'text-search-davinci-doc-001': 'text-embedding-ada-002',\n",
       " 'text-search-davinci-query-001': 'text-embedding-ada-002',\n",
       " 'gpt-3.5-turbo-0301': 'gpt-3.5-turbo-0613',\n",
       " 'gpt-4-0314': 'gpt-4-0613',\n",
       " 'gpt-4-32k-0314': 'gpt-4-32k-0613',\n",
       " 'code-davinci-001': 'gpt-4',\n",
       " 'code-cushman-002': 'gpt-4',\n",
       " 'code-cushman-001': 'gpt-4'}"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "replace_with = dict(zip(deprecations['Legacy model'], deprecations['Recommended replacement']))\n",
    "replace_with"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Testing the changes of oa"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['gpt-3.5-turbo-instruct',\n",
       " 'dall-e-3',\n",
       " 'dall-e-2',\n",
       " 'gpt-3.5-turbo-0125',\n",
       " 'text-embedding-ada-002',\n",
       " 'tts-1-hd-1106',\n",
       " 'text-embedding-3-small',\n",
       " 'tts-1-hd',\n",
       " 'gpt-4-0125-preview',\n",
       " 'gpt-4-turbo-preview',\n",
       " 'text-embedding-3-large',\n",
       " 'whisper-1',\n",
       " 'babbage-002',\n",
       " 'davinci-002',\n",
       " 'gpt-3.5-turbo-16k',\n",
       " 'gpt-4-0613',\n",
       " 'gpt-4',\n",
       " 'gpt-4-1106-preview',\n",
       " 'gpt-3.5-turbo',\n",
       " 'gpt-3.5-turbo-16k-0613',\n",
       " 'gpt-3.5-turbo-0613',\n",
       " 'gpt-3.5-turbo-1106',\n",
       " 'gpt-4-vision-preview',\n",
       " 'gpt-3.5-turbo-0301',\n",
       " 'tts-1-1106',\n",
       " 'tts-1',\n",
       " 'gpt-3.5-turbo-instruct-0914']"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import oa.base\n",
    "\n",
    "oa.base.list_engine_ids()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"🦊';\\n//Match 'the' using the RegExp test method\\nconst\""
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "oa.complete('the quick brown')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<img src=\"https://oaidalleapiprodscus.blob.core.windows.net/private/org-AY3lr3H3xB9yPQ0HGR498f9M/user-7ZNCDYLWzP0GT48V6DCiTFWt/img-yiONPSNxLnH9XGy16mhvVPwG.png?st=2024-02-09T12%3A29%3A50Z&se=2024-02-09T14%3A29%3A50Z&sp=r&sv=2021-08-06&sr=b&rscd=inline&rsct=image/png&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2024-02-09T03%3A29%3A46Z&ske=2024-02-10T03%3A29%3A46Z&sks=b&skv=2021-08-06&sig=%2BwSEAPlJvUMZAtcDmm9alVdMzFVjKS73dDLGoigPR9w%3D\"/>"
      ],
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from IPython.display import Image\n",
    "\n",
    "b = oa.dalle('A machine that generates dreams and routes them to peoples minds.')\n",
    "im = Image(url=b)\n",
    "im"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['user_story_to_code_for_dag',\n",
       " 'make_synopsis',\n",
       " 'description_to_software_specs',\n",
       " 'define_jargon',\n",
       " 'simple_tests_for_code',\n",
       " 'suggest_names',\n",
       " 'specs_to_code_for_dag']"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import oa\n",
    "from oa.ask import ai\n",
    "list(ai)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "AppWave\n",
      "IdeaBuilder\n",
      "SnapWeb\n",
      "BrainStorm\n",
      "CodeCraft\n",
      "WebGenius\n",
      "Appify\n",
      "StartSpark\n",
      "CodeMuse\n",
      "IdeaLab\n",
      "AppVibe\n",
      "WebWizard\n",
      "CreativeClick\n",
      "ByteMaker\n",
      "IdeaBlast\n",
      "AppXcel\n",
      "WebWhiz\n",
      "InnoTech\n",
      "CodeGuru\n",
      "IdeaHatch\n",
      "AppSculpt\n",
      "WebVerse\n",
      "MindMesh\n",
      "CodeCrafted\n",
      "IdeaForge\n",
      "AppCreator\n",
      "WebConstruct\n",
      "ThoughtFlow\n",
      "CodeGenie\n",
      "IdeaBox\n"
     ]
    }
   ],
   "source": [
    "print(ai.suggest_names(\n",
    "    'For a project that helps you bring your ideas to life in the form of an app or website'\n",
    "))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## A simple way to keep the images you create"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "One thing I learned the hard way is that those urls that Dalle gives you expire (within 24h when writing this).\n",
    "\n",
    "So you may want to make it so when you create an image, you also download it and save it locally. \n",
    "If you're working in a notebook, you also might want to automatically get your image bytes (once their saved) \n",
    "as something you can actually work with (view, edit, etc.), like a `PIL`` object or `IPython.display`` object.\n",
    "\n",
    "Below shows you some very simple, yet effective ways, you can do that."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "rootdir = '~/dalle_images'  # where to store the dalle images"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "from functools import partial\n",
    "import dol, graze\n",
    "\n",
    "graze_dalle = partial(\n",
    "    graze.graze, \n",
    "    rootdir = rootdir,\n",
    ")\n",
    "\n",
    "create_acquire_show = dol.Pipe(\n",
    "    oa.dalle,  # make the images and returns url\n",
    "    graze_dalle,  # downloads the url contents locally, indexing it with url\n",
    "    Image  # returns a (ipython-)displayable image object\n",
    ")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "This directory doesn't exist: ~/dalle_images\n",
      "Making /Users/thorwhalen/dalle_images...\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 1049852 characters]",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "create_acquire_show(\n",
    "    \"A photo-realistic image of a water fall that splits into two streams that merge back into one\"\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Returns:\n",
    "\n",
    "<img width=\"608\" alt=\"image\" src=\"https://github.com/thorwhalen/oa/assets/1906276/6e7b2ac4-648c-4ec0-81bf-078208f4ac39\">"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "First key: https://oaidalleapiprodscus.blob.core.windows.net/private/org-AY3lr3H3xB9yPQ0HGR498f9M/user-7ZNCDYLWzP0GT48V6DCiTFWt/img-Rocll6MdDMaBsIBTqbiWH33I.png?st=2023-09-07T05%3A42%3A36Z&se=2023-09-07T07%3A42%3A36Z&sp=r&sv=2021-08-06&sr=b&rscd=inline&rsct=image/png&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2023-09-06T23%3A48%3A07Z&ske=2023-09-07T23%3A48%3A07Z&sks=b&skv=2021-08-06&sig=pUExRSZbmPNJUkeKQCz06JYUjDXscvX83J4nlqoTWx0%3D\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 1049852 characters]",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from graze import Graze\n",
    "from dol import wrap_kvs, filt_iter\n",
    "\n",
    "dalle_images = wrap_kvs(\n",
    "    Graze(rootdir),  # a Mapping-interface to your local dalle images, indexed by url\n",
    "    obj_of_data=Image,  # decode bytes with Image to be able to display\n",
    ") \n",
    "\n",
    "# dalle_images is a Mapping, so you can do things like:\n",
    "#    list(dalle_images)\n",
    "#    for k, v in dalle_images.items(): ...\n",
    "#    etc.\n",
    "\n",
    "k = next(iter(dalle_images))  # get first key\n",
    "print(f\"First key: {k}\")\n",
    "dalle_images[k]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Returns:\n",
    "\n",
    "<img width=\"608\" alt=\"image\" src=\"https://github.com/thorwhalen/oa/assets/1906276/6e7b2ac4-648c-4ec0-81bf-078208f4ac39\">"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# oa embeddings"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from oa import embeddings"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "thor = embeddings('thor')\n",
    "loki, hulk = embeddings(['loki', 'bob'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "thor vs loki: 0.5565261188078034\n",
      "thor vs hulk: 0.2710115460636189\n",
      "loki vs hulk: 0.28862247037698663\n",
      "--> Observe here that thor and loki are closer than they are to hulk\n"
     ]
    }
   ],
   "source": [
    "from imbed.util import cosine_similarity\n",
    "\n",
    "print(f\"thor vs loki: {cosine_similarity(thor, loki)}\")\n",
    "print(f\"thor vs hulk: {cosine_similarity(thor, hulk)}\")\n",
    "print(f\"loki vs hulk: {cosine_similarity(loki, hulk)}\")\n",
    "print(f\"--> Observe here that thor and loki are closer than they are to hulk\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Dimensions of vectors: 1536\n"
     ]
    }
   ],
   "source": [
    "print(f\"Dimensions of vectors: {len(thor)}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Scrap"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Extracting pydantic models from json examples"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [],
   "source": [
    "from i2 import Sig\n",
    "from ju.pydantic_util import create_pydantic_model, is_valid_wrt_model, valid_models\n",
    "from lkj import truncate_dict_values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "metadata": {},
   "outputs": [],
   "source": [
    "from lkj import print_progress\n",
    "from dol import path_get\n",
    "\n",
    "from oa.stores import OaDacc\n",
    "\n",
    "dacc = OaDacc()\n",
    "\n",
    "items = iter(dacc.s.json_files.items())\n",
    "k, v = next(items)\n",
    "kk, vv = next(items)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {},
   "outputs": [],
   "source": [
    "M = create_pydantic_model('M', v)\n",
    "MM = create_pydantic_model('MM', v)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 108,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 2]"
      ]
     },
     "execution_count": 108,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "items = iter([1,2,3])\n",
    "import itertools\n",
    "items = itertools.islice(items, 2)\n",
    "list(items)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 116,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "set()"
      ]
     },
     "execution_count": 116,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "valid_models()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 135,
   "metadata": {},
   "outputs": [],
   "source": [
    "from ju import valid_models, truncate_dict_values\n",
    "import re\n",
    "\n",
    "# lambda to replace all \\W with _\n",
    "sanitize = lambda s: re.sub(r'\\W', '_', s)\n",
    "\n",
    "def gather_models(json_store, max_iterations=None):\n",
    "    \"\"\"Gather models infered from the values of a json_store.\n",
    "    \"\"\"\n",
    "    models = set()\n",
    "    model_is_new = lambda v: not next(valid_models(v, models), None)\n",
    "\n",
    "    def mk_new_model(k, reduced_v):\n",
    "        new_model = create_pydantic_model(f\"Model_{sanitize(k)}\", reduced_v)\n",
    "        models.add(new_model)\n",
    "        return {\n",
    "            'model': new_model,\n",
    "            'key_of_example_data': k,\n",
    "            'reduced_example_data': reduced_v\n",
    "        }\n",
    "    \n",
    "    items = iter(json_store.items())\n",
    "    k, v = next(items)\n",
    "    reduced_v = truncate_dict_values(v)\n",
    "    yield mk_new_model(k, v)\n",
    "\n",
    "    for i, (k, v) in enumerate(items, 1):\n",
    "        # print(f\"{i}, {k=}\")\n",
    "        reduced_v = truncate_dict_values(v)\n",
    "        if model_is_new(reduced_v):\n",
    "            yield mk_new_model(k, reduced_v)\n",
    "        if max_iterations and i >= max_iterations:\n",
    "            break\n",
    "\n",
    "            \n",
    "models_info = list(gather_models(dacc.s.json_files, max_iterations=50))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 128,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[__main__.file-g1iSPVYMatQRuCRQAkIGFBUA,\n",
       " __main__.file-d1dB20OYOXmnE3ENznpwvVZd]"
      ]
     },
     "execution_count": 128,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[x['model'] for x in models_info]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 137,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'model': __main__.file-g1iSPVYMatQRuCRQAkIGFBUA,\n",
       "  'key_of_example_data': 'file-g1iSPVYMatQRuCRQAkIGFBUA',\n",
       "  'reduced_example_data': {'id': 'batch_req_0qWxQ4rcAnzo9lEUMZR7xsgo',\n",
       "   'custom_id': 'embeddings_batch_id-1724503217185829120',\n",
       "   'response': {'status_code': 200,\n",
       "    'request_id': 'dacf8a2486eb1d6a7070852bf04d292d',\n",
       "    'body': {'object': 'list',\n",
       "     'data': [{'object': 'embedding',\n",
       "       'index': 0,\n",
       "       'embedding': [0.017829118, -0.0066988687]},\n",
       "      {'object': 'embedding',\n",
       "       'index': 1,\n",
       "       'embedding': [0.0010772116, -0.0015551111]}],\n",
       "     'model': 'text-embedding-3-small',\n",
       "     'usage': {'prompt_tokens': 629349, 'total_tokens': 629349}}},\n",
       "   'error': None}},\n",
       " {'model': __main__.file-d1dB20OYOXmnE3ENznpwvVZd,\n",
       "  'key_of_example_data': 'file-d1dB20OYOXmnE3ENznpwvVZd',\n",
       "  'reduced_example_data': {'custom_id': 'embeddings_batch_id-1724503217185829120',\n",
       "   'method': 'POST',\n",
       "   'url': '/v1/embeddings',\n",
       "   'body': {'input': ['Earning money on Medium is prim...y aiming for high view numbers.',\n",
       "     'How I earn money as a beginner writer '],\n",
       "    'model': 'text-embedding-3-small'}}}]"
      ]
     },
     "execution_count": 137,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "models_info"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 146,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{\n",
      "  \"custom_id\": \"embeddings_batch_id-1724503217185829120\",\n",
      "  \"method\": \"POST\",\n",
      "  \"url\": \"/v1/embeddings\",\n",
      "  \"body\": {\n",
      "    \"input\": [\n",
      "      \"Earning money on Medium is prim...y aiming for high view numbers.\",\n",
      "      \"How I earn money as a beginner writer \"\n",
      "    ],\n",
      "    \"model\": \"text-embedding-3-small\"\n",
      "  }\n",
      "}\n"
     ]
    }
   ],
   "source": [
    "# Here, I print the reduced example data for the various models,\n",
    "# then go to https://jsontopydantic.com/ to generate the pydantic models code\n",
    "# TODO: automate this code gen step with datamodel-code-generator\n",
    "import json\n",
    "\n",
    "idx = 1\n",
    "info_dict = models_info[1]['reduced_example_data']\n",
    "print(json.dumps(info_dict, indent=2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 173,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'$defs': {'Body': {'properties': {'input': {'items': {},\n",
       "     'title': 'Input',\n",
       "     'type': 'array'},\n",
       "    'model': {'title': 'Model', 'type': 'string'}},\n",
       "   'required': ['input', 'model'],\n",
       "   'title': 'Body',\n",
       "   'type': 'object'}},\n",
       " 'properties': {'custom_id': {'title': 'Custom Id', 'type': 'string'},\n",
       "  'method': {'title': 'Method', 'type': 'string'},\n",
       "  'url': {'title': 'Url', 'type': 'string'},\n",
       "  'body': {'$ref': '#/$defs/Body'}},\n",
       " 'required': ['custom_id', 'method', 'url', 'body'],\n",
       " 'title': 'DataBasedModel',\n",
       " 'type': 'object'}"
      ]
     },
     "execution_count": 173,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from ju import data_to_pydantic_model\n",
    "\n",
    "m = data_to_pydantic_model(info_dict)\n",
    "m.model_json_schema()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 174,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "from __future__ import annotations\n",
      "\n",
      "from typing import List\n",
      "\n",
      "from pydantic import BaseModel, Field\n",
      "\n",
      "\n",
      "class Body(BaseModel):\n",
      "    input: List = Field(..., title='Input')\n",
      "    model: str = Field(..., title='Model')\n",
      "\n",
      "\n",
      "class DataBasedModel(BaseModel):\n",
      "    custom_id: str = Field(..., title='Custom Id')\n",
      "    method: str = Field(..., title='Method')\n",
      "    url: str = Field(..., title='Url')\n",
      "    body: Body\n",
      "\n"
     ]
    }
   ],
   "source": [
    "from ju import pydantic_model_to_code\n",
    "\n",
    "print(pydantic_model_to_code(m))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Extract data using models"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 131,
   "metadata": {},
   "outputs": [],
   "source": [
    "from oa.oa_types import BatchRequest, EmbeddingResponse, InputDataJsonL\n",
    "from ju import ModelExtractor\n",
    "from dol import add_ipython_key_completions, Pipe\n",
    "\n",
    "models = [BatchRequest, EmbeddingResponse, InputDataJsonL]\n",
    "\n",
    "extractor = Pipe(ModelExtractor(models), add_ipython_key_completions)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 109,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "FileObject(id='file-g1iSPVYMatQRuCRQAkIGFBUA', bytes=41629954, created_at=1724503295, filename='batch_YY7gAytldnVxPRy3vgnlbsbT_output.jsonl', object='file', purpose='batch_output', status='processed', status_details=None)"
      ]
     },
     "execution_count": 109,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from oa.stores import OaStores\n",
    "\n",
    "s = OaStores()\n",
    "\n",
    "file_id, file_obj = s.files_base.head()\n",
    "\n",
    "file_id\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 110,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'id': 'file-g1iSPVYMatQRuCRQAkIGFBUA',\n",
       " 'bytes': 41629954,\n",
       " 'created_at': 1724503295,\n",
       " 'filename': 'batch_YY7gAytldnVxPRy3vgnlbsbT_output.jsonl',\n",
       " 'object': 'file',\n",
       " 'purpose': 'batch_output',\n",
       " 'status': 'processed',\n",
       " 'status_details': None}"
      ]
     },
     "execution_count": 110,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "file_id.to_dict()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 111,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dict"
      ]
     },
     "execution_count": 111,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "batch_output_json = s.jsonl_files[file_id.id]\n",
    "type(batch_output_json)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 112,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'id': 'batch_req_0qWxQ4rcAnzo9lEUMZR7xsgo',\n",
       " 'custom_id': 'embeddings_batch_id-1724503217185829120',\n",
       " 'response': {'status_code': 200,\n",
       "  'request_id': 'dacf8a2486eb1d6a7070852bf04d292d',\n",
       "  'body': {'object': 'list',\n",
       "   'data': [{'object': 'embedding',\n",
       "     'index': 0,\n",
       "     'embedding': [0.017829118, -0.0066988687]},\n",
       "    {'object': 'embedding',\n",
       "     'index': 1,\n",
       "     'embedding': [0.0010772116, -0.0015551111]}],\n",
       "   'model': 'text-embedding-3-small',\n",
       "   'usage': {'prompt_tokens': 629349, 'total_tokens': 629349}}},\n",
       " 'error': None}"
      ]
     },
     "execution_count": 112,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from lkj import truncate_dict_values\n",
    "\n",
    "truncate_dict_values(batch_output_json)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 132,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['id',\n",
       " 'custom_id',\n",
       " 'response.status_code',\n",
       " 'response.request_id',\n",
       " 'response.body.object',\n",
       " 'response.body.data.*.embedding',\n",
       " 'response.body.data.*.index',\n",
       " 'response.body.data.*.object',\n",
       " 'response.body.model',\n",
       " 'response.body.usage.prompt_tokens',\n",
       " 'response.body.usage.total_tokens',\n",
       " 'error']"
      ]
     },
     "execution_count": 132,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d = extractor(batch_output_json)\n",
    "list(d)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 136,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2000"
      ]
     },
     "execution_count": 136,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "embedding_vectors = d['response.body.data.*.embedding']\n",
    "len(embedding_vectors)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 142,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'id': 'batch_YY7gAytldnVxPRy3vgnlbsbT',\n",
       " 'completion_window': '24h',\n",
       " 'created_at': 1724503218,\n",
       " 'endpoint': '/v1/embeddings',\n",
       " 'input_file_id': 'file-d1dB20OYOXmnE3ENznpwvVZd',\n",
       " 'object': 'batch',\n",
       " 'status': 'completed',\n",
       " 'cancelled_at': None,\n",
       " 'cancelling_at': None,\n",
       " 'completed_at': 1724503296,\n",
       " 'error_file_id': None,\n",
       " 'errors': None,\n",
       " 'expired_at': None,\n",
       " 'expires_at': 1724589618,\n",
       " 'failed_at': None,\n",
       " 'finalizing_at': 1724503293,\n",
       " 'in_progress_at': 1724503219,\n",
       " 'metadata': None,\n",
       " 'output_file_id': 'file-g1iSPVYMatQRuCRQAkIGFBUA',\n",
       " 'request_counts': {'completed': 1, 'failed': 0, 'total': 1}}"
      ]
     },
     "execution_count": 142,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "k, batch_info = s.batches.head()\n",
    "batch_info.to_dict()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 209,
   "metadata": {},
   "outputs": [],
   "source": [
    "from oa.batches import batch_info_to_segments_and_embeddings\n",
    "import itertools \n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 188,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>segment</th>\n",
       "      <th>embedding</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Earning money on Medium is primarily through t...</td>\n",
       "      <td>[0.017829118, -0.0066988687, 0.04802007, 0.016...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>How I earn money as a beginner writer</td>\n",
       "      <td>[0.0010772116, -0.0015551111, 0.021341017, -0....</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Earning money as a beginner writer involves a ...</td>\n",
       "      <td>[0.019905386, 0.00076151197, 0.04861105, -0.00...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>whatsup</td>\n",
       "      <td>[-0.015610543, -0.017024491, -0.01291119, 0.07...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>Hello! I'm here to help answer your questions....</td>\n",
       "      <td>[0.026674468, -0.028525148, 0.03925909, 0.0029...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1995</th>\n",
       "      <td>Community Question in the Evening: Consider qu...</td>\n",
       "      <td>[0.037835263, -0.024473539, 0.03309055, 0.0437...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1996</th>\n",
       "      <td>Certainly! Engaging your community with a ques...</td>\n",
       "      <td>[0.034000326, -0.027244642, 0.0013753305, 0.04...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1997</th>\n",
       "      <td>I'm sorry I didn't include this at first, but,...</td>\n",
       "      <td>[-0.014053465, 0.007084434, -0.04413506, 0.028...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1998</th>\n",
       "      <td>No problem at all! Adjusting the content for a...</td>\n",
       "      <td>[0.008981955, -0.00018679323, -0.0549843, 0.04...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1999</th>\n",
       "      <td>So, let me introduce myself properly. I work f...</td>\n",
       "      <td>[-0.00034956887, -0.0064293817, -0.0019947963,...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>2000 rows × 2 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                                                segment  \\\n",
       "0     Earning money on Medium is primarily through t...   \n",
       "1                How I earn money as a beginner writer    \n",
       "2     Earning money as a beginner writer involves a ...   \n",
       "3                                               whatsup   \n",
       "4     Hello! I'm here to help answer your questions....   \n",
       "...                                                 ...   \n",
       "1995  Community Question in the Evening: Consider qu...   \n",
       "1996  Certainly! Engaging your community with a ques...   \n",
       "1997  I'm sorry I didn't include this at first, but,...   \n",
       "1998  No problem at all! Adjusting the content for a...   \n",
       "1999  So, let me introduce myself properly. I work f...   \n",
       "\n",
       "                                              embedding  \n",
       "0     [0.017829118, -0.0066988687, 0.04802007, 0.016...  \n",
       "1     [0.0010772116, -0.0015551111, 0.021341017, -0....  \n",
       "2     [0.019905386, 0.00076151197, 0.04861105, -0.00...  \n",
       "3     [-0.015610543, -0.017024491, -0.01291119, 0.07...  \n",
       "4     [0.026674468, -0.028525148, 0.03925909, 0.0029...  \n",
       "...                                                 ...  \n",
       "1995  [0.037835263, -0.024473539, 0.03309055, 0.0437...  \n",
       "1996  [0.034000326, -0.027244642, 0.0013753305, 0.04...  \n",
       "1997  [-0.014053465, 0.007084434, -0.04413506, 0.028...  \n",
       "1998  [0.008981955, -0.00018679323, -0.0549843, 0.04...  \n",
       "1999  [-0.00034956887, -0.0064293817, -0.0019947963,...  \n",
       "\n",
       "[2000 rows x 2 columns]"
      ]
     },
     "execution_count": 188,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "\n",
    "df = pd.DataFrame(dict(zip(['segment', 'embedding'], batch_info_to_segments_and_embeddings(s.jsonl_files, batch_info))))\n",
    "df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 197,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>segment</th>\n",
       "      <th>embedding</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Earning money on Medium is primarily through t...</td>\n",
       "      <td>[0.017829118, -0.0066988687, 0.04802007, 0.016...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>How I earn money as a beginner writer</td>\n",
       "      <td>[0.0010772116, -0.0015551111, 0.021341017, -0....</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Earning money as a beginner writer involves a ...</td>\n",
       "      <td>[0.019905386, 0.00076151197, 0.04861105, -0.00...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>whatsup</td>\n",
       "      <td>[-0.015610543, -0.017024491, -0.01291119, 0.07...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>Hello! I'm here to help answer your questions....</td>\n",
       "      <td>[0.026674468, -0.028525148, 0.03925909, 0.0029...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1995</th>\n",
       "      <td>Please write a humorous short story of at leas...</td>\n",
       "      <td>[0.02357671, 0.035022993, -0.03362839, -0.0022...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1996</th>\n",
       "      <td>I'm sorry for the confusion, but preparing a f...</td>\n",
       "      <td>[0.025884645, -0.019934151, -0.041274782, -0.0...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1997</th>\n",
       "      <td>Country - United Kingdom.\\n1. Write title use ...</td>\n",
       "      <td>[0.03417311, 0.042749066, 0.018995227, -0.0182...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1998</th>\n",
       "      <td>1. Title: \"Felling Weather Forecast: Daily Upd...</td>\n",
       "      <td>[0.023398804, 0.041698396, 0.044138342, 0.0093...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1999</th>\n",
       "      <td>Country - United Kingdom.\\n1. Write title use ...</td>\n",
       "      <td>[0.03809252, 0.022067213, 0.0051019085, -0.010...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>444000 rows × 2 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                                                segment  \\\n",
       "0     Earning money on Medium is primarily through t...   \n",
       "1                How I earn money as a beginner writer    \n",
       "2     Earning money as a beginner writer involves a ...   \n",
       "3                                               whatsup   \n",
       "4     Hello! I'm here to help answer your questions....   \n",
       "...                                                 ...   \n",
       "1995  Please write a humorous short story of at leas...   \n",
       "1996  I'm sorry for the confusion, but preparing a f...   \n",
       "1997  Country - United Kingdom.\\n1. Write title use ...   \n",
       "1998  1. Title: \"Felling Weather Forecast: Daily Upd...   \n",
       "1999  Country - United Kingdom.\\n1. Write title use ...   \n",
       "\n",
       "                                              embedding  \n",
       "0     [0.017829118, -0.0066988687, 0.04802007, 0.016...  \n",
       "1     [0.0010772116, -0.0015551111, 0.021341017, -0....  \n",
       "2     [0.019905386, 0.00076151197, 0.04861105, -0.00...  \n",
       "3     [-0.015610543, -0.017024491, -0.01291119, 0.07...  \n",
       "4     [0.026674468, -0.028525148, 0.03925909, 0.0029...  \n",
       "...                                                 ...  \n",
       "1995  [0.02357671, 0.035022993, -0.03362839, -0.0022...  \n",
       "1996  [0.025884645, -0.019934151, -0.041274782, -0.0...  \n",
       "1997  [0.03417311, 0.042749066, 0.018995227, -0.0182...  \n",
       "1998  [0.023398804, 0.041698396, 0.044138342, 0.0093...  \n",
       "1999  [0.03809252, 0.022067213, 0.0051019085, -0.010...  \n",
       "\n",
       "[444000 rows x 2 columns]"
      ]
     },
     "execution_count": 197,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from oa.stores import OaStores\n",
    "from imbed_data_prep.wildchat import *\n",
    "\n",
    "dacc = WildchatDacc()\n",
    "list(dacc.saves)\n",
    "df = dacc.saves['segment_and_embeddings.parquet']\n",
    "df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 201,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['embeddable_df.parquet',\n",
       " 'wildchat_train.parquet',\n",
       " 'segment_and_embeddings.parquet']"
      ]
     },
     "execution_count": 201,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(dacc.saves)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 202,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>conversation_hash</th>\n",
       "      <th>model</th>\n",
       "      <th>timestamp</th>\n",
       "      <th>turn</th>\n",
       "      <th>language</th>\n",
       "      <th>toxic</th>\n",
       "      <th>redacted</th>\n",
       "      <th>state</th>\n",
       "      <th>country</th>\n",
       "      <th>hashed_ip</th>\n",
       "      <th>...</th>\n",
       "      <th>openai_moderation.categories</th>\n",
       "      <th>openai_moderation.category_scores</th>\n",
       "      <th>openai_moderation.flagged</th>\n",
       "      <th>detoxify_moderation.identity_attack</th>\n",
       "      <th>detoxify_moderation.insult</th>\n",
       "      <th>detoxify_moderation.obscene</th>\n",
       "      <th>detoxify_moderation.severe_toxicity</th>\n",
       "      <th>detoxify_moderation.sexual_explicit</th>\n",
       "      <th>detoxify_moderation.threat</th>\n",
       "      <th>detoxify_moderation.toxicity</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>c9ec5b440fbdd2a269333dd241f32f64</td>\n",
       "      <td>gpt-4-0314</td>\n",
       "      <td>2023-04-09 00:02:53+00:00</td>\n",
       "      <td>1</td>\n",
       "      <td>English</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>Texas</td>\n",
       "      <td>United States</td>\n",
       "      <td>22fd87ba9b98f3d379b23c7b52961f2d4a8505127e58b3...</td>\n",
       "      <td>...</td>\n",
       "      <td>{'harassment': False, 'harassment/threatening'...</td>\n",
       "      <td>{'harassment': 0.000484861753648147, 'harassme...</td>\n",
       "      <td>False</td>\n",
       "      <td>0.000206</td>\n",
       "      <td>0.002148</td>\n",
       "      <td>0.000412</td>\n",
       "      <td>0.000030</td>\n",
       "      <td>0.000127</td>\n",
       "      <td>0.000065</td>\n",
       "      <td>0.005422</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>c9ec5b440fbdd2a269333dd241f32f64</td>\n",
       "      <td>gpt-4-0314</td>\n",
       "      <td>2023-04-09 00:02:53+00:00</td>\n",
       "      <td>1</td>\n",
       "      <td>English</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>Texas</td>\n",
       "      <td>United States</td>\n",
       "      <td>22fd87ba9b98f3d379b23c7b52961f2d4a8505127e58b3...</td>\n",
       "      <td>...</td>\n",
       "      <td>{'harassment': False, 'harassment/threatening'...</td>\n",
       "      <td>{'harassment': 0.0004535938787739724, 'harassm...</td>\n",
       "      <td>False</td>\n",
       "      <td>0.000142</td>\n",
       "      <td>0.001089</td>\n",
       "      <td>0.000603</td>\n",
       "      <td>0.000074</td>\n",
       "      <td>0.000394</td>\n",
       "      <td>0.000107</td>\n",
       "      <td>0.001757</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>34f1581760df304d539e2fe4653b40d3</td>\n",
       "      <td>gpt-4-0314</td>\n",
       "      <td>2023-04-09 00:03:20+00:00</td>\n",
       "      <td>2</td>\n",
       "      <td>Spanish</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>A Coruña</td>\n",
       "      <td>Spain</td>\n",
       "      <td>58369722cd0bdf7fc027a67491ba65b74576df6994c36c...</td>\n",
       "      <td>...</td>\n",
       "      <td>{'harassment': False, 'harassment/threatening'...</td>\n",
       "      <td>{'harassment': 0.0002833749749697745, 'harassm...</td>\n",
       "      <td>False</td>\n",
       "      <td>0.007171</td>\n",
       "      <td>0.004463</td>\n",
       "      <td>0.003697</td>\n",
       "      <td>0.000329</td>\n",
       "      <td>0.013898</td>\n",
       "      <td>0.000671</td>\n",
       "      <td>0.045744</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>34f1581760df304d539e2fe4653b40d3</td>\n",
       "      <td>gpt-4-0314</td>\n",
       "      <td>2023-04-09 00:03:20+00:00</td>\n",
       "      <td>2</td>\n",
       "      <td>Spanish</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>A Coruña</td>\n",
       "      <td>Spain</td>\n",
       "      <td>58369722cd0bdf7fc027a67491ba65b74576df6994c36c...</td>\n",
       "      <td>...</td>\n",
       "      <td>{'harassment': False, 'harassment/threatening'...</td>\n",
       "      <td>{'harassment': 0.00020527311426121742, 'harass...</td>\n",
       "      <td>False</td>\n",
       "      <td>0.000431</td>\n",
       "      <td>0.000592</td>\n",
       "      <td>0.000645</td>\n",
       "      <td>0.000124</td>\n",
       "      <td>0.000403</td>\n",
       "      <td>0.000151</td>\n",
       "      <td>0.001274</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>34f1581760df304d539e2fe4653b40d3</td>\n",
       "      <td>gpt-4-0314</td>\n",
       "      <td>2023-04-09 00:03:20+00:00</td>\n",
       "      <td>2</td>\n",
       "      <td>Spanish</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>A Coruña</td>\n",
       "      <td>Spain</td>\n",
       "      <td>58369722cd0bdf7fc027a67491ba65b74576df6994c36c...</td>\n",
       "      <td>...</td>\n",
       "      <td>{'harassment': False, 'harassment/threatening'...</td>\n",
       "      <td>{'harassment': 4.703977901954204e-05, 'harassm...</td>\n",
       "      <td>False</td>\n",
       "      <td>0.000129</td>\n",
       "      <td>0.000428</td>\n",
       "      <td>0.000513</td>\n",
       "      <td>0.000052</td>\n",
       "      <td>0.000047</td>\n",
       "      <td>0.000064</td>\n",
       "      <td>0.000625</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3930079</th>\n",
       "      <td>5f2c83f277b36699e674b23c4e51935a</td>\n",
       "      <td>gpt-4-0125-preview</td>\n",
       "      <td>2024-04-29 23:55:24+00:00</td>\n",
       "      <td>1</td>\n",
       "      <td>English</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>California</td>\n",
       "      <td>United States</td>\n",
       "      <td>a42cbaaaed64531aafcdf699ee2bab231f6fa67a238b37...</td>\n",
       "      <td>...</td>\n",
       "      <td>{'harassment': False, 'harassment/threatening'...</td>\n",
       "      <td>{'harassment': 0.004712412133812904, 'harassme...</td>\n",
       "      <td>False</td>\n",
       "      <td>0.000123</td>\n",
       "      <td>0.000500</td>\n",
       "      <td>0.000155</td>\n",
       "      <td>0.000029</td>\n",
       "      <td>0.000029</td>\n",
       "      <td>0.000047</td>\n",
       "      <td>0.001082</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3930080</th>\n",
       "      <td>229f97f68b4ab6991ffc3d5333cd17a9</td>\n",
       "      <td>gpt-4-0125-preview</td>\n",
       "      <td>2024-04-29 23:56:30+00:00</td>\n",
       "      <td>1</td>\n",
       "      <td>English</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>Kingston</td>\n",
       "      <td>Jamaica</td>\n",
       "      <td>724ca0e446996d2d4357c095bced44aa6124c6234048d5...</td>\n",
       "      <td>...</td>\n",
       "      <td>{'harassment': False, 'harassment/threatening'...</td>\n",
       "      <td>{'harassment': 0.003280139761045575, 'harassme...</td>\n",
       "      <td>False</td>\n",
       "      <td>0.000468</td>\n",
       "      <td>0.001880</td>\n",
       "      <td>0.001431</td>\n",
       "      <td>0.000262</td>\n",
       "      <td>0.000943</td>\n",
       "      <td>0.000169</td>\n",
       "      <td>0.002028</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3930081</th>\n",
       "      <td>229f97f68b4ab6991ffc3d5333cd17a9</td>\n",
       "      <td>gpt-4-0125-preview</td>\n",
       "      <td>2024-04-29 23:56:30+00:00</td>\n",
       "      <td>1</td>\n",
       "      <td>English</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>Kingston</td>\n",
       "      <td>Jamaica</td>\n",
       "      <td>724ca0e446996d2d4357c095bced44aa6124c6234048d5...</td>\n",
       "      <td>...</td>\n",
       "      <td>{'harassment': False, 'harassment/threatening'...</td>\n",
       "      <td>{'harassment': 0.004683782812207937, 'harassme...</td>\n",
       "      <td>False</td>\n",
       "      <td>0.000134</td>\n",
       "      <td>0.000310</td>\n",
       "      <td>0.000235</td>\n",
       "      <td>0.000031</td>\n",
       "      <td>0.000024</td>\n",
       "      <td>0.000043</td>\n",
       "      <td>0.000596</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3930082</th>\n",
       "      <td>1b4f888896d3a698891eec6ef32203e0</td>\n",
       "      <td>gpt-4-0125-preview</td>\n",
       "      <td>2024-04-29 23:59:51+00:00</td>\n",
       "      <td>1</td>\n",
       "      <td>Persian</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>Hesse</td>\n",
       "      <td>Germany</td>\n",
       "      <td>a17c3aa37d20fa7e415ccd283ceafa226d96abc0a7ffbc...</td>\n",
       "      <td>...</td>\n",
       "      <td>{'harassment': False, 'harassment/threatening'...</td>\n",
       "      <td>{'harassment': 0.00029593988438136876, 'harass...</td>\n",
       "      <td>False</td>\n",
       "      <td>0.007240</td>\n",
       "      <td>0.032655</td>\n",
       "      <td>0.036163</td>\n",
       "      <td>0.005414</td>\n",
       "      <td>0.000920</td>\n",
       "      <td>0.002299</td>\n",
       "      <td>0.000544</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3930083</th>\n",
       "      <td>1b4f888896d3a698891eec6ef32203e0</td>\n",
       "      <td>gpt-4-0125-preview</td>\n",
       "      <td>2024-04-29 23:59:51+00:00</td>\n",
       "      <td>1</td>\n",
       "      <td>Persian</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>Hesse</td>\n",
       "      <td>Germany</td>\n",
       "      <td>a17c3aa37d20fa7e415ccd283ceafa226d96abc0a7ffbc...</td>\n",
       "      <td>...</td>\n",
       "      <td>{'harassment': False, 'harassment/threatening'...</td>\n",
       "      <td>{'harassment': 0.0004717352276202291, 'harassm...</td>\n",
       "      <td>False</td>\n",
       "      <td>0.003460</td>\n",
       "      <td>0.013961</td>\n",
       "      <td>0.013387</td>\n",
       "      <td>0.002033</td>\n",
       "      <td>0.000290</td>\n",
       "      <td>0.000711</td>\n",
       "      <td>0.001929</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>3930084 rows × 32 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                        conversation_hash               model  \\\n",
       "0        c9ec5b440fbdd2a269333dd241f32f64          gpt-4-0314   \n",
       "1        c9ec5b440fbdd2a269333dd241f32f64          gpt-4-0314   \n",
       "2        34f1581760df304d539e2fe4653b40d3          gpt-4-0314   \n",
       "3        34f1581760df304d539e2fe4653b40d3          gpt-4-0314   \n",
       "4        34f1581760df304d539e2fe4653b40d3          gpt-4-0314   \n",
       "...                                   ...                 ...   \n",
       "3930079  5f2c83f277b36699e674b23c4e51935a  gpt-4-0125-preview   \n",
       "3930080  229f97f68b4ab6991ffc3d5333cd17a9  gpt-4-0125-preview   \n",
       "3930081  229f97f68b4ab6991ffc3d5333cd17a9  gpt-4-0125-preview   \n",
       "3930082  1b4f888896d3a698891eec6ef32203e0  gpt-4-0125-preview   \n",
       "3930083  1b4f888896d3a698891eec6ef32203e0  gpt-4-0125-preview   \n",
       "\n",
       "                        timestamp  turn language  toxic  redacted       state  \\\n",
       "0       2023-04-09 00:02:53+00:00     1  English  False     False       Texas   \n",
       "1       2023-04-09 00:02:53+00:00     1  English  False     False       Texas   \n",
       "2       2023-04-09 00:03:20+00:00     2  Spanish  False     False    A Coruña   \n",
       "3       2023-04-09 00:03:20+00:00     2  Spanish  False     False    A Coruña   \n",
       "4       2023-04-09 00:03:20+00:00     2  Spanish  False     False    A Coruña   \n",
       "...                           ...   ...      ...    ...       ...         ...   \n",
       "3930079 2024-04-29 23:55:24+00:00     1  English  False     False  California   \n",
       "3930080 2024-04-29 23:56:30+00:00     1  English  False     False    Kingston   \n",
       "3930081 2024-04-29 23:56:30+00:00     1  English  False     False    Kingston   \n",
       "3930082 2024-04-29 23:59:51+00:00     1  Persian  False     False       Hesse   \n",
       "3930083 2024-04-29 23:59:51+00:00     1  Persian  False     False       Hesse   \n",
       "\n",
       "               country                                          hashed_ip  \\\n",
       "0        United States  22fd87ba9b98f3d379b23c7b52961f2d4a8505127e58b3...   \n",
       "1        United States  22fd87ba9b98f3d379b23c7b52961f2d4a8505127e58b3...   \n",
       "2                Spain  58369722cd0bdf7fc027a67491ba65b74576df6994c36c...   \n",
       "3                Spain  58369722cd0bdf7fc027a67491ba65b74576df6994c36c...   \n",
       "4                Spain  58369722cd0bdf7fc027a67491ba65b74576df6994c36c...   \n",
       "...                ...                                                ...   \n",
       "3930079  United States  a42cbaaaed64531aafcdf699ee2bab231f6fa67a238b37...   \n",
       "3930080        Jamaica  724ca0e446996d2d4357c095bced44aa6124c6234048d5...   \n",
       "3930081        Jamaica  724ca0e446996d2d4357c095bced44aa6124c6234048d5...   \n",
       "3930082        Germany  a17c3aa37d20fa7e415ccd283ceafa226d96abc0a7ffbc...   \n",
       "3930083        Germany  a17c3aa37d20fa7e415ccd283ceafa226d96abc0a7ffbc...   \n",
       "\n",
       "         ...                       openai_moderation.categories  \\\n",
       "0        ...  {'harassment': False, 'harassment/threatening'...   \n",
       "1        ...  {'harassment': False, 'harassment/threatening'...   \n",
       "2        ...  {'harassment': False, 'harassment/threatening'...   \n",
       "3        ...  {'harassment': False, 'harassment/threatening'...   \n",
       "4        ...  {'harassment': False, 'harassment/threatening'...   \n",
       "...      ...                                                ...   \n",
       "3930079  ...  {'harassment': False, 'harassment/threatening'...   \n",
       "3930080  ...  {'harassment': False, 'harassment/threatening'...   \n",
       "3930081  ...  {'harassment': False, 'harassment/threatening'...   \n",
       "3930082  ...  {'harassment': False, 'harassment/threatening'...   \n",
       "3930083  ...  {'harassment': False, 'harassment/threatening'...   \n",
       "\n",
       "                         openai_moderation.category_scores  \\\n",
       "0        {'harassment': 0.000484861753648147, 'harassme...   \n",
       "1        {'harassment': 0.0004535938787739724, 'harassm...   \n",
       "2        {'harassment': 0.0002833749749697745, 'harassm...   \n",
       "3        {'harassment': 0.00020527311426121742, 'harass...   \n",
       "4        {'harassment': 4.703977901954204e-05, 'harassm...   \n",
       "...                                                    ...   \n",
       "3930079  {'harassment': 0.004712412133812904, 'harassme...   \n",
       "3930080  {'harassment': 0.003280139761045575, 'harassme...   \n",
       "3930081  {'harassment': 0.004683782812207937, 'harassme...   \n",
       "3930082  {'harassment': 0.00029593988438136876, 'harass...   \n",
       "3930083  {'harassment': 0.0004717352276202291, 'harassm...   \n",
       "\n",
       "        openai_moderation.flagged detoxify_moderation.identity_attack  \\\n",
       "0                           False                            0.000206   \n",
       "1                           False                            0.000142   \n",
       "2                           False                            0.007171   \n",
       "3                           False                            0.000431   \n",
       "4                           False                            0.000129   \n",
       "...                           ...                                 ...   \n",
       "3930079                     False                            0.000123   \n",
       "3930080                     False                            0.000468   \n",
       "3930081                     False                            0.000134   \n",
       "3930082                     False                            0.007240   \n",
       "3930083                     False                            0.003460   \n",
       "\n",
       "        detoxify_moderation.insult detoxify_moderation.obscene  \\\n",
       "0                         0.002148                    0.000412   \n",
       "1                         0.001089                    0.000603   \n",
       "2                         0.004463                    0.003697   \n",
       "3                         0.000592                    0.000645   \n",
       "4                         0.000428                    0.000513   \n",
       "...                            ...                         ...   \n",
       "3930079                   0.000500                    0.000155   \n",
       "3930080                   0.001880                    0.001431   \n",
       "3930081                   0.000310                    0.000235   \n",
       "3930082                   0.032655                    0.036163   \n",
       "3930083                   0.013961                    0.013387   \n",
       "\n",
       "         detoxify_moderation.severe_toxicity  \\\n",
       "0                                   0.000030   \n",
       "1                                   0.000074   \n",
       "2                                   0.000329   \n",
       "3                                   0.000124   \n",
       "4                                   0.000052   \n",
       "...                                      ...   \n",
       "3930079                             0.000029   \n",
       "3930080                             0.000262   \n",
       "3930081                             0.000031   \n",
       "3930082                             0.005414   \n",
       "3930083                             0.002033   \n",
       "\n",
       "        detoxify_moderation.sexual_explicit detoxify_moderation.threat  \\\n",
       "0                                  0.000127                   0.000065   \n",
       "1                                  0.000394                   0.000107   \n",
       "2                                  0.013898                   0.000671   \n",
       "3                                  0.000403                   0.000151   \n",
       "4                                  0.000047                   0.000064   \n",
       "...                                     ...                        ...   \n",
       "3930079                            0.000029                   0.000047   \n",
       "3930080                            0.000943                   0.000169   \n",
       "3930081                            0.000024                   0.000043   \n",
       "3930082                            0.000920                   0.002299   \n",
       "3930083                            0.000290                   0.000711   \n",
       "\n",
       "        detoxify_moderation.toxicity  \n",
       "0                           0.005422  \n",
       "1                           0.001757  \n",
       "2                           0.045744  \n",
       "3                           0.001274  \n",
       "4                           0.000625  \n",
       "...                              ...  \n",
       "3930079                     0.001082  \n",
       "3930080                     0.002028  \n",
       "3930081                     0.000596  \n",
       "3930082                     0.000544  \n",
       "3930083                     0.001929  \n",
       "\n",
       "[3930084 rows x 32 columns]"
      ]
     },
     "execution_count": 202,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "w = dacc.saves['wildchat_train.parquet']\n",
    "w"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 203,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "conversation_hash, model, timestamp, turn, language, toxic, redacted, state,\n",
      "country, hashed_ip, header, conversation.content, conversation.country,\n",
      "conversation.hashed_ip, conversation.header, conversation.language,\n",
      "conversation.redacted, conversation.role, conversation.state,\n",
      "conversation.timestamp, conversation.toxic, conversation.turn_identifier,\n",
      "openai_moderation.categories, openai_moderation.category_scores,\n",
      "openai_moderation.flagged, detoxify_moderation.identity_attack,\n",
      "detoxify_moderation.insult, detoxify_moderation.obscene,\n",
      "detoxify_moderation.severe_toxicity, detoxify_moderation.sexual_explicit,\n",
      "detoxify_moderation.threat, detoxify_moderation.toxicity\n"
     ]
    }
   ],
   "source": [
    "from lkj import wrapped_print\n",
    "\n",
    "wrapped_print(w.columns)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ww = pd.read_parquet('/Users/thorwhalen/Dropbox/_odata/app_data/imbed/saves/github_repos/github-repos.parquet')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 205,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "owner, name, stars, forks, watchers, isFork, isArchived, languages,\n",
      "languageCount, topics, topicCount, diskUsageKb, pullRequests, issues,\n",
      "description, primaryLanguage, createdAt, pushedAt, defaultBranchCommitCount,\n",
      "license, assignableUserCount, codeOfConduct, forkingAllowed, nameWithOwner,\n",
      "parent, embedding\n"
     ]
    }
   ],
   "source": [
    "wrapped_print(ww.columns)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 208,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "primaryLanguage\n",
       "Python              520831\n",
       "JavaScript          491681\n",
       "Java                219445\n",
       "C++                 167950\n",
       "TypeScript          140833\n",
       "PHP                 123726\n",
       "C                   123665\n",
       "C#                  121324\n",
       "HTML                106626\n",
       "Go                  104105\n",
       "Jupyter Notebook     96714\n",
       "Shell                91336\n",
       "Ruby                 69291\n",
       "CSS                  49720\n",
       "Name: count, dtype: int64"
      ]
     },
     "execution_count": 208,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ww.primaryLanguage.value_counts().iloc[:14]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Checking on model coverage"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "So now assume you've collected (and probably edited) all the pydantic models \n",
    "you want, and want to see what their coverage is like (i.e. validate them against\n",
    "your data)..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [],
   "source": [
    "# So now assum you've collected (and probably edited) all the pydantic models \n",
    "# you want, and want to see what their coverage is like (i.e. validate them against\n",
    "# your data)...\n",
    "\n",
    "from oa.oa_types import BatchRequest, EmbeddingResponse, InputDataJsonL\n",
    "from i2 import ObjectClassifier\n",
    "from ju import valid_models, is_valid_wrt_model\n",
    "from functools import partial\n",
    "\n",
    "your_models = [BatchRequest, EmbeddingResponse, InputDataJsonL]\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 9.0.0 (20230911.1827)\n",
       " -->\n",
       "<!-- Pages: 1 -->\n",
       "<svg width=\"698pt\" height=\"260pt\"\n",
       " viewBox=\"0.00 0.00 698.40 260.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 256)\">\n",
       "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-256 694.4,-256 694.4,4 -4,4\"/>\n",
       "<!-- BatchRequest -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>BatchRequest</title>\n",
       "<polygon fill=\"none\" stroke=\"black\" points=\"299.65,-252 208.65,-252 208.65,-216 299.65,-216 299.65,-252\"/>\n",
       "<text text-anchor=\"middle\" x=\"254.15\" y=\"-228.95\" font-family=\"Times,serif\" font-size=\"14.00\">BatchRequest</text>\n",
       "</g>\n",
       "<!-- custom_id -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>custom_id</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"64.15\" cy=\"-162\" rx=\"64.15\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"64.15\" y=\"-156.95\" font-family=\"Times,serif\" font-size=\"14.00\">custom_id: str</text>\n",
       "</g>\n",
       "<!-- BatchRequest&#45;&gt;custom_id -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>BatchRequest&#45;&gt;custom_id</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M208.15,-216.05C179.2,-205.39 141.88,-191.64 112.49,-180.81\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"114.07,-177.66 103.47,-177.49 111.65,-184.23 114.07,-177.66\"/>\n",
       "</g>\n",
       "<!-- method -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>method</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"200.15\" cy=\"-162\" rx=\"53.4\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"200.15\" y=\"-156.95\" font-family=\"Times,serif\" font-size=\"14.00\">method: str</text>\n",
       "</g>\n",
       "<!-- BatchRequest&#45;&gt;method -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>BatchRequest&#45;&gt;method</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M240.8,-215.7C234.49,-207.52 226.84,-197.6 219.88,-188.58\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"222.77,-186.6 213.89,-180.82 217.23,-190.88 222.77,-186.6\"/>\n",
       "</g>\n",
       "<!-- url -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>url</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"307.15\" cy=\"-162\" rx=\"35.49\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"307.15\" y=\"-156.95\" font-family=\"Times,serif\" font-size=\"14.00\">url: str</text>\n",
       "</g>\n",
       "<!-- BatchRequest&#45;&gt;url -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>BatchRequest&#45;&gt;url</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M267.25,-215.7C273.53,-207.4 281.17,-197.31 288.08,-188.19\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"290.76,-190.44 294.01,-180.35 285.18,-186.21 290.76,-190.44\"/>\n",
       "</g>\n",
       "<!-- body -->\n",
       "<g id=\"node5\" class=\"node\">\n",
       "<title>body</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"466.15\" cy=\"-162\" rx=\"105.6\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"466.15\" y=\"-156.95\" font-family=\"Times,serif\" font-size=\"14.00\">body: BatchRequestBody</text>\n",
       "</g>\n",
       "<!-- BatchRequest&#45;&gt;body -->\n",
       "<g id=\"edge4\" class=\"edge\">\n",
       "<title>BatchRequest&#45;&gt;body</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M299.89,-217.9C331.63,-207.42 374.17,-193.37 408.27,-182.11\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"409.19,-185.49 417.58,-179.03 406.99,-178.85 409.19,-185.49\"/>\n",
       "</g>\n",
       "<!-- BatchRequestBody -->\n",
       "<g id=\"node6\" class=\"node\">\n",
       "<title>BatchRequestBody</title>\n",
       "<polygon fill=\"none\" stroke=\"black\" points=\"526.27,-108 406.02,-108 406.02,-72 526.27,-72 526.27,-108\"/>\n",
       "<text text-anchor=\"middle\" x=\"466.15\" y=\"-84.95\" font-family=\"Times,serif\" font-size=\"14.00\">BatchRequestBody</text>\n",
       "</g>\n",
       "<!-- body&#45;&gt;BatchRequestBody -->\n",
       "<g id=\"edge7\" class=\"edge\">\n",
       "<title>body&#45;&gt;BatchRequestBody</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M460.23,-143.7C459.48,-136.41 459.24,-127.73 459.5,-119.54\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"462.99,-119.82 460.15,-109.61 456,-119.36 462.99,-119.82\"/>\n",
       "</g>\n",
       "<!-- body&#45;&gt;BatchRequestBody -->\n",
       "<g id=\"edge8\" class=\"edge\">\n",
       "<title>body&#45;&gt;BatchRequestBody</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M472.06,-143.7C472.81,-136.41 473.06,-127.73 472.79,-119.54\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"476.29,-119.36 472.14,-109.61 469.3,-119.82 476.29,-119.36\"/>\n",
       "</g>\n",
       "<!-- input -->\n",
       "<g id=\"node7\" class=\"node\">\n",
       "<title>input</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"606.15\" cy=\"-18\" rx=\"44.19\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"606.15\" y=\"-12.95\" font-family=\"Times,serif\" font-size=\"14.00\">input: str</text>\n",
       "</g>\n",
       "<!-- BatchRequestBody&#45;&gt;input -->\n",
       "<g id=\"edge5\" class=\"edge\">\n",
       "<title>BatchRequestBody&#45;&gt;input</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M501.11,-71.52C521.76,-61.19 547.89,-48.13 568.92,-37.62\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"570.35,-40.81 577.73,-33.21 567.22,-34.55 570.35,-40.81\"/>\n",
       "</g>\n",
       "<!-- model -->\n",
       "<g id=\"node8\" class=\"node\">\n",
       "<title>model</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"466.15\" cy=\"-18\" rx=\"48.79\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"466.15\" y=\"-12.95\" font-family=\"Times,serif\" font-size=\"14.00\">model: str</text>\n",
       "</g>\n",
       "<!-- BatchRequestBody&#45;&gt;model -->\n",
       "<g id=\"edge6\" class=\"edge\">\n",
       "<title>BatchRequestBody&#45;&gt;model</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M466.15,-71.7C466.15,-64.41 466.15,-55.73 466.15,-47.54\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"469.65,-47.62 466.15,-37.62 462.65,-47.62 469.65,-47.62\"/>\n",
       "</g>\n",
       "<!-- JsonL[InputText] -->\n",
       "<g id=\"node9\" class=\"node\">\n",
       "<title>JsonL[InputText]</title>\n",
       "<polygon fill=\"none\" stroke=\"black\" points=\"690.4,-252 579.9,-252 579.9,-216 690.4,-216 690.4,-252\"/>\n",
       "<text text-anchor=\"middle\" x=\"635.15\" y=\"-228.95\" font-family=\"Times,serif\" font-size=\"14.00\">JsonL[InputText]</text>\n",
       "</g>\n",
       "<!-- root -->\n",
       "<g id=\"node10\" class=\"node\">\n",
       "<title>root</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"635.15\" cy=\"-162\" rx=\"45.21\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"635.15\" y=\"-156.95\" font-family=\"Times,serif\" font-size=\"14.00\">root: List</text>\n",
       "</g>\n",
       "<!-- JsonL[InputText]&#45;&gt;root -->\n",
       "<g id=\"edge9\" class=\"edge\">\n",
       "<title>JsonL[InputText]&#45;&gt;root</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M635.15,-215.7C635.15,-208.41 635.15,-199.73 635.15,-191.54\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"638.65,-191.62 635.15,-181.62 631.65,-191.62 638.65,-191.62\"/>\n",
       "</g>\n",
       "<!-- InputText -->\n",
       "<g id=\"node11\" class=\"node\">\n",
       "<title>InputText</title>\n",
       "<polygon fill=\"none\" stroke=\"black\" points=\"669.77,-108 600.52,-108 600.52,-72 669.77,-72 669.77,-108\"/>\n",
       "<text text-anchor=\"middle\" x=\"635.15\" y=\"-84.95\" font-family=\"Times,serif\" font-size=\"14.00\">InputText</text>\n",
       "</g>\n",
       "<!-- root&#45;&gt;InputText -->\n",
       "<g id=\"edge10\" class=\"edge\">\n",
       "<title>root&#45;&gt;InputText</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M629.23,-143.7C628.48,-136.41 628.24,-127.73 628.5,-119.54\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"631.99,-119.82 629.15,-109.61 625,-119.36 631.99,-119.82\"/>\n",
       "</g>\n",
       "<!-- root&#45;&gt;InputText -->\n",
       "<g id=\"edge12\" class=\"edge\">\n",
       "<title>root&#45;&gt;InputText</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M641.06,-143.7C641.81,-136.41 642.06,-127.73 641.79,-119.54\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"645.29,-119.36 641.14,-109.61 638.3,-119.82 645.29,-119.36\"/>\n",
       "</g>\n",
       "<!-- InputText&#45;&gt;input -->\n",
       "<g id=\"edge11\" class=\"edge\">\n",
       "<title>InputText&#45;&gt;input</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M627.98,-71.7C624.85,-64.15 621.11,-55.12 617.61,-46.68\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"620.87,-45.4 613.81,-37.5 614.41,-48.08 620.87,-45.4\"/>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<graphviz.graphs.Digraph at 0x315f2a110>"
      ]
     },
     "execution_count": 86,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from ju import model_digraph\n",
    "\n",
    "model_digraph(your_models)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "BatchRequest\n",
      "{'body.input': typing.List[str],\n",
      " 'body.model': <class 'str'>,\n",
      " 'custom_id': <class 'str'>,\n",
      " 'method': <class 'str'>,\n",
      " 'url': <class 'str'>}\n",
      "\n",
      "EmbeddingResponse\n",
      "{'custom_id': <class 'str'>,\n",
      " 'error': typing.Any,\n",
      " 'id': <class 'str'>,\n",
      " 'response.body.data.*.embedding': typing.List[float],\n",
      " 'response.body.data.*.index': <class 'int'>,\n",
      " 'response.body.data.*.object': typing.Literal['embedding'],\n",
      " 'response.body.model': <class 'str'>,\n",
      " 'response.body.object': <class 'str'>,\n",
      " 'response.body.usage.prompt_tokens': <class 'int'>,\n",
      " 'response.body.usage.total_tokens': <class 'int'>,\n",
      " 'response.request_id': <class 'str'>,\n",
      " 'response.status_code': <class 'int'>}\n",
      "\n",
      "JsonL[InputText]\n",
      "{'root.*.input': <class 'str'>}\n",
      "\n"
     ]
    }
   ],
   "source": [
    "from ju import field_paths_and_annotations\n",
    "from pprint import pprint\n",
    "\n",
    "model_paths = {model.__name__: field_paths_and_annotations(model) for model in your_models}\n",
    "\n",
    "for name, paths in model_paths.items():\n",
    "    print(f\"{name}\")\n",
    "    pprint(paths)\n",
    "    print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 75,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "issubclass(EmbeddingResponse, BaseModel)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['id',\n",
       " 'custom_id',\n",
       " 'response.status_code',\n",
       " 'response.request_id',\n",
       " 'response.body.object',\n",
       " 'response.body.data.*.embedding',\n",
       " 'response.body.data.*.index',\n",
       " 'response.body.data.*.object',\n",
       " 'response.body.model',\n",
       " 'response.body.usage.prompt_tokens',\n",
       " 'response.body.usage.total_tokens',\n",
       " 'error']"
      ]
     },
     "execution_count": 92,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "t = extractors(batch_output_json)\n",
    "list(t)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2000"
      ]
     },
     "execution_count": 74,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "w = t['response.body.data.*.embedding']\n",
    "len(w)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "bytes"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "t = s.files[file_id.id]\n",
    "type(t)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "import json\n",
    "\n",
    "tt = json.loads(t)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['id', 'custom_id', 'response', 'error']"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(tt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['status_code', 'request_id', 'body']"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(tt['response'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['object', 'data', 'model', 'usage']"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(tt['response']['body'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "from lkj import truncate_dict_values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'id': 'batch_req_0qWxQ4rcAnzo9lEUMZR7xsgo',\n",
       " 'custom_id': 'embeddings_batch_id-1724503217185829120',\n",
       " 'response': {'status_code': 200,\n",
       "  'request_id': 'dacf8a2486eb1d6a7070852bf04d292d',\n",
       "  'body': {'object': 'list',\n",
       "   'data': [{'object': 'embedding',\n",
       "     'index': 0,\n",
       "     'embedding': [0.017829118, -0.0066988687]},\n",
       "    {'object': 'embedding',\n",
       "     'index': 1,\n",
       "     'embedding': [0.0010772116, -0.0015551111]}],\n",
       "   'model': 'text-embedding-3-small',\n",
       "   'usage': {'prompt_tokens': 629349, 'total_tokens': 629349}}},\n",
       " 'error': None}"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "truncate_dict_values(tt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from functools import partial\n",
    "from glom import glom\n",
    "extractor = partial(glom, spec='response.body.data.*.embedding')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 125,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 2]"
      ]
     },
     "execution_count": 125,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from dol import path_get\n",
    "from glom import glom\n",
    "\n",
    "d = {\n",
    "    'a': {\n",
    "        'b': [{'c': 1}, {'c': 2}],\n",
    "        'd': 'bar'\n",
    "    }\n",
    "}\n",
    "\n",
    "# extract the c values from d using glom\n",
    "\n",
    "glom(d, 'a.b.*.c')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pydantic import BaseModel\n",
    "\n",
    "def extract(jdict: dict, from_model: BaseModel, extract_model: BaseModel) -> callable:\n",
    "    \"\"\"\n",
    "    Extracts `extract_model`-valid data from a `from_model`-valid `jdict` dict. \n",
    "\n",
    "    That is, will validate the `jdict` against `from_model`, then extract the\n",
    "    data that is valid against `extract_model`, which should be some where in \n",
    "    the hierarchy of `from_model`.\n",
    "    \"\"\"\n",
    "BaseModel.model_dump"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'ID': 'user_id', 'Name': 'full_name', 'Date': None}\n"
     ]
    }
   ],
   "source": [
    "import re\n",
    "from typing import List, Dict, Callable, Union, Optional\n",
    "\n",
    "def alias_based_mapping(\n",
    "    table_columns: List[str], \n",
    "    aliases: Dict[str, Union[List[str], str, Callable[[List[str]], Optional[str]]]]\n",
    ") -> Dict[str, Optional[str]]:\n",
    "    \"\"\"\n",
    "    Maps roles to table columns based on aliases that can be a list of possible names, a regular expression, \n",
    "    or a custom matching function.\n",
    "    \n",
    "    Args:\n",
    "        table_columns (List[str]): A list of column headers from the input table.\n",
    "        aliases (Dict[str, Union[List[str], str, Callable[[List[str]], Optional[str]]]]): A dictionary where:\n",
    "            - Keys are roles (e.g., 'ID', 'Name').\n",
    "            - Values are either:\n",
    "                - A list of aliases (e.g., ['id', 'user_id']).\n",
    "                - A string representing a regular expression (e.g., r'user.*id').\n",
    "                - A function that takes a list of columns and returns a matched column or None.\n",
    "    \n",
    "    Returns:\n",
    "        Dict[str, Optional[str]]: A dictionary mapping each role to the first matching column found in the table, \n",
    "                                  or None if no match is found. Once a column is matched, it is removed from \n",
    "                                  further matching.\n",
    "    \"\"\"\n",
    "    \n",
    "    def normalize_alias(value: Union[List[str], str, Callable[[List[str]], Optional[str]]]) -> Callable[[List[str]], Optional[str]]:\n",
    "        \"\"\"Converts the alias to a matching function.\"\"\"\n",
    "        if isinstance(value, list):\n",
    "            # Convert the list into a regular expression\n",
    "            pattern = \"|\".join(re.escape(alias) for alias in value)\n",
    "            return lambda columns: next((col for col in columns if re.fullmatch(pattern, col)), None)\n",
    "        elif isinstance(value, str):\n",
    "            # Treat the string as a regular expression\n",
    "            return lambda columns: next((col for col in columns if re.fullmatch(value, col)), None)\n",
    "        elif callable(value):\n",
    "            # It's already a matching function\n",
    "            return value\n",
    "        else:\n",
    "            raise ValueError(\"Alias must be a list, string, or callable.\")\n",
    "    \n",
    "    # Normalize all alias entries into functions\n",
    "    alias_functions = {role: normalize_alias(alias) for role, alias in aliases.items()}\n",
    "    \n",
    "    role_to_column = {role: None for role in aliases}  # Initialize result dictionary\n",
    "    remaining_columns = set(table_columns)  # Set of columns that haven't been matched yet\n",
    "\n",
    "    # Process each role and its corresponding matching function\n",
    "    for role, match_func in alias_functions.items():\n",
    "        matched_column = match_func(list(remaining_columns))  # Apply the matching function to the remaining columns\n",
    "        if matched_column:\n",
    "            role_to_column[role] = matched_column\n",
    "            remaining_columns.remove(matched_column)  # Remove the matched column from further consideration\n",
    "    \n",
    "    return role_to_column\n",
    "\n",
    "# Example usage\n",
    "if __name__ == \"__main__\":\n",
    "    table_columns = ['user_id', 'full_name', 'created_at', 'email_address']\n",
    "    aliases = {\n",
    "        'ID': ['id', 'user_id'],               # List of possible aliases for 'ID'\n",
    "        'Name': r'.*name',                     # Regular expression for 'Name'\n",
    "        'Date': lambda cols: next((col for col in cols if \"date\" in col), None)  # Custom matching function\n",
    "    }\n",
    "    print(alias_based_mapping(table_columns, aliases))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "TestResults(failed=0, attempted=6)"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import re\n",
    "from typing import List, Dict, Callable, Union, Optional\n",
    "\n",
    "\n",
    "def alias_based_mapping(\n",
    "    table_columns: List[str], \n",
    "    aliases: Dict[str, Union[List[str], str, Callable[[List[str]], Optional[str]]]]\n",
    ") -> Dict[str, Optional[str]]:\n",
    "    \"\"\"\n",
    "    Maps roles to table columns based on aliases that can be a list of possible names, a regular expression, \n",
    "    or a custom matching function.\n",
    "    \n",
    "    Args:\n",
    "        table_columns (List[str]): A list of column headers from the input table.\n",
    "        aliases (Dict[str, Union[List[str], str, Callable[[List[str]], Optional[str]]]]): A dictionary where:\n",
    "            - Keys are roles (e.g., 'ID', 'Name').\n",
    "            - Values are either:\n",
    "                - A list of aliases (e.g., ['id', 'user_id']).\n",
    "                - A string representing a regular expression (e.g., r'user.*id').\n",
    "                - A function that takes a list of columns and returns a matched column or None.\n",
    "\n",
    "    Returns:\n",
    "        Dict[str, Optional[str]]: A dictionary mapping each role to the first matching column found in the table, \n",
    "                                  or None if no match is found. Once a column is matched, it is removed from \n",
    "                                  further matching.\n",
    "\n",
    "    Doctests:\n",
    "    \n",
    "    >>> # Example 1: List-based aliases, regex, and custom function matching\n",
    "    >>> table_columns = ['user_id', 'full_name', 'created_at', 'email_address']\n",
    "    >>> aliases = {\n",
    "    ...     'ID': ['id', 'user_id'],  # List of possible aliases for 'ID'\n",
    "    ...     'Name': r'.*name',  # Regular expression for 'Name'\n",
    "    ...     'Date': lambda cols: next((col for col in cols if \"date\" in col.lower() or \"created\" in col.lower()), None)  # Custom matching function\n",
    "    ... }\n",
    "    >>> alias_based_mapping(table_columns, aliases)\n",
    "    {'ID': 'user_id', 'Name': 'full_name', 'Date': 'created_at'}\n",
    "\n",
    "    >>> # Example 2: Handles conflict resolution by removing matched columns\n",
    "    >>> table_columns = ['id', 'full_name', 'id_created', 'email_address']\n",
    "    >>> aliases = {\n",
    "    ...     'Primary ID': ['id'],  # List-based alias that should match 'id' first\n",
    "    ...     'Secondary ID': r'id.*',  # Regex to match anything starting with 'id'\n",
    "    ...     'Email': lambda cols: next((col for col in cols if 'email' in col.lower()), None)  # Custom function for email\n",
    "    ... }\n",
    "    >>> alias_based_mapping(table_columns, aliases)\n",
    "    {'Primary ID': 'id', 'Secondary ID': 'id_created', 'Email': 'email_address'}\n",
    "    \"\"\"\n",
    "    \n",
    "    def normalize_alias(value: Union[List[str], str, Callable[[List[str]], Optional[str]]]) -> Callable[[List[str]], Optional[str]]:\n",
    "        \"\"\"Converts the alias to a matching function.\"\"\"\n",
    "        if isinstance(value, list):\n",
    "            # Convert the list into a regular expression\n",
    "            pattern = \"|\".join(re.escape(alias) for alias in value)\n",
    "            return lambda columns: next((col for col in columns if re.fullmatch(pattern, col)), None)\n",
    "        elif isinstance(value, str):\n",
    "            # Treat the string as a regular expression\n",
    "            return lambda columns: next((col for col in columns if re.fullmatch(value, col)), None)\n",
    "        elif callable(value):\n",
    "            # It's already a matching function\n",
    "            return value\n",
    "        else:\n",
    "            raise ValueError(\"Alias must be a list, string, or callable.\")\n",
    "    \n",
    "    # Normalize all alias entries into functions\n",
    "    alias_functions = {role: normalize_alias(alias) for role, alias in aliases.items()}\n",
    "    \n",
    "    role_to_column = {role: None for role in aliases}  # Initialize result dictionary\n",
    "    remaining_columns = set(table_columns)  # Set of columns that haven't been matched yet\n",
    "\n",
    "    # Process each role and its corresponding matching function\n",
    "    for role, match_func in alias_functions.items():\n",
    "        matched_column = match_func(list(remaining_columns))  # Apply the matching function to the remaining columns\n",
    "        if matched_column:\n",
    "            role_to_column[role] = matched_column\n",
    "            remaining_columns.remove(matched_column)  # Remove the matched column from further consideration\n",
    "    \n",
    "    return role_to_column\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "models_cover_this_data = lambda d: bool(next(valid_models(d, your_models), None))\n",
    "\n",
    "partial(valid_models, models=your_models)\n",
    "all(map(models_cover_this_data, [x['reduced_example_data'] for x in models_info]))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "files_base_df.shape=(2142, 8)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>id</th>\n",
       "      <th>bytes</th>\n",
       "      <th>created_at</th>\n",
       "      <th>filename</th>\n",
       "      <th>object</th>\n",
       "      <th>purpose</th>\n",
       "      <th>status</th>\n",
       "      <th>status_details</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>file-g1iSPVYMatQRuCRQAkIGFBUA</td>\n",
       "      <td>41629954</td>\n",
       "      <td>1724503295</td>\n",
       "      <td>batch_YY7gAytldnVxPRy3vgnlbsbT_output.jsonl</td>\n",
       "      <td>file</td>\n",
       "      <td>batch_output</td>\n",
       "      <td>processed</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>file-JUOe0LxPKzlJDauidqVAiYHd</td>\n",
       "      <td>41629905</td>\n",
       "      <td>1724503291</td>\n",
       "      <td>batch_sV6na1dUQabLp5jEEjTODCKX_output.jsonl</td>\n",
       "      <td>file</td>\n",
       "      <td>batch_output</td>\n",
       "      <td>processed</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>file-zqP3q2hDPVwOYp1Mw8lYAV38</td>\n",
       "      <td>41628327</td>\n",
       "      <td>1724503265</td>\n",
       "      <td>batch_31Ks4sc5G78nOYlbbjo2QXaQ_output.jsonl</td>\n",
       "      <td>file</td>\n",
       "      <td>batch_output</td>\n",
       "      <td>processed</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>file-QmvvLF1ToOcDtZhRNqo0CxQX</td>\n",
       "      <td>41628789</td>\n",
       "      <td>1724503261</td>\n",
       "      <td>batch_C4fvfp1QCYG0zDWLMhDnPC0Z_output.jsonl</td>\n",
       "      <td>file</td>\n",
       "      <td>batch_output</td>\n",
       "      <td>processed</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>file-5X41zNzZWqqhOmksQsmmfqrI</td>\n",
       "      <td>41633793</td>\n",
       "      <td>1724503259</td>\n",
       "      <td>batch_O1YgvIBmEs60RbsXPqkv9MB9_output.jsonl</td>\n",
       "      <td>file</td>\n",
       "      <td>batch_output</td>\n",
       "      <td>processed</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                              id     bytes  created_at  \\\n",
       "0  file-g1iSPVYMatQRuCRQAkIGFBUA  41629954  1724503295   \n",
       "1  file-JUOe0LxPKzlJDauidqVAiYHd  41629905  1724503291   \n",
       "2  file-zqP3q2hDPVwOYp1Mw8lYAV38  41628327  1724503265   \n",
       "3  file-QmvvLF1ToOcDtZhRNqo0CxQX  41628789  1724503261   \n",
       "4  file-5X41zNzZWqqhOmksQsmmfqrI  41633793  1724503259   \n",
       "\n",
       "                                      filename object       purpose  \\\n",
       "0  batch_YY7gAytldnVxPRy3vgnlbsbT_output.jsonl   file  batch_output   \n",
       "1  batch_sV6na1dUQabLp5jEEjTODCKX_output.jsonl   file  batch_output   \n",
       "2  batch_31Ks4sc5G78nOYlbbjo2QXaQ_output.jsonl   file  batch_output   \n",
       "3  batch_C4fvfp1QCYG0zDWLMhDnPC0Z_output.jsonl   file  batch_output   \n",
       "4  batch_O1YgvIBmEs60RbsXPqkv9MB9_output.jsonl   file  batch_output   \n",
       "\n",
       "      status status_details  \n",
       "0  processed           None  \n",
       "1  processed           None  \n",
       "2  processed           None  \n",
       "3  processed           None  \n",
       "4  processed           None  "
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from oa.stores import OaDacc\n",
    "from operator import methodcaller\n",
    "import pandas as pd\n",
    "\n",
    "dacc = OaDacc()\n",
    "files_base_df = pd.DataFrame(map(methodcaller('to_dict'), dacc.s.files_base))\n",
    "\n",
    "print(f\"{files_base_df.shape=}\")\n",
    "files_base_df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 303,
   "metadata": {},
   "outputs": [],
   "source": [
    "sample_ids = set()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 304,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "filename\n",
       "jsonl     1075\n",
       "upload    1067\n",
       "Name: count, dtype: int64"
      ]
     },
     "execution_count": 304,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# count of the extensions of filename\n",
    "files_base_df['filename'].map(lambda x: x.split('.')[-1]).value_counts()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 305,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'file-LIUSqUiT6i6hNql4IoSBXNh9', 'file-iM7az3OdiSB8IquweGY0A80U'}"
      ]
     },
     "execution_count": 305,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "t = files_base_df.copy()\n",
    "t['ext'] = files_base_df['filename'].map(lambda x: x.split('.')[-1])\n",
    "extensions = list(t.ext.value_counts().keys())\n",
    "sample_ids = sample_ids.union(\n",
    "    {t[t.ext == ext].sample(1).iloc[0].id for ext in extensions}\n",
    ")\n",
    "sample_ids"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 306,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "purpose\n",
       "batch           1075\n",
       "batch_output    1067\n",
       "Name: count, dtype: int64"
      ]
     },
     "execution_count": 306,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "files_base_df.purpose.value_counts()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 307,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'file-8NHJytpO1UV5ZNmdlK4YJKym', 'file-U5IcHh4HcNAHv5ttLEOR5ckK'}"
      ]
     },
     "execution_count": 307,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "purposes = list(files_base_df.purpose.value_counts().keys())\n",
    "sample_ids = {files_base_df[files_base_df.purpose == purpose].sample(1).iloc[0].id for purpose in purposes}\n",
    "sample_ids"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'file-34ZkXnCXrcQHzVhKoX5bdpRm',\n",
       " 'file-8NHJytpO1UV5ZNmdlK4YJKym',\n",
       " 'file-Cnsi7RwEqdlLhkEakYFibCPi',\n",
       " 'file-DVT6hjyjOfGSPvGS6sIMmV7b',\n",
       " 'file-PLd6aiVjYSi6it2vqlpQ1X3O',\n",
       " 'file-Pnm7OST8fgRmZiXGVZYOOWwy',\n",
       " 'file-U5IcHh4HcNAHv5ttLEOR5ckK',\n",
       " 'file-esrScSpwaugCAM3c7Ppe7r8q',\n",
       " 'file-gAJSQEXDwer8GmITjC2cxZzV',\n",
       " 'file-oO8Fxd9Og8NKOlXFEv9EZ4va',\n",
       " 'file-qEWRFpinTdG4PhxnD9k1GqMG',\n",
       " 'file-qxa6QOhHvs1niWX9l9VZp0ix',\n",
       " 'file-uaVi3cU9MzKUKYBj3VcnZCfu'}"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# pick rows with bytes of varied values\n",
    "\n",
    "# sort the df by the bytes column\n",
    "t = files_base_df.sort_values('bytes')\n",
    "# get the 0th, 10th, 20th, etc. percentile\n",
    "step = len(t)//10\n",
    "sample_ids = sample_ids.union(list(t.iloc[::step]['id'].values))\n",
    "sample_ids\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<bound method BaseModel.model_validate of <class '__main__.JsonL'>>"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from pydantic import RootModel\n",
    "from typing import List\n",
    "\n",
    "class JsonL(RootModel[List[dict]]):\n",
    "    pass\n",
    "\n",
    "\n",
    "t = [{'input': 'king'}, {'input': 'queen'}, {'input': 'male'}, {'input': 'female'}]\n",
    "\n",
    "JsonL.model_validate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [],
   "source": [
    "from oa.oa_types import *\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_not_covered_ids(ids, models=None):\n",
    "    if not models:\n",
    "        from oa.oa_types import BatchRequest, ResponseRoot, InputDataJsonL\n",
    "\n",
    "        models = [BatchRequest, ResponseRoot, InputDataJsonL]\n",
    "\n",
    "    models_cover_this_data = lambda d: bool(next(valid_models(d, models), None))\n",
    "\n",
    "    partial(valid_models, models=models)\n",
    "\n",
    "    def gen():\n",
    "        try:\n",
    "            for file_id in ids:\n",
    "                file_data = dacc.s.json_files[file_id]\n",
    "                if not models_cover_this_data(file_data):\n",
    "                    yield file_id\n",
    "        except Exception as e:\n",
    "            print(f\"Error for {file_id=}: {e}\")\n",
    "\n",
    "    return list(gen())\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [],
   "source": [
    "from oa.oa_types import BatchRequest, ResponseRoot, InputDataJsonL\n",
    "\n",
    "models = [BatchRequest, ResponseRoot, InputDataJsonL]\n",
    "\n",
    "not_covered_ids = get_not_covered_ids(sample_ids, models)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dict"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "w = dacc.s.json_files[next(iter(dacc.s.files_base.keys()))]\n",
    "type(w)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [],
   "source": [
    "t = dacc.s.files_base['file-DVT6hjyjOfGSPvGS6sIMmV7b']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [],
   "source": [
    "b = t.response.content"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'application/octet-stream'"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "t.response.headers['content-type']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'application/octet-stream'"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tt = next(iter(dacc.s.files_base.values()))\n",
    "tt.response.headers['content-type']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from oa.util import jsonl_loads, jsonl_dumps\n",
    "\n",
    "models_cover_this_data(jsonl_loads(b))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[oa.oa_types.BatchRequest, oa.oa_types.ResponseRoot]"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "t = [{'input': 'king'}, {'input': 'queen'}, {'input': 'male'}, {'input': 'female'}]\n",
    "your_models"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from functools import partial\n",
    "from typing import List, Dict, ClassVar, Type, Optional, Any\n",
    "from abc import abstractmethod\n",
    "from pprint import pformat\n",
    "\n",
    "from pydantic import BaseModel, Field, ValidationError\n",
    "from lkj import truncate_dict_values\n",
    "\n",
    "    \n",
    "truncate_dict_list_values = partial(truncate_dict_values, max_string_size=50)\n",
    "\n",
    "\n",
    "# Base class for all JSON responses\n",
    "class JsonResponse(BaseModel):\n",
    "    # Class-level registry for dynamically registering subclasses\n",
    "    _response_registry: ClassVar[Dict[str, Type['JsonResponse']]] = {}\n",
    "\n",
    "    custom_id: str\n",
    "\n",
    "    @abstractmethod\n",
    "    def value(self):\n",
    "        \"\"\"Extract main data from the JSON response\"\"\"\n",
    "        pass\n",
    "\n",
    "    @classmethod\n",
    "    def register_response_type(cls, name: str, response_cls: Type['JsonResponse']):\n",
    "        \"\"\"Register a new response type to the registry\"\"\"\n",
    "        cls._response_registry[name] = response_cls\n",
    "\n",
    "    @classmethod\n",
    "    def from_dict(cls, data: Dict) -> 'JsonResponse':\n",
    "        \"\"\"Determine which response type to instantiate by attempting validation\"\"\"\n",
    "        for response_type, response_cls in cls._response_registry.items():\n",
    "            try:\n",
    "                return response_cls.model_validate(data)\n",
    "            except ValidationError:\n",
    "                continue\n",
    "        \n",
    "        raise ValueError(\n",
    "            \"No valid response type found for this data: \\n\"\n",
    "            f\"{pformat(truncate_dict_values(data))}\"\n",
    "        )\n",
    "\n",
    "# Successful response model\n",
    "class ResponseBodyModel(BaseModel):\n",
    "    object: str\n",
    "    data: List[dict]\n",
    "\n",
    "class ResponseModel(BaseModel):\n",
    "    status_code: int = Field(..., ge=100, le=599)\n",
    "    body: ResponseBodyModel\n",
    "\n",
    "class ResponseSuccessModel(JsonResponse):\n",
    "    response: ResponseModel\n",
    "\n",
    "    def value(self):\n",
    "        return {\n",
    "            'object': self.response.body.object,\n",
    "            'n_data': len(self.response.body.data),\n",
    "        }\n",
    "\n",
    "\n",
    "class ErrorDetailsModel(BaseModel):\n",
    "    message: str\n",
    "    type: str\n",
    "    param: Optional[Any]\n",
    "    code: Optional[Any]\n",
    "\n",
    "class ErrorBodyModel(BaseModel):\n",
    "    error: ErrorDetailsModel\n",
    "\n",
    "class ResponseModel(BaseModel):\n",
    "    status_code: int = Field(..., eq=400)\n",
    "    body: ErrorBodyModel\n",
    "\n",
    "class ErrorResponseModel(BaseModel):\n",
    "    response: ResponseModel\n",
    "\n",
    "\n",
    "# Input data model\n",
    "class InputBodyModel(BaseModel):\n",
    "    input: List[List[int]]\n",
    "\n",
    "class InputModel(JsonResponse):\n",
    "    body: InputBodyModel\n",
    "\n",
    "    def value(self):\n",
    "        return {\n",
    "            'input_type': type(self.body.input),\n",
    "            'n_input': len(self.body.input),\n",
    "            'n_input_0': len(self.body.input[0]),\n",
    "        }\n",
    "\n",
    "\n",
    "\n",
    "# Registering the subclasses with appropriate names\n",
    "JsonResponse.register_response_type('response', ResponseSuccessModel)\n",
    "JsonResponse.register_response_type('response_error', ErrorResponseModel)\n",
    "JsonResponse.register_response_type('input', InputModel)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'id': 'batch_req_0qWxQ4rcAnzo9lEUMZR7xsgo',\n",
       " 'custom_id': 'embeddings_batch_id-1724503217185829120',\n",
       " 'response': {'status_code': 200,\n",
       "  'request_id': 'dacf8a2486eb1d6a7070852bf04d292d',\n",
       "  'body': {'object': 'list',\n",
       "   'data': [{'object': 'embedding',\n",
       "     'index': 0,\n",
       "     'embedding': [0.017829118, -0.0066988687]},\n",
       "    {'object': 'embedding',\n",
       "     'index': 1,\n",
       "     'embedding': [0.0010772116, -0.0015551111]}],\n",
       "   'model': 'text-embedding-3-small',\n",
       "   'usage': {'prompt_tokens': 629349, 'total_tokens': 629349}}},\n",
       " 'error': None}"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from pydantic import create_model\n",
    "\n",
    "M = create_pydantic_model(\"TestModel\", truncate_dict_values(v))\n",
    "from i2 import Sig\n",
    "\n",
    "Sig(M).defaults"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'file-g1iSPVYMatQRuCRQAkIGFBUA'"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "k = next(iter(dacc.s.json_files))\n",
    "k"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pydantic import create_model\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "next(iter(dacc.s))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "# for i, id_ in enumerate(sorted(all_files_df.id.to_list()[21:], reverse=True)):\n",
    "#     print_progress(f\"---> {i=}: {id_}\")\n",
    "#     jdict = dacc.s.json_files[id_]\n",
    "#     print(JsonResponse.from_dict(jdict))\n",
    "#     print(\"\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Extracting types from openai code"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import get_origin, Dict\n",
    "\n",
    "def is_generic_alias(annotation):\n",
    "    return get_origin(annotation) is not None\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Batch, Image, Model, ErrorObject, FunctionDefinition, ResponseFormatText,\n",
      "ResponseFormatJSONObject, ResponseFormatJSONSchema, Upload, Embedding,\n",
      "Completion, Moderation, BatchError, FileObject, FileContent, FileDeleted,\n",
      "ModelDeleted, ImagesResponse, CompletionUsage, FileListParams, BatchListParams,\n",
      "CompletionChoice, ImageEditParams, FileCreateParams, BatchCreateParams,\n",
      "BatchRequestCounts, UploadCreateParams, ImageGenerateParams,\n",
      "UploadCompleteParams, EmbeddingCreateParams, ModerationCreateParams,\n",
      "CreateEmbeddingResponse, ModerationCreateResponse, ImageCreateVariationParams\n",
      "\n",
      "FunctionParameters, ChatModel, AudioModel, ImageModel, FilePurpose,\n",
      "ModerationModel, CompletionCreateParams\n"
     ]
    }
   ],
   "source": [
    "import openai.types\n",
    "from lkj import wrapped_print\n",
    "\n",
    "type_classes = {k: v for k, v in vars(openai.types).items() if isinstance(v, type)}\n",
    "generic_aliases = {k: v for k, v in vars(openai.types).items() if is_generic_alias(v)}\n",
    "wrapped_print(type_classes)\n",
    "print(\"\")\n",
    "wrapped_print(generic_aliases)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Batch:\t['openai.BaseModel', 'pydantic.main.BaseModel', 'builtins.object']\n",
      "Image:\t['openai.BaseModel', 'pydantic.main.BaseModel', 'builtins.object']\n",
      "Model:\t['openai.BaseModel', 'pydantic.main.BaseModel', 'builtins.object']\n",
      "ErrorObject:\t['openai.BaseModel', 'pydantic.main.BaseModel', 'builtins.object']\n",
      "FunctionDefinition:\t['openai.BaseModel', 'pydantic.main.BaseModel', 'builtins.object']\n",
      "ResponseFormatText:\t['openai.BaseModel', 'pydantic.main.BaseModel', 'builtins.object']\n",
      "ResponseFormatJSONObject:\t['openai.BaseModel', 'pydantic.main.BaseModel', 'builtins.object']\n",
      "ResponseFormatJSONSchema:\t['openai.BaseModel', 'pydantic.main.BaseModel', 'builtins.object']\n",
      "Upload:\t['openai.BaseModel', 'pydantic.main.BaseModel', 'builtins.object']\n",
      "Embedding:\t['openai.BaseModel', 'pydantic.main.BaseModel', 'builtins.object']\n",
      "Completion:\t['openai.BaseModel', 'pydantic.main.BaseModel', 'builtins.object']\n",
      "Moderation:\t['openai.BaseModel', 'pydantic.main.BaseModel', 'builtins.object']\n",
      "BatchError:\t['openai.BaseModel', 'pydantic.main.BaseModel', 'builtins.object']\n",
      "FileObject:\t['openai.BaseModel', 'pydantic.main.BaseModel', 'builtins.object']\n",
      "FileContent:\t['builtins.object']\n",
      "FileDeleted:\t['openai.BaseModel', 'pydantic.main.BaseModel', 'builtins.object']\n",
      "ModelDeleted:\t['openai.BaseModel', 'pydantic.main.BaseModel', 'builtins.object']\n",
      "ImagesResponse:\t['openai.BaseModel', 'pydantic.main.BaseModel', 'builtins.object']\n",
      "CompletionUsage:\t['openai.BaseModel', 'pydantic.main.BaseModel', 'builtins.object']\n",
      "FileListParams:\t['builtins.dict', 'builtins.object']\n",
      "BatchListParams:\t['builtins.dict', 'builtins.object']\n",
      "CompletionChoice:\t['openai.BaseModel', 'pydantic.main.BaseModel', 'builtins.object']\n",
      "ImageEditParams:\t['builtins.dict', 'builtins.object']\n",
      "FileCreateParams:\t['builtins.dict', 'builtins.object']\n",
      "BatchCreateParams:\t['builtins.dict', 'builtins.object']\n",
      "BatchRequestCounts:\t['openai.BaseModel', 'pydantic.main.BaseModel', 'builtins.object']\n",
      "UploadCreateParams:\t['builtins.dict', 'builtins.object']\n",
      "ImageGenerateParams:\t['builtins.dict', 'builtins.object']\n",
      "UploadCompleteParams:\t['builtins.dict', 'builtins.object']\n",
      "EmbeddingCreateParams:\t['builtins.dict', 'builtins.object']\n",
      "ModerationCreateParams:\t['builtins.dict', 'builtins.object']\n",
      "CreateEmbeddingResponse:\t['openai.BaseModel', 'pydantic.main.BaseModel', 'builtins.object']\n",
      "ModerationCreateResponse:\t['openai.BaseModel', 'pydantic.main.BaseModel', 'builtins.object']\n",
      "ImageCreateVariationParams:\t['builtins.dict', 'builtins.object']\n"
     ]
    }
   ],
   "source": [
    "for k, v in type_classes.items():\n",
    "    mro_names = [f\"{c.__module__}.{c.__name__}\" for c in v.mro()]\n",
    "    print(f\"{k}:\\t{mro_names[1:]}\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## extracting prompt functions from files"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['define_jargon', 'suggest_names']"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from oa.tools import PromptFuncs\n",
    "\n",
    "f = PromptFuncs()\n",
    "list(f)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "_extract_names_and_specifiers_from_format_string"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## suggest names"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "from oa import prompt_function\n",
    "\n",
    "prompt_template = \"\"\"Suggest {n:30} names \n",
    "between {min_length:1} and {max_length:15} characters long for {thing}.\n",
    "Only output the names, one per line with no words before or after it, \n",
    "since I will be parsing the output.\n",
    "\"\"\"\n",
    "\n",
    "from i2 import Sig\n",
    "\n",
    "suggest_names = prompt_function(\n",
    "    prompt_template, \n",
    "    arg_kinds={'thing': Sig.POSITIONAL_OR_KEYWORD}\n",
    ")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "names = suggest_names(\n",
    "    \"\"\"A python package that helps you make functions that gauge ML model accuracy. \n",
    "    The names need to all be unique, and be a valid English word.\"\"\",\n",
    "    min_length=2,\n",
    "    max_length=6,\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "score\n",
      "metric\n",
      "rate\n",
      "grade\n",
      "rank\n",
      "eval\n",
      "valid\n",
      "check\n",
      "test\n",
      "assess\n",
      "judge\n",
      "mark\n",
      "measure\n",
      "assure\n",
      "probe\n",
      "level\n",
      "gauge\n",
      "assay\n",
      "probe\n",
      "probe\n",
      "verify\n",
      "examine\n",
      "audit\n",
      "scan\n",
      "monitor\n",
      "check\n",
      "check\n",
      "estimate\n",
      "assay\n",
      "probe\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print(names)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## OpenAPI OpenAI"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T13:43:57.223364Z",
     "start_time": "2023-04-22T13:43:57.204007Z"
    }
   },
   "outputs": [],
   "source": [
    "import yaml\n",
    "import io\n",
    "import pandas as pd\n",
    "from oa.util import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T17:31:49.026355Z",
     "start_time": "2023-04-22T17:31:49.000958Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<functools._lru_cache_wrapper at 0x140dcdfe0>"
      ]
     },
     "execution_count": 91,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Align OpenAPI specs and openai python functions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T20:43:05.105472Z",
     "start_time": "2023-04-22T20:43:01.684244Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['openapi', 'info', 'servers', 'tags', 'paths', 'components', 'x-oaiMeta']"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import oa\n",
    "from oa.openai_specs import *\n",
    "\n",
    "specs = get_openapi_spec_dict()\n",
    "list(specs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T20:43:05.108177Z",
     "start_time": "2023-04-22T20:43:05.106295Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['moderation',\n",
       " 'embedding',\n",
       " 'completion',\n",
       " 'edit',\n",
       " 'file',\n",
       " 'image',\n",
       " 'chatcompletion',\n",
       " 'finetune']"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(raw)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T20:43:05.141284Z",
     "start_time": "2023-04-22T20:43:05.108904Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'description': 'The maximum number of tokens allowed for the generated answer. By default, the number of tokens the model can return will be (4096 - prompt tokens).\\n',\n",
       " 'default': 'inf',\n",
       " 'type': 'integer'}"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# specs['components']['schemas']['CreateChatCompletionRequest']['properties']['max_tokens']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T20:46:35.601812Z",
     "start_time": "2023-04-22T20:46:34.914382Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<OpenAIObject text_completion id=cmpl-78EPr1zTxjdDLz5NWdVqVmuCFdSGp at 0x128af5260> JSON: {\n",
       "  \"choices\": [\n",
       "    {\n",
       "      \"finish_reason\": \"length\",\n",
       "      \"index\": 0,\n",
       "      \"logprobs\": null,\n",
       "      \"text\": \" famous Italian scientist and inventor who lived during the Italian Renaissance period. He was the\"\n",
       "    }\n",
       "  ],\n",
       "  \"created\": 1682196395,\n",
       "  \"id\": \"cmpl-78EPr1zTxjdDLz5NWdVqVmuCFdSGp\",\n",
       "  \"model\": \"text-davinci-003\",\n",
       "  \"object\": \"text_completion\",\n",
       "  \"usage\": {\n",
       "    \"completion_tokens\": 16,\n",
       "    \"prompt_tokens\": 5,\n",
       "    \"total_tokens\": 21\n",
       "  }\n",
       "}"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r = raw.completion(model='text-davinci-003', prompt='Davinci was a')\n",
    "r"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T20:47:05.057285Z",
     "start_time": "2023-04-22T20:47:05.048578Z"
    }
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T20:43:19.511145Z",
     "start_time": "2023-04-22T20:43:05.148760Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<OpenAIObject chat.completion id=chatcmpl-78EMTRRWSB3uGnVV5aJWyx3qqkPVu at 0x11fccbab0> JSON: {\n",
       "  \"choices\": [\n",
       "    {\n",
       "      \"finish_reason\": \"stop\",\n",
       "      \"index\": 0,\n",
       "      \"message\": {\n",
       "        \"content\": \"1. Simplify complex systems: Facades provide a simplified interface to complex systems, reducing the cognitive load on programmers and minimizing the risk of errors.\\n\\n2. Promote decoupling: Facades can serve as a decoupling layer between subsystems, allowing them to vary independently without affecting one another.\\n\\n3. Easy maintenance and refactoring: By hiding the implementation details, facades make it easier to maintain, modify, and refactor code without affecting the clients or other subsystems.\\n\\n4. Enhance security: Facades can encapsulate sensitive functionality and protect it from unauthorized access, thus enhancing security.\\n\\n5. Promote scalability: Facades can enable the addition of new subsystems easily, promoting scalability and adaptability.\\n\\n6. Standardize interfaces: Facades can establish standard interfaces for interacting with subsystems, promoting consistency and reducing errors.\\n\\n7. Improve code organization: Facades help organize code by grouping related functionality into cohesive subsystems. \\n\\n8. Facilitate testing: With facades, testing is simplified since testing a subsystem is limited to the interactions authorized by its facade interface.\",\n",
       "        \"role\": \"assistant\"\n",
       "      }\n",
       "    }\n",
       "  ],\n",
       "  \"created\": 1682196185,\n",
       "  \"id\": \"chatcmpl-78EMTRRWSB3uGnVV5aJWyx3qqkPVu\",\n",
       "  \"model\": \"gpt-3.5-turbo-0301\",\n",
       "  \"object\": \"chat.completion\",\n",
       "  \"usage\": {\n",
       "    \"completion_tokens\": 220,\n",
       "    \"prompt_tokens\": 19,\n",
       "    \"total_tokens\": 239\n",
       "  }\n",
       "}"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r = raw.chatcompletion(\n",
    "    model=oa.base.DFLT_MODEL, \n",
    "    messages=[{'role': 'user', 'content': 'What are the advantages of using facades in software programming'}],\n",
    ")\n",
    "r"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "raw."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 218,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T19:08:02.554951Z",
     "start_time": "2023-04-22T19:07:57.639127Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<OpenAIObject at 0x15f1d9c10> JSON: {\n",
       "  \"created\": 1682190482,\n",
       "  \"data\": [\n",
       "    {\n",
       "      \"url\": \"https://oaidalleapiprodscus.blob.core.windows.net/private/org-AY3lr3H3xB9yPQ0HGR498f9M/user-7ZNCDYLWzP0GT48V6DCiTFWt/img-C1cM6Rm5Gt0u0rWsDmMQ0YQi.png?st=2023-04-22T18%3A08%3A02Z&se=2023-04-22T20%3A08%3A02Z&sp=r&sv=2021-08-06&sr=b&rscd=inline&rsct=image/png&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2023-04-22T16%3A37%3A32Z&ske=2023-04-23T16%3A37%3A32Z&sks=b&skv=2021-08-06&sig=AoUuq0ityXULl%2BQ6nfpyXIrtvPFRxskIqSjDI5qAVfc%3D\"\n",
       "    }\n",
       "  ]\n",
       "}"
      ]
     },
     "execution_count": 218,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "oa.dalle('Simple interface to a complex system', user='oa')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 219,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T19:08:27.257037Z",
     "start_time": "2023-04-22T19:08:27.233365Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<bound method Image.create of <class 'openai.api_resources.image.Image'>>"
      ]
     },
     "execution_count": 219,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "oa.openai.Image.create"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T19:33:10.674650Z",
     "start_time": "2023-04-22T19:33:05.525999Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<OpenAIObject at 0x12f9d6ed0> JSON: {\n",
       "  \"created\": 1682191990,\n",
       "  \"data\": [\n",
       "    {\n",
       "      \"url\": \"https://oaidalleapiprodscus.blob.core.windows.net/private/org-AY3lr3H3xB9yPQ0HGR498f9M/user-7ZNCDYLWzP0GT48V6DCiTFWt/img-MgRw6okqv6hSRjGPSymBHKDj.png?st=2023-04-22T18%3A33%3A10Z&se=2023-04-22T20%3A33%3A10Z&sp=r&sv=2021-08-06&sr=b&rscd=inline&rsct=image/png&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2023-04-22T14%3A54%3A20Z&ske=2023-04-23T14%3A54%3A20Z&sks=b&skv=2021-08-06&sig=cDVJkyhgshlFElvEHSrp7WC26YmZ7lmSA8RR%2BKTSgDA%3D\"\n",
       "    }\n",
       "  ]\n",
       "}"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "resp2 = t.image('Simple interface to a complex system', size='512x512')\n",
    "resp2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Scrap to make raw"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T19:32:03.298669Z",
     "start_time": "2023-04-22T19:32:03.286058Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Sig (prompt: str, *, n: int = 1, size: str = '1024x1024', response_format: str = 'url', user: str = 'oa')>"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sig.CreateImageRequest\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T19:31:01.587547Z",
     "start_time": "2023-04-22T19:30:55.396468Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<OpenAIObject at 0x12fba1580> JSON: {\n",
       "  \"created\": 1682191861,\n",
       "  \"data\": [\n",
       "    {\n",
       "      \"url\": \"https://oaidalleapiprodscus.blob.core.windows.net/private/org-AY3lr3H3xB9yPQ0HGR498f9M/user-7ZNCDYLWzP0GT48V6DCiTFWt/img-iKnxgqk3bsBvyqpTwqACgQ3q.png?st=2023-04-22T18%3A31%3A01Z&se=2023-04-22T20%3A31%3A01Z&sp=r&sv=2021-08-06&sr=b&rscd=inline&rsct=image/png&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2023-04-22T15%3A28%3A53Z&ske=2023-04-23T15%3A28%3A53Z&sks=b&skv=2021-08-06&sig=%2BsWS0gGbxv9FcXRg5O1XZe/LWo4IsLthw/eAqCN0p3k%3D\"\n",
       "    }\n",
       "  ]\n",
       "}"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sig.CreateImageRequest\n",
    "\n",
    "schemas['CreateImageRequest']\n",
    "oa.openai.Image.create(prompt='Davinci')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 225,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T19:12:04.508110Z",
     "start_time": "2023-04-22T19:12:04.477639Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Sig (*args, **kwargs)>"
      ]
     },
     "execution_count": 225,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import i2\n",
    "i2.Sig(oa.openai.Image.create)\n",
    "i2.Sig(oa.openai.Completion.create)\n",
    "i2.Sig(oa.openai.ChatCompletion.create)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 226,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T19:13:20.478534Z",
     "start_time": "2023-04-22T19:13:20.456290Z"
    }
   },
   "outputs": [],
   "source": [
    "import openai"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T19:14:54.019543Z",
     "start_time": "2023-04-22T19:14:53.968606Z"
    }
   },
   "outputs": [],
   "source": [
    "# w = oa.openai.Completion(model=oa.base.DFLT_ENGINE, prompt='Davinci was a')\n",
    "# w.create()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 231,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T19:14:34.701725Z",
     "start_time": "2023-04-22T19:14:33.416016Z"
    }
   },
   "outputs": [],
   "source": [
    "from i2 import wrap\n",
    "\n",
    "def gen():\n",
    "    for name in matched_names:\n",
    "        sig_for_func = getattr(sig, f\"Create{name}Request\")\n",
    "        func = wrap(getattr(oa.openai, name).create, name = name.lower())\n",
    "        yield name.lower(), sig_for_func(func)\n",
    "        \n",
    "        \n",
    "t = list(gen())[2][1]\n",
    "\n",
    "resp = t(model='text-davinci-003', prompt='Davinci was a')\n",
    "# <OpenAIObject text_completion id=cmpl-78CeaQkdM5aZxaTaYiEWLzP2kaMWp at 0x15eb07d80> JSON: {\n",
    "#   \"choices\": [\n",
    "#     {\n",
    "#       \"finish_reason\": \"length\",\n",
    "#       \"index\": 0,\n",
    "#       \"logprobs\": null,\n",
    "#       \"text\": \" scientist.\\n\\nLeonardo da Vinci (1452-1519)\"\n",
    "#     }\n",
    "#   ],\n",
    "#   \"created\": 1682189620,\n",
    "#   \"id\": \"cmpl-78CeaQkdM5aZxaTaYiEWLzP2kaMWp\",\n",
    "#   \"model\": \"text-davinci-003\",\n",
    "#   \"object\": \"text_completion\",\n",
    "#   \"usage\": {\n",
    "#     \"completion_tokens\": 16,\n",
    "#     \"prompt_tokens\": 5,\n",
    "#     \"total_tokens\": 21\n",
    "#   }\n",
    "# }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 190,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T18:55:35.241882Z",
     "start_time": "2023-04-22T18:55:35.210818Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'id': 'cmpl-78CeaQkdM5aZxaTaYiEWLzP2kaMWp',\n",
       " 'object': 'text_completion',\n",
       " 'created': 1682189620,\n",
       " 'model': 'text-davinci-003',\n",
       " 'choices': [{'text': ' scientist.\\n\\nLeonardo da Vinci (1452-1519)',\n",
       "   'index': 0,\n",
       "   'logprobs': None,\n",
       "   'finish_reason': 'length'}],\n",
       " 'usage': {'prompt_tokens': 5, 'completion_tokens': 16, 'total_tokens': 21}}"
      ]
     },
     "execution_count": 190,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "resp.to_dict_recursive()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 191,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T18:56:10.929776Z",
     "start_time": "2023-04-22T18:56:10.901514Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "' scientist.\\n\\nLeonardo da Vinci (1452-1519)'"
      ]
     },
     "execution_count": 191,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "resp['choices'][0]['text']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 182,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T18:52:52.239566Z",
     "start_time": "2023-04-22T18:52:52.213322Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'text-davinci-003'"
      ]
     },
     "execution_count": 182,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "oa.base.DFLT_ENGINE"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 174,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T18:42:05.498399Z",
     "start_time": "2023-04-22T18:42:04.723692Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<i2.Wrap asd(x)>"
      ]
     },
     "execution_count": 174,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "wrap(lambda x: x, name='asd')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 144,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T18:27:13.953772Z",
     "start_time": "2023-04-22T18:27:13.927384Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Sig (input, *, model: str = 'text-moderation-latest')>"
      ]
     },
     "execution_count": 144,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sig.CreateTranscriptionRequest\n",
    "oa.openai."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 140,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T18:24:02.245755Z",
     "start_time": "2023-04-22T18:24:02.220639Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['Image',\n",
       " 'ContextVar',\n",
       " 'OpenAIError',\n",
       " 'Deployment',\n",
       " 'Engine',\n",
       " 'ErrorObject',\n",
       " 'Edit',\n",
       " 'Model',\n",
       " 'Completion',\n",
       " 'Embedding',\n",
       " 'Moderation',\n",
       " 'FineTune',\n",
       " 'Customer',\n",
       " 'File',\n",
       " 'APIError',\n",
       " 'InvalidRequestError',\n",
       " 'ChatCompletion',\n",
       " 'Audio']"
      ]
     },
     "execution_count": 140,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[x for x in list(attrs) if isinstance(getattr(oa.openai, x), type)]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### specs/shema scrap"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-29T13:46:14.690090Z",
     "start_time": "2023-03-29T13:46:14.661352Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n"
     ]
    }
   ],
   "source": [
    "from functools import partial\n",
    "import re\n",
    "from dol.paths import _path_get as path_get  # intending on switching both!\n",
    "\n",
    "from dol.recipes import search_paths\n",
    "\n",
    "def string_matching(pattern, p, k, v):\n",
    "    matches_string = re.compile(pattern).search\n",
    "    return (\n",
    "        isinstance(k, str) and matches_string(k)\n",
    "        or\n",
    "        isinstance(v, str) and matches_string(v)\n",
    "    )\n",
    "\n",
    "it = search_paths(specs, pkv_filt=partial(string_matching, '\\$ref'))\n",
    "t = list(it)\n",
    "print(f'{len(t)}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T14:25:42.936670Z",
     "start_time": "2023-04-22T14:25:42.910732Z"
    }
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-29T13:46:15.789126Z",
     "start_time": "2023-03-29T13:46:15.751898Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[]"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import jsonref\n",
    "expanded_specs = jsonref.JsonRef.replace_refs(specs)\n",
    "list(search_paths(expanded_specs, pkv_filt=partial(string_matching, '\\$ref')))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-29T13:46:24.344107Z",
     "start_time": "2023-03-29T13:46:24.327927Z"
    }
   },
   "outputs": [],
   "source": [
    "from http2py import HttpClient\n",
    "api = HttpClient(openapi_spec=expanded_specs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-29T13:46:26.490566Z",
     "start_time": "2023-03-29T13:46:26.478465Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['auth_type',\n",
       " 'base_url',\n",
       " 'ensure_login',\n",
       " 'handle_request',\n",
       " 'init_security',\n",
       " 'is_request_method',\n",
       " 'login_input_keys',\n",
       " 'login_url',\n",
       " 'openapi_spec',\n",
       " 'receive_login',\n",
       " 'refresh_input_keys',\n",
       " 'refresh_inputs',\n",
       " 'refresh_login',\n",
       " 'refresh_url',\n",
       " 'register_method',\n",
       " 'request_func',\n",
       " 'session',\n",
       " 'set_header',\n",
       " 'set_profile',\n",
       " 'title',\n",
       " 'verify_cert',\n",
       " 'version']"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(x for x in dir(api) if not x.startswith('_'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-29T12:46:55.447435Z",
     "start_time": "2023-03-29T12:46:55.416199Z"
    }
   },
   "outputs": [],
   "source": [
    "# from openapi_python_client import generate_client\n",
    "\n",
    "# OpenAPIGenerator.from_url(\n",
    "#     'https://raw.githubusercontent.com/openai/openai-openapi/master/openapi.yaml',\n",
    "#     output_dir='example_api_client',\n",
    "#     package_name='example_api_client'\n",
    "# )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-29T12:46:49.068869Z",
     "start_time": "2023-03-29T12:46:49.044869Z"
    }
   },
   "outputs": [],
   "source": [
    "import sys\n",
    "\n",
    "# Add the 'my_project' folder to the Python path\n",
    "sys.path.insert(0, '/Users/thorwhalen/tmp/open-ai-api-client')\n",
    "\n",
    "# # Import a module from the 'my_package' package\n",
    "# from my_package import my_module\n",
    "\n",
    "import open_ai_api_client as oc\n",
    "import open_ai_api_client.api\n",
    "from open_ai_api_client.api import open_ai"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# import extrude\n",
    "# from extrude import mk_api, run_api\n",
    "\n",
    "# def _make_children_story(story, image_style):\n",
    "#     return make_children_story(story, image_style)\n",
    "\n",
    "# app = mk_api([_make_children_story])\n",
    "# run_api(app, server='wsgiref')\n",
    "\n",
    "# check out:\n",
    "\n",
    "# http://localhost:3030/openapi\n",
    "\n",
    "# http://localhost:3030/swagger"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Schemas"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T16:51:27.793298Z",
     "start_time": "2023-04-22T16:51:27.753409Z"
    }
   },
   "outputs": [],
   "source": [
    "%load_ext autoreload\n",
    "%autoreload 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T16:52:24.212594Z",
     "start_time": "2023-04-22T16:52:24.190991Z"
    }
   },
   "outputs": [],
   "source": [
    "from oa.util import *\n",
    "from oa.openai_specs import *\n",
    "# import oa"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T16:59:27.831896Z",
     "start_time": "2023-04-22T16:59:26.589925Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<OpenAIObject text_completion id=cmpl-78As2dcVt7dtn4oaOhnGv7eEatKbM at 0x1570724d0> JSON: {\n",
       "  \"choices\": [\n",
       "    {\n",
       "      \"finish_reason\": \"length\",\n",
       "      \"index\": 0,\n",
       "      \"logprobs\": null,\n",
       "      \"text\": \"This is a dedicated private space exclusively only for you. It is the best option\"\n",
       "    }\n",
       "  ],\n",
       "  \"created\": 1682182766,\n",
       "  \"id\": \"cmpl-78As2dcVt7dtn4oaOhnGv7eEatKbM\",\n",
       "  \"model\": \"text-davinci-003\",\n",
       "  \"object\": \"text_completion\",\n",
       "  \"usage\": {\n",
       "    \"completion_tokens\": 16,\n",
       "    \"prompt_tokens\": 1,\n",
       "    \"total_tokens\": 17\n",
       "  }\n",
       "}"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from i2 import wrap\n",
    "\n",
    "f = wrap(oa.openai.Completion.create)\n",
    "f.__signature__ = sig.CreateCompletionRequest\n",
    "f(model=oa.base.DFLT_ENGINE)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T17:04:32.495235Z",
     "start_time": "2023-04-22T17:04:32.468802Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'Answer',\n",
       " 'Classification',\n",
       " 'ImageEdit',\n",
       " 'ImageVariation',\n",
       " 'Search',\n",
       " 'Transcription',\n",
       " 'Translation'}"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = [x[len('Create'):-len('Request')] for x in vars(sig) if x.startswith('Create') and x.endswith('Request')]\n",
    "aligned_service_names = [aa for aa in a if hasattr(oa.openai, aa)]\n",
    "not_aligned_service_names = set(a) - set(aligned_service_names)\n",
    "not_aligned_service_names"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T17:07:05.867138Z",
     "start_time": "2023-04-22T17:07:05.843854Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Sig (file: str, model: str, *, prompt: str, language: str, response_format: str = 'json', temperature: float = 0)>"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "oa.openai.Audio.transcribe\n",
    "\n",
    "sig.CreateTranscriptionRequest"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T17:07:50.424499Z",
     "start_time": "2023-04-22T17:07:50.397006Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['openapi', 'info', 'servers', 'tags', 'paths', 'components', 'x-oaiMeta']"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(specs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T17:08:44.111907Z",
     "start_time": "2023-04-22T17:08:44.089350Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['/engines',\n",
       " '/engines/{engine_id}',\n",
       " '/completions',\n",
       " '/chat/completions',\n",
       " '/edits',\n",
       " '/images/generations',\n",
       " '/images/edits',\n",
       " '/images/variations',\n",
       " '/embeddings',\n",
       " '/audio/transcriptions',\n",
       " '/audio/translations',\n",
       " '/engines/{engine_id}/search',\n",
       " '/files',\n",
       " '/files/{file_id}',\n",
       " '/files/{file_id}/content',\n",
       " '/answers',\n",
       " '/classifications',\n",
       " '/fine-tunes',\n",
       " '/fine-tunes/{fine_tune_id}',\n",
       " '/fine-tunes/{fine_tune_id}/cancel',\n",
       " '/fine-tunes/{fine_tune_id}/events',\n",
       " '/models',\n",
       " '/models/{model}',\n",
       " '/moderations']"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "paths = specs['paths']\n",
    "list(paths)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T17:09:41.831201Z",
     "start_time": "2023-04-22T17:09:41.804652Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['operationId', 'tags', 'summary', 'requestBody', 'responses', 'x-oaiMeta']"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(paths['/chat/completions']['post'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T17:09:51.307531Z",
     "start_time": "2023-04-22T17:09:51.283392Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'operationId': 'createChatCompletion',\n",
       " 'tags': ['OpenAI'],\n",
       " 'summary': 'Creates a completion for the chat message',\n",
       " 'requestBody': {'required': True,\n",
       "  'content': {'application/json': {'schema': {'type': 'object',\n",
       "     'properties': {'model': {'description': 'ID of the model to use. Currently, only `gpt-3.5-turbo` and `gpt-3.5-turbo-0301` are supported.',\n",
       "       'type': 'string'},\n",
       "      'messages': {'description': 'The messages to generate chat completions for, in the [chat format](/docs/guides/chat/introduction).',\n",
       "       'type': 'array',\n",
       "       'minItems': 1,\n",
       "       'items': {'type': 'object',\n",
       "        'properties': {'role': {'type': 'string',\n",
       "          'enum': ['system', 'user', 'assistant'],\n",
       "          'description': 'The role of the author of this message.'},\n",
       "         'content': {'type': 'string',\n",
       "          'description': 'The contents of the message'},\n",
       "         'name': {'type': 'string',\n",
       "          'description': 'The name of the user in a multi-user chat'}},\n",
       "        'required': ['role', 'content']}},\n",
       "      'temperature': {'type': 'number',\n",
       "       'minimum': 0,\n",
       "       'maximum': 2,\n",
       "       'default': 1,\n",
       "       'example': 1,\n",
       "       'nullable': True,\n",
       "       'description': 'What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\\n\\nWe generally recommend altering this or `top_p` but not both.\\n'},\n",
       "      'top_p': {'type': 'number',\n",
       "       'minimum': 0,\n",
       "       'maximum': 1,\n",
       "       'default': 1,\n",
       "       'example': 1,\n",
       "       'nullable': True,\n",
       "       'description': 'An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.\\n\\nWe generally recommend altering this or `temperature` but not both.\\n'},\n",
       "      'n': {'type': 'integer',\n",
       "       'minimum': 1,\n",
       "       'maximum': 128,\n",
       "       'default': 1,\n",
       "       'example': 1,\n",
       "       'nullable': True,\n",
       "       'description': 'How many chat completion choices to generate for each input message.'},\n",
       "      'stream': {'description': 'If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) as they become available, with the stream terminated by a `data: [DONE]` message.\\n',\n",
       "       'type': 'boolean',\n",
       "       'nullable': True,\n",
       "       'default': False},\n",
       "      'stop': {'description': 'Up to 4 sequences where the API will stop generating further tokens.\\n',\n",
       "       'default': None,\n",
       "       'oneOf': [{'type': 'string', 'nullable': True},\n",
       "        {'type': 'array',\n",
       "         'minItems': 1,\n",
       "         'maxItems': 4,\n",
       "         'items': {'type': 'string'}}]},\n",
       "      'max_tokens': {'description': 'The maximum number of tokens allowed for the generated answer. By default, the number of tokens the model can return will be (4096 - prompt tokens).\\n',\n",
       "       'default': 'inf',\n",
       "       'type': 'integer'},\n",
       "      'presence_penalty': {'type': 'number',\n",
       "       'default': 0,\n",
       "       'minimum': -2,\n",
       "       'maximum': 2,\n",
       "       'nullable': True,\n",
       "       'description': \"Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.\\n\\n[See more information about frequency and presence penalties.](/docs/api-reference/parameter-details)\\n\"},\n",
       "      'frequency_penalty': {'type': 'number',\n",
       "       'default': 0,\n",
       "       'minimum': -2,\n",
       "       'maximum': 2,\n",
       "       'nullable': True,\n",
       "       'description': \"Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.\\n\\n[See more information about frequency and presence penalties.](/docs/api-reference/parameter-details)\\n\"},\n",
       "      'logit_bias': {'type': 'object',\n",
       "       'x-oaiTypeLabel': 'map',\n",
       "       'default': None,\n",
       "       'nullable': True,\n",
       "       'description': 'Modify the likelihood of specified tokens appearing in the completion.\\n\\nAccepts a json object that maps tokens (specified by their token ID in the tokenizer) to an associated bias value from -100 to 100. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token.\\n'},\n",
       "      'user': {'type': 'string',\n",
       "       'example': 'user-1234',\n",
       "       'description': 'A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids).\\n'}},\n",
       "     'required': ['model', 'messages']}}}},\n",
       " 'responses': {'200': {'description': 'OK',\n",
       "   'content': {'application/json': {'schema': {'type': 'object',\n",
       "      'properties': {'id': {'type': 'string'},\n",
       "       'object': {'type': 'string'},\n",
       "       'created': {'type': 'integer'},\n",
       "       'model': {'type': 'string'},\n",
       "       'choices': {'type': 'array',\n",
       "        'items': {'type': 'object',\n",
       "         'properties': {'index': {'type': 'integer'},\n",
       "          'message': {'type': 'object',\n",
       "           'properties': {'role': {'type': 'string',\n",
       "             'enum': ['system', 'user', 'assistant'],\n",
       "             'description': 'The role of the author of this message.'},\n",
       "            'content': {'type': 'string',\n",
       "             'description': 'The contents of the message'}},\n",
       "           'required': ['role', 'content']},\n",
       "          'finish_reason': {'type': 'string'}}}},\n",
       "       'usage': {'type': 'object',\n",
       "        'properties': {'prompt_tokens': {'type': 'integer'},\n",
       "         'completion_tokens': {'type': 'integer'},\n",
       "         'total_tokens': {'type': 'integer'}},\n",
       "        'required': ['prompt_tokens', 'completion_tokens', 'total_tokens']}},\n",
       "      'required': ['id', 'object', 'created', 'model', 'choices']}}}}},\n",
       " 'x-oaiMeta': {'name': 'Create chat completion',\n",
       "  'group': 'chat',\n",
       "  'path': 'create',\n",
       "  'beta': True,\n",
       "  'examples': {'curl': 'curl https://api.openai.com/v1/chat/completions \\\\\\n  -H \\'Content-Type: application/json\\' \\\\\\n  -H \\'Authorization: Bearer YOUR_API_KEY\\' \\\\\\n  -d \\'{\\n  \"model\": \"gpt-3.5-turbo\",\\n  \"messages\": [{\"role\": \"user\", \"content\": \"Hello!\"}]\\n}\\'\\n',\n",
       "   'python': 'import os\\nimport openai\\nopenai.api_key = os.getenv(\"OPENAI_API_KEY\")\\n\\ncompletion = openai.ChatCompletion.create(\\n  model=\"gpt-3.5-turbo\",\\n  messages=[\\n    {\"role\": \"user\", \"content\": \"Hello!\"}\\n  ]\\n)\\n\\nprint(completion.choices[0].message)\\n',\n",
       "   'node.js': 'const { Configuration, OpenAIApi } = require(\"openai\");\\n\\nconst configuration = new Configuration({\\n  apiKey: process.env.OPENAI_API_KEY,\\n});\\nconst openai = new OpenAIApi(configuration);\\n\\nconst completion = await openai.createChatCompletion({\\n  model: \"gpt-3.5-turbo\",\\n  messages: [{role: \"user\", content: \"Hello world\"}],\\n});\\nconsole.log(completion.data.choices[0].message);\\n'},\n",
       "  'parameters': '{\\n  \"model\": \"gpt-3.5-turbo\",\\n  \"messages\": [{\"role\": \"user\", \"content\": \"Hello!\"}]\\n}\\n',\n",
       "  'response': '{\\n  \"id\": \"chatcmpl-123\",\\n  \"object\": \"chat.completion\",\\n  \"created\": 1677652288,\\n  \"choices\": [{\\n    \"index\": 0,\\n    \"message\": {\\n      \"role\": \"assistant\",\\n      \"content\": \"\\\\n\\\\nHello there, how may I assist you today?\",\\n    },\\n    \"finish_reason\": \"stop\"\\n  }],\\n  \"usage\": {\\n    \"prompt_tokens\": 9,\\n    \"completion_tokens\": 12,\\n    \"total_tokens\": 21\\n  }\\n}\\n'}}"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "paths['/chat/completions']['post']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T17:16:57.746333Z",
     "start_time": "2023-04-22T17:16:57.714226Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('paths', '/engines', 'get', 'operationId'),\n",
       " ('paths', '/engines/{engine_id}', 'get', 'operationId'),\n",
       " ('paths', '/completions', 'post', 'operationId'),\n",
       " ('paths', '/chat/completions', 'post', 'operationId'),\n",
       " ('paths', '/edits', 'post', 'operationId'),\n",
       " ('paths', '/images/generations', 'post', 'operationId'),\n",
       " ('paths', '/images/edits', 'post', 'operationId'),\n",
       " ('paths', '/images/variations', 'post', 'operationId'),\n",
       " ('paths', '/embeddings', 'post', 'operationId'),\n",
       " ('paths', '/audio/transcriptions', 'post', 'operationId'),\n",
       " ('paths', '/audio/translations', 'post', 'operationId'),\n",
       " ('paths', '/engines/{engine_id}/search', 'post', 'operationId'),\n",
       " ('paths', '/files', 'get', 'operationId'),\n",
       " ('paths', '/files', 'post', 'operationId'),\n",
       " ('paths', '/files/{file_id}', 'delete', 'operationId'),\n",
       " ('paths', '/files/{file_id}', 'get', 'operationId'),\n",
       " ('paths', '/files/{file_id}/content', 'get', 'operationId'),\n",
       " ('paths', '/answers', 'post', 'operationId'),\n",
       " ('paths', '/classifications', 'post', 'operationId'),\n",
       " ('paths', '/fine-tunes', 'post', 'operationId'),\n",
       " ('paths', '/fine-tunes', 'get', 'operationId'),\n",
       " ('paths', '/fine-tunes/{fine_tune_id}', 'get', 'operationId'),\n",
       " ('paths', '/fine-tunes/{fine_tune_id}/cancel', 'post', 'operationId'),\n",
       " ('paths', '/fine-tunes/{fine_tune_id}/events', 'get', 'operationId'),\n",
       " ('paths', '/models', 'get', 'operationId'),\n",
       " ('paths', '/models/{model}', 'get', 'operationId'),\n",
       " ('paths', '/models/{model}', 'delete', 'operationId'),\n",
       " ('paths', '/moderations', 'post', 'operationId')]"
      ]
     },
     "execution_count": 65,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T17:10:25.015054Z",
     "start_time": "2023-04-22T17:10:24.990771Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Creates a completion for the chat message'"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "paths['/chat/completions']['post']['summary']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "oa.openai.ChatCompletion.create"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T17:12:16.578213Z",
     "start_time": "2023-04-22T17:12:16.548739Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'type': 'object',\n",
       " 'properties': {'model': {'description': 'ID of the model to use. Currently, only `gpt-3.5-turbo` and `gpt-3.5-turbo-0301` are supported.',\n",
       "   'type': 'string'},\n",
       "  'messages': {'description': 'The messages to generate chat completions for, in the [chat format](/docs/guides/chat/introduction).',\n",
       "   'type': 'array',\n",
       "   'minItems': 1,\n",
       "   'items': {'type': 'object',\n",
       "    'properties': {'role': {'type': 'string',\n",
       "      'enum': ['system', 'user', 'assistant'],\n",
       "      'description': 'The role of the author of this message.'},\n",
       "     'content': {'type': 'string',\n",
       "      'description': 'The contents of the message'},\n",
       "     'name': {'type': 'string',\n",
       "      'description': 'The name of the user in a multi-user chat'}},\n",
       "    'required': ['role', 'content']}},\n",
       "  'temperature': {'type': 'number',\n",
       "   'minimum': 0,\n",
       "   'maximum': 2,\n",
       "   'default': 1,\n",
       "   'example': 1,\n",
       "   'nullable': True,\n",
       "   'description': 'What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\\n\\nWe generally recommend altering this or `top_p` but not both.\\n'},\n",
       "  'top_p': {'type': 'number',\n",
       "   'minimum': 0,\n",
       "   'maximum': 1,\n",
       "   'default': 1,\n",
       "   'example': 1,\n",
       "   'nullable': True,\n",
       "   'description': 'An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.\\n\\nWe generally recommend altering this or `temperature` but not both.\\n'},\n",
       "  'n': {'type': 'integer',\n",
       "   'minimum': 1,\n",
       "   'maximum': 128,\n",
       "   'default': 1,\n",
       "   'example': 1,\n",
       "   'nullable': True,\n",
       "   'description': 'How many chat completion choices to generate for each input message.'},\n",
       "  'stream': {'description': 'If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) as they become available, with the stream terminated by a `data: [DONE]` message.\\n',\n",
       "   'type': 'boolean',\n",
       "   'nullable': True,\n",
       "   'default': False},\n",
       "  'stop': {'description': 'Up to 4 sequences where the API will stop generating further tokens.\\n',\n",
       "   'default': None,\n",
       "   'oneOf': [{'type': 'string', 'nullable': True},\n",
       "    {'type': 'array',\n",
       "     'minItems': 1,\n",
       "     'maxItems': 4,\n",
       "     'items': {'type': 'string'}}]},\n",
       "  'max_tokens': {'description': 'The maximum number of tokens allowed for the generated answer. By default, the number of tokens the model can return will be (4096 - prompt tokens).\\n',\n",
       "   'default': 'inf',\n",
       "   'type': 'integer'},\n",
       "  'presence_penalty': {'type': 'number',\n",
       "   'default': 0,\n",
       "   'minimum': -2,\n",
       "   'maximum': 2,\n",
       "   'nullable': True,\n",
       "   'description': \"Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.\\n\\n[See more information about frequency and presence penalties.](/docs/api-reference/parameter-details)\\n\"},\n",
       "  'frequency_penalty': {'type': 'number',\n",
       "   'default': 0,\n",
       "   'minimum': -2,\n",
       "   'maximum': 2,\n",
       "   'nullable': True,\n",
       "   'description': \"Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.\\n\\n[See more information about frequency and presence penalties.](/docs/api-reference/parameter-details)\\n\"},\n",
       "  'logit_bias': {'type': 'object',\n",
       "   'x-oaiTypeLabel': 'map',\n",
       "   'default': None,\n",
       "   'nullable': True,\n",
       "   'description': 'Modify the likelihood of specified tokens appearing in the completion.\\n\\nAccepts a json object that maps tokens (specified by their token ID in the tokenizer) to an associated bias value from -100 to 100. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token.\\n'},\n",
       "  'user': {'type': 'string',\n",
       "   'example': 'user-1234',\n",
       "   'description': 'A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids).\\n'}},\n",
       " 'required': ['model', 'messages']}"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "paths['/chat/completions']['post']['requestBody']['content']['application/json']['schema']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T17:02:46.879047Z",
     "start_time": "2023-04-22T17:02:46.854549Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Completion\n",
      "ChatCompletion\n",
      "Edit\n",
      "Image\n",
      "Moderation\n",
      "File\n",
      "FineTune\n",
      "Embedding\n"
     ]
    }
   ],
   "source": [
    "for aa in a:\n",
    "    if hasattr(oa.openai, aa):\n",
    "        print(aa)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T16:53:29.596200Z",
     "start_time": "2023-04-22T16:53:29.552760Z"
    }
   },
   "outputs": [
    {
     "ename": "AttributeError",
     "evalue": "'method' object has no attribute '__signature__'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
      "Cell \u001b[0;32mIn[10], line 4\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01moa\u001b[39;00m\n\u001b[1;32m      2\u001b[0m i2\u001b[38;5;241m.\u001b[39mSig(oa\u001b[38;5;241m.\u001b[39mopenai\u001b[38;5;241m.\u001b[39mChatCompletion\u001b[38;5;241m.\u001b[39mcreate)\n\u001b[0;32m----> 4\u001b[0m \u001b[43mi2\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mSig\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43ma\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m(\u001b[49m\u001b[43moa\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mopenai\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mChatCompletion\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcreate\u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[0;32m~/Dropbox/py/proj/i/i2/i2/signatures.py:1121\u001b[0m, in \u001b[0;36mSig.__call__\u001b[0;34m(self, func)\u001b[0m\n\u001b[1;32m   1116\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__call__\u001b[39m(\u001b[38;5;28mself\u001b[39m, func: Callable):\n\u001b[1;32m   1117\u001b[0m     \u001b[38;5;124;03m\"\"\"Gives the input function the signature.\u001b[39;00m\n\u001b[1;32m   1118\u001b[0m \u001b[38;5;124;03m    Just calls Sig.wrap so see docs of Sig.wrap (which contains examples and\u001b[39;00m\n\u001b[1;32m   1119\u001b[0m \u001b[38;5;124;03m    doctests).\u001b[39;00m\n\u001b[1;32m   1120\u001b[0m \u001b[38;5;124;03m    \"\"\"\u001b[39;00m\n\u001b[0;32m-> 1121\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mwrap\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfunc\u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[0;32m~/Dropbox/py/proj/i/i2/i2/signatures.py:1101\u001b[0m, in \u001b[0;36mSig.wrap\u001b[0;34m(self, func, ignore_incompatible_signatures, copy_function)\u001b[0m\n\u001b[1;32m   1097\u001b[0m _validate_sanity_of_signature_change(func, \u001b[38;5;28mself\u001b[39m, ignore_incompatible_signatures)\n\u001b[1;32m   1099\u001b[0m \u001b[38;5;66;03m# Change (mutate!) func, writing a new __signature__, __annotations__,\u001b[39;00m\n\u001b[1;32m   1100\u001b[0m \u001b[38;5;66;03m# __defaults__ and __kwdefaults__\u001b[39;00m\n\u001b[0;32m-> 1101\u001b[0m \u001b[43mfunc\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m__signature__\u001b[49m \u001b[38;5;241m=\u001b[39m Sig(\n\u001b[1;32m   1102\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mparameters\u001b[38;5;241m.\u001b[39mvalues(), return_annotation\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreturn_annotation\n\u001b[1;32m   1103\u001b[0m )\n\u001b[1;32m   1104\u001b[0m func\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__annotations__\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mannotations\n\u001b[1;32m   1105\u001b[0m func\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__defaults__\u001b[39m, func\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__kwdefaults__\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_dunder_defaults_and_kwdefaults()\n",
      "\u001b[0;31mAttributeError\u001b[0m: 'method' object has no attribute '__signature__'"
     ]
    }
   ],
   "source": [
    "import oa\n",
    "i2.Sig(oa.openai.ChatCompletion.create)\n",
    "\n",
    "i2.Sig('a')(oa.openai.ChatCompletion.create)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T16:38:49.232779Z",
     "start_time": "2023-04-22T16:38:49.221446Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'description': 'ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](/docs/models/overview) for descriptions of them.',\n",
       " 'type': 'string'}"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "schemas['CreateCompletionRequest']['properties']['model']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T16:38:49.244886Z",
     "start_time": "2023-04-22T16:38:49.234818Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Sig (model: str, messages: List[oa.openai_specs.Message], *, temperature: float = 1, top_p: float = 1, n: int = 1, stream: bool = False, stop=None, max_tokens: int = 'inf', presence_penalty: float = 0, frequency_penalty: float = 0, logit_bias: dict = None, user: str = 'oa')>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sig.CreateChatCompletionRequest"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T16:38:49.255582Z",
     "start_time": "2023-04-22T16:38:49.245752Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['model',\n",
       " 'prompt',\n",
       " 'suffix',\n",
       " 'max_tokens',\n",
       " 'temperature',\n",
       " 'top_p',\n",
       " 'n',\n",
       " 'stream',\n",
       " 'logprobs',\n",
       " 'echo',\n",
       " 'stop',\n",
       " 'presence_penalty',\n",
       " 'frequency_penalty',\n",
       " 'best_of',\n",
       " 'logit_bias',\n",
       " 'user']"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sig.CreateImageRequest.names"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T16:39:01.981450Z",
     "start_time": "2023-04-22T16:39:01.955946Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Sig (prompt: str = None, model: str = 'gpt-3.5-turbo', messages: List[oa.openai_specs.Message] = None, *, temperature: float = 1, top_p: float = 1, n: int = 1, stream: bool = False, stop=None, max_tokens: int = 'inf', presence_penalty: float = 0, frequency_penalty: float = 0, logit_bias: dict = None, user: str = 'oa')>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import i2, oa\n",
    "\n",
    "i2.Sig(oa.chat)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T16:40:26.190872Z",
     "start_time": "2023-04-22T16:40:26.159552Z"
    }
   },
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "chat() missing 1 required keyword-only argument: 'messages'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "Cell \u001b[0;32mIn[8], line 3\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01moa\u001b[39;00m\n\u001b[0;32m----> 3\u001b[0m resp \u001b[38;5;241m=\u001b[39m \u001b[43moa\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mchat\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mWhat are the pros and cons of layering engineering complexities with a simple interface?\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n",
      "\u001b[0;31mTypeError\u001b[0m: chat() missing 1 required keyword-only argument: 'messages'"
     ]
    }
   ],
   "source": [
    "import oa\n",
    "\n",
    "resp = oa.chat('What are the pros and cons of layering engineering complexities with a simple interface?')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "oa.openai"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T16:31:15.959760Z",
     "start_time": "2023-04-22T16:31:15.933962Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Sig (model: str, messages: List[oa.openai_specs.Message], *, temperature: float = 1, top_p: float = 1, n: int = 1, stream: bool = False, stop=None, max_tokens: int = 'inf', presence_penalty: float = 0, frequency_penalty: float = 0, logit_bias: dict = None, user: str = 'oa')>"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sig.CreateChatCompletionRequest"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T15:45:42.258738Z",
     "start_time": "2023-04-22T15:45:42.252737Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ListEnginesResponse ListModelsResponse DeleteModelResponse CreateCompletionRequest CreateCompletionResponse ChatCompletionRequestMessage ChatCompletionResponseMessage CreateChatCompletionRequest CreateChatCompletionResponse CreateEditRequest CreateEditResponse CreateImageRequest ImagesResponse CreateImageEditRequest CreateImageVariationRequest CreateModerationRequest CreateModerationResponse CreateSearchRequest CreateSearchResponse ListFilesResponse CreateFileRequest DeleteFileResponse CreateAnswerRequest CreateAnswerResponse CreateClassificationRequest CreateClassificationResponse CreateFineTuneRequest ListFineTunesResponse ListFineTuneEventsResponse CreateEmbeddingRequest CreateEmbeddingResponse CreateTranscriptionRequest CreateTranscriptionResponse CreateTranslationRequest CreateTranslationResponse Engine Model OpenAIFile FineTune FineTuneEvent\n"
     ]
    }
   ],
   "source": [
    "schemas = specs['components']['schemas']\n",
    "print(*schemas)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T13:44:05.310907Z",
     "start_time": "2023-04-22T13:44:05.285791Z"
    }
   },
   "outputs": [],
   "source": [
    "# api = HttpClient(openapi_spec=specs)\n",
    "# print(*dir(api))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T15:44:52.764835Z",
     "start_time": "2023-04-22T15:44:52.747194Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<Param \"as=1\">, <Param \"aa\">]"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sorted([Param('as', default=1), Param('aa', Param.KO)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T15:42:36.335232Z",
     "start_time": "2023-04-22T15:42:36.284177Z"
    }
   },
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "missing a required argument: 'user'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "Cell \u001b[0;32mIn[38], line 8\u001b[0m\n\u001b[1;32m      5\u001b[0m     kwargs \u001b[38;5;241m=\u001b[39m Sig(foo)\u001b[38;5;241m.\u001b[39mkwargs_from_args_and_kwargs(args, kwargs)\n\u001b[1;32m      6\u001b[0m     \u001b[38;5;28mprint\u001b[39m(kwargs)\n\u001b[0;32m----> 8\u001b[0m \u001b[43mfoo\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m,\u001b[49m\u001b[38;5;241;43m2\u001b[39;49m\u001b[43m)\u001b[49m\n",
      "Cell \u001b[0;32mIn[38], line 5\u001b[0m, in \u001b[0;36mfoo\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m      3\u001b[0m \u001b[38;5;129m@sig\u001b[39m\u001b[38;5;241m.\u001b[39mCreateChatCompletionRequest\n\u001b[1;32m      4\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mfoo\u001b[39m(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[0;32m----> 5\u001b[0m     kwargs \u001b[38;5;241m=\u001b[39m \u001b[43mSig\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfoo\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mkwargs_from_args_and_kwargs\u001b[49m\u001b[43m(\u001b[49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m      6\u001b[0m     \u001b[38;5;28mprint\u001b[39m(kwargs)\n",
      "File \u001b[0;32m~/Dropbox/py/proj/i/i2/i2/signatures.py:2352\u001b[0m, in \u001b[0;36mSig.kwargs_from_args_and_kwargs\u001b[0;34m(self, args, kwargs, apply_defaults, allow_partial, allow_excess, ignore_kind, debug)\u001b[0m\n\u001b[1;32m   2347\u001b[0m     max_allowed_num_of_posisional_args \u001b[38;5;241m=\u001b[39m \u001b[38;5;28msum\u001b[39m(\n\u001b[1;32m   2348\u001b[0m         k \u001b[38;5;241m<\u001b[39m\u001b[38;5;241m=\u001b[39m PK \u001b[38;5;28;01mfor\u001b[39;00m k \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mkinds\u001b[38;5;241m.\u001b[39mvalues()\n\u001b[1;32m   2349\u001b[0m     )\n\u001b[1;32m   2350\u001b[0m     args \u001b[38;5;241m=\u001b[39m args[:max_allowed_num_of_posisional_args]\n\u001b[0;32m-> 2352\u001b[0m b \u001b[38;5;241m=\u001b[39m \u001b[43mbinder\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43msig_relevant_kwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m   2353\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m apply_defaults:\n\u001b[1;32m   2354\u001b[0m     b\u001b[38;5;241m.\u001b[39mapply_defaults()\n",
      "File \u001b[0;32m~/.pyenv/versions/3.10.8/lib/python3.10/inspect.py:3182\u001b[0m, in \u001b[0;36mSignature.bind\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m   3177\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mbind\u001b[39m(\u001b[38;5;28mself\u001b[39m, \u001b[38;5;241m/\u001b[39m, \u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m   3178\u001b[0m     \u001b[38;5;124;03m\"\"\"Get a BoundArguments object, that maps the passed `args`\u001b[39;00m\n\u001b[1;32m   3179\u001b[0m \u001b[38;5;124;03m    and `kwargs` to the function's signature.  Raises `TypeError`\u001b[39;00m\n\u001b[1;32m   3180\u001b[0m \u001b[38;5;124;03m    if the passed arguments can not be bound.\u001b[39;00m\n\u001b[1;32m   3181\u001b[0m \u001b[38;5;124;03m    \"\"\"\u001b[39;00m\n\u001b[0;32m-> 3182\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_bind\u001b[49m\u001b[43m(\u001b[49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[0;32m~/.pyenv/versions/3.10.8/lib/python3.10/inspect.py:3152\u001b[0m, in \u001b[0;36mSignature._bind\u001b[0;34m(self, args, kwargs, partial)\u001b[0m\n\u001b[1;32m   3145\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mKeyError\u001b[39;00m:\n\u001b[1;32m   3146\u001b[0m     \u001b[38;5;66;03m# We have no value for this parameter.  It's fine though,\u001b[39;00m\n\u001b[1;32m   3147\u001b[0m     \u001b[38;5;66;03m# if it has a default value, or it is an '*args'-like\u001b[39;00m\n\u001b[1;32m   3148\u001b[0m     \u001b[38;5;66;03m# parameter, left alone by the processing of positional\u001b[39;00m\n\u001b[1;32m   3149\u001b[0m     \u001b[38;5;66;03m# arguments.\u001b[39;00m\n\u001b[1;32m   3150\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m (\u001b[38;5;129;01mnot\u001b[39;00m partial \u001b[38;5;129;01mand\u001b[39;00m param\u001b[38;5;241m.\u001b[39mkind \u001b[38;5;241m!=\u001b[39m _VAR_POSITIONAL \u001b[38;5;129;01mand\u001b[39;00m\n\u001b[1;32m   3151\u001b[0m                                         param\u001b[38;5;241m.\u001b[39mdefault \u001b[38;5;129;01mis\u001b[39;00m _empty):\n\u001b[0;32m-> 3152\u001b[0m         \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mTypeError\u001b[39;00m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mmissing a required argument: \u001b[39m\u001b[38;5;132;01m{arg!r}\u001b[39;00m\u001b[38;5;124m'\u001b[39m\u001b[38;5;241m.\u001b[39m \\\n\u001b[1;32m   3153\u001b[0m                         \u001b[38;5;28mformat\u001b[39m(arg\u001b[38;5;241m=\u001b[39mparam_name)) \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;28mNone\u001b[39m\n\u001b[1;32m   3155\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m   3156\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m param\u001b[38;5;241m.\u001b[39mkind \u001b[38;5;241m==\u001b[39m _POSITIONAL_ONLY:\n\u001b[1;32m   3157\u001b[0m         \u001b[38;5;66;03m# This should never happen in case of a properly built\u001b[39;00m\n\u001b[1;32m   3158\u001b[0m         \u001b[38;5;66;03m# Signature object (but let's have this check here\u001b[39;00m\n\u001b[1;32m   3159\u001b[0m         \u001b[38;5;66;03m# to ensure correct behaviour just in case)\u001b[39;00m\n",
      "\u001b[0;31mTypeError\u001b[0m: missing a required argument: 'user'"
     ]
    }
   ],
   "source": [
    "from i2 import Sig, Param\n",
    "\n",
    "@sig.CreateChatCompletionRequest\n",
    "def foo(*args, **kwargs):\n",
    "    kwargs = Sig(foo).kwargs_from_args_and_kwargs(args, kwargs)\n",
    "    print(kwargs)\n",
    "\n",
    "foo(1,2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T15:30:54.025332Z",
     "start_time": "2023-04-22T15:30:54.016978Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'description': 'ID of the model to use. Currently, only `gpt-3.5-turbo` and `gpt-3.5-turbo-0301` are supported.',\n",
       " 'type': 'string'}"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tt = schemas['CreateChatCompletionRequest']\n",
    "tt['properties']['model']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T15:31:11.236781Z",
     "start_time": "2023-04-22T15:31:11.188723Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>description</th>\n",
       "      <th>type</th>\n",
       "      <th>minItems</th>\n",
       "      <th>items</th>\n",
       "      <th>minimum</th>\n",
       "      <th>maximum</th>\n",
       "      <th>default</th>\n",
       "      <th>example</th>\n",
       "      <th>nullable</th>\n",
       "      <th>oneOf</th>\n",
       "      <th>x-oaiTypeLabel</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>model</th>\n",
       "      <td>ID of the model to use. Currently, only `gpt-3...</td>\n",
       "      <td>string</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>messages</th>\n",
       "      <td>The messages to generate chat completions for,...</td>\n",
       "      <td>array</td>\n",
       "      <td>1</td>\n",
       "      <td>{'type': 'object', 'properties': {'role': {'ty...</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>temperature</th>\n",
       "      <td>What sampling temperature to use, between 0 an...</td>\n",
       "      <td>number</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>True</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>top_p</th>\n",
       "      <td>An alternative to sampling with temperature, c...</td>\n",
       "      <td>number</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>True</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>n</th>\n",
       "      <td>How many chat completion choices to generate f...</td>\n",
       "      <td>integer</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td>1</td>\n",
       "      <td>128</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>True</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>stream</th>\n",
       "      <td>If set, partial message deltas will be sent, l...</td>\n",
       "      <td>boolean</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td>False</td>\n",
       "      <td></td>\n",
       "      <td>True</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>stop</th>\n",
       "      <td>Up to 4 sequences where the API will stop gene...</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td>[{'type': 'string', 'nullable': True}, {'type'...</td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max_tokens</th>\n",
       "      <td>The maximum number of tokens allowed for the g...</td>\n",
       "      <td>integer</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td>inf</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>presence_penalty</th>\n",
       "      <td>Number between -2.0 and 2.0. Positive values p...</td>\n",
       "      <td>number</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td>-2</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td></td>\n",
       "      <td>True</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>frequency_penalty</th>\n",
       "      <td>Number between -2.0 and 2.0. Positive values p...</td>\n",
       "      <td>number</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td>-2</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td></td>\n",
       "      <td>True</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>logit_bias</th>\n",
       "      <td>Modify the likelihood of specified tokens appe...</td>\n",
       "      <td>object</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td>True</td>\n",
       "      <td></td>\n",
       "      <td>map</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>user</th>\n",
       "      <td>A unique identifier representing your end-user...</td>\n",
       "      <td>string</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td>user-1234</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                                         description     type  \\\n",
       "model              ID of the model to use. Currently, only `gpt-3...   string   \n",
       "messages           The messages to generate chat completions for,...    array   \n",
       "temperature        What sampling temperature to use, between 0 an...   number   \n",
       "top_p              An alternative to sampling with temperature, c...   number   \n",
       "n                  How many chat completion choices to generate f...  integer   \n",
       "stream             If set, partial message deltas will be sent, l...  boolean   \n",
       "stop               Up to 4 sequences where the API will stop gene...            \n",
       "max_tokens         The maximum number of tokens allowed for the g...  integer   \n",
       "presence_penalty   Number between -2.0 and 2.0. Positive values p...   number   \n",
       "frequency_penalty  Number between -2.0 and 2.0. Positive values p...   number   \n",
       "logit_bias         Modify the likelihood of specified tokens appe...   object   \n",
       "user               A unique identifier representing your end-user...   string   \n",
       "\n",
       "                  minItems                                              items  \\\n",
       "model                                                                           \n",
       "messages                 1  {'type': 'object', 'properties': {'role': {'ty...   \n",
       "temperature                                                                     \n",
       "top_p                                                                           \n",
       "n                                                                               \n",
       "stream                                                                          \n",
       "stop                                                                            \n",
       "max_tokens                                                                      \n",
       "presence_penalty                                                                \n",
       "frequency_penalty                                                               \n",
       "logit_bias                                                                      \n",
       "user                                                                            \n",
       "\n",
       "                  minimum maximum default    example nullable  \\\n",
       "model                                                           \n",
       "messages                                                        \n",
       "temperature             0       2       1          1     True   \n",
       "top_p                   0       1       1          1     True   \n",
       "n                       1     128       1          1     True   \n",
       "stream                              False                True   \n",
       "stop                                                            \n",
       "max_tokens                            inf                       \n",
       "presence_penalty       -2       2       0                True   \n",
       "frequency_penalty      -2       2       0                True   \n",
       "logit_bias                                               True   \n",
       "user                                       user-1234            \n",
       "\n",
       "                                                               oneOf  \\\n",
       "model                                                                  \n",
       "messages                                                               \n",
       "temperature                                                            \n",
       "top_p                                                                  \n",
       "n                                                                      \n",
       "stream                                                                 \n",
       "stop               [{'type': 'string', 'nullable': True}, {'type'...   \n",
       "max_tokens                                                             \n",
       "presence_penalty                                                       \n",
       "frequency_penalty                                                      \n",
       "logit_bias                                                             \n",
       "user                                                                   \n",
       "\n",
       "                  x-oaiTypeLabel  \n",
       "model                             \n",
       "messages                          \n",
       "temperature                       \n",
       "top_p                             \n",
       "n                                 \n",
       "stream                            \n",
       "stop                              \n",
       "max_tokens                        \n",
       "presence_penalty                  \n",
       "frequency_penalty                 \n",
       "logit_bias                   map  \n",
       "user                              "
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "schema = schemas['CreateChatCompletionRequest']\n",
    "chat_schema = pd.DataFrame(schema['properties']).T.fillna('')\n",
    "chat_schema"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T13:47:08.262123Z",
     "start_time": "2023-04-22T13:47:08.236953Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "- model: ID of the model to use. Currently, only `gpt-3.5-turbo` and `gpt-3.5-turbo-0301` are supported.\n",
      "\n",
      "- messages: The messages to generate chat completions for, in the [chat format](/docs/guides/chat/introduction).\n",
      "\n",
      "- temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\n",
      "\n",
      "We generally recommend altering this or `top_p` but not both.\n",
      "\n",
      "\n",
      "- top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.\n",
      "\n",
      "We generally recommend altering this or `temperature` but not both.\n",
      "\n",
      "\n",
      "- n: How many chat completion choices to generate for each input message.\n",
      "\n",
      "- stream: If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) as they become available, with the stream terminated by a `data: [DONE]` message.\n",
      "\n",
      "\n",
      "- stop: Up to 4 sequences where the API will stop generating further tokens.\n",
      "\n",
      "\n",
      "- max_tokens: The maximum number of tokens allowed for the generated answer. By default, the number of tokens the model can return will be (4096 - prompt tokens).\n",
      "\n",
      "\n",
      "- presence_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.\n",
      "\n",
      "[See more information about frequency and presence penalties.](/docs/api-reference/parameter-details)\n",
      "\n",
      "\n",
      "- frequency_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.\n",
      "\n",
      "[See more information about frequency and presence penalties.](/docs/api-reference/parameter-details)\n",
      "\n",
      "\n",
      "- logit_bias: Modify the likelihood of specified tokens appearing in the completion.\n",
      "\n",
      "Accepts a json object that maps tokens (specified by their token ID in the tokenizer) to an associated bias value from -100 to 100. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token.\n",
      "\n",
      "\n",
      "- user: A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids).\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print(*(f\"- {k}: {v}\" for k, v in chat_schema['description'].items()), sep='\\n\\n')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T15:07:27.996208Z",
     "start_time": "2023-04-22T15:07:27.660413Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['ListEnginesResponse',\n",
       " 'ListModelsResponse',\n",
       " 'DeleteModelResponse',\n",
       " 'CreateCompletionRequest',\n",
       " 'CreateCompletionResponse',\n",
       " 'ChatCompletionRequestMessage',\n",
       " 'ChatCompletionResponseMessage',\n",
       " 'CreateChatCompletionRequest',\n",
       " 'CreateChatCompletionResponse',\n",
       " 'CreateEditRequest',\n",
       " 'CreateEditResponse',\n",
       " 'CreateImageRequest',\n",
       " 'ImagesResponse',\n",
       " 'CreateImageEditRequest',\n",
       " 'CreateImageVariationRequest',\n",
       " 'CreateModerationRequest',\n",
       " 'CreateModerationResponse',\n",
       " 'CreateSearchRequest',\n",
       " 'CreateSearchResponse',\n",
       " 'ListFilesResponse',\n",
       " 'CreateFileRequest',\n",
       " 'DeleteFileResponse',\n",
       " 'CreateAnswerRequest',\n",
       " 'CreateAnswerResponse',\n",
       " 'CreateClassificationRequest',\n",
       " 'CreateClassificationResponse',\n",
       " 'CreateFineTuneRequest',\n",
       " 'ListFineTunesResponse',\n",
       " 'ListFineTuneEventsResponse',\n",
       " 'CreateEmbeddingRequest',\n",
       " 'CreateEmbeddingResponse',\n",
       " 'CreateTranscriptionRequest',\n",
       " 'CreateTranscriptionResponse',\n",
       " 'CreateTranslationRequest',\n",
       " 'CreateTranslationResponse',\n",
       " 'Engine',\n",
       " 'Model',\n",
       " 'OpenAIFile',\n",
       " 'FineTune',\n",
       " 'FineTuneEvent']"
      ]
     },
     "execution_count": 84,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T14:12:39.496222Z",
     "start_time": "2023-04-22T14:12:39.465176Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>description</th>\n",
       "      <th>type</th>\n",
       "      <th>default</th>\n",
       "      <th>nullable</th>\n",
       "      <th>oneOf</th>\n",
       "      <th>example</th>\n",
       "      <th>minimum</th>\n",
       "      <th>maximum</th>\n",
       "      <th>x-oaiTypeLabel</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>model</th>\n",
       "      <td>ID of the model to use. You can use the [List ...</td>\n",
       "      <td>string</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>prompt</th>\n",
       "      <td>The prompt(s) to generate completions for, enc...</td>\n",
       "      <td></td>\n",
       "      <td>&lt;|endoftext|&gt;</td>\n",
       "      <td>True</td>\n",
       "      <td>[{'type': 'string', 'default': '', 'example': ...</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>suffix</th>\n",
       "      <td>The suffix that comes after a completion of in...</td>\n",
       "      <td>string</td>\n",
       "      <td></td>\n",
       "      <td>True</td>\n",
       "      <td></td>\n",
       "      <td>test.</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max_tokens</th>\n",
       "      <td>The maximum number of [tokens](/tokenizer) to ...</td>\n",
       "      <td>integer</td>\n",
       "      <td>16</td>\n",
       "      <td>True</td>\n",
       "      <td></td>\n",
       "      <td>16</td>\n",
       "      <td>0</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>temperature</th>\n",
       "      <td>What sampling temperature to use, between 0 an...</td>\n",
       "      <td>number</td>\n",
       "      <td>1</td>\n",
       "      <td>True</td>\n",
       "      <td></td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>top_p</th>\n",
       "      <td>An alternative to sampling with temperature, c...</td>\n",
       "      <td>number</td>\n",
       "      <td>1</td>\n",
       "      <td>True</td>\n",
       "      <td></td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>n</th>\n",
       "      <td>How many completions to generate for each prom...</td>\n",
       "      <td>integer</td>\n",
       "      <td>1</td>\n",
       "      <td>True</td>\n",
       "      <td></td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>128</td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>stream</th>\n",
       "      <td>Whether to stream back partial progress. If se...</td>\n",
       "      <td>boolean</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>logprobs</th>\n",
       "      <td>Include the log probabilities on the `logprobs...</td>\n",
       "      <td>integer</td>\n",
       "      <td></td>\n",
       "      <td>True</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td>0</td>\n",
       "      <td>5</td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>echo</th>\n",
       "      <td>Echo back the prompt in addition to the comple...</td>\n",
       "      <td>boolean</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>stop</th>\n",
       "      <td>Up to 4 sequences where the API will stop gene...</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td>True</td>\n",
       "      <td>[{'type': 'string', 'default': '&lt;|endoftext|&gt;'...</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>presence_penalty</th>\n",
       "      <td>Number between -2.0 and 2.0. Positive values p...</td>\n",
       "      <td>number</td>\n",
       "      <td>0</td>\n",
       "      <td>True</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td>-2</td>\n",
       "      <td>2</td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>frequency_penalty</th>\n",
       "      <td>Number between -2.0 and 2.0. Positive values p...</td>\n",
       "      <td>number</td>\n",
       "      <td>0</td>\n",
       "      <td>True</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td>-2</td>\n",
       "      <td>2</td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>best_of</th>\n",
       "      <td>Generates `best_of` completions server-side an...</td>\n",
       "      <td>integer</td>\n",
       "      <td>1</td>\n",
       "      <td>True</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td>0</td>\n",
       "      <td>20</td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>logit_bias</th>\n",
       "      <td>Modify the likelihood of specified tokens appe...</td>\n",
       "      <td>object</td>\n",
       "      <td></td>\n",
       "      <td>True</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td>map</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>user</th>\n",
       "      <td>A unique identifier representing your end-user...</td>\n",
       "      <td>string</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td>user-1234</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                                         description     type  \\\n",
       "model              ID of the model to use. You can use the [List ...   string   \n",
       "prompt             The prompt(s) to generate completions for, enc...            \n",
       "suffix             The suffix that comes after a completion of in...   string   \n",
       "max_tokens         The maximum number of [tokens](/tokenizer) to ...  integer   \n",
       "temperature        What sampling temperature to use, between 0 an...   number   \n",
       "top_p              An alternative to sampling with temperature, c...   number   \n",
       "n                  How many completions to generate for each prom...  integer   \n",
       "stream             Whether to stream back partial progress. If se...  boolean   \n",
       "logprobs           Include the log probabilities on the `logprobs...  integer   \n",
       "echo               Echo back the prompt in addition to the comple...  boolean   \n",
       "stop               Up to 4 sequences where the API will stop gene...            \n",
       "presence_penalty   Number between -2.0 and 2.0. Positive values p...   number   \n",
       "frequency_penalty  Number between -2.0 and 2.0. Positive values p...   number   \n",
       "best_of            Generates `best_of` completions server-side an...  integer   \n",
       "logit_bias         Modify the likelihood of specified tokens appe...   object   \n",
       "user               A unique identifier representing your end-user...   string   \n",
       "\n",
       "                         default nullable  \\\n",
       "model                                       \n",
       "prompt             <|endoftext|>     True   \n",
       "suffix                               True   \n",
       "max_tokens                    16     True   \n",
       "temperature                    1     True   \n",
       "top_p                          1     True   \n",
       "n                              1     True   \n",
       "stream                     False     True   \n",
       "logprobs                             True   \n",
       "echo                       False     True   \n",
       "stop                                 True   \n",
       "presence_penalty               0     True   \n",
       "frequency_penalty              0     True   \n",
       "best_of                        1     True   \n",
       "logit_bias                           True   \n",
       "user                                        \n",
       "\n",
       "                                                               oneOf  \\\n",
       "model                                                                  \n",
       "prompt             [{'type': 'string', 'default': '', 'example': ...   \n",
       "suffix                                                                 \n",
       "max_tokens                                                             \n",
       "temperature                                                            \n",
       "top_p                                                                  \n",
       "n                                                                      \n",
       "stream                                                                 \n",
       "logprobs                                                               \n",
       "echo                                                                   \n",
       "stop               [{'type': 'string', 'default': '<|endoftext|>'...   \n",
       "presence_penalty                                                       \n",
       "frequency_penalty                                                      \n",
       "best_of                                                                \n",
       "logit_bias                                                             \n",
       "user                                                                   \n",
       "\n",
       "                     example minimum maximum x-oaiTypeLabel  \n",
       "model                                                        \n",
       "prompt                                                       \n",
       "suffix                 test.                                 \n",
       "max_tokens                16       0                         \n",
       "temperature                1       0       2                 \n",
       "top_p                      1       0       1                 \n",
       "n                          1       1     128                 \n",
       "stream                                                       \n",
       "logprobs                           0       5                 \n",
       "echo                                                         \n",
       "stop                                                         \n",
       "presence_penalty                  -2       2                 \n",
       "frequency_penalty                 -2       2                 \n",
       "best_of                            0      20                 \n",
       "logit_bias                                              map  \n",
       "user               user-1234                                 "
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "schema = schemas['CreateCompletionRequest']\n",
    "completion_schema = pd.DataFrame(schema['properties']).T.fillna('')\n",
    "completion_schema"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T14:12:49.757608Z",
     "start_time": "2023-04-22T14:12:49.729214Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "- model: ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](/docs/models/overview) for descriptions of them.\n",
      "\n",
      "- prompt: The prompt(s) to generate completions for, encoded as a string, array of strings, array of tokens, or array of token arrays.\n",
      "\n",
      "Note that <|endoftext|> is the document separator that the model sees during training, so if a prompt is not specified the model will generate as if from the beginning of a new document.\n",
      "\n",
      "\n",
      "- suffix: The suffix that comes after a completion of inserted text.\n",
      "\n",
      "- max_tokens: The maximum number of [tokens](/tokenizer) to generate in the completion.\n",
      "\n",
      "The token count of your prompt plus `max_tokens` cannot exceed the model's context length. Most models have a context length of 2048 tokens (except for the newest models, which support 4096).\n",
      "\n",
      "\n",
      "- temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\n",
      "\n",
      "We generally recommend altering this or `top_p` but not both.\n",
      "\n",
      "\n",
      "- top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.\n",
      "\n",
      "We generally recommend altering this or `temperature` but not both.\n",
      "\n",
      "\n",
      "- n: How many completions to generate for each prompt.\n",
      "\n",
      "**Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`.\n",
      "\n",
      "\n",
      "- stream: Whether to stream back partial progress. If set, tokens will be sent as data-only [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) as they become available, with the stream terminated by a `data: [DONE]` message.\n",
      "\n",
      "\n",
      "- logprobs: Include the log probabilities on the `logprobs` most likely tokens, as well the chosen tokens. For example, if `logprobs` is 5, the API will return a list of the 5 most likely tokens. The API will always return the `logprob` of the sampled token, so there may be up to `logprobs+1` elements in the response.\n",
      "\n",
      "The maximum value for `logprobs` is 5. If you need more than this, please contact us through our [Help center](https://help.openai.com) and describe your use case.\n",
      "\n",
      "\n",
      "- echo: Echo back the prompt in addition to the completion\n",
      "\n",
      "\n",
      "- stop: Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence.\n",
      "\n",
      "\n",
      "- presence_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.\n",
      "\n",
      "[See more information about frequency and presence penalties.](/docs/api-reference/parameter-details)\n",
      "\n",
      "\n",
      "- frequency_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.\n",
      "\n",
      "[See more information about frequency and presence penalties.](/docs/api-reference/parameter-details)\n",
      "\n",
      "\n",
      "- best_of: Generates `best_of` completions server-side and returns the \"best\" (the one with the highest log probability per token). Results cannot be streamed.\n",
      "\n",
      "When used with `n`, `best_of` controls the number of candidate completions and `n` specifies how many to return – `best_of` must be greater than `n`.\n",
      "\n",
      "**Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`.\n",
      "\n",
      "\n",
      "- logit_bias: Modify the likelihood of specified tokens appearing in the completion.\n",
      "\n",
      "Accepts a json object that maps tokens (specified by their token ID in the GPT tokenizer) to an associated bias value from -100 to 100. You can use this [tokenizer tool](/tokenizer?view=bpe) (which works for both GPT-2 and GPT-3) to convert text to token IDs. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token.\n",
      "\n",
      "As an example, you can pass `{\"50256\": -100}` to prevent the <|endoftext|> token from being generated.\n",
      "\n",
      "\n",
      "- user: A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids).\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print(*(f\"- {k}: {v}\" for k, v in completion_schema['description'].items()), sep='\\n\\n')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T15:00:05.825102Z",
     "start_time": "2023-04-22T15:00:05.799333Z"
    }
   },
   "outputs": [],
   "source": [
    "from oa.openai_specs import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T15:04:02.332349Z",
     "start_time": "2023-04-22T15:04:02.309114Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"(model: str, messages: List[dict], *, temperature: float = 1, top_p: float = 1, n: int = 1, stream: bool = False, stop=None, max_tokens: int = 'inf', presence_penalty: float = 0, frequency_penalty: float = 0, logit_bias: dict = None, user: str)\""
      ]
     },
     "execution_count": 80,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "str(schema_to_signature(schema))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-22T15:00:55.645217Z",
     "start_time": "2023-04-22T15:00:55.619004Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'model': {'description': 'ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](/docs/models/overview) for descriptions of them.',\n",
       "  'type': 'string'},\n",
       " 'prompt': {'description': 'The prompt(s) to generate completions for, encoded as a string, array of strings, array of tokens, or array of token arrays.\\n\\nNote that <|endoftext|> is the document separator that the model sees during training, so if a prompt is not specified the model will generate as if from the beginning of a new document.\\n',\n",
       "  'default': '<|endoftext|>',\n",
       "  'nullable': True,\n",
       "  'oneOf': [{'type': 'string', 'default': '', 'example': 'This is a test.'},\n",
       "   {'type': 'array',\n",
       "    'items': {'type': 'string', 'default': '', 'example': 'This is a test.'}},\n",
       "   {'type': 'array',\n",
       "    'minItems': 1,\n",
       "    'items': {'type': 'integer'},\n",
       "    'example': '[1212, 318, 257, 1332, 13]'},\n",
       "   {'type': 'array',\n",
       "    'minItems': 1,\n",
       "    'items': {'type': 'array', 'minItems': 1, 'items': {'type': 'integer'}},\n",
       "    'example': '[[1212, 318, 257, 1332, 13]]'}]},\n",
       " 'suffix': {'description': 'The suffix that comes after a completion of inserted text.',\n",
       "  'default': None,\n",
       "  'nullable': True,\n",
       "  'type': 'string',\n",
       "  'example': 'test.'},\n",
       " 'max_tokens': {'type': 'integer',\n",
       "  'minimum': 0,\n",
       "  'default': 16,\n",
       "  'example': 16,\n",
       "  'nullable': True,\n",
       "  'description': \"The maximum number of [tokens](/tokenizer) to generate in the completion.\\n\\nThe token count of your prompt plus `max_tokens` cannot exceed the model's context length. Most models have a context length of 2048 tokens (except for the newest models, which support 4096).\\n\"},\n",
       " 'temperature': {'type': 'number',\n",
       "  'minimum': 0,\n",
       "  'maximum': 2,\n",
       "  'default': 1,\n",
       "  'example': 1,\n",
       "  'nullable': True,\n",
       "  'description': 'What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\\n\\nWe generally recommend altering this or `top_p` but not both.\\n'},\n",
       " 'top_p': {'type': 'number',\n",
       "  'minimum': 0,\n",
       "  'maximum': 1,\n",
       "  'default': 1,\n",
       "  'example': 1,\n",
       "  'nullable': True,\n",
       "  'description': 'An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.\\n\\nWe generally recommend altering this or `temperature` but not both.\\n'},\n",
       " 'n': {'type': 'integer',\n",
       "  'minimum': 1,\n",
       "  'maximum': 128,\n",
       "  'default': 1,\n",
       "  'example': 1,\n",
       "  'nullable': True,\n",
       "  'description': 'How many completions to generate for each prompt.\\n\\n**Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`.\\n'},\n",
       " 'stream': {'description': 'Whether to stream back partial progress. If set, tokens will be sent as data-only [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) as they become available, with the stream terminated by a `data: [DONE]` message.\\n',\n",
       "  'type': 'boolean',\n",
       "  'nullable': True,\n",
       "  'default': False},\n",
       " 'logprobs': {'type': 'integer',\n",
       "  'minimum': 0,\n",
       "  'maximum': 5,\n",
       "  'default': None,\n",
       "  'nullable': True,\n",
       "  'description': 'Include the log probabilities on the `logprobs` most likely tokens, as well the chosen tokens. For example, if `logprobs` is 5, the API will return a list of the 5 most likely tokens. The API will always return the `logprob` of the sampled token, so there may be up to `logprobs+1` elements in the response.\\n\\nThe maximum value for `logprobs` is 5. If you need more than this, please contact us through our [Help center](https://help.openai.com) and describe your use case.\\n'},\n",
       " 'echo': {'type': 'boolean',\n",
       "  'default': False,\n",
       "  'nullable': True,\n",
       "  'description': 'Echo back the prompt in addition to the completion\\n'},\n",
       " 'stop': {'description': 'Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence.\\n',\n",
       "  'default': None,\n",
       "  'nullable': True,\n",
       "  'oneOf': [{'type': 'string',\n",
       "    'default': '<|endoftext|>',\n",
       "    'example': '\\n',\n",
       "    'nullable': True},\n",
       "   {'type': 'array',\n",
       "    'minItems': 1,\n",
       "    'maxItems': 4,\n",
       "    'items': {'type': 'string', 'example': '[\"\\\\n\"]'}}]},\n",
       " 'presence_penalty': {'type': 'number',\n",
       "  'default': 0,\n",
       "  'minimum': -2,\n",
       "  'maximum': 2,\n",
       "  'nullable': True,\n",
       "  'description': \"Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.\\n\\n[See more information about frequency and presence penalties.](/docs/api-reference/parameter-details)\\n\"},\n",
       " 'frequency_penalty': {'type': 'number',\n",
       "  'default': 0,\n",
       "  'minimum': -2,\n",
       "  'maximum': 2,\n",
       "  'nullable': True,\n",
       "  'description': \"Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.\\n\\n[See more information about frequency and presence penalties.](/docs/api-reference/parameter-details)\\n\"},\n",
       " 'best_of': {'type': 'integer',\n",
       "  'default': 1,\n",
       "  'minimum': 0,\n",
       "  'maximum': 20,\n",
       "  'nullable': True,\n",
       "  'description': 'Generates `best_of` completions server-side and returns the \"best\" (the one with the highest log probability per token). Results cannot be streamed.\\n\\nWhen used with `n`, `best_of` controls the number of candidate completions and `n` specifies how many to return – `best_of` must be greater than `n`.\\n\\n**Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`.\\n'},\n",
       " 'logit_bias': {'type': 'object',\n",
       "  'x-oaiTypeLabel': 'map',\n",
       "  'default': None,\n",
       "  'nullable': True,\n",
       "  'description': 'Modify the likelihood of specified tokens appearing in the completion.\\n\\nAccepts a json object that maps tokens (specified by their token ID in the GPT tokenizer) to an associated bias value from -100 to 100. You can use this [tokenizer tool](/tokenizer?view=bpe) (which works for both GPT-2 and GPT-3) to convert text to token IDs. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token.\\n\\nAs an example, you can pass `{\"50256\": -100}` to prevent the <|endoftext|> token from being generated.\\n'},\n",
       " 'user': {'type': 'string',\n",
       "  'example': 'user-1234',\n",
       "  'description': 'A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids).\\n'}}"
      ]
     },
     "execution_count": 74,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Paths"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-27T08:05:49.352582Z",
     "start_time": "2023-03-27T08:05:49.328212Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['/engines',\n",
       " '/engines/{engine_id}',\n",
       " '/completions',\n",
       " '/chat/completions',\n",
       " '/edits',\n",
       " '/images/generations',\n",
       " '/images/edits',\n",
       " '/images/variations',\n",
       " '/embeddings',\n",
       " '/audio/transcriptions',\n",
       " '/audio/translations',\n",
       " '/engines/{engine_id}/search',\n",
       " '/files',\n",
       " '/files/{file_id}',\n",
       " '/files/{file_id}/content',\n",
       " '/answers',\n",
       " '/classifications',\n",
       " '/fine-tunes',\n",
       " '/fine-tunes/{fine_tune_id}',\n",
       " '/fine-tunes/{fine_tune_id}/cancel',\n",
       " '/fine-tunes/{fine_tune_id}/events',\n",
       " '/models',\n",
       " '/models/{model}',\n",
       " '/moderations']"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(specs['paths'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-27T07:57:05.400226Z",
     "start_time": "2023-03-27T07:57:05.379075Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "model                {'description': 'ID of the model to use. Curre...\n",
      "messages             {'description': 'The messages to generate chat...\n",
      "temperature          {'type': 'number', 'minimum': 0, 'maximum': 2,...\n",
      "top_p                {'type': 'number', 'minimum': 0, 'maximum': 1,...\n",
      "n                    {'type': 'integer', 'minimum': 1, 'maximum': 1...\n",
      "stream               {'description': 'If set, partial message delta...\n",
      "stop                 {'description': 'Up to 4 sequences where the A...\n",
      "max_tokens           {'description': 'The maximum number of tokens ...\n",
      "presence_penalty     {'type': 'number', 'default': 0, 'minimum': -2...\n",
      "frequency_penalty    {'type': 'number', 'default': 0, 'minimum': -2...\n",
      "logit_bias           {'type': 'object', 'x-oaiTypeLabel': 'map', 'd...\n",
      "user                 {'type': 'string', 'example': 'user-1234', 'de...\n",
      "dtype: object\n",
      "['model', 'messages']\n"
     ]
    }
   ],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-27T07:53:28.271497Z",
     "start_time": "2023-03-27T07:53:28.252176Z"
    }
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-27T07:44:17.516750Z",
     "start_time": "2023-03-27T07:44:17.503486Z"
    }
   },
   "outputs": [],
   "source": [
    "from collections.abc import MutableMapping\n",
    "\n",
    "def flatten_dict(d: MutableMapping, parent_key: str = '', sep: str ='.') -> MutableMapping:\n",
    "    items = []\n",
    "    for k, v in d.items():\n",
    "        new_key = parent_key + sep + k if parent_key else k\n",
    "        if isinstance(v, MutableMapping):\n",
    "            items.extend(flatten_dict(v, new_key, sep=sep).items())\n",
    "        else:\n",
    "            items.append((new_key, v))\n",
    "    return dict(items)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-27T07:44:20.074690Z",
     "start_time": "2023-03-27T07:44:20.050856Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1215"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from dol import flatten\n",
    "\n",
    "tt = flatten_dict(t)\n",
    "len(tt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-31T14:01:08.480927Z",
     "start_time": "2023-03-31T14:01:08.466494Z"
    }
   },
   "outputs": [],
   "source": [
    "# list(tt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-07T11:46:52.221788Z",
     "start_time": "2023-03-07T11:46:52.201615Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'get': {'operationId': 'listEngines',\n",
       "  'deprecated': True,\n",
       "  'tags': ['OpenAI'],\n",
       "  'summary': 'Lists the currently available (non-finetuned) models, and provides basic information about each one such as the owner and availability.',\n",
       "  'responses': {'200': {'description': 'OK',\n",
       "    'content': {'application/json': {'schema': {'$ref': '#/components/schemas/ListEnginesResponse'}}}}},\n",
       "  'x-oaiMeta': {'name': 'List engines',\n",
       "   'group': 'engines',\n",
       "   'path': 'list',\n",
       "   'examples': {'curl': \"curl https://api.openai.com/v1/engines \\\\\\n  -H 'Authorization: Bearer YOUR_API_KEY'\\n\",\n",
       "    'python': 'import os\\nimport openai\\nopenai.api_key = os.getenv(\"OPENAI_API_KEY\")\\nopenai.Engine.list()\\n',\n",
       "    'node.js': 'const { Configuration, OpenAIApi } = require(\"openai\");\\nconst configuration = new Configuration({\\n  apiKey: process.env.OPENAI_API_KEY,\\n});\\nconst openai = new OpenAIApi(configuration);\\nconst response = await openai.listEngines();\\n'},\n",
       "   'response': '{\\n  \"data\": [\\n    {\\n      \"id\": \"engine-id-0\",\\n      \"object\": \"engine\",\\n      \"owner\": \"organization-owner\",\\n      \"ready\": true\\n    },\\n    {\\n      \"id\": \"engine-id-2\",\\n      \"object\": \"engine\",\\n      \"owner\": \"organization-owner\",\\n      \"ready\": true\\n    },\\n    {\\n      \"id\": \"engine-id-3\",\\n      \"object\": \"engine\",\\n      \"owner\": \"openai\",\\n      \"ready\": false\\n    },\\n  ],\\n  \"object\": \"list\"\\n}\\n'}}}"
      ]
     },
     "execution_count": 88,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "t['paths']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-07T12:01:24.823457Z",
     "start_time": "2023-03-07T12:01:24.807777Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'get': {'operationId': 'listEngines',\n",
       "  'deprecated': True,\n",
       "  'tags': ['OpenAI'],\n",
       "  'summary': 'Lists the currently available (non-finetuned) models, and provides basic information about each one such as the owner and availability.',\n",
       "  'responses': {'200': {'description': 'OK',\n",
       "    'content': {'application/json': {'schema': {'$ref': '#/components/schemas/ListEnginesResponse'}}}}},\n",
       "  'x-oaiMeta': {'name': 'List engines',\n",
       "   'group': 'engines',\n",
       "   'path': 'list',\n",
       "   'examples': {'curl': \"curl https://api.openai.com/v1/engines \\\\\\n  -H 'Authorization: Bearer YOUR_API_KEY'\\n\",\n",
       "    'python': 'import os\\nimport openai\\nopenai.api_key = os.getenv(\"OPENAI_API_KEY\")\\nopenai.Engine.list()\\n',\n",
       "    'node.js': 'const { Configuration, OpenAIApi } = require(\"openai\");\\nconst configuration = new Configuration({\\n  apiKey: process.env.OPENAI_API_KEY,\\n});\\nconst openai = new OpenAIApi(configuration);\\nconst response = await openai.listEngines();\\n'},\n",
       "   'response': '{\\n  \"data\": [\\n    {\\n      \"id\": \"engine-id-0\",\\n      \"object\": \"engine\",\\n      \"owner\": \"organization-owner\",\\n      \"ready\": true\\n    },\\n    {\\n      \"id\": \"engine-id-2\",\\n      \"object\": \"engine\",\\n      \"owner\": \"organization-owner\",\\n      \"ready\": true\\n    },\\n    {\\n      \"id\": \"engine-id-3\",\\n      \"object\": \"engine\",\\n      \"owner\": \"openai\",\\n      \"ready\": false\\n    },\\n  ],\\n  \"object\": \"list\"\\n}\\n'}}}"
      ]
     },
     "execution_count": 90,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from dol import path_get\n",
    "\n",
    "path_get(t, 'paths./engines')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Engine/Model list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 108,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-08T11:22:10.939187Z",
     "start_time": "2023-03-08T11:22:10.534374Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "APIError Audio ChatCompletion Completion ContextVar Customer Deployment Edit Embedding Engine ErrorObject File FineTune Image InvalidRequestError Model Moderation OpenAIError Optional TYPE_CHECKING __all__ __annotations__ __builtins__ __cached__ __doc__ __file__ __loader__ __name__ __package__ __path__ __spec__ aiosession api_base api_key api_key_path api_requestor api_resources api_type api_version app_info ca_bundle_path datalib debug enable_telemetry error log object_classes openai_object openai_response organization os proxy util verify_ssl_certs version\n"
     ]
    }
   ],
   "source": [
    "from oa import openai\n",
    "from glom import glom\n",
    "print(*dir(openai))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-08T11:21:28.980647Z",
     "start_time": "2023-03-08T11:21:28.414367Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "__class__ __class_getitem__ __contains__ __copy__ __deepcopy__ __delattr__ __delitem__ __dict__ __dir__ __doc__ __eq__ __format__ __ge__ __getattr__ __getattribute__ __getitem__ __gt__ __hash__ __init__ __init_subclass__ __ior__ __iter__ __le__ __len__ __lt__ __module__ __ne__ __new__ __or__ __reduce__ __reduce_ex__ __repr__ __reversed__ __ror__ __setattr__ __setitem__ __setstate__ __sizeof__ __str__ __subclasshook__ __weakref__ _previous _response_ms _retrieve_params api_base api_base_override api_key api_type api_version arequest clear construct_from copy engine fromkeys get items keys openai_id organization pop popitem refresh_from request response_ms setdefault to_dict to_dict_recursive typed_api_type update values\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "['object', 'data']"
      ]
     },
     "execution_count": 103,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "t = openai.Model.list()\n",
    "print(*dir(t))\n",
    "list(t)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 122,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-08T11:28:27.665719Z",
     "start_time": "2023-03-08T11:28:27.647262Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['babbage',\n",
       " 'davinci',\n",
       " 'gpt-3.5-turbo-0301',\n",
       " 'text-davinci-003',\n",
       " 'babbage-code-search-code',\n",
       " 'text-similarity-babbage-001',\n",
       " 'text-davinci-001',\n",
       " 'ada',\n",
       " 'curie-instruct-beta',\n",
       " 'babbage-code-search-text',\n",
       " 'babbage-similarity',\n",
       " 'code-search-babbage-text-001',\n",
       " 'text-embedding-ada-002',\n",
       " 'code-cushman-001',\n",
       " 'whisper-1',\n",
       " 'gpt-3.5-turbo',\n",
       " 'code-search-babbage-code-001',\n",
       " 'audio-transcribe-deprecated',\n",
       " 'text-ada-001',\n",
       " 'text-similarity-ada-001',\n",
       " 'text-davinci-insert-002',\n",
       " 'ada-code-search-code',\n",
       " 'ada-similarity',\n",
       " 'code-search-ada-text-001',\n",
       " 'text-search-ada-query-001',\n",
       " 'text-curie-001',\n",
       " 'text-davinci-edit-001',\n",
       " 'davinci-search-document',\n",
       " 'ada-code-search-text',\n",
       " 'text-search-ada-doc-001',\n",
       " 'code-davinci-edit-001',\n",
       " 'davinci-instruct-beta',\n",
       " 'text-similarity-curie-001',\n",
       " 'code-search-ada-code-001',\n",
       " 'ada-search-query',\n",
       " 'text-search-davinci-query-001',\n",
       " 'curie-search-query',\n",
       " 'davinci-search-query',\n",
       " 'text-davinci-insert-001',\n",
       " 'babbage-search-document',\n",
       " 'ada-search-document',\n",
       " 'text-search-curie-query-001',\n",
       " 'text-search-babbage-doc-001',\n",
       " 'text-davinci-002',\n",
       " 'curie-search-document',\n",
       " 'text-search-curie-doc-001',\n",
       " 'babbage-search-query',\n",
       " 'text-babbage-001',\n",
       " 'text-search-davinci-doc-001',\n",
       " 'code-davinci-002',\n",
       " 'text-search-babbage-query-001',\n",
       " 'curie-similarity',\n",
       " 'curie',\n",
       " 'text-similarity-davinci-001',\n",
       " 'davinci-similarity',\n",
       " 'cushman:2020-05-03',\n",
       " 'ada:2020-05-03',\n",
       " 'babbage:2020-05-03',\n",
       " 'curie:2020-05-03',\n",
       " 'davinci:2020-05-03',\n",
       " 'if-davinci-v2',\n",
       " 'if-curie-v2',\n",
       " 'if-davinci:3.0.0',\n",
       " 'davinci-if:3.0.0',\n",
       " 'davinci-instruct-beta:2.0.0',\n",
       " 'text-ada:001',\n",
       " 'text-davinci:001',\n",
       " 'text-curie:001',\n",
       " 'text-babbage:001']"
      ]
     },
     "execution_count": 122,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# glom(t['data'], '*.root')\n",
    "import glom\n",
    "field = 'root'\n",
    "tt = t['data']\n",
    "# glom.glom(tt, glom.Spec(field))\n",
    "from functools import partial\n",
    "field_extractor = lambda field: partial(\n",
    "    map, \n",
    "    partial(glom.glom, spec=glom.Spec(field))\n",
    ")\n",
    "f = field_extractor('root')\n",
    "list(f(tt))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-08T11:21:24.219065Z",
     "start_time": "2023-03-08T11:21:23.824218Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "__class__ __class_getitem__ __contains__ __copy__ __deepcopy__ __delattr__ __delitem__ __dict__ __dir__ __doc__ __eq__ __format__ __ge__ __getattr__ __getattribute__ __getitem__ __gt__ __hash__ __init__ __init_subclass__ __ior__ __iter__ __le__ __len__ __lt__ __module__ __ne__ __new__ __or__ __reduce__ __reduce_ex__ __repr__ __reversed__ __ror__ __setattr__ __setitem__ __setstate__ __sizeof__ __str__ __subclasshook__ __weakref__ _previous _response_ms _retrieve_params api_base api_base_override api_key api_type api_version arequest clear construct_from copy engine fromkeys get items keys openai_id organization pop popitem refresh_from request response_ms setdefault to_dict to_dict_recursive typed_api_type update values\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "['object', 'data']"
      ]
     },
     "execution_count": 102,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "t = openai.Engine.list()\n",
    "print(*dir(t))\n",
    "list(t)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-07T10:34:02.052131Z",
     "start_time": "2023-03-07T10:34:01.984217Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>object</th>\n",
       "      <th>id</th>\n",
       "      <th>ready</th>\n",
       "      <th>owner</th>\n",
       "      <th>permissions</th>\n",
       "      <th>created</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>engine</td>\n",
       "      <td>babbage</td>\n",
       "      <td>True</td>\n",
       "      <td>openai</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>engine</td>\n",
       "      <td>davinci</td>\n",
       "      <td>True</td>\n",
       "      <td>openai</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>engine</td>\n",
       "      <td>gpt-3.5-turbo-0301</td>\n",
       "      <td>True</td>\n",
       "      <td>openai</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>engine</td>\n",
       "      <td>text-davinci-003</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-internal</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>engine</td>\n",
       "      <td>babbage-code-search-code</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>engine</td>\n",
       "      <td>text-similarity-babbage-001</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>engine</td>\n",
       "      <td>text-davinci-001</td>\n",
       "      <td>True</td>\n",
       "      <td>openai</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>engine</td>\n",
       "      <td>ada</td>\n",
       "      <td>True</td>\n",
       "      <td>openai</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>engine</td>\n",
       "      <td>curie-instruct-beta</td>\n",
       "      <td>True</td>\n",
       "      <td>openai</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>engine</td>\n",
       "      <td>babbage-code-search-text</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>engine</td>\n",
       "      <td>babbage-similarity</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>engine</td>\n",
       "      <td>gpt-3.5-turbo</td>\n",
       "      <td>True</td>\n",
       "      <td>openai</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>engine</td>\n",
       "      <td>code-davinci-002</td>\n",
       "      <td>True</td>\n",
       "      <td>openai</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>engine</td>\n",
       "      <td>code-search-babbage-text-001</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>engine</td>\n",
       "      <td>text-embedding-ada-002</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-internal</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>15</th>\n",
       "      <td>engine</td>\n",
       "      <td>code-cushman-001</td>\n",
       "      <td>True</td>\n",
       "      <td>openai</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>16</th>\n",
       "      <td>engine</td>\n",
       "      <td>whisper-1</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-internal</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17</th>\n",
       "      <td>engine</td>\n",
       "      <td>code-search-babbage-code-001</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18</th>\n",
       "      <td>engine</td>\n",
       "      <td>audio-transcribe-deprecated</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-internal</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>19</th>\n",
       "      <td>engine</td>\n",
       "      <td>text-ada-001</td>\n",
       "      <td>True</td>\n",
       "      <td>openai</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20</th>\n",
       "      <td>engine</td>\n",
       "      <td>text-similarity-ada-001</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>21</th>\n",
       "      <td>engine</td>\n",
       "      <td>text-davinci-insert-002</td>\n",
       "      <td>True</td>\n",
       "      <td>openai</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>22</th>\n",
       "      <td>engine</td>\n",
       "      <td>ada-code-search-code</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>23</th>\n",
       "      <td>engine</td>\n",
       "      <td>ada-similarity</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>24</th>\n",
       "      <td>engine</td>\n",
       "      <td>code-search-ada-text-001</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25</th>\n",
       "      <td>engine</td>\n",
       "      <td>text-search-ada-query-001</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>26</th>\n",
       "      <td>engine</td>\n",
       "      <td>text-curie-001</td>\n",
       "      <td>True</td>\n",
       "      <td>openai</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>27</th>\n",
       "      <td>engine</td>\n",
       "      <td>text-davinci-edit-001</td>\n",
       "      <td>True</td>\n",
       "      <td>openai</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>28</th>\n",
       "      <td>engine</td>\n",
       "      <td>davinci-search-document</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>29</th>\n",
       "      <td>engine</td>\n",
       "      <td>ada-code-search-text</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>30</th>\n",
       "      <td>engine</td>\n",
       "      <td>text-search-ada-doc-001</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>31</th>\n",
       "      <td>engine</td>\n",
       "      <td>code-davinci-edit-001</td>\n",
       "      <td>True</td>\n",
       "      <td>openai</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>32</th>\n",
       "      <td>engine</td>\n",
       "      <td>davinci-instruct-beta</td>\n",
       "      <td>True</td>\n",
       "      <td>openai</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>33</th>\n",
       "      <td>engine</td>\n",
       "      <td>text-similarity-curie-001</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>34</th>\n",
       "      <td>engine</td>\n",
       "      <td>code-search-ada-code-001</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>35</th>\n",
       "      <td>engine</td>\n",
       "      <td>ada-search-query</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>36</th>\n",
       "      <td>engine</td>\n",
       "      <td>text-search-davinci-query-001</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>37</th>\n",
       "      <td>engine</td>\n",
       "      <td>curie-search-query</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>38</th>\n",
       "      <td>engine</td>\n",
       "      <td>davinci-search-query</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>39</th>\n",
       "      <td>engine</td>\n",
       "      <td>text-davinci-insert-001</td>\n",
       "      <td>True</td>\n",
       "      <td>openai</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>40</th>\n",
       "      <td>engine</td>\n",
       "      <td>babbage-search-document</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>41</th>\n",
       "      <td>engine</td>\n",
       "      <td>ada-search-document</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>42</th>\n",
       "      <td>engine</td>\n",
       "      <td>text-search-curie-query-001</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>43</th>\n",
       "      <td>engine</td>\n",
       "      <td>text-search-babbage-doc-001</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>44</th>\n",
       "      <td>engine</td>\n",
       "      <td>text-davinci-002</td>\n",
       "      <td>True</td>\n",
       "      <td>openai</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>45</th>\n",
       "      <td>engine</td>\n",
       "      <td>curie-search-document</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>46</th>\n",
       "      <td>engine</td>\n",
       "      <td>text-search-curie-doc-001</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>47</th>\n",
       "      <td>engine</td>\n",
       "      <td>babbage-search-query</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>48</th>\n",
       "      <td>engine</td>\n",
       "      <td>text-babbage-001</td>\n",
       "      <td>True</td>\n",
       "      <td>openai</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>49</th>\n",
       "      <td>engine</td>\n",
       "      <td>text-search-davinci-doc-001</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50</th>\n",
       "      <td>engine</td>\n",
       "      <td>text-search-babbage-query-001</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>51</th>\n",
       "      <td>engine</td>\n",
       "      <td>curie-similarity</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>52</th>\n",
       "      <td>engine</td>\n",
       "      <td>curie</td>\n",
       "      <td>True</td>\n",
       "      <td>openai</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>53</th>\n",
       "      <td>engine</td>\n",
       "      <td>text-similarity-davinci-001</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>54</th>\n",
       "      <td>engine</td>\n",
       "      <td>davinci-similarity</td>\n",
       "      <td>True</td>\n",
       "      <td>openai-dev</td>\n",
       "      <td>None</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    object                             id  ...  permissions created\n",
       "0   engine                        babbage  ...         None    None\n",
       "1   engine                        davinci  ...         None    None\n",
       "2   engine             gpt-3.5-turbo-0301  ...         None    None\n",
       "3   engine               text-davinci-003  ...         None    None\n",
       "4   engine       babbage-code-search-code  ...         None    None\n",
       "5   engine    text-similarity-babbage-001  ...         None    None\n",
       "6   engine               text-davinci-001  ...         None    None\n",
       "7   engine                            ada  ...         None    None\n",
       "8   engine            curie-instruct-beta  ...         None    None\n",
       "9   engine       babbage-code-search-text  ...         None    None\n",
       "10  engine             babbage-similarity  ...         None    None\n",
       "11  engine                  gpt-3.5-turbo  ...         None    None\n",
       "12  engine               code-davinci-002  ...         None    None\n",
       "13  engine   code-search-babbage-text-001  ...         None    None\n",
       "14  engine         text-embedding-ada-002  ...         None    None\n",
       "15  engine               code-cushman-001  ...         None    None\n",
       "16  engine                      whisper-1  ...         None    None\n",
       "17  engine   code-search-babbage-code-001  ...         None    None\n",
       "18  engine    audio-transcribe-deprecated  ...         None    None\n",
       "19  engine                   text-ada-001  ...         None    None\n",
       "20  engine        text-similarity-ada-001  ...         None    None\n",
       "21  engine        text-davinci-insert-002  ...         None    None\n",
       "22  engine           ada-code-search-code  ...         None    None\n",
       "23  engine                 ada-similarity  ...         None    None\n",
       "24  engine       code-search-ada-text-001  ...         None    None\n",
       "25  engine      text-search-ada-query-001  ...         None    None\n",
       "26  engine                 text-curie-001  ...         None    None\n",
       "27  engine          text-davinci-edit-001  ...         None    None\n",
       "28  engine        davinci-search-document  ...         None    None\n",
       "29  engine           ada-code-search-text  ...         None    None\n",
       "30  engine        text-search-ada-doc-001  ...         None    None\n",
       "31  engine          code-davinci-edit-001  ...         None    None\n",
       "32  engine          davinci-instruct-beta  ...         None    None\n",
       "33  engine      text-similarity-curie-001  ...         None    None\n",
       "34  engine       code-search-ada-code-001  ...         None    None\n",
       "35  engine               ada-search-query  ...         None    None\n",
       "36  engine  text-search-davinci-query-001  ...         None    None\n",
       "37  engine             curie-search-query  ...         None    None\n",
       "38  engine           davinci-search-query  ...         None    None\n",
       "39  engine        text-davinci-insert-001  ...         None    None\n",
       "40  engine        babbage-search-document  ...         None    None\n",
       "41  engine            ada-search-document  ...         None    None\n",
       "42  engine    text-search-curie-query-001  ...         None    None\n",
       "43  engine    text-search-babbage-doc-001  ...         None    None\n",
       "44  engine               text-davinci-002  ...         None    None\n",
       "45  engine          curie-search-document  ...         None    None\n",
       "46  engine      text-search-curie-doc-001  ...         None    None\n",
       "47  engine           babbage-search-query  ...         None    None\n",
       "48  engine               text-babbage-001  ...         None    None\n",
       "49  engine    text-search-davinci-doc-001  ...         None    None\n",
       "50  engine  text-search-babbage-query-001  ...         None    None\n",
       "51  engine               curie-similarity  ...         None    None\n",
       "52  engine                          curie  ...         None    None\n",
       "53  engine    text-similarity-davinci-001  ...         None    None\n",
       "54  engine             davinci-similarity  ...         None    None\n",
       "\n",
       "[55 rows x 6 columns]"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "tt = t.to_dict_recursive()\n",
    "pd.DataFrame(tt['data'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## illustrating a story"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-05-07T09:21:13.978013Z",
     "start_time": "2023-05-07T09:21:13.969030Z"
    }
   },
   "outputs": [],
   "source": [
    "import oa.examples.illustrate_stories as ii"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-05-07T09:21:37.960058Z",
     "start_time": "2023-05-07T09:21:20.381344Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " \n",
      "\n",
      "Once upon a time, there lived a girl \n",
      "Red Riding Hood and her hood so curled \n",
      "It twirled and twirled with each twirl\n",
      "As she travelled through the forest so green, she smiled \n",
      "\n",
      "The sun shone brightly, atop the trees in town \n",
      "But a wolf was waiting and Red never saw his frown \n",
      "He followed her closely, unseen behind the trees \n",
      "As Red rode on, she failed to notice\n",
      "\n",
      "The big bad wolf he thought with glee \n",
      "“Surely I will have that Red Riding Hood for dinner, not me!” \n",
      "He thought this plan would be so great\n",
      "So he followed Red Riding Hood and his belly opened to bait \n",
      "\n",
      "But Red heard a howl and quickened her pace \n",
      "She peered behind and saw the wolf's face \n",
      "She ran as fast as she could throughout the day\n",
      "Til finally, Red's granny spotter her, and she was saved \n",
      "\n",
      "The wolf's plan was foiled, for he had not a chance \n",
      "Red wise was entertained and got to keep her lunch \n",
      "From then on, Red stayed away from the forest so green \n",
      "But she still kept her hood so curled, with joy so serene.\n"
     ]
    }
   ],
   "source": [
    "story_text = ii.make_it_rhyming('Red riding hood')\n",
    "print(story_text)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-31T14:54:13.637743Z",
     "start_time": "2023-03-31T14:54:12.044655Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Red riding hood is standing outside her grandma's house, wearing a red cape and hood. She knocks on the door, and her grandma says \"come in\". Red riding hood takes off her cape and hood, and her grandma gives her a big hug.\n"
     ]
    }
   ],
   "source": [
    "image_description = ii.get_image_description(story_text)\n",
    "print(image_description)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-31T14:54:18.633873Z",
     "start_time": "2023-03-31T14:54:13.646766Z"
    }
   },
   "outputs": [],
   "source": [
    "image_url = ii.get_image_url(image_description)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-31T14:54:18.662856Z",
     "start_time": "2023-03-31T14:54:18.638925Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<html>\n",
       "    <body>\n",
       "    <img src=\"https://oaidalleapiprodscus.blob.core.windows.net/private/org-AY3lr3H3xB9yPQ0HGR498f9M/user-7ZNCDYLWzP0GT48V6DCiTFWt/img-JfBXG6inGZl71VTgxh8IJPZ0.png?st=2023-03-31T13%3A54%3A18Z&se=2023-03-31T15%3A54%3A18Z&sp=r&sv=2021-08-06&sr=b&rscd=inline&rsct=image/png&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2023-03-30T15%3A54%3A53Z&ske=2023-03-31T15%3A54%3A53Z&sks=b&skv=2021-08-06&sig=D6JEMJ5n1ySJ7pewC30wdq%2BIJYou3CvDWDTVDzLsyug%3D\" />\n",
       "    <p><p>Red riding hood went to visit her grandma<br>She was wearing a red cape and a red hood<br>She knocked on the door and her grandma said &quot;come in&quot;<br>Red riding hood took off her red cape and her red hood<br>And her grandma gave her a big hug</p></p>\n",
       "    </body>\n",
       "    </html>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.display import HTML\n",
    "\n",
    "HTML(ii.aggregate_story_and_image(image_url, story_text))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-31T14:57:24.804862Z",
     "start_time": "2023-03-31T14:57:24.691613Z"
    }
   },
   "outputs": [],
   "source": [
    "from plunk.tw.i2i_demos.play.resources import make_children_story"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-31T14:57:31.842952Z",
     "start_time": "2023-03-31T14:57:29.720473Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 7.1.0 (20230121.1956)\n",
       " -->\n",
       "<!-- Pages: 1 -->\n",
       "<svg width=\"223pt\" height=\"476pt\"\n",
       " viewBox=\"0.00 0.00 222.50 476.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 472)\">\n",
       "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-472 218.5,-472 218.5,4 -4,4\"/>\n",
       "<!-- rhyming_story -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>rhyming_story</title>\n",
       "<text text-anchor=\"middle\" x=\"157.5\" y=\"-302.3\" font-family=\"Times,serif\" font-size=\"14.00\">rhyming_story</text>\n",
       "</g>\n",
       "<!-- get_illustration -->\n",
       "<g id=\"node6\" class=\"node\">\n",
       "<title>get_illustration</title>\n",
       "<polygon fill=\"none\" stroke=\"black\" points=\"129.5,-252 31.5,-252 31.5,-216 129.5,-216 129.5,-252\"/>\n",
       "<text text-anchor=\"middle\" x=\"80.5\" y=\"-230.3\" font-family=\"Times,serif\" font-size=\"14.00\">get_illustration</text>\n",
       "</g>\n",
       "<!-- rhyming_story&#45;&gt;get_illustration -->\n",
       "<g id=\"edge4\" class=\"edge\">\n",
       "<title>rhyming_story&#45;&gt;get_illustration</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M138.86,-288.05C129.54,-279.58 118.08,-269.17 107.8,-259.82\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"110.38,-257.43 100.62,-253.29 105.67,-262.61 110.38,-257.43\"/>\n",
       "</g>\n",
       "<!-- aggregate_story_and_image -->\n",
       "<g id=\"node8\" class=\"node\">\n",
       "<title>aggregate_story_and_image</title>\n",
       "<polygon fill=\"none\" stroke=\"black\" points=\"203.5,-108 33.5,-108 33.5,-72 203.5,-72 203.5,-108\"/>\n",
       "<text text-anchor=\"middle\" x=\"118.5\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">aggregate_story_and_image</text>\n",
       "</g>\n",
       "<!-- rhyming_story&#45;&gt;aggregate_story_and_image -->\n",
       "<g id=\"edge8\" class=\"edge\">\n",
       "<title>rhyming_story&#45;&gt;aggregate_story_and_image</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M154.44,-288.21C147.78,-251.67 131.91,-164.59 123.67,-119.37\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"127.16,-119.01 121.93,-109.8 120.28,-120.26 127.16,-119.01\"/>\n",
       "</g>\n",
       "<!-- story -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>story</title>\n",
       "<text text-anchor=\"middle\" x=\"157.5\" y=\"-446.3\" font-family=\"Times,serif\" font-size=\"14.00\">story</text>\n",
       "</g>\n",
       "<!-- make_it_rhyming -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>make_it_rhyming</title>\n",
       "<polygon fill=\"none\" stroke=\"black\" points=\"214.5,-396 100.5,-396 100.5,-360 214.5,-360 214.5,-396\"/>\n",
       "<text text-anchor=\"middle\" x=\"157.5\" y=\"-374.3\" font-family=\"Times,serif\" font-size=\"14.00\">make_it_rhyming</text>\n",
       "</g>\n",
       "<!-- story&#45;&gt;make_it_rhyming -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>story&#45;&gt;make_it_rhyming</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M157.5,-432.05C157.5,-424.68 157.5,-415.84 157.5,-407.51\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"161,-407.79 157.5,-397.79 154,-407.79 161,-407.79\"/>\n",
       "</g>\n",
       "<!-- make_it_rhyming&#45;&gt;rhyming_story -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>make_it_rhyming&#45;&gt;rhyming_story</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M157.5,-359.7C157.5,-352.21 157.5,-343.26 157.5,-334.88\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"161,-335.14 157.5,-325.14 154,-335.14 161,-335.14\"/>\n",
       "</g>\n",
       "<!-- image -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>image</title>\n",
       "<text text-anchor=\"middle\" x=\"91.5\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\">image</text>\n",
       "</g>\n",
       "<!-- image&#45;&gt;aggregate_story_and_image -->\n",
       "<g id=\"edge7\" class=\"edge\">\n",
       "<title>image&#45;&gt;aggregate_story_and_image</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M98.04,-144.05C100.94,-136.52 104.45,-127.44 107.72,-118.94\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"110.96,-120.28 111.29,-109.69 104.43,-117.76 110.96,-120.28\"/>\n",
       "</g>\n",
       "<!-- image_style -->\n",
       "<g id=\"node5\" class=\"node\">\n",
       "<title>image_style</title>\n",
       "<text text-anchor=\"middle\" x=\"45.5\" y=\"-302.3\" font-family=\"Times,serif\" font-size=\"14.00\">image_style=</text>\n",
       "</g>\n",
       "<!-- image_style&#45;&gt;get_illustration -->\n",
       "<g id=\"edge5\" class=\"edge\">\n",
       "<title>image_style&#45;&gt;get_illustration</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M53.97,-288.05C57.83,-280.35 62.49,-271.03 66.82,-262.36\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"69.84,-264.14 71.19,-253.63 63.58,-261.01 69.84,-264.14\"/>\n",
       "</g>\n",
       "<!-- get_illustration&#45;&gt;image -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>get_illustration&#45;&gt;image</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M83.22,-215.7C84.4,-208.21 85.8,-199.26 87.12,-190.88\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"90.56,-191.54 88.65,-181.12 83.64,-190.45 90.56,-191.54\"/>\n",
       "</g>\n",
       "<!-- page -->\n",
       "<g id=\"node7\" class=\"node\">\n",
       "<title>page</title>\n",
       "<text text-anchor=\"middle\" x=\"118.5\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">page</text>\n",
       "</g>\n",
       "<!-- aggregate_story_and_image&#45;&gt;page -->\n",
       "<g id=\"edge6\" class=\"edge\">\n",
       "<title>aggregate_story_and_image&#45;&gt;page</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M118.5,-71.7C118.5,-64.21 118.5,-55.26 118.5,-46.88\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"122,-47.14 118.5,-37.14 115,-47.14 122,-47.14\"/>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<graphviz.graphs.Digraph at 0x118f53a00>"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "make_children_story.dot_digraph()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-03T14:49:08.198762Z",
     "start_time": "2023-04-03T14:49:08.191118Z"
    }
   },
   "outputs": [],
   "source": [
    "from IPython.display import HTML\n",
    "\n",
    "# HTML(make_children_story('hansel and gretel'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-06T10:57:04.333833Z",
     "start_time": "2023-03-06T10:57:04.324059Z"
    }
   },
   "source": [
    "## illustrating concepts"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-06T08:13:45.043119Z",
     "start_time": "2023-04-06T08:13:44.999792Z"
    }
   },
   "outputs": [],
   "source": [
    "%load_ext autoreload\n",
    "%autoreload 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-06T08:13:57.670573Z",
     "start_time": "2023-04-06T08:13:45.045144Z"
    }
   },
   "outputs": [],
   "source": [
    "from oa.base import chatgpt, dalle\n",
    "from oa.examples.illustrate_stories import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-06T08:14:28.263296Z",
     "start_time": "2023-04-06T08:14:26.962195Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "• Streamlined development processes  \n",
      "• Strong focus on customer satisfaction \n",
      "• Increased collaboration among team members\n"
     ]
    }
   ],
   "source": [
    "import json\n",
    "print(topic_points('The benefits of extreme programming'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-06T07:29:13.907185Z",
     "start_time": "2023-04-06T07:29:09.549507Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'Team-Oriented Approach': 'The Agile framework fosters collaboration between team members and promotes a project-oriented approach to problem solving.',\n",
       " 'Transparency & Flexibility': 'With Agile, progress and changes are visible to everyone involved, and scope is easily validatable or modified. ',\n",
       " 'Adaptable Environment': 'Agile provides a flexible and adaptive workspace, where teams can shift their plans quickly and easily when needed to suit the particular project.'}"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import json\n",
    "t = json.loads(\n",
    "    topic_points_json('The benefits of the Agile framework', max_n_words=30)\n",
    ")\n",
    "t"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-06T07:20:12.500482Z",
     "start_time": "2023-04-06T07:20:07.809370Z"
    }
   },
   "outputs": [],
   "source": [
    "t = oa.chatgpt(prompt, max_tokens=2048, n=1)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-06T07:22:40.707793Z",
     "start_time": "2023-04-06T07:22:40.681354Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['Benefits of Extreme Programming',\n",
       " 'Increased Quality',\n",
       " 'Increased Efficiency']"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import json\n",
    "\n",
    "d = json.loads(t['choices'][0]['text'].strip()[1:-1])\n",
    "list(d)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-06T07:06:32.346551Z",
     "start_time": "2023-04-06T07:06:32.097672Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['babbage',\n",
       " 'davinci',\n",
       " 'text-davinci-edit-001',\n",
       " 'babbage-code-search-code',\n",
       " 'text-similarity-babbage-001',\n",
       " 'code-davinci-edit-001',\n",
       " 'text-davinci-001',\n",
       " 'ada',\n",
       " 'babbage-code-search-text',\n",
       " 'babbage-similarity',\n",
       " 'code-search-babbage-text-001',\n",
       " 'text-curie-001',\n",
       " 'code-search-babbage-code-001',\n",
       " 'text-davinci-003',\n",
       " 'text-ada-001',\n",
       " 'text-embedding-ada-002',\n",
       " 'text-similarity-ada-001',\n",
       " 'curie-instruct-beta',\n",
       " 'ada-code-search-code',\n",
       " 'ada-similarity',\n",
       " 'code-search-ada-text-001',\n",
       " 'text-search-ada-query-001',\n",
       " 'davinci-search-document',\n",
       " 'ada-code-search-text',\n",
       " 'text-search-ada-doc-001',\n",
       " 'davinci-instruct-beta',\n",
       " 'text-similarity-curie-001',\n",
       " 'code-search-ada-code-001',\n",
       " 'ada-search-query',\n",
       " 'text-search-davinci-query-001',\n",
       " 'curie-search-query',\n",
       " 'davinci-search-query',\n",
       " 'babbage-search-document',\n",
       " 'ada-search-document',\n",
       " 'text-search-curie-query-001',\n",
       " 'text-search-babbage-doc-001',\n",
       " 'curie-search-document',\n",
       " 'gpt-3.5-turbo',\n",
       " 'whisper-1',\n",
       " 'text-search-curie-doc-001',\n",
       " 'babbage-search-query',\n",
       " 'text-babbage-001',\n",
       " 'text-search-davinci-doc-001',\n",
       " 'text-search-babbage-query-001',\n",
       " 'curie-similarity',\n",
       " 'gpt-3.5-turbo-0301',\n",
       " 'curie',\n",
       " 'text-similarity-davinci-001',\n",
       " 'text-davinci-002',\n",
       " 'davinci-similarity']"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import oa.base\n",
    "oa.base.list_engine_ids()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-07T10:35:52.050069Z",
     "start_time": "2023-03-07T10:35:52.040701Z"
    }
   },
   "outputs": [],
   "source": [
    "# openai.Engine.list()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-06T15:30:21.369584Z",
     "start_time": "2023-03-06T15:30:19.223966Z"
    }
   },
   "outputs": [],
   "source": [
    "profile = \"an illustrator who knows software principles\"\n",
    "\n",
    "description = \"\"\"which is a software development approach that emphasizes understanding and modeling the business \n",
    "domain to build software that is aligned with business needs.\"\"\"\n",
    "\n",
    "r = chatgpt(template.format(profile=profile, description=description))\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-06T15:30:39.068263Z",
     "start_time": "2023-03-06T15:30:39.062471Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<OpenAIObject text_completion id=cmpl-6r752hwhpjQGtpHscV7ziNftomKqS at 0x11ab58e50> JSON: {\n",
       "  \"choices\": [\n",
       "    {\n",
       "      \"finish_reason\": \"length\",\n",
       "      \"index\": 0,\n",
       "      \"logprobs\": null,\n",
       "      \"text\": \" from the tiniest basis details to the specific application. A freelancer he\"\n",
       "    }\n",
       "  ],\n",
       "  \"created\": 1678116620,\n",
       "  \"id\": \"cmpl-6r752hwhpjQGtpHscV7ziNftomKqS\",\n",
       "  \"model\": \"davinci\",\n",
       "  \"object\": \"text_completion\",\n",
       "  \"usage\": {\n",
       "    \"completion_tokens\": 16,\n",
       "    \"prompt_tokens\": 7,\n",
       "    \"total_tokens\": 23\n",
       "  }\n",
       "}"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-06T15:31:17.115888Z",
     "start_time": "2023-03-06T15:31:17.101504Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "' from the tiniest basis details to the specific application. A freelancer he'"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r['choices'][0]['text']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## open ai tutorial examples"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-06T10:57:54.392450Z",
     "start_time": "2023-03-06T10:57:49.165062Z"
    }
   },
   "outputs": [],
   "source": [
    "from oa.util import openai\n",
    "\n",
    "image_resp = openai.Image.create(\n",
    "    prompt=\"two dogs playing chess, oil painting\", n=2, size=\"512x512\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-06T10:58:51.634823Z",
     "start_time": "2023-03-06T10:58:51.622026Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<OpenAIObject at 0x1141da750> JSON: {\n",
       "  \"created\": 1678100274,\n",
       "  \"data\": [\n",
       "    {\n",
       "      \"url\": \"https://oaidalleapiprodscus.blob.core.windows.net/private/org-AY3lr3H3xB9yPQ0HGR498f9M/user-7ZNCDYLWzP0GT48V6DCiTFWt/img-cZTRQYIOYLJ8PqjUK5A340FJ.png?st=2023-03-06T09%3A57%3A54Z&se=2023-03-06T11%3A57%3A54Z&sp=r&sv=2021-08-06&sr=b&rscd=inline&rsct=image/png&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2023-03-06T02%3A38%3A13Z&ske=2023-03-07T02%3A38%3A13Z&sks=b&skv=2021-08-06&sig=PI0GdIDAZYbeZhUim5pndE3N0eiPGk83Wj/CDgJCKXQ%3D\"\n",
       "    },\n",
       "    {\n",
       "      \"url\": \"https://oaidalleapiprodscus.blob.core.windows.net/private/org-AY3lr3H3xB9yPQ0HGR498f9M/user-7ZNCDYLWzP0GT48V6DCiTFWt/img-a3pizi7UpPlH4Zbuo0z3P0Jg.png?st=2023-03-06T09%3A57%3A54Z&se=2023-03-06T11%3A57%3A54Z&sp=r&sv=2021-08-06&sr=b&rscd=inline&rsct=image/png&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2023-03-06T02%3A38%3A13Z&ske=2023-03-07T02%3A38%3A13Z&sks=b&skv=2021-08-06&sig=53H4WPi1XHmUkn96ud5K2ubbsfbHU/XN3JlaCSZGwEk%3D\"\n",
       "    }\n",
       "  ]\n",
       "}"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "image_resp"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-06T15:15:57.145618Z",
     "start_time": "2023-03-06T15:15:56.888043Z"
    }
   },
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'image_resp' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Cell \u001b[0;32mIn[2], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mimage_resp\u001b[49m\n",
      "\u001b[0;31mNameError\u001b[0m: name 'image_resp' is not defined"
     ]
    }
   ],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-06T13:25:51.643336Z",
     "start_time": "2023-03-06T13:25:51.629327Z"
    }
   },
   "outputs": [],
   "source": [
    "import requests\n",
    "\n",
    "# r = requests.get(image_resp['data'][0]['url'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-06T10:59:04.893668Z",
     "start_time": "2023-03-06T10:59:04.879908Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<img src=\"https://oaidalleapiprodscus.blob.core.windows.net/private/org-AY3lr3H3xB9yPQ0HGR498f9M/user-7ZNCDYLWzP0GT48V6DCiTFWt/img-cZTRQYIOYLJ8PqjUK5A340FJ.png?st=2023-03-06T09%3A57%3A54Z&se=2023-03-06T11%3A57%3A54Z&sp=r&sv=2021-08-06&sr=b&rscd=inline&rsct=image/png&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2023-03-06T02%3A38%3A13Z&ske=2023-03-07T02%3A38%3A13Z&sks=b&skv=2021-08-06&sig=PI0GdIDAZYbeZhUim5pndE3N0eiPGk83Wj/CDgJCKXQ%3D\"/>"
      ],
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Image(url=image_resp['data'][0]['url'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-06T10:59:27.276883Z",
     "start_time": "2023-03-06T10:59:27.262490Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<img src=\"https://oaidalleapiprodscus.blob.core.windows.net/private/org-AY3lr3H3xB9yPQ0HGR498f9M/user-7ZNCDYLWzP0GT48V6DCiTFWt/img-a3pizi7UpPlH4Zbuo0z3P0Jg.png?st=2023-03-06T09%3A57%3A54Z&se=2023-03-06T11%3A57%3A54Z&sp=r&sv=2021-08-06&sr=b&rscd=inline&rsct=image/png&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2023-03-06T02%3A38%3A13Z&ske=2023-03-07T02%3A38%3A13Z&sks=b&skv=2021-08-06&sig=53H4WPi1XHmUkn96ud5K2ubbsfbHU/XN3JlaCSZGwEk%3D\"/>"
      ],
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Image(url=image_resp['data'][1]['url'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## chatGPTs code for illustrate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-29T13:29:57.641436Z",
     "start_time": "2023-03-29T13:29:57.635971Z"
    },
    "hidden": true
   },
   "outputs": [],
   "source": [
    "from oa.scrap.illustrating_stories import illustrate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-29T13:30:17.888709Z",
     "start_time": "2023-03-29T13:30:17.877800Z"
    },
    "hidden": true
   },
   "outputs": [],
   "source": [
    "it = illustrate(\"the ant and the grasshopper\", image_style='Salavadore Dali')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-29T13:30:38.824563Z",
     "start_time": "2023-03-29T13:30:27.030731Z"
    },
    "hidden": true
   },
   "outputs": [],
   "source": [
    "t = next(it)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-29T13:31:12.149389Z",
     "start_time": "2023-03-29T13:31:12.140958Z"
    }
   },
   "outputs": [],
   "source": [
    "images = t['images']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-29T13:31:13.551225Z",
     "start_time": "2023-03-29T13:31:13.534754Z"
    },
    "hidden": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<img src=\"https://oaidalleapiprodscus.blob.core.windows.net/private/org-AY3lr3H3xB9yPQ0HGR498f9M/user-7ZNCDYLWzP0GT48V6DCiTFWt/img-4ircaau5ETaqAQBfH0BQKA9O.png?st=2023-03-29T12%3A30%3A34Z&se=2023-03-29T14%3A30%3A34Z&sp=r&sv=2021-08-06&sr=b&rscd=inline&rsct=image/png&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2023-03-29T11%3A05%3A44Z&ske=2023-03-30T11%3A05%3A44Z&sks=b&skv=2021-08-06&sig=nIQoxjlWNa8cL2Q9Y2PcLI0BVAZ3IeHCXKZ7dY4rqM8%3D\"/>"
      ],
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.display import Image\n",
    "\n",
    "Image(url=images[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-03-29T13:31:16.473225Z",
     "start_time": "2023-03-29T13:31:16.453474Z"
    },
    "hidden": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<img src=\"https://oaidalleapiprodscus.blob.core.windows.net/private/org-AY3lr3H3xB9yPQ0HGR498f9M/user-7ZNCDYLWzP0GT48V6DCiTFWt/img-8vWP8PD8u03CrGoYw2BWbzWt.png?st=2023-03-29T12%3A30%3A38Z&se=2023-03-29T14%3A30%3A38Z&sp=r&sv=2021-08-06&sr=b&rscd=inline&rsct=image/png&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2023-03-29T11%3A42%3A53Z&ske=2023-03-30T11%3A42%3A53Z&sks=b&skv=2021-08-06&sig=GrEZBtd%2BtPt5aaxECx73xdtDs3LqaRam6jKhSRfACDI%3D\"/>"
      ],
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Image(url=images[1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "hidden": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "hidden": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "hidden": true
   },
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "hidden": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "p10",
   "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.10.13"
  },
  "latex_envs": {
   "LaTeX_envs_menu_present": true,
   "autoclose": false,
   "autocomplete": true,
   "bibliofile": "biblio.bib",
   "cite_by": "apalike",
   "current_citInitial": 1,
   "eqLabelWithNumbers": true,
   "eqNumInitial": 1,
   "hotkeys": {
    "equation": "Ctrl-E",
    "itemize": "Ctrl-I"
   },
   "labels_anchors": false,
   "latex_user_defs": false,
   "report_style_numbering": false,
   "user_envs_cfg": false
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": true,
   "toc_position": {
    "height": "2515.56px",
    "left": "223px",
    "top": "111.45px",
    "width": "173px"
   },
   "toc_section_display": true,
   "toc_window_display": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
