{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "ee4b18be-3bf0-4f7c-8ac5-ef68b7566750",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "!pip install lancedb rerankers together -q"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "3f3d4a75-bc50-46e2-ac26-2e4c975cfa9d",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Cloning into 'MM-Demo'...\n",
      "remote: Enumerating objects: 27, done.\u001b[K\n",
      "remote: Counting objects: 100% (23/23), done.\u001b[K\n",
      "remote: Compressing objects: 100% (23/23), done.\u001b[K\n",
      "remote: Total 27 (delta 5), reused 0 (delta 0), pack-reused 4 (from 1)\u001b[K\n",
      "Unpacking objects: 100% (27/27), 930.83 KiB | 4.70 MiB/s, done.\n"
     ]
    }
   ],
   "source": [
    "!git clone https://huggingface.co/datasets/Sanyam/MM-Demo"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "fd7f755b-c9cc-468d-b4f1-8d2f9e7b3d8d",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--2024-10-05 20:26:21--  https://huggingface.co/datasets/Sanyam/MM-Demo/resolve/main/archive.zip?download=true\n",
      "Resolving fwdproxy (fwdproxy)... 2401:db00:2ff:e002:face:b00c:0:1e10\n",
      "Connecting to fwdproxy (fwdproxy)|2401:db00:2ff:e002:face:b00c:0:1e10|:8080... connected.\n",
      "Proxy request sent, awaiting response... 302 Found\n",
      "Location: https://cdn-lfs-us-1.hf.co/repos/cd/e8/cde814535d30074dcdff9e1ffb015dfa1cc1e60be4b2906951b47df88d9571ed/89615a7f69ba75f09c19dc40e4214110134c6f533f950b2894440ee0741d8c53?response-content-disposition=attachment%3B+filename*%3DUTF-8%27%27archive.zip%3B+filename%3D%22archive.zip%22%3B&response-content-type=application%2Fzip&Expires=1728444381&Policy=eyJTdGF0ZW1lbnQiOlt7IkNvbmRpdGlvbiI6eyJEYXRlTGVzc1RoYW4iOnsiQVdTOkVwb2NoVGltZSI6MTcyODQ0NDM4MX19LCJSZXNvdXJjZSI6Imh0dHBzOi8vY2RuLWxmcy11cy0xLmhmLmNvL3JlcG9zL2NkL2U4L2NkZTgxNDUzNWQzMDA3NGRjZGZmOWUxZmZiMDE1ZGZhMWNjMWU2MGJlNGIyOTA2OTUxYjQ3ZGY4OGQ5NTcxZWQvODk2MTVhN2Y2OWJhNzVmMDljMTlkYzQwZTQyMTQxMTAxMzRjNmY1MzNmOTUwYjI4OTQ0NDBlZTA3NDFkOGM1Mz9yZXNwb25zZS1jb250ZW50LWRpc3Bvc2l0aW9uPSomcmVzcG9uc2UtY29udGVudC10eXBlPSoifV19&Signature=PRxfZ0hTsxpVy6-zXOiJGgowwXH9REo2-rZik-Fj7slmyF%7E7AbN-4JPcyKPQG3hp8k5ZjXUVjnIzUGsgPxOiUSZy3J54OlqOnYcDIAxeg6srtAqSjmWehwUFfXzWO%7E5w8165mnogdViS48MudFk8y51g0-MZMmjSlc5wRgDxahqQajR-C6Kz9mMeNdk%7EnTSF-vRQancglubpn1-p%7EzBbCuS10AstMozCw3rsOD4LMct2vytbo8lA1kvqBWLstGlq%7EkIxJdU8tk9pF%7Ef8p9lDXeR2QDU2SJ8HjIonRBslydCIr6sMN-8f2xH1y8tSWi59tUMbucBtiw-6BH6vlRzbyw__&Key-Pair-Id=K24J24Z295AEI9 [following]\n",
      "--2024-10-05 20:26:21--  https://cdn-lfs-us-1.hf.co/repos/cd/e8/cde814535d30074dcdff9e1ffb015dfa1cc1e60be4b2906951b47df88d9571ed/89615a7f69ba75f09c19dc40e4214110134c6f533f950b2894440ee0741d8c53?response-content-disposition=attachment%3B+filename*%3DUTF-8%27%27archive.zip%3B+filename%3D%22archive.zip%22%3B&response-content-type=application%2Fzip&Expires=1728444381&Policy=eyJTdGF0ZW1lbnQiOlt7IkNvbmRpdGlvbiI6eyJEYXRlTGVzc1RoYW4iOnsiQVdTOkVwb2NoVGltZSI6MTcyODQ0NDM4MX19LCJSZXNvdXJjZSI6Imh0dHBzOi8vY2RuLWxmcy11cy0xLmhmLmNvL3JlcG9zL2NkL2U4L2NkZTgxNDUzNWQzMDA3NGRjZGZmOWUxZmZiMDE1ZGZhMWNjMWU2MGJlNGIyOTA2OTUxYjQ3ZGY4OGQ5NTcxZWQvODk2MTVhN2Y2OWJhNzVmMDljMTlkYzQwZTQyMTQxMTAxMzRjNmY1MzNmOTUwYjI4OTQ0NDBlZTA3NDFkOGM1Mz9yZXNwb25zZS1jb250ZW50LWRpc3Bvc2l0aW9uPSomcmVzcG9uc2UtY29udGVudC10eXBlPSoifV19&Signature=PRxfZ0hTsxpVy6-zXOiJGgowwXH9REo2-rZik-Fj7slmyF%7E7AbN-4JPcyKPQG3hp8k5ZjXUVjnIzUGsgPxOiUSZy3J54OlqOnYcDIAxeg6srtAqSjmWehwUFfXzWO%7E5w8165mnogdViS48MudFk8y51g0-MZMmjSlc5wRgDxahqQajR-C6Kz9mMeNdk%7EnTSF-vRQancglubpn1-p%7EzBbCuS10AstMozCw3rsOD4LMct2vytbo8lA1kvqBWLstGlq%7EkIxJdU8tk9pF%7Ef8p9lDXeR2QDU2SJ8HjIonRBslydCIr6sMN-8f2xH1y8tSWi59tUMbucBtiw-6BH6vlRzbyw__&Key-Pair-Id=K24J24Z295AEI9\n",
      "Connecting to fwdproxy (fwdproxy)|2401:db00:2ff:e002:face:b00c:0:1e10|:8080... connected.\n",
      "Proxy request sent, awaiting response... 200 OK\n",
      "Length: 164078460 (156M) [application/zip]\n",
      "Saving to: ‘archive.zip’\n",
      "\n",
      "archive.zip         100%[===================>] 156.48M   232MB/s    in 0.7s    \n",
      "\n",
      "2024-10-05 20:26:22 (232 MB/s) - ‘archive.zip’ saved [164078460/164078460]\n",
      "\n"
     ]
    }
   ],
   "source": [
    "!wget https://huggingface.co/datasets/Sanyam/MM-Demo/resolve/main/archive.zip?download=true -O archive.zip"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "3db34179-91c4-4377-b186-978bbe9d4fee",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Archive:  archive.zip\n",
      "replace __MACOSX/._archive? [y]es, [n]o, [A]ll, [N]one, [r]ename: ^C\n"
     ]
    }
   ],
   "source": [
    "!unzip archive.zip"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "a13b002d-26bc-4fb0-bd08-193163f2a3d7",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "\n",
    "df = pd.read_csv(\"./final_balanced_sample_dataset.csv\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "e2078d99-959e-4bb6-a702-ff3e31761db2",
   "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>Filename</th>\n",
       "      <th>Title</th>\n",
       "      <th>Size</th>\n",
       "      <th>Gender</th>\n",
       "      <th>Description</th>\n",
       "      <th>Category</th>\n",
       "      <th>Type</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>d7ed1d64-2c65-427f-9ae4-eb4aaa3e2389.jpg</td>\n",
       "      <td>Stylish and Trendy Tank Top with Celestial Design</td>\n",
       "      <td>M</td>\n",
       "      <td>F</td>\n",
       "      <td>This white tank top is a stylish and trendy pi...</td>\n",
       "      <td>Tops</td>\n",
       "      <td>Casual</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>5c1b7a77-1fa3-4af8-9722-cd38e45d89da.jpg</td>\n",
       "      <td>Classic White Sweatshirt</td>\n",
       "      <td>M</td>\n",
       "      <td>F</td>\n",
       "      <td>This classic white sweatshirt is a timeless pi...</td>\n",
       "      <td>Tops</td>\n",
       "      <td>Casual</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>b2e084c7-e3a0-4182-8671-b908544a7cf2.jpg</td>\n",
       "      <td>Grey T-shirt</td>\n",
       "      <td>M</td>\n",
       "      <td>Unisex</td>\n",
       "      <td>This is a short-sleeved, crew neck t-shirt tha...</td>\n",
       "      <td>T-Shirt</td>\n",
       "      <td>Casual</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>87846aa9-86cc-404a-af2c-7e8fe941081d.jpg</td>\n",
       "      <td>Long-Sleeved V-Neck Shirt</td>\n",
       "      <td>L</td>\n",
       "      <td>U</td>\n",
       "      <td>A long-sleeved, V-neck shirt with a solid purp...</td>\n",
       "      <td>Tops</td>\n",
       "      <td>Casual</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>04fa06fb-d71a-4293-9804-fe799375a682.jpg</td>\n",
       "      <td>Silver Metallic Buckle Sandals</td>\n",
       "      <td>L</td>\n",
       "      <td>F</td>\n",
       "      <td>These silver metallic buckle sandals feature a...</td>\n",
       "      <td>Shoes</td>\n",
       "      <td>Casual</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                   Filename  \\\n",
       "0  d7ed1d64-2c65-427f-9ae4-eb4aaa3e2389.jpg   \n",
       "1  5c1b7a77-1fa3-4af8-9722-cd38e45d89da.jpg   \n",
       "2  b2e084c7-e3a0-4182-8671-b908544a7cf2.jpg   \n",
       "3  87846aa9-86cc-404a-af2c-7e8fe941081d.jpg   \n",
       "4  04fa06fb-d71a-4293-9804-fe799375a682.jpg   \n",
       "\n",
       "                                               Title Size  Gender  \\\n",
       "0  Stylish and Trendy Tank Top with Celestial Design    M       F   \n",
       "1                           Classic White Sweatshirt    M       F   \n",
       "2                                       Grey T-shirt    M  Unisex   \n",
       "3                          Long-Sleeved V-Neck Shirt    L       U   \n",
       "4                     Silver Metallic Buckle Sandals    L       F   \n",
       "\n",
       "                                         Description Category    Type  \n",
       "0  This white tank top is a stylish and trendy pi...     Tops  Casual  \n",
       "1  This classic white sweatshirt is a timeless pi...     Tops  Casual  \n",
       "2  This is a short-sleeved, crew neck t-shirt tha...  T-Shirt  Casual  \n",
       "3  A long-sleeved, V-neck shirt with a solid purp...     Tops  Casual  \n",
       "4  These silver metallic buckle sandals feature a...    Shoes  Casual  "
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "806b1ab5-e3ca-46ec-851d-85bb4e371795",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'This white tank top is a stylish and trendy piece of clothing that features a captivating celestial design. The design showcases a mesmerizing array of stars, planets, and moons in black and white, creating a visually appealing and eye-catching pattern. The tank top has a relaxed fit with a round neckline and sleeveless design, making it a comfortable and versatile piece that can be worn on its own or layered under a cardigan or jacket. Perfect for a casual day out or a night on the town, this tank top is a must-have for any fashion-conscious woman.'"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df[\"Description\"][0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "efec4e5e-3371-435a-8b49-2a4b69d7776c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Number of empty descriptions: 0\n"
     ]
    }
   ],
   "source": [
    "import lancedb\n",
    "from lancedb.pydantic import LanceModel, Vector\n",
    "from lancedb.embeddings import get_registry\n",
    "from lancedb.rerankers import ColbertReranker\n",
    "from pathlib import Path\n",
    "from PIL import Image\n",
    "import pandas as pd\n",
    "\n",
    "model = get_registry().get(\"sentence-transformers\").create(name=\"BAAI/bge-small-en-v1.5\", device=\"cuda\")\n",
    "\n",
    "class Schema(LanceModel):\n",
    "    Filename: str\n",
    "    Title: str\n",
    "    Size: str\n",
    "    Gender: str\n",
    "    Description: str = model.SourceField()\n",
    "    Category: str\n",
    "    Type: str\n",
    "    vector: Vector(model.ndims()) = model.VectorField()\n",
    "\n",
    "db = lancedb.connect(\"~/.lancedb\")\n",
    "tbl = db.create_table(name=\"clothes\", schema=Schema, mode=\"overwrite\")\n",
    "\n",
    "# Function to clean and convert data types\n",
    "def clean_data(df):\n",
    "    # Convert all columns to string type\n",
    "    for col in df.columns:\n",
    "        df[col] = df[col].astype(str)\n",
    "    \n",
    "    # Remove any rows with NaN values\n",
    "    df = df.dropna()\n",
    "    \n",
    "    return df\n",
    "\n",
    "# Clean the data\n",
    "cleaned_df = clean_data(df)\n",
    "\n",
    "# Convert cleaned DataFrame to list of dictionaries\n",
    "data = cleaned_df.to_dict('records')\n",
    "\n",
    "empty_count = len([d for d in data if d.get('Description', '').strip() == ''])\n",
    "print(f\"Number of empty descriptions: {empty_count}\")\n",
    "\n",
    "# automatically generate vectors\n",
    "tbl.add(data)\n",
    "\n",
    "tbl.search().to_pandas()\n",
    "\n",
    "def show_image_from_response(rs):\n",
    "    names = rs[\"Filename\"].to_list()\n",
    "    return [Image.open(Path(\"archive\") / \"images_compressed\" / name) for name in names]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "e4917d40-3ade-49e5-aaf1-865a87bf50bf",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# automatically generate vectors\n",
    "tbl.add(data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "c90f9005-ee3c-44ff-8bfd-b020bd4e6091",
   "metadata": {
    "tags": []
   },
   "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>Filename</th>\n",
       "      <th>Title</th>\n",
       "      <th>Size</th>\n",
       "      <th>Gender</th>\n",
       "      <th>Description</th>\n",
       "      <th>Category</th>\n",
       "      <th>Type</th>\n",
       "      <th>vector</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>d7ed1d64-2c65-427f-9ae4-eb4aaa3e2389.jpg</td>\n",
       "      <td>Stylish and Trendy Tank Top with Celestial Design</td>\n",
       "      <td>M</td>\n",
       "      <td>F</td>\n",
       "      <td>This white tank top is a stylish and trendy pi...</td>\n",
       "      <td>Tops</td>\n",
       "      <td>Casual</td>\n",
       "      <td>[-0.06355423, 0.02385288, 0.03382446, -0.00212...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>5c1b7a77-1fa3-4af8-9722-cd38e45d89da.jpg</td>\n",
       "      <td>Classic White Sweatshirt</td>\n",
       "      <td>M</td>\n",
       "      <td>F</td>\n",
       "      <td>This classic white sweatshirt is a timeless pi...</td>\n",
       "      <td>Tops</td>\n",
       "      <td>Casual</td>\n",
       "      <td>[-0.011691423, 0.049270794, 0.030319242, -0.02...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>b2e084c7-e3a0-4182-8671-b908544a7cf2.jpg</td>\n",
       "      <td>Grey T-shirt</td>\n",
       "      <td>M</td>\n",
       "      <td>Unisex</td>\n",
       "      <td>This is a short-sleeved, crew neck t-shirt tha...</td>\n",
       "      <td>T-Shirt</td>\n",
       "      <td>Casual</td>\n",
       "      <td>[-0.010150914, 0.09637642, -0.0012558334, 0.04...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>87846aa9-86cc-404a-af2c-7e8fe941081d.jpg</td>\n",
       "      <td>Long-Sleeved V-Neck Shirt</td>\n",
       "      <td>L</td>\n",
       "      <td>U</td>\n",
       "      <td>A long-sleeved, V-neck shirt with a solid purp...</td>\n",
       "      <td>Tops</td>\n",
       "      <td>Casual</td>\n",
       "      <td>[-0.058710814, 0.053951632, -0.047531255, 0.03...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>04fa06fb-d71a-4293-9804-fe799375a682.jpg</td>\n",
       "      <td>Silver Metallic Buckle Sandals</td>\n",
       "      <td>L</td>\n",
       "      <td>F</td>\n",
       "      <td>These silver metallic buckle sandals feature a...</td>\n",
       "      <td>Shoes</td>\n",
       "      <td>Casual</td>\n",
       "      <td>[0.0123484805, 0.02398385, 0.059779372, -0.006...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>8f576f1a-839d-4fb2-a224-a4700b2d05da.jpg</td>\n",
       "      <td>Orange Long Sleeve T-Shirt</td>\n",
       "      <td>S</td>\n",
       "      <td>U</td>\n",
       "      <td>This long sleeve t-shirt is made of a lightwei...</td>\n",
       "      <td>Tops</td>\n",
       "      <td>Casual</td>\n",
       "      <td>[-0.016778396, 0.06664105, -0.010597771, 0.052...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>e976a8f6-6731-485f-8a9a-2872a5208818.jpg</td>\n",
       "      <td>Green T-Shirt</td>\n",
       "      <td>L</td>\n",
       "      <td>M</td>\n",
       "      <td>The green t-shirt is a relaxed fit with a V-ne...</td>\n",
       "      <td>Tops</td>\n",
       "      <td>Casual</td>\n",
       "      <td>[0.015946185, 0.07543863, 0.032447945, 0.00442...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>bbf0d9c7-663d-46d1-a9f8-66e8e5678541.jpg</td>\n",
       "      <td>White Quarter Zip Pullover Top</td>\n",
       "      <td>L</td>\n",
       "      <td>U</td>\n",
       "      <td>This pullover top has a quarter zip closure at...</td>\n",
       "      <td>Tops</td>\n",
       "      <td>Casual</td>\n",
       "      <td>[-0.05592024, 0.03401515, -0.0057456787, 0.030...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>e25a7faa-7a49-4e72-a7ef-e74427f77784.jpg</td>\n",
       "      <td>Aviator Sunglasses T-Shirt</td>\n",
       "      <td>M</td>\n",
       "      <td>F</td>\n",
       "      <td>This sleeveless red T-shirt features a large b...</td>\n",
       "      <td>Tops</td>\n",
       "      <td>Casual</td>\n",
       "      <td>[-0.040058654, 0.090077035, -0.020889325, 0.03...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>d995ac1f-fbd0-482c-a308-dafb6a93cfd0.jpg</td>\n",
       "      <td>Beige Top</td>\n",
       "      <td>M</td>\n",
       "      <td>F</td>\n",
       "      <td>This beige top has a boat neck, a pocket in fr...</td>\n",
       "      <td>Tops</td>\n",
       "      <td>Casual</td>\n",
       "      <td>[-0.020475557, 0.032990508, 0.0145089375, -0.0...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                   Filename  \\\n",
       "0  d7ed1d64-2c65-427f-9ae4-eb4aaa3e2389.jpg   \n",
       "1  5c1b7a77-1fa3-4af8-9722-cd38e45d89da.jpg   \n",
       "2  b2e084c7-e3a0-4182-8671-b908544a7cf2.jpg   \n",
       "3  87846aa9-86cc-404a-af2c-7e8fe941081d.jpg   \n",
       "4  04fa06fb-d71a-4293-9804-fe799375a682.jpg   \n",
       "5  8f576f1a-839d-4fb2-a224-a4700b2d05da.jpg   \n",
       "6  e976a8f6-6731-485f-8a9a-2872a5208818.jpg   \n",
       "7  bbf0d9c7-663d-46d1-a9f8-66e8e5678541.jpg   \n",
       "8  e25a7faa-7a49-4e72-a7ef-e74427f77784.jpg   \n",
       "9  d995ac1f-fbd0-482c-a308-dafb6a93cfd0.jpg   \n",
       "\n",
       "                                               Title Size  Gender  \\\n",
       "0  Stylish and Trendy Tank Top with Celestial Design    M       F   \n",
       "1                           Classic White Sweatshirt    M       F   \n",
       "2                                       Grey T-shirt    M  Unisex   \n",
       "3                          Long-Sleeved V-Neck Shirt    L       U   \n",
       "4                     Silver Metallic Buckle Sandals    L       F   \n",
       "5                         Orange Long Sleeve T-Shirt    S       U   \n",
       "6                                      Green T-Shirt    L       M   \n",
       "7                     White Quarter Zip Pullover Top    L       U   \n",
       "8                         Aviator Sunglasses T-Shirt    M       F   \n",
       "9                                          Beige Top    M       F   \n",
       "\n",
       "                                         Description Category    Type  \\\n",
       "0  This white tank top is a stylish and trendy pi...     Tops  Casual   \n",
       "1  This classic white sweatshirt is a timeless pi...     Tops  Casual   \n",
       "2  This is a short-sleeved, crew neck t-shirt tha...  T-Shirt  Casual   \n",
       "3  A long-sleeved, V-neck shirt with a solid purp...     Tops  Casual   \n",
       "4  These silver metallic buckle sandals feature a...    Shoes  Casual   \n",
       "5  This long sleeve t-shirt is made of a lightwei...     Tops  Casual   \n",
       "6  The green t-shirt is a relaxed fit with a V-ne...     Tops  Casual   \n",
       "7  This pullover top has a quarter zip closure at...     Tops  Casual   \n",
       "8  This sleeveless red T-shirt features a large b...     Tops  Casual   \n",
       "9  This beige top has a boat neck, a pocket in fr...     Tops  Casual   \n",
       "\n",
       "                                              vector  \n",
       "0  [-0.06355423, 0.02385288, 0.03382446, -0.00212...  \n",
       "1  [-0.011691423, 0.049270794, 0.030319242, -0.02...  \n",
       "2  [-0.010150914, 0.09637642, -0.0012558334, 0.04...  \n",
       "3  [-0.058710814, 0.053951632, -0.047531255, 0.03...  \n",
       "4  [0.0123484805, 0.02398385, 0.059779372, -0.006...  \n",
       "5  [-0.016778396, 0.06664105, -0.010597771, 0.052...  \n",
       "6  [0.015946185, 0.07543863, 0.032447945, 0.00442...  \n",
       "7  [-0.05592024, 0.03401515, -0.0057456787, 0.030...  \n",
       "8  [-0.040058654, 0.090077035, -0.020889325, 0.03...  \n",
       "9  [-0.020475557, 0.032990508, 0.0145089375, -0.0...  "
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tbl.search().to_pandas()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "94652723-7813-48db-8089-cbee2ee8fc85",
   "metadata": {},
   "source": [
    "### Pattern 1: text input"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "84a9a7a0-8849-4cdc-b802-ab28b7438099",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Jeans are a classic pairing option. Dark wash skinny jeans create a sleek look, while light wash boyfriend jeans add a casual touch. Black trousers offer a dressier alternative. Khaki chinos provide a neutral background for the plaid pattern. Corduroy pants add a rustic feel. Wool trousers bring a sophisticated element. Leather pants create a bold statement.\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "from together import Together\n",
    "\n",
    "os.environ[\"TOGETHER_API_KEY\"] = \"\"\n",
    "client = Together(api_key=os.environ.get('TOGETHER_API_KEY'))\n",
    "\n",
    "prompt = prompt + \"Please answer within 100 words consisely and only provide the answer, don't\" \\\n",
    "            \"repeat any word from the input, start your response from the clothing items that can be paired with the input\"\n",
    "response = client.chat.completions.create(\n",
    "    model=\"meta-llama/Llama-Vision-Free\",\n",
    "    messages=[\n",
    "                {\n",
    "                \"role\": \"user\",\n",
    "                \"content\": [\n",
    "                        {\n",
    "                                \"type\": \"text\",\n",
    "                                \"text\": prompt\n",
    "                        }\n",
    "                ]\n",
    "        },\n",
    "    ],\n",
    "    max_tokens=512,\n",
    "    temperature=0.7,\n",
    "    top_p=0.7,\n",
    "    top_k=50,\n",
    "    repetition_penalty=1,\n",
    "    stop=[\"<|eot_id|>\",\"<|eom_id|>\"],\n",
    ")\n",
    "print(response.choices[0].message.content)\n",
    "response = response.choices[0].message.content"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "5f0b36e0-761b-4e6f-a3df-e12c36caca0a",
   "metadata": {
    "tags": []
   },
   "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>Filename</th>\n",
       "      <th>Title</th>\n",
       "      <th>Size</th>\n",
       "      <th>Gender</th>\n",
       "      <th>Description</th>\n",
       "      <th>Category</th>\n",
       "      <th>Type</th>\n",
       "      <th>vector</th>\n",
       "      <th>_distance</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>7a6e7ddb-ac03-4d78-9d71-75320e5913da.jpg</td>\n",
       "      <td>Light-Washed Jeans</td>\n",
       "      <td>S</td>\n",
       "      <td>F</td>\n",
       "      <td>These light-washed jeans are a pair of stylish...</td>\n",
       "      <td>Jeans</td>\n",
       "      <td>Casual</td>\n",
       "      <td>[-0.063473865, 0.060125574, 0.02189098, -0.002...</td>\n",
       "      <td>0.407864</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>7a6e7ddb-ac03-4d78-9d71-75320e5913da.jpg</td>\n",
       "      <td>Light-Washed Jeans</td>\n",
       "      <td>S</td>\n",
       "      <td>F</td>\n",
       "      <td>These light-washed jeans are a pair of stylish...</td>\n",
       "      <td>Jeans</td>\n",
       "      <td>Casual</td>\n",
       "      <td>[-0.063473865, 0.060125574, 0.02189098, -0.002...</td>\n",
       "      <td>0.407864</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>8db4d594-4688-4447-a5b9-cd5c68b1870e.jpg</td>\n",
       "      <td>Black Pant</td>\n",
       "      <td>S</td>\n",
       "      <td>U</td>\n",
       "      <td>This pair of black pants appears to be made of...</td>\n",
       "      <td>Pants</td>\n",
       "      <td>Casual</td>\n",
       "      <td>[-0.014388849, 0.082536675, 0.011225891, -0.00...</td>\n",
       "      <td>0.412849</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                   Filename               Title Size Gender  \\\n",
       "0  7a6e7ddb-ac03-4d78-9d71-75320e5913da.jpg  Light-Washed Jeans    S      F   \n",
       "1  7a6e7ddb-ac03-4d78-9d71-75320e5913da.jpg  Light-Washed Jeans    S      F   \n",
       "2  8db4d594-4688-4447-a5b9-cd5c68b1870e.jpg          Black Pant    S      U   \n",
       "\n",
       "                                         Description Category    Type  \\\n",
       "0  These light-washed jeans are a pair of stylish...    Jeans  Casual   \n",
       "1  These light-washed jeans are a pair of stylish...    Jeans  Casual   \n",
       "2  This pair of black pants appears to be made of...    Pants  Casual   \n",
       "\n",
       "                                              vector  _distance  \n",
       "0  [-0.063473865, 0.060125574, 0.02189098, -0.002...   0.407864  \n",
       "1  [-0.063473865, 0.060125574, 0.02189098, -0.002...   0.407864  \n",
       "2  [-0.014388849, 0.082536675, 0.011225891, -0.00...   0.412849  "
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# automatically converted to vector respresentation\n",
    "rs = tbl.search(response).limit(3).to_pandas()\n",
    "rs\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "e74a805a-28a9-4442-9477-65808321cb3c",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "imgs = show_image_from_response(rs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "ffa32a2e-de10-4a68-b480-9639394564cc",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/jpeg": "[encoded data, 30772 characters]",
      "image/png": "[encoded data, 273884 characters]",
      "text/plain": [
       "<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=400x534>"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "imgs[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "943d2358-d378-4446-860b-cda9f9154752",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/jpeg": "[encoded data, 30772 characters]",
      "image/png": "[encoded data, 273884 characters]",
      "text/plain": [
       "<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=400x534>"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "imgs[1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "56efb82d-8e63-4ad1-97c2-29135ae361e2",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/jpeg": "[encoded data, 23472 characters]",
      "image/png": "[encoded data, 224832 characters]",
      "text/plain": [
       "<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=400x533>"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "imgs[2]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4096bf87-a6fe-4ca2-bfe2-0381922dd6bd",
   "metadata": {},
   "source": [
    "### Limitations of semantic search\n",
    "-- "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "908e8c15-9e42-4457-b60d-b0b1fdca7b23",
   "metadata": {},
   "source": [
    "## Let's try Full-text search/ BM25"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 128,
   "id": "141a5e42-32fc-4e8d-9efb-e0c1e00305ba",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "tbl.create_fts_index(\"Description\", replace=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 139,
   "id": "c08a8699-24b2-4843-9437-842cb0d09c5b",
   "metadata": {
    "tags": []
   },
   "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>filename</th>\n",
       "      <th>Description</th>\n",
       "      <th>vector</th>\n",
       "      <th>Title</th>\n",
       "      <th>Size</th>\n",
       "      <th>Category</th>\n",
       "      <th>Type</th>\n",
       "      <th>Gender</th>\n",
       "      <th>_score</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0e20abb0-d56a-4f83-b254-9db70fb92794.jpg</td>\n",
       "      <td>This shirt is a long-sleeved, black and grey s...</td>\n",
       "      <td>[-0.045025624, 0.041662034, -0.0006505165, 0.0...</td>\n",
       "      <td>Black and Grey Striped Shirt with Pink Accents</td>\n",
       "      <td>S</td>\n",
       "      <td>Tops</td>\n",
       "      <td>Casual</td>\n",
       "      <td>F</td>\n",
       "      <td>52.089787</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>10e51a41-3729-472e-b288-f3b8f895577a.jpg</td>\n",
       "      <td>This plaid shirt features a classic plaid patt...</td>\n",
       "      <td>[-0.044541422, 0.05006024, -0.04257077, 0.0401...</td>\n",
       "      <td>Plaid shirt with embroidered hem</td>\n",
       "      <td>L</td>\n",
       "      <td>Tops</td>\n",
       "      <td>Casual</td>\n",
       "      <td>F</td>\n",
       "      <td>35.616638</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>bd289469-607c-45df-bad3-ed1057e277bf.jpg</td>\n",
       "      <td>This is a red and black plaid skirt with a cla...</td>\n",
       "      <td>[-0.021971317, 0.12156065, -0.002515854, 0.034...</td>\n",
       "      <td>Red and Black Plaid Skirt</td>\n",
       "      <td>S</td>\n",
       "      <td>Skirts</td>\n",
       "      <td>Casual</td>\n",
       "      <td>F</td>\n",
       "      <td>34.096905</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>64c5d20e-7cec-4965-8c50-315389f44b22.jpg</td>\n",
       "      <td>These light washed blue jeans are distressed w...</td>\n",
       "      <td>[-0.07545003, 0.05375045, 0.00353413, -0.01551...</td>\n",
       "      <td>Light Washed Blue Ripped Jeans</td>\n",
       "      <td>L</td>\n",
       "      <td>Jeans</td>\n",
       "      <td>Casual</td>\n",
       "      <td>M</td>\n",
       "      <td>29.116760</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>b0c03127-9dfb-4573-8934-1958396937bf.jpg</td>\n",
       "      <td>This red flannel plaid shirt has a classic and...</td>\n",
       "      <td>[-0.03013145, 0.060508166, -0.03642542, 0.0301...</td>\n",
       "      <td>Red Flannel Plaid Shirt</td>\n",
       "      <td>S</td>\n",
       "      <td>Shirts</td>\n",
       "      <td>Casual</td>\n",
       "      <td>M</td>\n",
       "      <td>28.444168</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                   filename  \\\n",
       "0  0e20abb0-d56a-4f83-b254-9db70fb92794.jpg   \n",
       "1  10e51a41-3729-472e-b288-f3b8f895577a.jpg   \n",
       "2  bd289469-607c-45df-bad3-ed1057e277bf.jpg   \n",
       "3  64c5d20e-7cec-4965-8c50-315389f44b22.jpg   \n",
       "4  b0c03127-9dfb-4573-8934-1958396937bf.jpg   \n",
       "\n",
       "                                         Description  \\\n",
       "0  This shirt is a long-sleeved, black and grey s...   \n",
       "1  This plaid shirt features a classic plaid patt...   \n",
       "2  This is a red and black plaid skirt with a cla...   \n",
       "3  These light washed blue jeans are distressed w...   \n",
       "4  This red flannel plaid shirt has a classic and...   \n",
       "\n",
       "                                              vector  \\\n",
       "0  [-0.045025624, 0.041662034, -0.0006505165, 0.0...   \n",
       "1  [-0.044541422, 0.05006024, -0.04257077, 0.0401...   \n",
       "2  [-0.021971317, 0.12156065, -0.002515854, 0.034...   \n",
       "3  [-0.07545003, 0.05375045, 0.00353413, -0.01551...   \n",
       "4  [-0.03013145, 0.060508166, -0.03642542, 0.0301...   \n",
       "\n",
       "                                            Title Size Category    Type  \\\n",
       "0  Black and Grey Striped Shirt with Pink Accents    S     Tops  Casual   \n",
       "1                Plaid shirt with embroidered hem    L     Tops  Casual   \n",
       "2                       Red and Black Plaid Skirt    S   Skirts  Casual   \n",
       "3                  Light Washed Blue Ripped Jeans    L    Jeans  Casual   \n",
       "4                         Red Flannel Plaid Shirt    S   Shirts  Casual   \n",
       "\n",
       "  Gender     _score  \n",
       "0      F  52.089787  \n",
       "1      F  35.616638  \n",
       "2      F  34.096905  \n",
       "3      M  29.116760  \n",
       "4      M  28.444168  "
      ]
     },
     "execution_count": 139,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "rs = tbl.search(response, query_type=\"fts\").limit(5).to_pandas()\n",
    "rs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 140,
   "id": "a8b196b4-f526-41f5-95ad-08781b1d2f0d",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "imgs = show_image_from_response(rs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 145,
   "id": "e631f244-3e99-43e3-878b-15ac639e5bb9",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/jpeg": "[encoded data, 55448 characters]",
      "image/png": "[encoded data, 510812 characters]",
      "text/plain": [
       "<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=400x533>"
      ]
     },
     "execution_count": 145,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "imgs[-1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 146,
   "id": "e011f438-8899-4605-ba05-55df0ce95d01",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/jpeg": "[encoded data, 35840 characters]",
      "image/png": "[encoded data, 314496 characters]",
      "text/plain": [
       "<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=400x534>"
      ]
     },
     "execution_count": 146,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "imgs[-2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 148,
   "id": "1d6cbbd3-9fbb-4cfe-978d-4ece85a65f33",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/jpeg": "[encoded data, 59548 characters]",
      "image/png": "[encoded data, 456644 characters]",
      "text/plain": [
       "<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=533x400>"
      ]
     },
     "execution_count": 148,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "imgs[-3]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6370d9aa-3262-4234-915a-0459db9144ad",
   "metadata": {},
   "source": [
    "### Hybrid search\n",
    " \n",
    " \n",
    "-- Let's use ColBert Reranker"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 153,
   "id": "46bcbeba-0f7b-4a84-a064-220ab61f1bbf",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Loading ColBERTRanker model colbert-ir/colbertv2.0\n",
      "No device set\n",
      "Using device cuda\n",
      "No dtype set\n",
      "Using dtype torch.float16\n",
      "Loading model colbert-ir/colbertv2.0, this might take a while...\n",
      "Linear Dim set to: {linear_dim} for downcasting\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>filename</th>\n",
       "      <th>Description</th>\n",
       "      <th>vector</th>\n",
       "      <th>Title</th>\n",
       "      <th>Size</th>\n",
       "      <th>Category</th>\n",
       "      <th>Type</th>\n",
       "      <th>Gender</th>\n",
       "      <th>_relevance_score</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0e20abb0-d56a-4f83-b254-9db70fb92794.jpg</td>\n",
       "      <td>This shirt is a long-sleeved, black and grey s...</td>\n",
       "      <td>[-0.045025624, 0.041662034, -0.0006505165, 0.0...</td>\n",
       "      <td>Black and Grey Striped Shirt with Pink Accents</td>\n",
       "      <td>S</td>\n",
       "      <td>Tops</td>\n",
       "      <td>Casual</td>\n",
       "      <td>F</td>\n",
       "      <td>0.744141</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>10e51a41-3729-472e-b288-f3b8f895577a.jpg</td>\n",
       "      <td>This plaid shirt features a classic plaid patt...</td>\n",
       "      <td>[-0.044541422, 0.05006024, -0.04257077, 0.0401...</td>\n",
       "      <td>Plaid shirt with embroidered hem</td>\n",
       "      <td>L</td>\n",
       "      <td>Tops</td>\n",
       "      <td>Casual</td>\n",
       "      <td>F</td>\n",
       "      <td>0.735352</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>300a4125-acec-46aa-b0b9-68b4b2142c70.jpg</td>\n",
       "      <td>These plaid shorts are a stylish and comfortab...</td>\n",
       "      <td>[-0.002765015, 0.030705247, -0.010424565, -0.0...</td>\n",
       "      <td>Plaid Shorts</td>\n",
       "      <td>S</td>\n",
       "      <td>Pants</td>\n",
       "      <td>Casual</td>\n",
       "      <td>M</td>\n",
       "      <td>0.728516</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>bd289469-607c-45df-bad3-ed1057e277bf.jpg</td>\n",
       "      <td>This is a red and black plaid skirt with a cla...</td>\n",
       "      <td>[-0.021971317, 0.12156065, -0.002515854, 0.034...</td>\n",
       "      <td>Red and Black Plaid Skirt</td>\n",
       "      <td>S</td>\n",
       "      <td>Skirts</td>\n",
       "      <td>Casual</td>\n",
       "      <td>F</td>\n",
       "      <td>0.699219</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>b0c03127-9dfb-4573-8934-1958396937bf.jpg</td>\n",
       "      <td>This red flannel plaid shirt has a classic and...</td>\n",
       "      <td>[-0.03013145, 0.060508166, -0.03642542, 0.0301...</td>\n",
       "      <td>Red Flannel Plaid Shirt</td>\n",
       "      <td>S</td>\n",
       "      <td>Shirts</td>\n",
       "      <td>Casual</td>\n",
       "      <td>M</td>\n",
       "      <td>0.679199</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                   filename  \\\n",
       "0  0e20abb0-d56a-4f83-b254-9db70fb92794.jpg   \n",
       "1  10e51a41-3729-472e-b288-f3b8f895577a.jpg   \n",
       "2  300a4125-acec-46aa-b0b9-68b4b2142c70.jpg   \n",
       "3  bd289469-607c-45df-bad3-ed1057e277bf.jpg   \n",
       "4  b0c03127-9dfb-4573-8934-1958396937bf.jpg   \n",
       "\n",
       "                                         Description  \\\n",
       "0  This shirt is a long-sleeved, black and grey s...   \n",
       "1  This plaid shirt features a classic plaid patt...   \n",
       "2  These plaid shorts are a stylish and comfortab...   \n",
       "3  This is a red and black plaid skirt with a cla...   \n",
       "4  This red flannel plaid shirt has a classic and...   \n",
       "\n",
       "                                              vector  \\\n",
       "0  [-0.045025624, 0.041662034, -0.0006505165, 0.0...   \n",
       "1  [-0.044541422, 0.05006024, -0.04257077, 0.0401...   \n",
       "2  [-0.002765015, 0.030705247, -0.010424565, -0.0...   \n",
       "3  [-0.021971317, 0.12156065, -0.002515854, 0.034...   \n",
       "4  [-0.03013145, 0.060508166, -0.03642542, 0.0301...   \n",
       "\n",
       "                                            Title Size Category    Type  \\\n",
       "0  Black and Grey Striped Shirt with Pink Accents    S     Tops  Casual   \n",
       "1                Plaid shirt with embroidered hem    L     Tops  Casual   \n",
       "2                                    Plaid Shorts    S    Pants  Casual   \n",
       "3                       Red and Black Plaid Skirt    S   Skirts  Casual   \n",
       "4                         Red Flannel Plaid Shirt    S   Shirts  Casual   \n",
       "\n",
       "  Gender  _relevance_score  \n",
       "0      F          0.744141  \n",
       "1      F          0.735352  \n",
       "2      M          0.728516  \n",
       "3      F          0.699219  \n",
       "4      M          0.679199  "
      ]
     },
     "execution_count": 153,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from lancedb.rerankers import ColbertReranker\n",
    "\n",
    "reranker = ColbertReranker(column=\"Description\")\n",
    "rs = tbl.search(response, query_type=\"hybrid\").rerank(reranker=reranker).limit(5).to_pandas()\n",
    "rs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 154,
   "id": "965061ed-59ad-4ab3-a15d-fd7766321cf8",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "imgs = show_image_from_response(rs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 155,
   "id": "1e397943-5a60-4067-96e1-2d4981193e8c",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/jpeg": "[encoded data, 55448 characters]",
      "image/png": "[encoded data, 510812 characters]",
      "text/plain": [
       "<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=400x533>"
      ]
     },
     "execution_count": 155,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "imgs[-1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 156,
   "id": "06c35240-f9d8-4518-84e6-cd46bb567330",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/jpeg": "[encoded data, 59548 characters]",
      "image/png": "[encoded data, 456644 characters]",
      "text/plain": [
       "<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=533x400>"
      ]
     },
     "execution_count": 156,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "imgs[-2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "e458bdda-4ac0-424a-8b04-a4f2261e0f57",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "6cf3b9eca0bc4120b6fc7303bf82dc2f",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "VBox(children=(FileUpload(value=(), accept='image/*', description='Upload'), Text(value='', placeholder='Enter…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import lancedb\n",
    "from lancedb.pydantic import LanceModel, Vector\n",
    "from lancedb.embeddings import get_registry\n",
    "from pathlib import Path\n",
    "from PIL import Image\n",
    "import io\n",
    "import base64\n",
    "from together import Together\n",
    "import os\n",
    "from ipywidgets import FileUpload, Output, VBox, HBox, Button, Text\n",
    "from IPython.display import display, clear_output\n",
    "\n",
    "# Set up the sentence transformer model\n",
    "model = get_registry().get(\"sentence-transformers\").create(name=\"BAAI/bge-small-en-v1.5\", device=\"cuda\")\n",
    "\n",
    "# Define the schema for our LanceDB table\n",
    "class Schema(LanceModel):\n",
    "    Filename: str\n",
    "    Title: str\n",
    "    Size: str\n",
    "    Gender: str\n",
    "    Description: str = model.SourceField()\n",
    "    Category: str\n",
    "    Type: str\n",
    "    vector: Vector(model.ndims()) = model.VectorField()\n",
    "\n",
    "# Connect to LanceDB and create/load the table\n",
    "db = lancedb.connect(\"~/.lancedb\")\n",
    "tbl = db.create_table(name=\"clothes\", schema=Schema, mode=\"overwrite\")\n",
    "\n",
    "# Load and clean data (assuming this part is already done)\n",
    "df = pd.read_csv(\"./final_balanced_sample_dataset.csv\")\n",
    "df = df.dropna().astype(str)\n",
    "tbl.add(df.to_dict('records'))\n",
    "\n",
    "# Set up the Together API client\n",
    "os.environ[\"TOGETHER_API_KEY\"] = \"714312b00529afd04be6c863e71d813a309f764ecf487c7538ab6da6a2addd5a\"\n",
    "client = Together(api_key=os.environ.get('TOGETHER_API_KEY'))\n",
    "\n",
    "def encode_image(image_content):\n",
    "    return base64.b64encode(image_content).decode('utf-8')\n",
    "\n",
    "def generate_description(image_content):\n",
    "    base64_image = encode_image(image_content)\n",
    "    response = client.chat.completions.create(\n",
    "        model=\"meta-llama/Llama-Vision-Free\",\n",
    "        messages=[\n",
    "            {\n",
    "                \"role\": \"user\",\n",
    "                \"content\": [\n",
    "                    {\n",
    "                        \"type\": \"image_url\",\n",
    "                        \"image_url\": {\n",
    "                            \"url\": f\"data:image/jpeg;base64,{base64_image}\"\n",
    "                        }\n",
    "                    },\n",
    "                    {\n",
    "                        \"type\": \"text\",\n",
    "                        \"text\": \"Describe this clothing item in detail.\"\n",
    "                    }\n",
    "                ]\n",
    "            }\n",
    "        ],\n",
    "        max_tokens=512,\n",
    "        temperature=0.7,\n",
    "    )\n",
    "    return response.choices[0].message.content\n",
    "\n",
    "def retrieve_similar_items(description, n=10):\n",
    "    results = tbl.search(description).limit(n).to_pandas()\n",
    "    return results\n",
    "\n",
    "def show_images(results, output):\n",
    "    with output:\n",
    "        clear_output(wait=True)\n",
    "        for _, row in results.iterrows():\n",
    "            img_path = Path(\"archive\") / \"images_compressed\" / row['Filename']\n",
    "            img = Image.open(img_path)\n",
    "            display(img)\n",
    "            print(f\"Title: {row['Title']}\")\n",
    "            print(f\"Description: {row['Description']}\")\n",
    "            print(\"---\")\n",
    "\n",
    "def create_fashion_assistant():\n",
    "    upload = FileUpload(accept='image/*', multiple=False)\n",
    "    output = Output()\n",
    "    description_text = Text(placeholder='Enter a description or refinement prompt')\n",
    "    search_button = Button(description='Search')\n",
    "    \n",
    "    def on_upload_change(change):\n",
    "        if change['type'] == 'change' and change['name'] == 'value':\n",
    "            with output:\n",
    "                clear_output(wait=True)\n",
    "                if upload.value:\n",
    "                    file_info = next(iter(upload.value))\n",
    "                    image_content = file_info.content\n",
    "                    try:\n",
    "                        description = generate_description(image_content)\n",
    "                        description_text.value = description\n",
    "                        print(f\"Generated description: {description}\")\n",
    "                    except Exception as e:\n",
    "                        print(f\"Error generating description: {str(e)}\")\n",
    "    \n",
    "    def on_search_click(b):\n",
    "        with output:\n",
    "            clear_output(wait=True)\n",
    "            description = description_text.value\n",
    "            results = retrieve_similar_items(description)\n",
    "            show_images(results, output)\n",
    "    \n",
    "    upload.observe(on_upload_change, names='value')\n",
    "    search_button.on_click(on_search_click)\n",
    "    \n",
    "    display(VBox([upload, description_text, search_button, output]))\n",
    "\n",
    "# Call this function to start the fashion assistant\n",
    "create_fashion_assistant()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "765dac51-23fa-44de-a30c-334282b20bcc",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "c1c3ece898fd4e6bbcd7bb3c01233880",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "VBox(children=(FileUpload(value=(), accept='image/*', description='Upload'), Text(value='', placeholder='Enter…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import lancedb\n",
    "from lancedb.pydantic import LanceModel, Vector\n",
    "from lancedb.embeddings import get_registry\n",
    "from pathlib import Path\n",
    "from PIL import Image\n",
    "import io\n",
    "import base64\n",
    "from together import Together\n",
    "import os\n",
    "from ipywidgets import FileUpload, Output, VBox, HBox, Button, Text\n",
    "from IPython.display import display, clear_output\n",
    "\n",
    "# ... (previous setup code remains the same)\n",
    "\n",
    "def encode_image(image_content):\n",
    "    return base64.b64encode(image_content).decode('utf-8')\n",
    "\n",
    "def generate_description(image_content):\n",
    "    base64_image = encode_image(image_content)\n",
    "    response = client.chat.completions.create(\n",
    "        model=\"meta-llama/Llama-Vision-Free\",\n",
    "        messages=[\n",
    "            {\n",
    "                \"role\": \"user\",\n",
    "                \"content\": [\n",
    "                    {\n",
    "                        \"type\": \"image_url\",\n",
    "                        \"image_url\": {\n",
    "                            \"url\": f\"data:image/jpeg;base64,{base64_image}\"\n",
    "                        }\n",
    "                    },\n",
    "                    {\n",
    "                        \"type\": \"text\",\n",
    "                        \"text\": \"Describe this clothing item in detail.\"\n",
    "                    }\n",
    "                ]\n",
    "            }\n",
    "        ],\n",
    "        max_tokens=512,\n",
    "        temperature=0.7,\n",
    "    )\n",
    "    return response.choices[0].message.content\n",
    "\n",
    "def process_text_input(text):\n",
    "    response = client.chat.completions.create(\n",
    "        model=\"meta-llama/Llama-Vision-Free\",\n",
    "        messages=[\n",
    "            {\n",
    "                \"role\": \"user\",\n",
    "                \"content\": f\"Based on the following description or refinement, provide a detailed description of the clothing item: {text}\"\n",
    "            }\n",
    "        ],\n",
    "        max_tokens=512,\n",
    "        temperature=0.7,\n",
    "    )\n",
    "    return response.choices[0].message.content\n",
    "\n",
    "def retrieve_similar_items(description, n=10):\n",
    "    results = tbl.search(description).limit(n).to_pandas()\n",
    "    return results\n",
    "\n",
    "def show_images(results, output):\n",
    "    with output:\n",
    "        clear_output(wait=True)\n",
    "        for _, row in results.iterrows():\n",
    "            img_path = Path(\"archive\") / \"images_compressed\" / row['Filename']\n",
    "            img = Image.open(img_path)\n",
    "            display(img)\n",
    "            print(f\"Title: {row['Title']}\")\n",
    "            print(f\"Description: {row['Description']}\")\n",
    "            print(\"---\")\n",
    "\n",
    "def create_fashion_assistant():\n",
    "    upload = FileUpload(accept='image/*', multiple=False)\n",
    "    output = Output()\n",
    "    description_text = Text(placeholder='Enter a description or refinement prompt')\n",
    "    search_button = Button(description='Search')\n",
    "    \n",
    "    def on_upload_change(change):\n",
    "        if change['type'] == 'change' and change['name'] == 'value':\n",
    "            with output:\n",
    "                clear_output(wait=True)\n",
    "                if upload.value:\n",
    "                    file_info = next(iter(upload.value))\n",
    "                    image_content = file_info.content\n",
    "                    try:\n",
    "                        description = generate_description(image_content)\n",
    "                        description_text.value = description\n",
    "                        print(f\"Generated description: {description}\")\n",
    "                    except Exception as e:\n",
    "                        print(f\"Error generating description: {str(e)}\")\n",
    "    \n",
    "    def on_search_click(b):\n",
    "        with output:\n",
    "            clear_output(wait=True)\n",
    "            input_text = description_text.value\n",
    "            try:\n",
    "                processed_description = process_text_input(input_text)\n",
    "                print(f\"Processed description: {processed_description}\")\n",
    "                results = retrieve_similar_items(processed_description)\n",
    "                show_images(results, output)\n",
    "            except Exception as e:\n",
    "                print(f\"Error processing input or retrieving results: {str(e)}\")\n",
    "    \n",
    "    upload.observe(on_upload_change, names='value')\n",
    "    search_button.on_click(on_search_click)\n",
    "    \n",
    "    display(VBox([upload, description_text, search_button, output]))\n",
    "\n",
    "# Call this function to start the fashion assistant\n",
    "create_fashion_assistant()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "id": "605f9456-a396-457c-b738-b85890b18240",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "eeb086a415794690b94887ef83f98159",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "VBox(children=(FileUpload(value=(), accept='image/*', description='Upload'), Text(value='', placeholder='Enter…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import lancedb\n",
    "from lancedb.pydantic import LanceModel, Vector\n",
    "from lancedb.embeddings import get_registry\n",
    "from pathlib import Path\n",
    "from PIL import Image\n",
    "import io\n",
    "import base64\n",
    "from together import Together\n",
    "import os\n",
    "from ipywidgets import FileUpload, Output, VBox, HBox, Button, Text\n",
    "from IPython.display import display, clear_output\n",
    "\n",
    "# Set up the sentence transformer model\n",
    "model = get_registry().get(\"sentence-transformers\").create(name=\"BAAI/bge-small-en-v1.5\", device=\"cuda\")\n",
    "\n",
    "# Define the schema for our LanceDB table\n",
    "class Schema(LanceModel):\n",
    "    Filename: str\n",
    "    Title: str\n",
    "    Size: str\n",
    "    Gender: str\n",
    "    Description: str = model.SourceField()\n",
    "    Category: str\n",
    "    Type: str\n",
    "    vector: Vector(model.ndims()) = model.VectorField()\n",
    "\n",
    "# Connect to LanceDB and create/load the table\n",
    "db = lancedb.connect(\"~/.lancedb\")\n",
    "tbl = db.create_table(name=\"clothes\", schema=Schema, mode=\"overwrite\")\n",
    "\n",
    "# Load and clean data (assuming this part is already done)\n",
    "df = pd.read_csv(\"./final_balanced_sample_dataset.csv\")\n",
    "df = df.dropna().astype(str)\n",
    "tbl.add(df.to_dict('records'))\n",
    "\n",
    "# Set up the Together API client\n",
    "os.environ[\"TOGETHER_API_KEY\"] = \"714312b00529afd04be6c863e71d813a309f764ecf487c7538ab6da6a2addd5a\"\n",
    "client = Together(api_key=os.environ.get('TOGETHER_API_KEY'))\n",
    "\n",
    "def encode_image(image_content):\n",
    "    return base64.b64encode(image_content).decode('utf-8')\n",
    "\n",
    "def generate_description(image_content):\n",
    "    base64_image = encode_image(image_content)\n",
    "    response = client.chat.completions.create(\n",
    "        model=\"meta-llama/Llama-Vision-Free\",\n",
    "        messages=[\n",
    "            {\n",
    "                \"role\": \"user\",\n",
    "                \"content\": [\n",
    "                    {\n",
    "                        \"type\": \"image_url\",\n",
    "                        \"image_url\": {\n",
    "                            \"url\": f\"data:image/jpeg;base64,{base64_image}\"\n",
    "                        }\n",
    "                    },\n",
    "                    {\n",
    "                        \"type\": \"text\",\n",
    "                        \"text\": \"Describe this clothing item in detail.\"\n",
    "                    }\n",
    "                ]\n",
    "            }\n",
    "        ],\n",
    "        max_tokens=512,\n",
    "        temperature=0.7,\n",
    "    )\n",
    "    return response.choices[0].message.content\n",
    "\n",
    "def suggest_complementary_clothes(description):\n",
    "    response = client.chat.completions.create(\n",
    "        model=\"meta-llama/Llama-Vision-Free\",\n",
    "        messages=[\n",
    "            {\n",
    "                \"role\": \"user\",\n",
    "                \"content\": f\"Based on this description of a clothing item: '{description}', suggest complementary clothes that would go well with it. Provide a detailed description of these complementary items suitable for a vector database query.\"\n",
    "            }\n",
    "        ],\n",
    "        max_tokens=512,\n",
    "        temperature=0.7,\n",
    "    )\n",
    "    return response.choices[0].message.content\n",
    "\n",
    "def process_human_input(text):\n",
    "    response = client.chat.completions.create(\n",
    "        model=\"meta-llama/Llama-Vision-Free\",\n",
    "        messages=[\n",
    "            {\n",
    "                \"role\": \"user\",\n",
    "                \"content\": f\"Based on this user input about clothing: '{text}', create a detailed query suitable for searching a vector database of clothing items. Expand on the key features and attributes mentioned.\"\n",
    "            }\n",
    "        ],\n",
    "        max_tokens=512,\n",
    "        temperature=0.7,\n",
    "    )\n",
    "    return response.choices[0].message.content\n",
    "\n",
    "def retrieve_similar_items(description, n=10):\n",
    "    results = tbl.search(description).limit(n).to_pandas()\n",
    "    return results\n",
    "\n",
    "def show_images(results, output):\n",
    "    with output:\n",
    "        clear_output(wait=True)\n",
    "        for _, row in results.iterrows():\n",
    "            img_path = Path(\"archive\") / \"images_compressed\" / row['Filename']\n",
    "            img = Image.open(img_path)\n",
    "            display(img)\n",
    "            print(f\"Title: {row['Title']}\")\n",
    "            print(f\"Description: {row['Description']}\")\n",
    "            print(\"---\")\n",
    "\n",
    "def create_fashion_assistant():\n",
    "    upload = FileUpload(accept='image/*', multiple=False)\n",
    "    output = Output()\n",
    "    description_text = Text(placeholder='Enter a description or refinement prompt')\n",
    "    search_button = Button(description='Search')\n",
    "    \n",
    "    def on_upload_change(change):\n",
    "        if change['type'] == 'change' and change['name'] == 'value':\n",
    "            with output:\n",
    "                clear_output(wait=True)\n",
    "                if upload.value:\n",
    "                    file_info = next(iter(upload.value))\n",
    "                    image_content = file_info.content\n",
    "                    try:\n",
    "                        description = generate_description(image_content)\n",
    "                        description_text.value = description\n",
    "                        print(f\"Generated description: {description}\")\n",
    "                    except Exception as e:\n",
    "                        print(f\"Error generating description: {str(e)}\")\n",
    "    \n",
    "    def on_search_click(b):\n",
    "        with output:\n",
    "            clear_output(wait=True)\n",
    "            input_text = description_text.value\n",
    "            try:\n",
    "                if input_text.startswith(\"Generated description:\"):\n",
    "                    # For generated descriptions, suggest complementary clothes\n",
    "                    query = suggest_complementary_clothes(input_text)\n",
    "                    print(f\"Suggesting complementary clothes for: {input_text}\")\n",
    "                    print(f\"Query for complementary items: {query}\")\n",
    "                else:\n",
    "                    # For human input, process it to create a query\n",
    "                    query = process_human_input(input_text)\n",
    "                    print(f\"Processing human input: {input_text}\")\n",
    "                    print(f\"Generated query: {query}\")\n",
    "                \n",
    "                results = retrieve_similar_items(query)\n",
    "                show_images(results, output)\n",
    "            except Exception as e:\n",
    "                print(f\"Error processing input or retrieving results: {str(e)}\")\n",
    "    \n",
    "    upload.observe(on_upload_change, names='value')\n",
    "    search_button.on_click(on_search_click)\n",
    "    \n",
    "    display(VBox([upload, description_text, search_button, output]))\n",
    "\n",
    "# Call this function to start the fashion assistant\n",
    "create_fashion_assistant()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f9b82b17-3270-4b37-80d0-e989e13c4fea",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "environment": {
   "kernel": "conda-base-py",
   "name": "workbench-notebooks.m125",
   "type": "gcloud",
   "uri": "us-docker.pkg.dev/deeplearning-platform-release/gcr.io/workbench-notebooks:m125"
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
