{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T02:39:13.961215Z",
     "start_time": "2024-04-14T02:39:12.140207Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_2604718/4201459797.py:1: DeprecationWarning: \n",
      "Pyarrow will become a required dependency of pandas in the next major release of pandas (pandas 3.0),\n",
      "(to allow more performant data types, such as the Arrow string type, and better interoperability with other libraries)\n",
      "but was not found to be installed on your system.\n",
      "If this would cause problems for you,\n",
      "please provide us feedback at https://github.com/pandas-dev/pandas/issues/54466\n",
      "        \n",
      "  import pandas as pd\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import os\n",
    "from tqdm import tqdm\n",
    "from sklearn.model_selection import train_test_split\n",
    "from suno_utils.utils.s3 import download_s3_files\n",
    "import sys\n",
    "from collections import defaultdict\n",
    "from suno_utils.utils.text import (\n",
    "    write_jsonl,\n",
    "    read_jsonl,\n",
    "    write_json,\n",
    "    read_json,\n",
    ")\n",
    "import shutil\n",
    "import ast\n",
    "from preference_helper import *\n",
    "\n",
    "sys.path.insert(0, \"/home/tony/Work/glockenspiel/sunoGPT/scripts/\")\n",
    "\n",
    "from data_preparation_7b import *\n",
    "import numpy as np\n",
    "\n",
    "pd.set_option('display.max_rows', 500)\n",
    "pd.set_option('display.max_columns', 500)\n",
    "pd.set_option('display.width', 1000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T02:39:14.003424Z",
     "start_time": "2024-04-14T02:39:13.962773Z"
    }
   },
   "outputs": [],
   "source": [
    "OUT_DATA_DIR = \"/app/suno/data/dpo/7v_r2_v0/\"\n",
    "# OUT_DATA_DIR = \"/home/tony/Data/test/7v_v6_full/\"\n",
    "os.makedirs(OUT_DATA_DIR, exist_ok=True)\n",
    "shutil.copyfile(\"/app/suno/data/dpo/7v_v1_full/tokenizer_60k.json\", os.path.join(OUT_DATA_DIR, \"tokenizer_60k.json\"))\n",
    "NPZ_DIR = \"/app/suno/data/dpo/v3_npz\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T02:39:14.241888Z",
     "start_time": "2024-04-14T02:39:14.004509Z"
    }
   },
   "outputs": [],
   "source": [
    "# df_origin = pd.read_csv(\"/home/tony/Data/Preference/7b_v1/interesting_clips.csv\")\n",
    "# df_origin[df_origin[\"id\"] == \"75f69d46-1d81-4327-9253-a8a4886777d1\"]\n",
    "# df_origin[df_origin[\"request_id\"] == \"9414f356-88d6-40ba-b95e-9f4c5004a4aa\"]\n",
    "# df_origin[df_origin[\"request_id\"] == \"b2a150c1-f058-4bff-a013-1961e574631d\"]\n",
    "# df_origin[df_origin[\"id\"] == \"574ba431-18a1-4e28-ac7c-d3e401dba6fe\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T02:41:14.726423Z",
     "start_time": "2024-04-14T02:39:14.243378Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_2604718/2261549902.py:1: DtypeWarning: Columns (3,10,13,16,17,19,20,21,26,28,30,31,32,33,34,35,36) have mixed types. Specify dtype option on import or set low_memory=False.\n",
      "  df = pd.read_csv(\"/home/tony/Data/Preference/7b_v2/interesting_clips_20240413.csv\")\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "(6005656, 43)"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df = pd.read_csv(\"/home/tony/Data/Preference/7b_v2/interesting_clips_20240413.csv\")\n",
    "df.shape\n",
    "# v0: (68746, 31)\n",
    "# v5: (938008, 37)\n",
    "# v6: (1097024, 38)\n",
    "# v21: (1822704, 41)\n",
    "# r1 \n",
    "# v2: 2620268 (pre fixes...lots of imperfections...)\n",
    "# v3: 1552512"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T02:41:15.978864Z",
     "start_time": "2024-04-14T02:41:14.727763Z"
    }
   },
   "outputs": [],
   "source": [
    "# download all clips; 883k\n",
    "from suno_utils.utils.s3 import download_s3_files\n",
    "\n",
    "s3_ids = df[\"s3_id\"].values\n",
    "s3_paths = [f\"s3://suno-data-uploads/studio/uploads/{s3_id}.npz\" for s3_id in s3_ids]\n",
    "local_paths = [f\"{NPZ_DIR}/{s3_id}.npz\" for s3_id in s3_ids]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T02:41:15.982106Z",
     "start_time": "2024-04-14T02:41:15.980316Z"
    }
   },
   "outputs": [],
   "source": [
    "# finished_paths = os.listdir(NPZ_DIR)\n",
    "# finished_paths_set = set(finished_paths)\n",
    "# unfinished_s3_paths = [\n",
    "#     path for path in s3_paths if os.path.basename(path) not in finished_paths_set\n",
    "# ]\n",
    "# unfinished_paths = [\n",
    "#     path for path in local_paths if os.path.basename(path) not in finished_paths_set\n",
    "# ]\n",
    "# print(\"jobs to be done\", len(unfinished_paths), len(unfinished_s3_paths))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T02:41:16.046388Z",
     "start_time": "2024-04-14T02:41:15.983258Z"
    }
   },
   "outputs": [],
   "source": [
    "# _ = download_s3_files(unfinished_s3_paths, unfinished_paths, n_cores=64)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T02:41:16.312383Z",
     "start_time": "2024-04-14T02:41:16.267916Z"
    }
   },
   "outputs": [],
   "source": [
    "# # # deleted files are at: deleted; try to get them as well\n",
    "# finished_paths = os.listdir(NPZ_DIR)\n",
    "# finished_paths_set = set(finished_paths)\n",
    "# unfinished_s3_paths = [\n",
    "#     path for path in s3_paths if os.path.basename(path) not in finished_paths_set\n",
    "# ]\n",
    "# unfinished_paths = [\n",
    "#     path for path in local_paths if os.path.basename(path) not in finished_paths_set\n",
    "# ]\n",
    "# print(\"jobs to be done\", len(unfinished_paths), len(unfinished_s3_paths))\n",
    "# unfinished_deleted_s3_paths = [\n",
    "#     path.replace(\"/uploads/\", \"/deleted/\") for path in unfinished_s3_paths\n",
    "# ]\n",
    "# _ = download_s3_files(unfinished_deleted_s3_paths, unfinished_paths, n_cores=32)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T02:41:16.378455Z",
     "start_time": "2024-04-14T02:41:16.313703Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Finish downloads\n"
     ]
    }
   ],
   "source": [
    "print(\"Finish downloads\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T02:41:40.037162Z",
     "start_time": "2024-04-14T02:41:16.380947Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "8330743\n"
     ]
    }
   ],
   "source": [
    "converted_paths = os.listdir(NPZ_DIR)\n",
    "print(len(converted_paths))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T02:41:40.040834Z",
     "start_time": "2024-04-14T02:41:40.038708Z"
    }
   },
   "outputs": [],
   "source": [
    "# # don't run this unless you kill some job accidentally\n",
    "# for s3_processed_file in tqdm.tqdm(converted_paths):\n",
    "#     processed_file = os.path.basename(s3_processed_file)\n",
    "#     processed_file_path = os.path.join(\"/app/suno/data/dpo/v3_npz\", processed_file)\n",
    "#     # could have been removed already\n",
    "#     if os.path.exists(processed_file_path):\n",
    "#         file_size = os.stat(processed_file_path).st_size\n",
    "#         # print(processed_file_path, file_size)\n",
    "#         # break\n",
    "#         if file_size < 2000:\n",
    "#             print(processed_file_path, file_size)\n",
    "#             os.remove(processed_file_path)\n",
    "# converted_paths = os.listdir(NPZ_DIR)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T02:41:42.743286Z",
     "start_time": "2024-04-14T02:41:40.042259Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "8330743\n"
     ]
    }
   ],
   "source": [
    "converted_paths = set([f.replace(\".npz\", \"\") for f in converted_paths])\n",
    "print(len(converted_paths))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T02:42:01.768667Z",
     "start_time": "2024-04-14T02:41:42.744834Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "pre-downloaded df (6005656, 43)\n",
      "downloaded df (6005390, 43)\n"
     ]
    }
   ],
   "source": [
    "print(\"pre-downloaded df\", df.shape)\n",
    "df[df[\"s3_id\"].isin(converted_paths)].shape\n",
    "df = df[df[\"s3_id\"].isin(converted_paths)].copy()\n",
    "print(\"downloaded df\", df.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T02:42:03.233388Z",
     "start_time": "2024-04-14T02:42:01.770213Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "is_7b\n",
       "True    6005390\n",
       "Name: count, dtype: int64"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df[\"is_7b\"] = df[\"model_name\"].str.contains(\"v3\")\n",
    "df[\"is_7b\"].value_counts()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# LET's do the data prep"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T02:42:03.240741Z",
     "start_time": "2024-04-14T02:42:03.234835Z"
    }
   },
   "outputs": [],
   "source": [
    "date_cut = '2024-03-22 04:30:00' # v3 launch test time"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T02:42:03.938067Z",
     "start_time": "2024-04-14T02:42:03.242168Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "preference  model_name         \n",
      "False       chirp-v3-engine-i      2176398\n",
      "            chirp-v3-engine-v0      417018\n",
      "            chirp-v3-engine-d       350812\n",
      "            chirp-v3-engine-s        52958\n",
      "            chirp-v3-engine-i-d       5489\n",
      "True        chirp-v3-engine-i      2190946\n",
      "            chirp-v3-engine-d       481606\n",
      "            chirp-v3-engine-v0      280512\n",
      "            chirp-v3-engine-s        44712\n",
      "            chirp-v3-engine-i-d       4937\n",
      "Name: count, dtype: int64\n",
      "(6005390, 44)\n",
      "(6005390, 44)\n"
     ]
    }
   ],
   "source": [
    "# # let's also kick out the ... ipo and ipo-dpoed model for now?\n",
    "print(df.groupby([\"preference\"])[\"model_name\"].value_counts())\n",
    "print(df.shape)\n",
    "# df = df[df[\"model_name\"].isin([\"chirp-v3-engine-d\", \"chirp-v3-engine-v0\", \"chirp-v3-engine-i\"])]\n",
    "# df = df[df[\"model_name\"].isin([\"chirp-v3-engine-d\", \"chirp-v3-engine-v0\"])]\n",
    "# only IPO\n",
    "# df = df[(df[\"model_name\"].isin([\"chirp-v3-engine-i\"]) ) & (df[\"created_at\"] >= date_cut)]\n",
    "# for some reason...we can't train dpo on the ipo data...it just doesn't follow lyrics...X.x\n",
    "# df = df[\n",
    "#     (\n",
    "#         (df[\"model_name\"].isin([\"chirp-v3-engine-d\", \"chirp-v3-engine-v0\"]))\n",
    "#         & (df[\"preference\"] == True)\n",
    "#     )\n",
    "#     | (df[\"preference\"] == False)\n",
    "# ]\n",
    "print(df.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T02:42:14.215145Z",
     "start_time": "2024-04-14T02:42:03.939713Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(6005390, 44)\n",
      "(6005182, 44)\n",
      "preference  model_name         \n",
      "False       chirp-v3-engine-i      2176317\n",
      "            chirp-v3-engine-v0      417017\n",
      "            chirp-v3-engine-d       350809\n",
      "            chirp-v3-engine-s        52958\n",
      "            chirp-v3-engine-i-d       5489\n",
      "True        chirp-v3-engine-i      2190828\n",
      "            chirp-v3-engine-d       481602\n",
      "            chirp-v3-engine-v0      280512\n",
      "            chirp-v3-engine-s        44711\n",
      "            chirp-v3-engine-i-d       4937\n",
      "Name: count, dtype: int64\n"
     ]
    }
   ],
   "source": [
    "print(df.shape)\n",
    "df = df[\n",
    "    df[\"request_id\"].isin(\n",
    "        df[\"request_id\"].value_counts().index[df[\"request_id\"].value_counts() == 2]\n",
    "    )\n",
    "]\n",
    "print(df.shape)\n",
    "print(df.groupby([\"preference\"])[\"model_name\"].value_counts())\n",
    "assert df.shape[0] == df[\"request_id\"].nunique() * 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:05:23.470740Z",
     "start_time": "2024-04-14T02:42:14.216757Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "unique_requests 3002591\n"
     ]
    }
   ],
   "source": [
    "# expand the metadata columns -- this takes forever...~ 15 mins\n",
    "test_slice = df[\"metadata\"].apply(lambda x: ast.literal_eval(x))\n",
    "test_slice_series = test_slice.apply(pd.Series)\n",
    "df = pd.concat([df, test_slice_series], axis=1, join=\"inner\")\n",
    "print(\"unique_requests\", df[\"request_id\"].nunique())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:05:24.158535Z",
     "start_time": "2024-04-14T03:05:23.502440Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "has_bad_gpt_prompt\n",
       "False    5825406\n",
       "True      179776\n",
       "Name: count, dtype: int64"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# cut on v3 time\n",
    "df[\"has_bad_gpt_prompt\"] = (~df[\"gpt_description_prompt\"].isna()) & (df[\"created_at\"] <= date_cut)\n",
    "df[\"has_bad_gpt_prompt\"].value_counts()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:05:32.013886Z",
     "start_time": "2024-04-14T03:05:24.189083Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "unique_requests 2912703\n"
     ]
    }
   ],
   "source": [
    "# double check we removed the gpt prompted ones for now \n",
    "df = df[df[\"has_bad_gpt_prompt\"] == False]\n",
    "print(\"unique_requests\", df[\"request_id\"].nunique())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:43:23.998342Z",
     "start_time": "2024-04-14T03:43:19.303015Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "unique_requests 2912702\n"
     ]
    }
   ],
   "source": [
    "df = df[~df[\"dislike_count\"].isna()]\n",
    "print(\"unique_requests\", df[\"request_id\"].nunique())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:05:32.178440Z",
     "start_time": "2024-04-14T03:05:32.043860Z"
    }
   },
   "outputs": [],
   "source": [
    "# get the original duration of the clips, if they are concacted\n",
    "df[\"original_duration_s\"] = df[\"total_start_s\"] + df[\"duration\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:06.098009Z",
     "start_time": "2024-04-14T03:05:32.180068Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "878233\n",
      "good_continue_at\n",
      "True     5702770\n",
      "False     122636\n",
      "Name: count, dtype: int64\n"
     ]
    }
   ],
   "source": [
    "# classify the continue at behavoirs by the duration choice\n",
    "audio_prompt_id_to_continue_at = {}\n",
    "for _, row in df[~df[\"audio_prompt_id\"].isna()].iterrows():\n",
    "    audio_prompt_id = row[\"audio_prompt_id\"]\n",
    "    if audio_prompt_id not in audio_prompt_id_to_continue_at:\n",
    "        audio_prompt_id_to_continue_at[audio_prompt_id] = row[\"continue_at\"]\n",
    "    else:\n",
    "        # pick the max\n",
    "        audio_prompt_id = max(\n",
    "            audio_prompt_id_to_continue_at[audio_prompt_id], row[\"continue_at\"]\n",
    "        )\n",
    "print(len(audio_prompt_id_to_continue_at))\n",
    "df[\"has_continue_and_start_continue_at\"] = df[\"id\"].apply(\n",
    "    lambda x: audio_prompt_id_to_continue_at.get(x)\n",
    ")\n",
    "# we want continue at to be at least half of the clip...\n",
    "df[\"good_continue_at\"] = (\n",
    "    (df[\"has_continue_and_start_continue_at\"] / df[\"duration\"]) > 0.9\n",
    ") | df[\"has_continue_and_start_continue_at\"].isna()\n",
    "print(df[\"good_continue_at\"].value_counts())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:07.043102Z",
     "start_time": "2024-04-14T03:07:06.099360Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "preference\n",
      "False    2912702\n",
      "True     2912702\n",
      "Name: count, dtype: int64 is_7b\n",
      "True    5825406\n",
      "Name: count, dtype: int64 model_name\n",
      "chirp-v3-engine-i      4344907\n",
      "chirp-v3-engine-d       747586\n",
      "chirp-v3-engine-v0      626008\n",
      "chirp-v3-engine-s        97669\n",
      "chirp-v3-engine-i-d       9236\n",
      "Name: count, dtype: int64 preference  model_name         \n",
      "False       chirp-v3-engine-i      2165423\n",
      "            chirp-v3-engine-v0      371746\n",
      "            chirp-v3-engine-d       317727\n",
      "            chirp-v3-engine-s        52958\n",
      "            chirp-v3-engine-i-d       4848\n",
      "True        chirp-v3-engine-i      2179482\n",
      "            chirp-v3-engine-d       429859\n",
      "            chirp-v3-engine-v0      254262\n",
      "            chirp-v3-engine-s        44711\n",
      "            chirp-v3-engine-i-d       4388\n",
      "Name: count, dtype: int64\n"
     ]
    }
   ],
   "source": [
    "print(\n",
    "    df[\"preference\"].value_counts(),\n",
    "    df[\"is_7b\"].value_counts(),\n",
    "    df[\"model_name\"].value_counts(),\n",
    "    df.groupby([\"preference\"])[\"model_name\"].value_counts()\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:21.467705Z",
     "start_time": "2024-04-14T03:07:07.044396Z"
    }
   },
   "outputs": [],
   "source": [
    "df = df.sort_values(by=[\"request_id\", \"preference\"])\n",
    "df[\"duration_rel_diff\"] = df['duration'].diff() \n",
    "df[\"play_rel_diff\"] = df['reaction_play_count'].diff() "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:21.581914Z",
     "start_time": "2024-04-14T03:07:21.469503Z"
    }
   },
   "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>request_id</th>\n",
       "      <th>preference</th>\n",
       "      <th>duration</th>\n",
       "      <th>duration_rel_diff</th>\n",
       "      <th>reaction_play_count</th>\n",
       "      <th>play_rel_diff</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>6005644</th>\n",
       "      <td>ffffd17a-01f1-4350-a680-68b81d1ee774</td>\n",
       "      <td>False</td>\n",
       "      <td>47.200000</td>\n",
       "      <td>-12.799979</td>\n",
       "      <td>1.0</td>\n",
       "      <td>-3.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6005645</th>\n",
       "      <td>ffffd17a-01f1-4350-a680-68b81d1ee774</td>\n",
       "      <td>True</td>\n",
       "      <td>51.200000</td>\n",
       "      <td>4.000000</td>\n",
       "      <td>3.0</td>\n",
       "      <td>2.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6005646</th>\n",
       "      <td>ffffd361-2cc2-402f-9001-fafb482d976f</td>\n",
       "      <td>False</td>\n",
       "      <td>54.359979</td>\n",
       "      <td>3.159979</td>\n",
       "      <td>3.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6005647</th>\n",
       "      <td>ffffd361-2cc2-402f-9001-fafb482d976f</td>\n",
       "      <td>True</td>\n",
       "      <td>56.359979</td>\n",
       "      <td>2.000000</td>\n",
       "      <td>3.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6005648</th>\n",
       "      <td>ffffe214-d069-4001-8295-b0e53b8eec2a</td>\n",
       "      <td>False</td>\n",
       "      <td>120.000000</td>\n",
       "      <td>63.640021</td>\n",
       "      <td>1.0</td>\n",
       "      <td>-2.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6005649</th>\n",
       "      <td>ffffe214-d069-4001-8295-b0e53b8eec2a</td>\n",
       "      <td>True</td>\n",
       "      <td>120.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>10.0</td>\n",
       "      <td>9.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6005652</th>\n",
       "      <td>ffffe8e2-f537-4a6c-9736-bf91ac5b2b5b</td>\n",
       "      <td>False</td>\n",
       "      <td>97.600000</td>\n",
       "      <td>-22.400000</td>\n",
       "      <td>2.0</td>\n",
       "      <td>-8.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6005653</th>\n",
       "      <td>ffffe8e2-f537-4a6c-9736-bf91ac5b2b5b</td>\n",
       "      <td>True</td>\n",
       "      <td>93.560000</td>\n",
       "      <td>-4.040000</td>\n",
       "      <td>3.0</td>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6005654</th>\n",
       "      <td>fffff257-ae07-4f25-9c36-50d798214d71</td>\n",
       "      <td>False</td>\n",
       "      <td>110.400000</td>\n",
       "      <td>16.840000</td>\n",
       "      <td>6.0</td>\n",
       "      <td>3.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6005655</th>\n",
       "      <td>fffff257-ae07-4f25-9c36-50d798214d71</td>\n",
       "      <td>True</td>\n",
       "      <td>118.400000</td>\n",
       "      <td>8.000000</td>\n",
       "      <td>9.0</td>\n",
       "      <td>3.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                   request_id preference    duration  duration_rel_diff  reaction_play_count  play_rel_diff\n",
       "6005644  ffffd17a-01f1-4350-a680-68b81d1ee774      False   47.200000         -12.799979                  1.0           -3.0\n",
       "6005645  ffffd17a-01f1-4350-a680-68b81d1ee774       True   51.200000           4.000000                  3.0            2.0\n",
       "6005646  ffffd361-2cc2-402f-9001-fafb482d976f      False   54.359979           3.159979                  3.0            0.0\n",
       "6005647  ffffd361-2cc2-402f-9001-fafb482d976f       True   56.359979           2.000000                  3.0            0.0\n",
       "6005648  ffffe214-d069-4001-8295-b0e53b8eec2a      False  120.000000          63.640021                  1.0           -2.0\n",
       "6005649  ffffe214-d069-4001-8295-b0e53b8eec2a       True  120.000000           0.000000                 10.0            9.0\n",
       "6005652  ffffe8e2-f537-4a6c-9736-bf91ac5b2b5b      False   97.600000         -22.400000                  2.0           -8.0\n",
       "6005653  ffffe8e2-f537-4a6c-9736-bf91ac5b2b5b       True   93.560000          -4.040000                  3.0            1.0\n",
       "6005654  fffff257-ae07-4f25-9c36-50d798214d71      False  110.400000          16.840000                  6.0            3.0\n",
       "6005655  fffff257-ae07-4f25-9c36-50d798214d71       True  118.400000           8.000000                  9.0            3.0"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df[\n",
    "    [\n",
    "        \"request_id\",\n",
    "        \"preference\",\n",
    "        \"duration\",\n",
    "        \"duration_rel_diff\",\n",
    "        \"reaction_play_count\",\n",
    "        \"play_rel_diff\",\n",
    "    ]\n",
    "].tail(n=10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:26.883122Z",
     "start_time": "2024-04-14T03:07:21.583363Z"
    }
   },
   "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>user_id</th>\n",
       "      <th>discord_message_id</th>\n",
       "      <th>prompt_id</th>\n",
       "      <th>upvote_count</th>\n",
       "      <th>play_count</th>\n",
       "      <th>skip_count</th>\n",
       "      <th>slug</th>\n",
       "      <th>user_n_clips</th>\n",
       "      <th>reaction_play_count</th>\n",
       "      <th>total_start_s</th>\n",
       "      <th>total_clip_s</th>\n",
       "      <th>concat_play_counts</th>\n",
       "      <th>concat_likes</th>\n",
       "      <th>duration</th>\n",
       "      <th>options</th>\n",
       "      <th>continue_at</th>\n",
       "      <th>priority</th>\n",
       "      <th>original_duration_s</th>\n",
       "      <th>has_continue_and_start_continue_at</th>\n",
       "      <th>duration_rel_diff</th>\n",
       "      <th>play_rel_diff</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>count</th>\n",
       "      <td>2.912702e+06</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>2.912702e+06</td>\n",
       "      <td>2.912702e+06</td>\n",
       "      <td>2912702.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>2.912702e+06</td>\n",
       "      <td>2.911398e+06</td>\n",
       "      <td>1.194222e+06</td>\n",
       "      <td>1.193699e+06</td>\n",
       "      <td>1.194222e+06</td>\n",
       "      <td>1.194222e+06</td>\n",
       "      <td>2.912702e+06</td>\n",
       "      <td>0.0</td>\n",
       "      <td>995718.000000</td>\n",
       "      <td>1.456961e+06</td>\n",
       "      <td>1.194222e+06</td>\n",
       "      <td>601122.000000</td>\n",
       "      <td>2.912702e+06</td>\n",
       "      <td>2.883284e+06</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>6.296483e+06</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>4.293886e-01</td>\n",
       "      <td>6.908220e+00</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>6.766298e+02</td>\n",
       "      <td>6.393845e+00</td>\n",
       "      <td>5.297075e+01</td>\n",
       "      <td>2.063073e+02</td>\n",
       "      <td>4.892328e+01</td>\n",
       "      <td>1.320667e+00</td>\n",
       "      <td>8.326319e+01</td>\n",
       "      <td>NaN</td>\n",
       "      <td>78.707508</td>\n",
       "      <td>6.562983e+00</td>\n",
       "      <td>1.182247e+02</td>\n",
       "      <td>68.777386</td>\n",
       "      <td>8.241957e-01</td>\n",
       "      <td>3.588100e+00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>3.103847e+06</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>6.635786e-01</td>\n",
       "      <td>4.384964e+02</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>1.215092e+03</td>\n",
       "      <td>4.209037e+02</td>\n",
       "      <td>5.729678e+01</td>\n",
       "      <td>1.206780e+02</td>\n",
       "      <td>1.258048e+03</td>\n",
       "      <td>3.552692e+01</td>\n",
       "      <td>3.267209e+01</td>\n",
       "      <td>NaN</td>\n",
       "      <td>52.522919</td>\n",
       "      <td>4.749432e+00</td>\n",
       "      <td>5.113023e+01</td>\n",
       "      <td>32.886117</td>\n",
       "      <td>2.143640e+01</td>\n",
       "      <td>4.226210e+02</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min</th>\n",
       "      <td>3.000000e+00</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>-2.000000e+00</td>\n",
       "      <td>0.000000e+00</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>4.000000e+01</td>\n",
       "      <td>1.000000e+00</td>\n",
       "      <td>0.000000e+00</td>\n",
       "      <td>5.479979e+00</td>\n",
       "      <td>1.000000e+00</td>\n",
       "      <td>-1.000000e+00</td>\n",
       "      <td>3.600000e-01</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.800000</td>\n",
       "      <td>0.000000e+00</td>\n",
       "      <td>8.000000e-01</td>\n",
       "      <td>0.800000</td>\n",
       "      <td>-2.412800e+02</td>\n",
       "      <td>-1.183000e+04</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>4.692848e+06</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.000000e+00</td>\n",
       "      <td>0.000000e+00</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>9.800000e+01</td>\n",
       "      <td>3.000000e+00</td>\n",
       "      <td>0.000000e+00</td>\n",
       "      <td>1.492400e+02</td>\n",
       "      <td>2.000000e+00</td>\n",
       "      <td>0.000000e+00</td>\n",
       "      <td>5.840000e+01</td>\n",
       "      <td>NaN</td>\n",
       "      <td>51.359979</td>\n",
       "      <td>0.000000e+00</td>\n",
       "      <td>8.848000e+01</td>\n",
       "      <td>49.639979</td>\n",
       "      <td>-3.200000e+00</td>\n",
       "      <td>1.000000e+00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>6.374350e+06</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.000000e+00</td>\n",
       "      <td>4.000000e+00</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>2.720000e+02</td>\n",
       "      <td>4.000000e+00</td>\n",
       "      <td>5.263998e+01</td>\n",
       "      <td>1.800000e+02</td>\n",
       "      <td>4.000000e+00</td>\n",
       "      <td>0.000000e+00</td>\n",
       "      <td>8.276000e+01</td>\n",
       "      <td>NaN</td>\n",
       "      <td>60.000000</td>\n",
       "      <td>1.000000e+01</td>\n",
       "      <td>1.184000e+02</td>\n",
       "      <td>59.999979</td>\n",
       "      <td>0.000000e+00</td>\n",
       "      <td>2.000000e+00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>8.577679e+06</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>1.000000e+00</td>\n",
       "      <td>8.000000e+00</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>6.820000e+02</td>\n",
       "      <td>6.000000e+00</td>\n",
       "      <td>8.500000e+01</td>\n",
       "      <td>2.368000e+02</td>\n",
       "      <td>8.000000e+00</td>\n",
       "      <td>1.000000e+00</td>\n",
       "      <td>1.184000e+02</td>\n",
       "      <td>NaN</td>\n",
       "      <td>117.640000</td>\n",
       "      <td>1.000000e+01</td>\n",
       "      <td>1.355200e+02</td>\n",
       "      <td>99.359979</td>\n",
       "      <td>5.000000e+00</td>\n",
       "      <td>4.000000e+00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>1.222934e+07</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>4.250000e+02</td>\n",
       "      <td>7.008920e+05</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>1.821700e+04</td>\n",
       "      <td>6.988550e+05</td>\n",
       "      <td>3.540000e+03</td>\n",
       "      <td>4.049840e+03</td>\n",
       "      <td>2.848090e+05</td>\n",
       "      <td>9.525000e+03</td>\n",
       "      <td>2.460000e+02</td>\n",
       "      <td>NaN</td>\n",
       "      <td>3600.000000</td>\n",
       "      <td>1.000000e+01</td>\n",
       "      <td>3.600000e+03</td>\n",
       "      <td>1800.000000</td>\n",
       "      <td>1.904000e+02</td>\n",
       "      <td>6.988520e+05</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            user_id  discord_message_id  prompt_id  upvote_count    play_count  skip_count  slug  user_n_clips  reaction_play_count  total_start_s  total_clip_s  concat_play_counts  concat_likes      duration  options    continue_at      priority  original_duration_s  has_continue_and_start_continue_at  duration_rel_diff  play_rel_diff\n",
       "count  2.912702e+06                 0.0        0.0  2.912702e+06  2.912702e+06   2912702.0   0.0  2.912702e+06         2.911398e+06   1.194222e+06  1.193699e+06        1.194222e+06  1.194222e+06  2.912702e+06      0.0  995718.000000  1.456961e+06         1.194222e+06                       601122.000000       2.912702e+06   2.883284e+06\n",
       "mean   6.296483e+06                 NaN        NaN  4.293886e-01  6.908220e+00         0.0   NaN  6.766298e+02         6.393845e+00   5.297075e+01  2.063073e+02        4.892328e+01  1.320667e+00  8.326319e+01      NaN      78.707508  6.562983e+00         1.182247e+02                           68.777386       8.241957e-01   3.588100e+00\n",
       "std    3.103847e+06                 NaN        NaN  6.635786e-01  4.384964e+02         0.0   NaN  1.215092e+03         4.209037e+02   5.729678e+01  1.206780e+02        1.258048e+03  3.552692e+01  3.267209e+01      NaN      52.522919  4.749432e+00         5.113023e+01                           32.886117       2.143640e+01   4.226210e+02\n",
       "min    3.000000e+00                 NaN        NaN -2.000000e+00  0.000000e+00         0.0   NaN  4.000000e+01         1.000000e+00   0.000000e+00  5.479979e+00        1.000000e+00 -1.000000e+00  3.600000e-01      NaN       0.800000  0.000000e+00         8.000000e-01                            0.800000      -2.412800e+02  -1.183000e+04\n",
       "25%    4.692848e+06                 NaN        NaN  0.000000e+00  0.000000e+00         0.0   NaN  9.800000e+01         3.000000e+00   0.000000e+00  1.492400e+02        2.000000e+00  0.000000e+00  5.840000e+01      NaN      51.359979  0.000000e+00         8.848000e+01                           49.639979      -3.200000e+00   1.000000e+00\n",
       "50%    6.374350e+06                 NaN        NaN  0.000000e+00  4.000000e+00         0.0   NaN  2.720000e+02         4.000000e+00   5.263998e+01  1.800000e+02        4.000000e+00  0.000000e+00  8.276000e+01      NaN      60.000000  1.000000e+01         1.184000e+02                           59.999979       0.000000e+00   2.000000e+00\n",
       "75%    8.577679e+06                 NaN        NaN  1.000000e+00  8.000000e+00         0.0   NaN  6.820000e+02         6.000000e+00   8.500000e+01  2.368000e+02        8.000000e+00  1.000000e+00  1.184000e+02      NaN     117.640000  1.000000e+01         1.355200e+02                           99.359979       5.000000e+00   4.000000e+00\n",
       "max    1.222934e+07                 NaN        NaN  4.250000e+02  7.008920e+05         0.0   NaN  1.821700e+04         6.988550e+05   3.540000e+03  4.049840e+03        2.848090e+05  9.525000e+03  2.460000e+02      NaN    3600.000000  1.000000e+01         3.600000e+03                         1800.000000       1.904000e+02   6.988520e+05"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df[df[\"preference\"] == True].describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:32.039268Z",
     "start_time": "2024-04-14T03:07:26.892964Z"
    }
   },
   "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>user_id</th>\n",
       "      <th>discord_message_id</th>\n",
       "      <th>prompt_id</th>\n",
       "      <th>upvote_count</th>\n",
       "      <th>play_count</th>\n",
       "      <th>skip_count</th>\n",
       "      <th>slug</th>\n",
       "      <th>user_n_clips</th>\n",
       "      <th>reaction_play_count</th>\n",
       "      <th>total_start_s</th>\n",
       "      <th>total_clip_s</th>\n",
       "      <th>concat_play_counts</th>\n",
       "      <th>concat_likes</th>\n",
       "      <th>duration</th>\n",
       "      <th>options</th>\n",
       "      <th>continue_at</th>\n",
       "      <th>priority</th>\n",
       "      <th>original_duration_s</th>\n",
       "      <th>has_continue_and_start_continue_at</th>\n",
       "      <th>duration_rel_diff</th>\n",
       "      <th>play_rel_diff</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>count</th>\n",
       "      <td>2.912702e+06</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>2.912702e+06</td>\n",
       "      <td>2.912702e+06</td>\n",
       "      <td>2912702.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>2.912702e+06</td>\n",
       "      <td>2.883791e+06</td>\n",
       "      <td>113.000000</td>\n",
       "      <td>111.000000</td>\n",
       "      <td>113.000000</td>\n",
       "      <td>113.000000</td>\n",
       "      <td>2.912702e+06</td>\n",
       "      <td>0.0</td>\n",
       "      <td>995718.000000</td>\n",
       "      <td>1.456961e+06</td>\n",
       "      <td>113.000000</td>\n",
       "      <td>2042.000000</td>\n",
       "      <td>2.912701e+06</td>\n",
       "      <td>2.882499e+06</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>6.296483e+06</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>2.602395e-04</td>\n",
       "      <td>2.797351e+00</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>6.766298e+02</td>\n",
       "      <td>2.815473e+00</td>\n",
       "      <td>37.160705</td>\n",
       "      <td>165.540882</td>\n",
       "      <td>7.610619</td>\n",
       "      <td>0.389381</td>\n",
       "      <td>8.243899e+01</td>\n",
       "      <td>NaN</td>\n",
       "      <td>78.707508</td>\n",
       "      <td>6.562983e+00</td>\n",
       "      <td>97.593619</td>\n",
       "      <td>70.384971</td>\n",
       "      <td>-8.242226e-01</td>\n",
       "      <td>-3.581663e+00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>3.103847e+06</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>4.679372e-02</td>\n",
       "      <td>1.317425e+01</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>1.215092e+03</td>\n",
       "      <td>1.219237e+01</td>\n",
       "      <td>49.702983</td>\n",
       "      <td>73.274600</td>\n",
       "      <td>13.301070</td>\n",
       "      <td>0.557956</td>\n",
       "      <td>3.425118e+01</td>\n",
       "      <td>NaN</td>\n",
       "      <td>52.522919</td>\n",
       "      <td>4.749432e+00</td>\n",
       "      <td>48.566581</td>\n",
       "      <td>36.176901</td>\n",
       "      <td>4.733929e+01</td>\n",
       "      <td>4.231702e+02</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min</th>\n",
       "      <td>3.000000e+00</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>-2.000000e+00</td>\n",
       "      <td>0.000000e+00</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>4.000000e+01</td>\n",
       "      <td>1.000000e+00</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>59.839979</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>4.000000e-01</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.800000</td>\n",
       "      <td>0.000000e+00</td>\n",
       "      <td>5.680000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>-2.304000e+02</td>\n",
       "      <td>-6.988540e+05</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>4.692848e+06</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.000000e+00</td>\n",
       "      <td>0.000000e+00</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>9.800000e+01</td>\n",
       "      <td>1.000000e+00</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>116.559979</td>\n",
       "      <td>2.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>5.840000e+01</td>\n",
       "      <td>NaN</td>\n",
       "      <td>51.359979</td>\n",
       "      <td>0.000000e+00</td>\n",
       "      <td>60.000000</td>\n",
       "      <td>50.449979</td>\n",
       "      <td>-3.611998e+01</td>\n",
       "      <td>-4.000000e+00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>6.374350e+06</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.000000e+00</td>\n",
       "      <td>1.000000e+00</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>2.720000e+02</td>\n",
       "      <td>2.000000e+00</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>154.999979</td>\n",
       "      <td>3.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>8.272000e+01</td>\n",
       "      <td>NaN</td>\n",
       "      <td>60.000000</td>\n",
       "      <td>1.000000e+01</td>\n",
       "      <td>106.479958</td>\n",
       "      <td>60.000000</td>\n",
       "      <td>0.000000e+00</td>\n",
       "      <td>-2.000000e+00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>8.577679e+06</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.000000e+00</td>\n",
       "      <td>4.000000e+00</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>6.820000e+02</td>\n",
       "      <td>3.000000e+00</td>\n",
       "      <td>63.999979</td>\n",
       "      <td>190.379979</td>\n",
       "      <td>7.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.184000e+02</td>\n",
       "      <td>NaN</td>\n",
       "      <td>117.640000</td>\n",
       "      <td>1.000000e+01</td>\n",
       "      <td>120.000000</td>\n",
       "      <td>115.150000</td>\n",
       "      <td>3.432000e+01</td>\n",
       "      <td>0.000000e+00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>1.222934e+07</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>5.000000e+01</td>\n",
       "      <td>1.203200e+04</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>1.821700e+04</td>\n",
       "      <td>1.184000e+04</td>\n",
       "      <td>236.839979</td>\n",
       "      <td>479.759979</td>\n",
       "      <td>93.000000</td>\n",
       "      <td>3.000000</td>\n",
       "      <td>3.470000e+02</td>\n",
       "      <td>NaN</td>\n",
       "      <td>3600.000000</td>\n",
       "      <td>1.000000e+01</td>\n",
       "      <td>240.519979</td>\n",
       "      <td>300.000000</td>\n",
       "      <td>3.152400e+02</td>\n",
       "      <td>1.183200e+04</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            user_id  discord_message_id  prompt_id  upvote_count    play_count  skip_count  slug  user_n_clips  reaction_play_count  total_start_s  total_clip_s  concat_play_counts  concat_likes      duration  options    continue_at      priority  original_duration_s  has_continue_and_start_continue_at  duration_rel_diff  play_rel_diff\n",
       "count  2.912702e+06                 0.0        0.0  2.912702e+06  2.912702e+06   2912702.0   0.0  2.912702e+06         2.883791e+06     113.000000    111.000000          113.000000    113.000000  2.912702e+06      0.0  995718.000000  1.456961e+06           113.000000                         2042.000000       2.912701e+06   2.882499e+06\n",
       "mean   6.296483e+06                 NaN        NaN  2.602395e-04  2.797351e+00         0.0   NaN  6.766298e+02         2.815473e+00      37.160705    165.540882            7.610619      0.389381  8.243899e+01      NaN      78.707508  6.562983e+00            97.593619                           70.384971      -8.242226e-01  -3.581663e+00\n",
       "std    3.103847e+06                 NaN        NaN  4.679372e-02  1.317425e+01         0.0   NaN  1.215092e+03         1.219237e+01      49.702983     73.274600           13.301070      0.557956  3.425118e+01      NaN      52.522919  4.749432e+00            48.566581                           36.176901       4.733929e+01   4.231702e+02\n",
       "min    3.000000e+00                 NaN        NaN -2.000000e+00  0.000000e+00         0.0   NaN  4.000000e+01         1.000000e+00       0.000000     59.839979            1.000000      0.000000  4.000000e-01      NaN       0.800000  0.000000e+00             5.680000                            1.000000      -2.304000e+02  -6.988540e+05\n",
       "25%    4.692848e+06                 NaN        NaN  0.000000e+00  0.000000e+00         0.0   NaN  9.800000e+01         1.000000e+00       0.000000    116.559979            2.000000      0.000000  5.840000e+01      NaN      51.359979  0.000000e+00            60.000000                           50.449979      -3.611998e+01  -4.000000e+00\n",
       "50%    6.374350e+06                 NaN        NaN  0.000000e+00  1.000000e+00         0.0   NaN  2.720000e+02         2.000000e+00       0.000000    154.999979            3.000000      0.000000  8.272000e+01      NaN      60.000000  1.000000e+01           106.479958                           60.000000       0.000000e+00  -2.000000e+00\n",
       "75%    8.577679e+06                 NaN        NaN  0.000000e+00  4.000000e+00         0.0   NaN  6.820000e+02         3.000000e+00      63.999979    190.379979            7.000000      1.000000  1.184000e+02      NaN     117.640000  1.000000e+01           120.000000                          115.150000       3.432000e+01   0.000000e+00\n",
       "max    1.222934e+07                 NaN        NaN  5.000000e+01  1.203200e+04         0.0   NaN  1.821700e+04         1.184000e+04     236.839979    479.759979           93.000000      3.000000  3.470000e+02      NaN    3600.000000  1.000000e+01           240.519979                          300.000000       3.152400e+02   1.183200e+04"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df[df[\"preference\"] == False].describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:57:25.763023Z",
     "start_time": "2024-04-14T03:57:16.915008Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "negative 1698851 positive 806533\n",
      "total pair requests 2912702 selected pair requests 751497 frac 0.258\n"
     ]
    }
   ],
   "source": [
    "normal_pos_play_count = 3\n",
    "# this is lower, cause a concat is probably already ensuring that it is good\n",
    "concat_pos_play_count = 1\n",
    "# this is a filter on the concated clip\n",
    "concat_total_play_count = 3\n",
    "\n",
    "neg_filter_selection_mask = (\n",
    "    (df[\"preference\"] == False)  # get basics aligned\n",
    "    & (df[\"reaction_play_count\"] >= 1)  # has to be played once -- just villian?\n",
    "    & (\n",
    "        df[\"reaction_play_count\"] <= 5\n",
    "    )  # if it is actually bad, shouldn't be listened often\n",
    "    & (df[\"duration\"] >= 10)  # can't be too short, otherwise it is obvious\n",
    "    & (df[\"duration\"] <= 120)  # can't be badly long\n",
    "    & (df[\"continue_at\"].isna()) # itself isn't a continue\n",
    "    & (df[\"part_of_concat\"] == False) # itself can't be concat\n",
    "    #     & (\n",
    "    #         (df[\"dislike_count\"].astype(int) >= 1)\n",
    "    #         | (df[\"flag_count\"].astype(int) >= 1)\n",
    "    #         | (df[\"deleted\"] == True)\n",
    "    #     )  # this is kinda strict\n",
    "    #     & (\n",
    "    #         (df_slice[\"is_in_playlist\"] == False)\n",
    "    #         & (df_slice[\"concat_in_playlist\"] == False)\n",
    "    #     )  # can't be part of a playlist -- otherwise there are some like signal in it?\n",
    ")\n",
    "pos_filter_selectin_mask = (\n",
    "    (df[\"preference\"] == True)  # get basics aligned\n",
    "    & (\n",
    "        df[\"good_continue_at\"] == True\n",
    "    )  # if continue, needs to continue off a certain percentage\n",
    "    & (df[\"continue_at\"].isna()) # itself isn't a continue\n",
    "    & (\n",
    "        (\n",
    "            (df[\"part_of_concat\"] == True)\n",
    "            & (df[\"reaction_play_count\"] >= concat_pos_play_count)\n",
    "            & (df[\"concat_play_counts\"] >= concat_total_play_count)\n",
    "        )\n",
    "        | (\n",
    "            (df[\"part_of_concat\"] == False)\n",
    "            & (df[\"reaction_play_count\"] >= normal_pos_play_count)\n",
    "        )\n",
    "    )\n",
    "    & (df[\"play_rel_diff\"] >= 0)  # this is more like quality assurance\n",
    "    & (df[\"duration\"] >= 10)  # can't be too short, otherwise it is obvious\n",
    "    & (df[\"duration\"] <= 120)  # can't be badly long\n",
    "    & (df[\"dislike_count\"] == 0)  # can't have dislikes\n",
    "    & (df[\"flag_count\"] == 0)  # can't have issues\n",
    "    & (df[\"deleted\"] == False)  # can't have issues\n",
    "    & (df[\"user_n_clips\"] >= 50)  # user needs to have genereated at least 40\n",
    "    # & (df[\"duration_rel_diff\"] < 10) # positive isn't just longer\n",
    "    & (df[\"upvote_count\"] >= 1)\n",
    ")\n",
    "print(\n",
    "    \"negative\",\n",
    "    sum(neg_filter_selection_mask),\n",
    "    \"positive\",\n",
    "    sum(pos_filter_selectin_mask),\n",
    ")\n",
    "\n",
    "neg_filter_requests = df[neg_filter_selection_mask][\"request_id\"].unique()\n",
    "pos_filter_requests = df[pos_filter_selectin_mask][\"request_id\"].unique()\n",
    "# looking for very strong signal here:\n",
    "# listen to the positive/negative more than once\n",
    "# disliked one of the clips\n",
    "unique_requests = set(pos_filter_requests).intersection(neg_filter_requests)\n",
    "print(\n",
    "    \"total pair requests\",\n",
    "    df[\"request_id\"].nunique(),\n",
    "    \"selected pair requests\",\n",
    "    len(unique_requests),\n",
    "    f\"frac {len(unique_requests) / df['request_id'].nunique():.3f}\",\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:55:58.961879Z",
     "start_time": "2024-04-14T03:55:55.087432Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "requests 751497 clips 1502994 total khrs 42.425; N gpus for 1250 iters 37.575; n unique users 110549\n"
     ]
    }
   ],
   "source": [
    "df_slice = df[df[\"request_id\"].isin(set(unique_requests))].copy()\n",
    "print(\n",
    "    \"requests\",\n",
    "    df_slice[\"request_id\"].nunique(),\n",
    "    \"clips\",\n",
    "    df_slice.shape[0],\n",
    "    f\"total khrs {sum(df_slice['duration'] / 3600 / 1000):.3f};\",\n",
    "    f\"N gpus for 1250 iters {df_slice.shape[0] / 8 / 4 / 1250:.3f};\",\n",
    "    f\"n unique users {df_slice['user_id'].nunique()}\",\n",
    ")\n",
    "# 76171 152342 total khrs 2.880 n gpus for 1250 iters 3.809"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:58:41.872741Z",
     "start_time": "2024-04-14T03:58:35.387306Z"
    }
   },
   "outputs": [],
   "source": [
    "last_continue_requests = df[\n",
    "    ((df[\"has_continue_and_start_continue_at\"] / df[\"duration\"]) > 0.99)\n",
    "][\"request_id\"].unique()\n",
    "early_continue_requests = df[\n",
    "    ((df[\"has_continue_and_start_continue_at\"] / df[\"duration\"]) < 0.99)\n",
    "    & ((df[\"has_continue_and_start_continue_at\"] / df[\"duration\"]) > 0.01)\n",
    "][\"request_id\"].unique()\n",
    "not_continue_requests = df[df[\"has_continue_and_start_continue_at\"].isna()][\n",
    "    \"request_id\"\n",
    "].unique()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:58:42.017693Z",
     "start_time": "2024-04-14T03:58:41.874814Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "preference  model_name         \n",
      "False       chirp-v3-engine-i      563259\n",
      "            chirp-v3-engine-v0     100331\n",
      "            chirp-v3-engine-d       72917\n",
      "            chirp-v3-engine-s       13675\n",
      "            chirp-v3-engine-i-d      1315\n",
      "True        chirp-v3-engine-i      566821\n",
      "            chirp-v3-engine-d      123457\n",
      "            chirp-v3-engine-v0      50098\n",
      "            chirp-v3-engine-s       10065\n",
      "            chirp-v3-engine-i-d      1056\n",
      "Name: count, dtype: int64\n"
     ]
    }
   ],
   "source": [
    "print(df_slice.groupby([\"preference\"])[\"model_name\"].value_counts())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:58:44.608131Z",
     "start_time": "2024-04-14T03:58:42.019593Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "chirp-v3-engine-d_win_over_chirp-v3-engine-d, win ratio 1.000, counts 37648\n",
      "chirp-v3-engine-d_win_over_chirp-v3-engine-i, win ratio 0.553, counts 12680\n",
      "chirp-v3-engine-d_win_over_chirp-v3-engine-i-d, win ratio 0.554, counts 677\n",
      "chirp-v3-engine-d_win_over_chirp-v3-engine-s, win ratio 0.597, counts 6925\n",
      "chirp-v3-engine-d_win_over_chirp-v3-engine-v0, win ratio 0.768, counts 65527\n",
      "chirp-v3-engine-i-d_win_over_chirp-v3-engine-d, win ratio 0.446, counts 546\n",
      "chirp-v3-engine-i-d_win_over_chirp-v3-engine-i, win ratio 0.390, counts 336\n",
      "chirp-v3-engine-i-d_win_over_chirp-v3-engine-i-d, win ratio 1.000, counts 10\n",
      "chirp-v3-engine-i-d_win_over_chirp-v3-engine-v0, win ratio 0.614, counts 164\n",
      "chirp-v3-engine-i_win_over_chirp-v3-engine-d, win ratio 0.447, counts 10235\n",
      "chirp-v3-engine-i_win_over_chirp-v3-engine-i, win ratio 1.000, counts 542470\n",
      "chirp-v3-engine-i_win_over_chirp-v3-engine-i-d, win ratio 0.610, counts 525\n",
      "chirp-v3-engine-i_win_over_chirp-v3-engine-s, win ratio 0.556, counts 6750\n",
      "chirp-v3-engine-i_win_over_chirp-v3-engine-v0, win ratio 0.741, counts 6841\n",
      "chirp-v3-engine-s_win_over_chirp-v3-engine-d, win ratio 0.403, counts 4684\n",
      "chirp-v3-engine-s_win_over_chirp-v3-engine-i, win ratio 0.444, counts 5381\n",
      "chirp-v3-engine-v0_win_over_chirp-v3-engine-d, win ratio 0.232, counts 19804\n",
      "chirp-v3-engine-v0_win_over_chirp-v3-engine-i, win ratio 0.259, counts 2392\n",
      "chirp-v3-engine-v0_win_over_chirp-v3-engine-i-d, win ratio 0.386, counts 103\n",
      "chirp-v3-engine-v0_win_over_chirp-v3-engine-v0, win ratio 1.000, counts 27799\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<Figure size 640x480 with 0 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 1000x800 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "get_preferfence_counts(df_slice)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:58:44.612041Z",
     "start_time": "2024-04-14T03:58:44.610232Z"
    }
   },
   "outputs": [],
   "source": [
    "# get_preferfence_counts(df_slice[df_slice[\"request_id\"].isin(not_continue_requests)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:58:44.680025Z",
     "start_time": "2024-04-14T03:58:44.613151Z"
    }
   },
   "outputs": [],
   "source": [
    "# get_preferfence_counts(df_slice[df_slice[\"request_id\"].isin(last_continue_requests)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:58:44.740989Z",
     "start_time": "2024-04-14T03:58:44.688460Z"
    }
   },
   "outputs": [],
   "source": [
    "# get_preferfence_counts(df_slice[df_slice[\"request_id\"].isin(early_continue_requests)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:58:45.953365Z",
     "start_time": "2024-04-14T03:58:44.742008Z"
    }
   },
   "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>user_id</th>\n",
       "      <th>discord_message_id</th>\n",
       "      <th>prompt_id</th>\n",
       "      <th>upvote_count</th>\n",
       "      <th>play_count</th>\n",
       "      <th>skip_count</th>\n",
       "      <th>slug</th>\n",
       "      <th>user_n_clips</th>\n",
       "      <th>reaction_play_count</th>\n",
       "      <th>total_start_s</th>\n",
       "      <th>total_clip_s</th>\n",
       "      <th>concat_play_counts</th>\n",
       "      <th>concat_likes</th>\n",
       "      <th>duration</th>\n",
       "      <th>options</th>\n",
       "      <th>continue_at</th>\n",
       "      <th>priority</th>\n",
       "      <th>original_duration_s</th>\n",
       "      <th>has_continue_and_start_continue_at</th>\n",
       "      <th>duration_rel_diff</th>\n",
       "      <th>play_rel_diff</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>count</th>\n",
       "      <td>7.514970e+05</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>751497.000000</td>\n",
       "      <td>751497.000000</td>\n",
       "      <td>751497.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>751497.000000</td>\n",
       "      <td>751497.000000</td>\n",
       "      <td>52729.0</td>\n",
       "      <td>52715.000000</td>\n",
       "      <td>52729.000000</td>\n",
       "      <td>52729.000000</td>\n",
       "      <td>751497.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>384529.000000</td>\n",
       "      <td>52729.000000</td>\n",
       "      <td>58221.000000</td>\n",
       "      <td>751497.000000</td>\n",
       "      <td>751497.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>6.274635e+06</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>1.012926</td>\n",
       "      <td>7.943263</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>730.043778</td>\n",
       "      <td>7.341112</td>\n",
       "      <td>0.0</td>\n",
       "      <td>181.514284</td>\n",
       "      <td>90.836352</td>\n",
       "      <td>2.504447</td>\n",
       "      <td>101.602408</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>7.451792</td>\n",
       "      <td>98.369192</td>\n",
       "      <td>97.209234</td>\n",
       "      <td>-0.031194</td>\n",
       "      <td>5.294062</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>3.239718e+06</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.599638</td>\n",
       "      <td>166.315414</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>1215.091473</td>\n",
       "      <td>149.963056</td>\n",
       "      <td>0.0</td>\n",
       "      <td>65.786210</td>\n",
       "      <td>1667.821450</td>\n",
       "      <td>45.173888</td>\n",
       "      <td>24.219050</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>4.357610</td>\n",
       "      <td>27.195017</td>\n",
       "      <td>27.504128</td>\n",
       "      <td>22.435546</td>\n",
       "      <td>149.960964</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min</th>\n",
       "      <td>3.000000e+00</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>50.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>13.679979</td>\n",
       "      <td>3.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>10.000000</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>10.199979</td>\n",
       "      <td>10.239979</td>\n",
       "      <td>-110.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>4.589972e+06</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>132.000000</td>\n",
       "      <td>3.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>144.999979</td>\n",
       "      <td>4.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>86.440000</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>76.879979</td>\n",
       "      <td>75.000000</td>\n",
       "      <td>-5.440000</td>\n",
       "      <td>2.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>6.365282e+06</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>5.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>328.000000</td>\n",
       "      <td>5.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>176.999979</td>\n",
       "      <td>6.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>117.600000</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>10.000000</td>\n",
       "      <td>118.400000</td>\n",
       "      <td>113.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>3.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>8.745425e+06</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>9.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>756.000000</td>\n",
       "      <td>7.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>204.719979</td>\n",
       "      <td>12.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>119.999979</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>10.000000</td>\n",
       "      <td>119.999979</td>\n",
       "      <td>119.999979</td>\n",
       "      <td>5.040000</td>\n",
       "      <td>5.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>1.222934e+07</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>425.000000</td>\n",
       "      <td>91464.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>18217.000000</td>\n",
       "      <td>91067.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>3099.670750</td>\n",
       "      <td>112266.000000</td>\n",
       "      <td>3765.000000</td>\n",
       "      <td>120.000000</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>10.000000</td>\n",
       "      <td>120.000000</td>\n",
       "      <td>600.000000</td>\n",
       "      <td>110.000000</td>\n",
       "      <td>91066.000000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            user_id  discord_message_id  prompt_id   upvote_count     play_count  skip_count  slug   user_n_clips  reaction_play_count  total_start_s  total_clip_s  concat_play_counts  concat_likes       duration  options  continue_at       priority  original_duration_s  has_continue_and_start_continue_at  duration_rel_diff  play_rel_diff\n",
       "count  7.514970e+05                 0.0        0.0  751497.000000  751497.000000    751497.0   0.0  751497.000000        751497.000000        52729.0  52715.000000        52729.000000  52729.000000  751497.000000      0.0          0.0  384529.000000         52729.000000                        58221.000000      751497.000000  751497.000000\n",
       "mean   6.274635e+06                 NaN        NaN       1.012926       7.943263         0.0   NaN     730.043778             7.341112            0.0    181.514284           90.836352      2.504447     101.602408      NaN          NaN       7.451792            98.369192                           97.209234          -0.031194       5.294062\n",
       "std    3.239718e+06                 NaN        NaN       0.599638     166.315414         0.0   NaN    1215.091473           149.963056            0.0     65.786210         1667.821450     45.173888      24.219050      NaN          NaN       4.357610            27.195017                           27.504128          22.435546     149.960964\n",
       "min    3.000000e+00                 NaN        NaN       1.000000       0.000000         0.0   NaN      50.000000             1.000000            0.0     13.679979            3.000000      0.000000      10.000000      NaN          NaN       0.000000            10.199979                           10.239979        -110.000000       0.000000\n",
       "25%    4.589972e+06                 NaN        NaN       1.000000       0.000000         0.0   NaN     132.000000             3.000000            0.0    144.999979            4.000000      0.000000      86.440000      NaN          NaN       0.000000            76.879979                           75.000000          -5.440000       2.000000\n",
       "50%    6.365282e+06                 NaN        NaN       1.000000       5.000000         0.0   NaN     328.000000             5.000000            0.0    176.999979            6.000000      1.000000     117.600000      NaN          NaN      10.000000           118.400000                          113.000000           0.000000       3.000000\n",
       "75%    8.745425e+06                 NaN        NaN       1.000000       9.000000         0.0   NaN     756.000000             7.000000            0.0    204.719979           12.000000      1.000000     119.999979      NaN          NaN      10.000000           119.999979                          119.999979           5.040000       5.000000\n",
       "max    1.222934e+07                 NaN        NaN     425.000000   91464.000000         0.0   NaN   18217.000000         91067.000000            0.0   3099.670750       112266.000000   3765.000000     120.000000      NaN          NaN      10.000000           120.000000                          600.000000         110.000000   91066.000000"
      ]
     },
     "execution_count": 99,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_slice[df_slice[\"preference\"] == True].describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:58:47.073707Z",
     "start_time": "2024-04-14T03:58:45.954799Z"
    }
   },
   "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>user_id</th>\n",
       "      <th>discord_message_id</th>\n",
       "      <th>prompt_id</th>\n",
       "      <th>upvote_count</th>\n",
       "      <th>play_count</th>\n",
       "      <th>skip_count</th>\n",
       "      <th>slug</th>\n",
       "      <th>user_n_clips</th>\n",
       "      <th>reaction_play_count</th>\n",
       "      <th>total_start_s</th>\n",
       "      <th>total_clip_s</th>\n",
       "      <th>concat_play_counts</th>\n",
       "      <th>concat_likes</th>\n",
       "      <th>duration</th>\n",
       "      <th>options</th>\n",
       "      <th>continue_at</th>\n",
       "      <th>priority</th>\n",
       "      <th>original_duration_s</th>\n",
       "      <th>has_continue_and_start_continue_at</th>\n",
       "      <th>duration_rel_diff</th>\n",
       "      <th>play_rel_diff</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>count</th>\n",
       "      <td>7.514970e+05</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>751497.000000</td>\n",
       "      <td>751497.000000</td>\n",
       "      <td>751497.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>751497.000000</td>\n",
       "      <td>751497.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>751497.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>384529.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>141.000000</td>\n",
       "      <td>751497.000000</td>\n",
       "      <td>751162.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>6.274635e+06</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.000093</td>\n",
       "      <td>2.051357</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>730.043778</td>\n",
       "      <td>2.047050</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>101.633602</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>7.451792</td>\n",
       "      <td>NaN</td>\n",
       "      <td>81.749214</td>\n",
       "      <td>18.411700</td>\n",
       "      <td>-4.198880</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>3.239718e+06</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.011764</td>\n",
       "      <td>3.198161</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>1215.091473</td>\n",
       "      <td>1.144127</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>24.677476</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>4.357610</td>\n",
       "      <td>NaN</td>\n",
       "      <td>39.421838</td>\n",
       "      <td>40.909626</td>\n",
       "      <td>117.469354</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min</th>\n",
       "      <td>3.000000e+00</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>-2.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>50.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>10.000000</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>NaN</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>-190.720021</td>\n",
       "      <td>-91064.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>4.589972e+06</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>132.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>86.400000</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>NaN</td>\n",
       "      <td>49.320000</td>\n",
       "      <td>-2.400000</td>\n",
       "      <td>-5.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>6.365282e+06</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>328.000000</td>\n",
       "      <td>2.000000</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>118.400000</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>10.000000</td>\n",
       "      <td>NaN</td>\n",
       "      <td>95.200000</td>\n",
       "      <td>12.800000</td>\n",
       "      <td>-2.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>8.745425e+06</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>3.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>756.000000</td>\n",
       "      <td>3.000000</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>119.999979</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>10.000000</td>\n",
       "      <td>NaN</td>\n",
       "      <td>119.999979</td>\n",
       "      <td>56.800000</td>\n",
       "      <td>-1.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>1.222934e+07</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>2.000000</td>\n",
       "      <td>40.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>18217.000000</td>\n",
       "      <td>5.000000</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>120.000000</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>10.000000</td>\n",
       "      <td>NaN</td>\n",
       "      <td>120.000000</td>\n",
       "      <td>119.200000</td>\n",
       "      <td>4.000000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            user_id  discord_message_id  prompt_id   upvote_count     play_count  skip_count  slug   user_n_clips  reaction_play_count  total_start_s  total_clip_s  concat_play_counts  concat_likes       duration  options  continue_at       priority  original_duration_s  has_continue_and_start_continue_at  duration_rel_diff  play_rel_diff\n",
       "count  7.514970e+05                 0.0        0.0  751497.000000  751497.000000    751497.0   0.0  751497.000000        751497.000000            0.0           0.0                 0.0           0.0  751497.000000      0.0          0.0  384529.000000                  0.0                          141.000000      751497.000000  751162.000000\n",
       "mean   6.274635e+06                 NaN        NaN       0.000093       2.051357         0.0   NaN     730.043778             2.047050            NaN           NaN                 NaN           NaN     101.633602      NaN          NaN       7.451792                  NaN                           81.749214          18.411700      -4.198880\n",
       "std    3.239718e+06                 NaN        NaN       0.011764       3.198161         0.0   NaN    1215.091473             1.144127            NaN           NaN                 NaN           NaN      24.677476      NaN          NaN       4.357610                  NaN                           39.421838          40.909626     117.469354\n",
       "min    3.000000e+00                 NaN        NaN      -2.000000       0.000000         0.0   NaN      50.000000             1.000000            NaN           NaN                 NaN           NaN      10.000000      NaN          NaN       0.000000                  NaN                            1.000000        -190.720021  -91064.000000\n",
       "25%    4.589972e+06                 NaN        NaN       0.000000       0.000000         0.0   NaN     132.000000             1.000000            NaN           NaN                 NaN           NaN      86.400000      NaN          NaN       0.000000                  NaN                           49.320000          -2.400000      -5.000000\n",
       "50%    6.365282e+06                 NaN        NaN       0.000000       0.000000         0.0   NaN     328.000000             2.000000            NaN           NaN                 NaN           NaN     118.400000      NaN          NaN      10.000000                  NaN                           95.200000          12.800000      -2.000000\n",
       "75%    8.745425e+06                 NaN        NaN       0.000000       3.000000         0.0   NaN     756.000000             3.000000            NaN           NaN                 NaN           NaN     119.999979      NaN          NaN      10.000000                  NaN                          119.999979          56.800000      -1.000000\n",
       "max    1.222934e+07                 NaN        NaN       2.000000      40.000000         0.0   NaN   18217.000000             5.000000            NaN           NaN                 NaN           NaN     120.000000      NaN          NaN      10.000000                  NaN                          120.000000         119.200000       4.000000"
      ]
     },
     "execution_count": 100,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_slice[df_slice[\"preference\"] == False].describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:58:47.350299Z",
     "start_time": "2024-04-14T03:58:47.075058Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "positive in playlist (101107, 77)\n"
     ]
    }
   ],
   "source": [
    "test_mask = (df_slice[\"preference\"] == True) & (\n",
    "    (df_slice[\"is_in_playlist\"] == True) | (df_slice[\"concat_in_playlist\"] == True)\n",
    ")\n",
    "print(\"positive in playlist\", df_slice[test_mask].shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:58:47.595515Z",
     "start_time": "2024-04-14T03:58:47.352276Z"
    }
   },
   "outputs": [],
   "source": [
    "interesting_clips_must_be_positive_mask = (\n",
    "    (df_slice[\"upvoted\"] == True)\n",
    "    | (df_slice[\"has_action\"] == True)\n",
    "    | (df_slice[\"part_of_concat\"] == True)\n",
    ")\n",
    "interesting_clips_must_be_not_negative_mask = df_slice[\"downvoted\"] == False\n",
    "interesting_clips_mask = interesting_clips_must_be_positive_mask & interesting_clips_must_be_not_negative_mask\n",
    "assert interesting_clips_mask.eq(df_slice[\"preference\"]).all()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:56.421438Z",
     "start_time": "2024-04-14T03:07:55.826381Z"
    }
   },
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'BREAK' 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[40], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mBREAK\u001b[49m\n",
      "\u001b[0;31mNameError\u001b[0m: name 'BREAK' is not defined"
     ]
    }
   ],
   "source": [
    "BREAK"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T05:06:58.080038Z",
     "start_time": "2024-04-14T05:06:57.970401Z"
    }
   },
   "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>id</th>\n",
       "      <th>created_at</th>\n",
       "      <th>updated_at</th>\n",
       "      <th>time_used</th>\n",
       "      <th>metadata</th>\n",
       "      <th>user_id</th>\n",
       "      <th>status</th>\n",
       "      <th>discord_message_id</th>\n",
       "      <th>prompt_id</th>\n",
       "      <th>request_id</th>\n",
       "      <th>is_generated</th>\n",
       "      <th>s3_id</th>\n",
       "      <th>upvote_count</th>\n",
       "      <th>batch_index</th>\n",
       "      <th>model_name</th>\n",
       "      <th>prompt_text</th>\n",
       "      <th>daily_theme_id</th>\n",
       "      <th>is_deleted</th>\n",
       "      <th>image_s3_id</th>\n",
       "      <th>is_public</th>\n",
       "      <th>dislike_count</th>\n",
       "      <th>flag_count</th>\n",
       "      <th>play_count</th>\n",
       "      <th>skip_count</th>\n",
       "      <th>title</th>\n",
       "      <th>slug</th>\n",
       "      <th>is_in_playlist</th>\n",
       "      <th>continued_parent</th>\n",
       "      <th>is_pro_user</th>\n",
       "      <th>user_n_clips</th>\n",
       "      <th>upvoted</th>\n",
       "      <th>deleted</th>\n",
       "      <th>has_continued</th>\n",
       "      <th>part_of_concat</th>\n",
       "      <th>has_action</th>\n",
       "      <th>downvoted</th>\n",
       "      <th>preference</th>\n",
       "      <th>reaction_play_count</th>\n",
       "      <th>total_start_s</th>\n",
       "      <th>total_clip_s</th>\n",
       "      <th>concat_play_counts</th>\n",
       "      <th>concat_in_playlist</th>\n",
       "      <th>concat_likes</th>\n",
       "      <th>is_7b</th>\n",
       "      <th>tags</th>\n",
       "      <th>type</th>\n",
       "      <th>prompt</th>\n",
       "      <th>stream</th>\n",
       "      <th>duration</th>\n",
       "      <th>experiment</th>\n",
       "      <th>gpt_prompt</th>\n",
       "      <th>refund_credits</th>\n",
       "      <th>make_instrumental</th>\n",
       "      <th>gpt_description_prompt</th>\n",
       "      <th>history</th>\n",
       "      <th>options</th>\n",
       "      <th>continue_at</th>\n",
       "      <th>audio_prompt_id</th>\n",
       "      <th>continued_from_prompt</th>\n",
       "      <th>priority</th>\n",
       "      <th>image_s3_id</th>\n",
       "      <th>concat_history</th>\n",
       "      <th>title</th>\n",
       "      <th>extra</th>\n",
       "      <th>promotion</th>\n",
       "      <th>check_copyright</th>\n",
       "      <th>check_artist_names</th>\n",
       "      <th>error_type</th>\n",
       "      <th>error_message</th>\n",
       "      <th>is_square</th>\n",
       "      <th>continue_discord_message_url</th>\n",
       "      <th>has_bad_gpt_prompt</th>\n",
       "      <th>original_duration_s</th>\n",
       "      <th>has_continue_and_start_continue_at</th>\n",
       "      <th>good_continue_at</th>\n",
       "      <th>duration_rel_diff</th>\n",
       "      <th>play_rel_diff</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>3299258</th>\n",
       "      <td>dfa73697-352c-4427-a047-e14272ce07d0</td>\n",
       "      <td>2024-04-08 17:18:08.635337+00:00</td>\n",
       "      <td>2024-04-08 17:18:08.635345+00:00</td>\n",
       "      <td>173.776925</td>\n",
       "      <td>{'tags': 'Edgy, gypsy jazz ', 'type': 'gen', '...</td>\n",
       "      <td>11003413.0</td>\n",
       "      <td>complete</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>8c9952d7-2ab4-4f7c-b50c-897c68f474fe</td>\n",
       "      <td>True</td>\n",
       "      <td>dfa73697-352c-4427-a047-e14272ce07d0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1</td>\n",
       "      <td>chirp-v3-engine-i</td>\n",
       "      <td>I can’t believe this,\\nall that has happened\\n...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>False</td>\n",
       "      <td>image_dfa73697-352c-4427-a047-e14272ce07d0</td>\n",
       "      <td>False</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>7.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>Roam</td>\n",
       "      <td>NaN</td>\n",
       "      <td>False</td>\n",
       "      <td>NaN</td>\n",
       "      <td>True</td>\n",
       "      <td>273.0</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>5.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>True</td>\n",
       "      <td>Edgy, gypsy jazz</td>\n",
       "      <td>gen</td>\n",
       "      <td>I can’t believe this,\\nall that has happened\\n...</td>\n",
       "      <td>True</td>\n",
       "      <td>118.4</td>\n",
       "      <td>[chirp-v3-engine-i, chirp-v3-engine-i]</td>\n",
       "      <td>None</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>None</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>10.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>False</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>True</td>\n",
       "      <td>-1.6</td>\n",
       "      <td>-48.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3299259</th>\n",
       "      <td>bba6c18d-acc8-496c-b6a4-a6e0844be632</td>\n",
       "      <td>2024-04-08 17:18:08.635215+00:00</td>\n",
       "      <td>2024-04-08 17:18:08.635233+00:00</td>\n",
       "      <td>182.719319</td>\n",
       "      <td>{'tags': 'Edgy, gypsy jazz ', 'type': 'gen', '...</td>\n",
       "      <td>11003413.0</td>\n",
       "      <td>complete</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>8c9952d7-2ab4-4f7c-b50c-897c68f474fe</td>\n",
       "      <td>True</td>\n",
       "      <td>bba6c18d-acc8-496c-b6a4-a6e0844be632</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0</td>\n",
       "      <td>chirp-v3-engine-i</td>\n",
       "      <td>I can’t believe this,\\nall that has happened\\n...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>False</td>\n",
       "      <td>image_bba6c18d-acc8-496c-b6a4-a6e0844be632</td>\n",
       "      <td>True</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>31.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>Roam</td>\n",
       "      <td>NaN</td>\n",
       "      <td>True</td>\n",
       "      <td>NaN</td>\n",
       "      <td>True</td>\n",
       "      <td>273.0</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>26.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>True</td>\n",
       "      <td>Edgy, gypsy jazz</td>\n",
       "      <td>gen</td>\n",
       "      <td>I can’t believe this,\\nall that has happened\\n...</td>\n",
       "      <td>True</td>\n",
       "      <td>118.4</td>\n",
       "      <td>[chirp-v3-engine-i, chirp-v3-engine-i]</td>\n",
       "      <td>None</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>None</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>10.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>False</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>True</td>\n",
       "      <td>0.0</td>\n",
       "      <td>21.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                           id                        created_at                        updated_at   time_used                                           metadata     user_id    status  discord_message_id  prompt_id                            request_id is_generated                                 s3_id  upvote_count batch_index         model_name                                        prompt_text daily_theme_id is_deleted                                 image_s3_id is_public dislike_count flag_count  play_count  skip_count title  slug is_in_playlist continued_parent is_pro_user  user_n_clips upvoted deleted has_continued part_of_concat has_action downvoted preference  reaction_play_count  total_start_s  total_clip_s  concat_play_counts concat_in_playlist  concat_likes  is_7b               tags type                                             prompt  stream  duration                              experiment gpt_prompt  refund_credits make_instrumental  \\\n",
       "3299258  dfa73697-352c-4427-a047-e14272ce07d0  2024-04-08 17:18:08.635337+00:00  2024-04-08 17:18:08.635345+00:00  173.776925  {'tags': 'Edgy, gypsy jazz ', 'type': 'gen', '...  11003413.0  complete                 NaN        NaN  8c9952d7-2ab4-4f7c-b50c-897c68f474fe         True  dfa73697-352c-4427-a047-e14272ce07d0           0.0           1  chirp-v3-engine-i  I can’t believe this,\\nall that has happened\\n...            NaN      False  image_dfa73697-352c-4427-a047-e14272ce07d0     False             0          0         7.0         0.0  Roam   NaN          False              NaN        True         273.0   False   False         False          False      False     False      False                  5.0            NaN           NaN                 NaN                NaN           NaN   True  Edgy, gypsy jazz   gen  I can’t believe this,\\nall that has happened\\n...    True     118.4  [chirp-v3-engine-i, chirp-v3-engine-i]       None           False             False   \n",
       "3299259  bba6c18d-acc8-496c-b6a4-a6e0844be632  2024-04-08 17:18:08.635215+00:00  2024-04-08 17:18:08.635233+00:00  182.719319  {'tags': 'Edgy, gypsy jazz ', 'type': 'gen', '...  11003413.0  complete                 NaN        NaN  8c9952d7-2ab4-4f7c-b50c-897c68f474fe         True  bba6c18d-acc8-496c-b6a4-a6e0844be632           1.0           0  chirp-v3-engine-i  I can’t believe this,\\nall that has happened\\n...            NaN      False  image_bba6c18d-acc8-496c-b6a4-a6e0844be632      True             0          0        31.0         0.0  Roam   NaN           True              NaN        True         273.0    True   False         False          False       True     False       True                 26.0            NaN           NaN                 NaN                NaN           NaN   True  Edgy, gypsy jazz   gen  I can’t believe this,\\nall that has happened\\n...    True     118.4  [chirp-v3-engine-i, chirp-v3-engine-i]       None           False             False   \n",
       "\n",
       "        gpt_description_prompt history  options  continue_at audio_prompt_id continued_from_prompt  priority image_s3_id concat_history title extra promotion check_copyright check_artist_names error_type error_message is_square continue_discord_message_url  has_bad_gpt_prompt  original_duration_s  has_continue_and_start_continue_at  good_continue_at  duration_rel_diff  play_rel_diff  \n",
       "3299258                   None     NaN      NaN          NaN             NaN                   NaN      10.0         NaN            NaN   NaN   NaN       NaN             NaN                NaN        NaN           NaN       NaN                          NaN               False                  NaN                                 NaN              True               -1.6          -48.0  \n",
       "3299259                   None     NaN      NaN          NaN             NaN                   NaN      10.0         NaN            NaN   NaN   NaN       NaN             NaN                NaN        NaN           NaN       NaN                          NaN               False                  NaN                                 NaN              True                0.0           21.0  "
      ]
     },
     "execution_count": 105,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_slice[df_slice[\"request_id\"] == \"8c9952d7-2ab4-4f7c-b50c-897c68f474fe\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T04:00:54.811878Z",
     "start_time": "2024-04-14T03:59:35.927166Z"
    }
   },
   "outputs": [],
   "source": [
    "# df_slice.to_csv(\"/home/tony/Data/Preference/7b_v2/pre_model_20240413_recut.csv\", index=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:56.423973Z",
     "start_time": "2024-04-14T03:07:56.423963Z"
    }
   },
   "outputs": [],
   "source": [
    "# df_slice[\"id\"].to_json(\"/home/tony/Data/Preference/7b_v2/pre_model_20240413_recut_id.json\", orient='values')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:56.424823Z",
     "start_time": "2024-04-14T03:07:56.424813Z"
    }
   },
   "outputs": [],
   "source": [
    "BREAK"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Need to kick out the ones has gpt prompt -- these are pairs with different text inputs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:56.425748Z",
     "start_time": "2024-04-14T03:07:56.425737Z"
    }
   },
   "outputs": [],
   "source": [
    "# don't have continue at\n",
    "df_slice[df_slice[\"continue_at\"].isna()][\"request_id\"].nunique()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:56.426522Z",
     "start_time": "2024-04-14T03:07:56.426512Z"
    }
   },
   "outputs": [],
   "source": [
    "final_filtered_requests = df_slice[\"request_id\"].unique()\n",
    "print(len(final_filtered_requests))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:56.427326Z",
     "start_time": "2024-04-14T03:07:56.427317Z"
    }
   },
   "outputs": [],
   "source": [
    "train_requests, val_requests = train_test_split(\n",
    "    sorted(list(final_filtered_requests)), test_size=0.01, random_state=42\n",
    ")\n",
    "print(len(train_requests), len(val_requests))\n",
    "\n",
    "train_df = df_slice[df_slice[\"request_id\"].isin(set(train_requests))].copy()\n",
    "val_df = df_slice[df_slice[\"request_id\"].isin(set(val_requests))].copy()\n",
    "train_df = train_df.sort_values(by=[\"request_id\", \"preference\"])\n",
    "train_df = train_df.reset_index()\n",
    "val_df = val_df.sort_values(by=[\"request_id\", \"preference\"])\n",
    "val_df = val_df.reset_index()\n",
    "\n",
    "print(train_df.shape, val_df.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:56.428274Z",
     "start_time": "2024-04-14T03:07:56.428265Z"
    }
   },
   "outputs": [],
   "source": [
    "def reshift(arr):\n",
    "    sem_start_idx = 0\n",
    "    sem_end_idx = len(arr) - 1\n",
    "    semantic_arr = arr[:, :SEMANTIC_N_CODEBOOKS]\n",
    "    coarse_arr = arr[:, SEMANTIC_N_CODEBOOKS:]\n",
    "\n",
    "    coarse_start_idx = int(round(sem_start_idx * COARSE_RATE_HZ / SEMANTIC_RATE_HZ))\n",
    "    coarse_end_idx = int(round(sem_end_idx * COARSE_RATE_HZ / SEMANTIC_RATE_HZ))\n",
    "    assert sem_end_idx >= 0 and coarse_start_idx >= 0\n",
    "    assert not (sem_end_idx > len(semantic_arr) or coarse_end_idx > len(coarse_arr))\n",
    "\n",
    "    # get array segments\n",
    "    arr_s = semantic_arr[sem_start_idx:sem_end_idx, :].copy()\n",
    "    arr_c = coarse_arr[coarse_start_idx:coarse_end_idx, :].copy()\n",
    "    assert arr_s.max() <= SEMANTIC_PAD_TOKEN\n",
    "    assert arr_c.max() <= COARSE_PAD_TOKEN\n",
    "    assert len(arr_s) == len(arr_c)\n",
    "    # concat and stack\n",
    "    if len(arr_c) < N_TOKENS_AUDIO:\n",
    "        arr_c = np.pad(\n",
    "            arr_c,\n",
    "            ((0, N_TOKENS_AUDIO - len(arr_c)), (0, 0)),\n",
    "            constant_values=COARSE_PAD_TOKEN,\n",
    "            mode=\"constant\",\n",
    "        )\n",
    "        arr_s = np.pad(\n",
    "            arr_s,\n",
    "            ((0, N_TOKENS_AUDIO - len(arr_s)), (0, 0)),\n",
    "            constant_values=SEMANTIC_PAD_TOKEN,\n",
    "            mode=\"constant\",\n",
    "        )\n",
    "    arr = np.concatenate([arr_s, arr_c], axis=-1)\n",
    "    arr = arr.astype(np.uint16)\n",
    "    assert arr.shape == (N_TOKENS_AUDIO, SEMANTIC_N_CODEBOOKS + COARSE_N_CODEBOOKS)\n",
    "    return arr\n",
    "\n",
    "\n",
    "def make_dataset(input_df, is_val=False):\n",
    "    dset_type = \"val\" if is_val else \"tr\"\n",
    "    out_mmap_path = os.path.join(OUT_DATA_DIR, f\"data_{dset_type}.bin\")\n",
    "    out_metas_path = os.path.join(OUT_DATA_DIR, f\"meta_{dset_type}.jsonl\")\n",
    "    out_info_filepath = os.path.join(OUT_DATA_DIR, f\"info_{dset_type}.json\")\n",
    "\n",
    "    # gather the data\n",
    "    _ = np.memmap(out_mmap_path, dtype=np.uint16, mode=\"w+\", shape=(1,))\n",
    "    n_offs = 0\n",
    "    tot_duration_dict = defaultdict(int)\n",
    "    datasets_info = defaultdict(dict)\n",
    "    n = 0\n",
    "    for i, row in tqdm.tqdm(input_df.iterrows(), total=len(input_df)):\n",
    "        # we need to alternate between preference: neg, pos\n",
    "        # print(i, row)\n",
    "        assert row[\"preference\"] == (i % 2 == 1)\n",
    "        # make mmap -- two different paths\n",
    "        local_path = (\n",
    "            f\"{NPZ_DIR}/{row['s3_id']}.npz\"\n",
    "            if row[\"is_7b\"]\n",
    "            else f\"/app/suno/data/dpo/7b_npz/{row['s3_id']}.npz\"\n",
    "        )\n",
    "        if not os.path.exists(local_path):\n",
    "            # print(row, local_path)\n",
    "            raise ValueError()\n",
    "        # print(local_path)\n",
    "        # print( np.load(local_path))\n",
    "        try:\n",
    "            arr = (\n",
    "                np.load(local_path)[\"v3.0_raw\"]\n",
    "                if row[\"is_7b\"]\n",
    "                else np.load(local_path)[\"v2_raw\"]\n",
    "            )\n",
    "        except Exception as e:\n",
    "            print(local_path)\n",
    "            raise e\n",
    "        assert arr.shape[0] <= 3000\n",
    "        assert arr.shape[1] == 13\n",
    "        arr_duration = arr.shape[0] / 25\n",
    "        # print(arr.shape)\n",
    "        arr = reshift(arr)\n",
    "        # print(\"after shift and pad\", arr.shape)\n",
    "        arr = arr.reshape(\n",
    "            -1,\n",
    "        )\n",
    "        # print(arr.shape)\n",
    "        out_mm = np.memmap(\n",
    "            out_mmap_path,\n",
    "            dtype=np.uint16,\n",
    "            mode=\"r+\",\n",
    "            shape=(n_offs + arr.size,),\n",
    "        )\n",
    "        out_mm[n_offs : n_offs + arr.size] = arr\n",
    "        # print(f\"offset is: {n_offs}\")\n",
    "        # break\n",
    "        # write it once\n",
    "        out_mm.flush()\n",
    "        del out_mm\n",
    "\n",
    "        add_metas = []\n",
    "        add_meta = {\n",
    "            \"dataset\": f\"perference_{int(row['preference'])}\",\n",
    "            \"id\": row[\"s3_id\"],  # this is the row s3_id\n",
    "            \"start_s\": row[\"total_start_s\"] if row[\"total_start_s\"] >= 0 else None,\n",
    "            \"end_s\": (\n",
    "                row[\"total_clip_s\"] if row[\"total_clip_s\"] >= 0 else None\n",
    "            ),  # for full clips we do know it has an edding, other wise, we don't know\n",
    "            \"original_duration_s\": (\n",
    "                row[\"original_duration_s\"]\n",
    "                if row[\"original_duration_s\"] >= 0\n",
    "                else arr_duration\n",
    "            ),  # this nees to be... a bit more complicated, only works with concat!\n",
    "            \"vocal_start_s\": None,  # these are unfortunately missing for now\n",
    "            \"vocal_end_s\": None,  # these are unfortunately missing for now\n",
    "            \"tags\": [\n",
    "                row[\"tags\"] if row[\"tags\"] else \"\"\n",
    "            ],  # tags is a list, do you know :)\n",
    "            \"text\": row[\"prompt\"] if row[\"prompt\"] else \"\",\n",
    "        }\n",
    "        add_metas.append(add_meta)\n",
    "        tot_duration_dict[row[\"preference\"]] += arr_duration\n",
    "        write_jsonl(\n",
    "            add_metas,\n",
    "            os.path.join(out_metas_path),\n",
    "            do_append=bool(n_offs != 0),\n",
    "        )\n",
    "        if \"idx_list\" not in datasets_info[add_meta[\"dataset\"]]:\n",
    "            datasets_info[add_meta[\"dataset\"]][\"idx_list\"] = [n]\n",
    "        else:\n",
    "            datasets_info[add_meta[\"dataset\"]][\"idx_list\"].append(n)\n",
    "        n += 1\n",
    "        n_offs += arr.size\n",
    "\n",
    "    write_json(datasets_info, out_info_filepath)\n",
    "    print(f\"Total {n} clips\")\n",
    "    for k, v in tot_duration_dict.items():\n",
    "        print(f\"{round(v / 60 / 60):,} hours of {k}\")\n",
    "    print(f\"Done\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Actually make"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:56.429071Z",
     "start_time": "2024-04-14T03:07:56.429061Z"
    }
   },
   "outputs": [],
   "source": [
    "# val_df[[\"request_id\", \"metadata\", \"updated_at\", \"user_id\", \"preference\"]].head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:56.429833Z",
     "start_time": "2024-04-14T03:07:56.429824Z"
    }
   },
   "outputs": [],
   "source": [
    "total_duration = 0\n",
    "for i, row in tqdm.tqdm(train_df.iterrows(), total=len(train_df)):\n",
    "    # we need to alternate between preference: neg, pos\n",
    "    # print(i, row)\n",
    "    try:\n",
    "        assert row[\"preference\"] == (i % 2 == 1)\n",
    "    except:\n",
    "        print(i, row)\n",
    "    total_duration += row[\"duration\"]\n",
    "print(f\"{round(total_duration / 60 / 60):,} hours of {train_df.shape[0]} clips, {train_df.shape[0] / 8 / 4 / 1000} nodes\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:56.430659Z",
     "start_time": "2024-04-14T03:07:56.430649Z"
    }
   },
   "outputs": [],
   "source": [
    "make_dataset(val_df, is_val=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:56.431475Z",
     "start_time": "2024-04-14T03:07:56.431466Z"
    }
   },
   "outputs": [],
   "source": [
    "make_dataset(train_df, is_val=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-29T19:46:47.549860Z",
     "start_time": "2024-01-29T19:46:47.548015Z"
    }
   },
   "source": [
    "# Validation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:56.432270Z",
     "start_time": "2024-04-14T03:07:56.432261Z"
    }
   },
   "outputs": [],
   "source": [
    "# verify\n",
    "mm = np.memmap(os.path.join(OUT_DATA_DIR, f\"data_val.bin\"), dtype=np.uint16, mode=\"r\")\n",
    "test_metas = read_jsonl(os.path.join(OUT_DATA_DIR, f\"meta_val.jsonl\"))\n",
    "test_info = read_json(os.path.join(OUT_DATA_DIR, f\"info_val.json\"))\n",
    "mm = mm.reshape(-1, 3008, 13)\n",
    "assert len(mm) == len(test_metas)\n",
    "assert mm[:100, :, 0].min() >= 0\n",
    "assert mm[:100, :, 0].max() <= 4000\n",
    "assert mm[:100, :, 1:].min() >= 0\n",
    "assert mm[:100, :, 1:].max() <= 2048"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:56.433063Z",
     "start_time": "2024-04-14T03:07:56.433053Z"
    }
   },
   "outputs": [],
   "source": [
    "# randomly listen to some stuff\n",
    "from suno_utils.tasks.dac_2c_12cb import preload_models as preload_codec_models\n",
    "from suno_utils.tasks.dac_2c_12cb import (\n",
    "    encode as codec_encode,\n",
    "    decode_stream_to_full_audio as codec_decode,\n",
    "    EMBEDDING_RATE as CODEC_EMBEDDING_RATE,\n",
    "    decode as decode\n",
    ")\n",
    "os.environ[\"CUDA_VISIBLE_DEVICES\"] = \"3\"\n",
    "_ = preload_codec_models(\"/app/suno/tony/v3/dac_2c_25x12.pt\", device=\"cuda\")\n",
    "assert len(test_metas) == len(mm)\n",
    "idx_list = list(range(len(test_metas)))\n",
    "# random.shuffle(idx_list)\n",
    "# idx_list = [idx for idx in idx_list if \"text\" in test_metas[idx]]\n",
    "print(len(mm))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:56.433877Z",
     "start_time": "2024-04-14T03:07:56.433868Z"
    }
   },
   "outputs": [],
   "source": [
    "idx = random.choice(test_info[\"perference_0\"][\"idx_list\"])\n",
    "assert \"original_duration_s\" in test_metas[idx]\n",
    "# positive index should be shifted by 1\n",
    "pos_idx = idx + 1\n",
    "print(\n",
    "    \"tags:\",\n",
    "    test_metas[idx].get(\"tags\") == test_metas[pos_idx].get(\"tags\"),\n",
    "    test_metas[idx].get(\"tags\"),\n",
    ")\n",
    "arr = mm[idx, 1:].copy().astype(np.int16)[:, 1:]\n",
    "pos_arr = mm[pos_idx, 1:].copy().astype(np.int16)[:, 1:]\n",
    "pad_idx_arr = np.where(arr == COARSE_PAD_TOKEN)[0]\n",
    "if len(pad_idx_arr) > 0:\n",
    "    arr = arr[: pad_idx_arr[0], :]\n",
    "pos_pad_idx_arr = np.where(pos_arr == COARSE_PAD_TOKEN)[0]\n",
    "if len(pos_pad_idx_arr) > 0:\n",
    "    pos_arr = pos_arr[: pos_pad_idx_arr[0], :]\n",
    "a = decode(arr)\n",
    "print(\"negative example\", test_metas[idx])\n",
    "a.play(compress=False)\n",
    "pos_a = decode(pos_arr)\n",
    "print(\"positive example\", test_metas[pos_idx])\n",
    "pos_a.play(compress=False)\n",
    "print(\n",
    "    \"text:\",\n",
    "    test_metas[idx].get(\"text\") == test_metas[pos_idx].get(\"text\"),\n",
    "    test_metas[idx].get(\"text\"),\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:56.434788Z",
     "start_time": "2024-04-14T03:07:56.434779Z"
    }
   },
   "outputs": [],
   "source": [
    "# val_df[val_df[\"tags\"] == 'a vibrant blend of experimental jazz fusion, drum-and-bass and swagger fuzzed-out guitars']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:56.435431Z",
     "start_time": "2024-04-14T03:07:56.435423Z"
    }
   },
   "outputs": [],
   "source": [
    "# from collections import Counter\n",
    "# c = Counter()\n",
    "# for _, row in df_slice.iterrows():\n",
    "#     # print(row[\"metadata\"])\n",
    "#     for k in ast.literal_eval(row[\"metadata\"]).keys():\n",
    "#         c[k] += 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:56.436575Z",
     "start_time": "2024-04-14T03:07:56.436565Z"
    }
   },
   "outputs": [],
   "source": [
    "# original_npz_path = f\"/app/suno/data/dpo/7b_npz/{test_metas[idx]['id']}.npz\"\n",
    "# original_npz_path = \"/app/suno/data/dpo/7b_npz/729c3011-f672-4ccd-8d82-1cbf2b52ff69.npz\"\n",
    "# original_arr = np.load(original_npz_path)[\"v2_raw\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:56.437343Z",
     "start_time": "2024-04-14T03:07:56.437333Z"
    }
   },
   "outputs": [],
   "source": [
    "def validation_on_metas(input_metas):\n",
    "\n",
    "    total_bad = 0\n",
    "    total_good = 0\n",
    "    for idx in range(len(input_metas)):\n",
    "        if idx % 2 == 0:\n",
    "            pos_idx = idx + 1\n",
    "            if input_metas[idx].get(\"tags\") != input_metas[pos_idx].get(\"tags\"):\n",
    "                # print(test_metas[idx].get(\"text\") == test_metas[pos_idx].get(\"text\"), test_metas[idx].get(\"tags\"), test_metas[pos_idx].get(\"tags\"))\n",
    "                total_bad += 1\n",
    "            else:\n",
    "                total_good += 1\n",
    "    print(total_good, total_bad)\n",
    "    return\n",
    "\n",
    "\n",
    "validation_on_metas(test_metas)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:56.438139Z",
     "start_time": "2024-04-14T03:07:56.438130Z"
    }
   },
   "outputs": [],
   "source": [
    "train_info = read_json(os.path.join(OUT_DATA_DIR, f\"info_tr.json\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:56.438997Z",
     "start_time": "2024-04-14T03:07:56.438987Z"
    }
   },
   "outputs": [],
   "source": [
    "n_neg_tr = train_info[\"perference_0\"][\"idx_list\"]\n",
    "n_pos_tr = train_info[\"perference_1\"][\"idx_list\"]\n",
    "assert len(n_pos_tr) == len(n_neg_tr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:56.439656Z",
     "start_time": "2024-04-14T03:07:56.439648Z"
    }
   },
   "outputs": [],
   "source": [
    "total_iters = (len(n_neg_tr) + len(n_pos_tr))\n",
    "print(\"total samples\", total_iters, train_df.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T17:45:02.723050Z",
     "start_time": "2024-04-14T17:45:02.709488Z"
    }
   },
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'total_iters' 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[107], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m1 epoch per batch 4, total\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[43mtotal_iters\u001b[49m \u001b[38;5;241m/\u001b[39m \u001b[38;5;241m8\u001b[39m \u001b[38;5;241m/\u001b[39m \u001b[38;5;241m4\u001b[39m \u001b[38;5;241m/\u001b[39m \u001b[38;5;241m4\u001b[39m)\n",
      "\u001b[0;31mNameError\u001b[0m: name 'total_iters' is not defined"
     ]
    }
   ],
   "source": [
    "print(\"1 epoch per batch 4, total\", total_iters / 8 / 4 / 4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T03:07:56.441252Z",
     "start_time": "2024-04-14T03:07:56.441244Z"
    }
   },
   "outputs": [],
   "source": [
    "!cd /home/tony/Work/tony/slurm && sbatch sbatch_dpo"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 111,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-14T17:53:48.053462Z",
     "start_time": "2024-04-14T17:53:48.051130Z"
    }
   },
   "outputs": [],
   "source": [
    "# converted_paths = os.listdir(\"/app/suno/data/dpo/7b_recycle_npz\")\n",
    "\n",
    "# # don't run this unless you kill some job accidentally\n",
    "# for s3_processed_file in tqdm.tqdm(converted_paths):\n",
    "#     processed_file = os.path.basename(s3_processed_file)\n",
    "#     processed_file_path = os.path.join(\"/app/suno/data/dpo/7b_recycle_npz\", processed_file)\n",
    "#     # could have been removed already\n",
    "#     if os.path.exists(processed_file_path):\n",
    "#         file_size = os.stat(processed_file_path).st_size\n",
    "#         # print(processed_file_path, file_size)\n",
    "#         # break\n",
    "#         if file_size < 2000:\n",
    "#             print(processed_file_path, file_size)\n",
    "#             os.remove(processed_file_path)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.13"
  },
  "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": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
