{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T03:35:15.562656Z",
     "start_time": "2024-04-23T03:35:14.293616Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_3641923/325804709.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",
    "from preference_data_preparation import make_dataset\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-23T03:35:15.596321Z",
     "start_time": "2024-04-23T03:35:15.564266Z"
    }
   },
   "outputs": [],
   "source": [
    "OUT_DATA_DIR = \"/app/suno/data/dpo/7v_r2_v4_dandv0_resample/\"\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/7b_recycle_npz\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T03:35:15.626188Z",
     "start_time": "2024-04-23T03:35:15.597407Z"
    }
   },
   "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-23T03:35:26.438918Z",
     "start_time": "2024-04-23T03:35:15.627809Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(466484, 43)"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df = pd.read_csv(\"/home/tony/Data/Preference/7b_v2/interesting_clips_20240421_prev_model.csv\") # , engine='python')\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-23T03:35:57.457259Z",
     "start_time": "2024-04-23T03:35:26.440102Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1116210\n",
      "1116210\n",
      "pre-downloaded df (466484, 43)\n",
      "downloaded df (170771, 43)\n"
     ]
    }
   ],
   "source": [
    "converted_paths = os.listdir(NPZ_DIR)\n",
    "print(len(converted_paths))\n",
    "\n",
    "converted_paths = set([f.replace(\".npz\", \"\") for f in converted_paths])\n",
    "print(len(converted_paths))\n",
    "\n",
    "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": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T03:35:57.523983Z",
     "start_time": "2024-04-23T03:35:57.460205Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "is_7b\n",
       "True    170771\n",
       "Name: count, dtype: int64"
      ]
     },
     "execution_count": 6,
     "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": 7,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T03:35:57.557309Z",
     "start_time": "2024-04-23T03:35:57.525078Z"
    }
   },
   "outputs": [],
   "source": [
    "date_cut = '2024-03-22 04:30:00'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T03:35:57.695286Z",
     "start_time": "2024-04-23T03:35:57.558312Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "preference  model_name        \n",
      "False       chirp-v3-engine-v0    64454\n",
      "            chirp-v3-engine-d     20746\n",
      "True        chirp-v3-engine-v0    49516\n",
      "            chirp-v3-engine-d     36055\n",
      "Name: count, dtype: int64\n",
      "(170771, 44)\n",
      "(170771, 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",
    "# df = df[df[\"model_name\"].isin([\"chirp-v3-engine-v0\"])]\n",
    "print(df.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T03:35:57.862807Z",
     "start_time": "2024-04-23T03:35:57.697319Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(170771, 44)\n",
      "(153906, 44)\n",
      "preference  model_name        \n",
      "False       chirp-v3-engine-v0    62652\n",
      "            chirp-v3-engine-d     14301\n",
      "True        chirp-v3-engine-v0    48812\n",
      "            chirp-v3-engine-d     28141\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": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T03:36:32.603985Z",
     "start_time": "2024-04-23T03:35:57.864052Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "unique_requests 76953\n"
     ]
    }
   ],
   "source": [
    "# Let's use the old selection for now -- for quality assurance\n",
    "# expand the metadata columns -- this takes forever...~ 6 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": 11,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T03:36:32.608233Z",
     "start_time": "2024-04-23T03:36:32.605692Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Index(['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', 'history', 'options', 'duration', 'priority', 'experiment', 'gpt_prompt', 'continue_at', 'refund_credits', 'audio_prompt_id', 'make_instrumental', 'continued_from_prompt', 'gpt_description_prompt', 'image_s3_id', 'concat_history'], dtype='object')"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.columns"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T03:36:32.965207Z",
     "start_time": "2024-04-23T03:36:32.610002Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "unique_requests 76953\n",
      "unique_requests 76953\n"
     ]
    }
   ],
   "source": [
    "# double check we removed the gpt prompted ones for now\n",
    "# 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()\n",
    "# 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())\n",
    "df = df[~df[\"dislike_count\"].isna()]\n",
    "print(\"unique_requests\", df[\"request_id\"].nunique())\n",
    "# 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": 13,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T03:36:32.970959Z",
     "start_time": "2024-04-23T03:36:32.968729Z"
    }
   },
   "outputs": [],
   "source": [
    "# this is a hard replacement for after data, cause the original is fucked\n",
    "df[\"play_count\"] = df[\"reaction_play_count\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T03:36:35.653840Z",
     "start_time": "2024-04-23T03:36:32.972072Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "26450\n",
      "good_continue_at\n",
      "True     153899\n",
      "False         7\n",
      "Name: count, dtype: int64\n",
      "preference\n",
      "False    76953\n",
      "True     76953\n",
      "Name: count, dtype: int64 is_7b\n",
      "True    153906\n",
      "Name: count, dtype: int64 model_name\n",
      "chirp-v3-engine-v0    111464\n",
      "chirp-v3-engine-d      42442\n",
      "Name: count, dtype: int64 preference  model_name        \n",
      "False       chirp-v3-engine-v0    62652\n",
      "            chirp-v3-engine-d     14301\n",
      "True        chirp-v3-engine-v0    48812\n",
      "            chirp-v3-engine-d     28141\n",
      "Name: count, dtype: int64\n"
     ]
    }
   ],
   "source": [
    "# get the original duration of the clips, if they are concacted\n",
    "df[\"original_duration_s\"] = df[\"total_start_s\"] + df[\"duration\"]\n",
    "\n",
    "# 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())\n",
    "\n",
    "\n",
    "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",
    ")\n",
    "\n",
    "df = df.sort_values(by=[\"request_id\", \"preference\"])\n",
    "df[\"duration_rel_diff\"] = df['duration'].diff() \n",
    "df[\"play_rel_diff\"] = df['play_count'].diff() "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T03:36:35.837957Z",
     "start_time": "2024-04-23T03:36:35.655579Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "negative 76908 positive 76922\n",
      "total pair requests 76953 selected pair requests 76880 frac 0.999\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[\"play_count\"] >= 1)  # has to be played once\n",
    "    & (df[\"play_count\"] <= 3)  # 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[\"has_continue_and_start_continue_at\"].isna())  # won't have any continues\n",
    "    # & (df[\"dislike_count\"] >= 1) # 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",
    "        ((df[\"is_7b\"] == False) & (df[\"play_count\"] >= 2) & (df[\"duration\"] >= 10))\n",
    "        | ((df[\"is_7b\"] == True) & (df[\"play_count\"] >= 1))\n",
    "    )\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",
    "    & (\n",
    "        ((df[\"play_count\"] >= 1) & (df[\"is_7b\"] == True))\n",
    "        | ((df[\"play_count\"] >= 10) & (df[\"is_7b\"] == False))\n",
    "    )\n",
    "    & (\n",
    "        (\n",
    "            (df[\"part_of_concat\"] == True)\n",
    "            & (df[\"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[\"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[\"user_n_clips\"] >= 20)  # user needs to have genereated at least 20\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": 16,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T03:36:36.017619Z",
     "start_time": "2024-04-23T03:36:35.839749Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "requests 76880 clips 153760 total khrs 3.418; N gpus for 1000 iters 4.805; n unique users 53293\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 1000 iters {df_slice.shape[0] / 8 / 4 / 1000:.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": 17,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T03:36:36.037032Z",
     "start_time": "2024-04-23T03:36:36.019539Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "positive in playlist (12664, 68)\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": 18,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T03:36:36.095572Z",
     "start_time": "2024-04-23T03:36:36.038281Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "preference  model_name        \n",
       "False       chirp-v3-engine-v0    62588\n",
       "            chirp-v3-engine-d     14292\n",
       "True        chirp-v3-engine-v0    48768\n",
       "            chirp-v3-engine-d     28112\n",
       "Name: count, dtype: int64"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_slice.groupby([\"preference\"])[\"model_name\"].value_counts()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T03:36:36.147625Z",
     "start_time": "2024-04-23T03:36:36.096647Z"
    }
   },
   "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) # & (df_slice[\"dislike_count\"] < 1)\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": 20,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T03:36:36.203958Z",
     "start_time": "2024-04-23T03:36:36.149206Z"
    }
   },
   "outputs": [],
   "source": [
    "# # save positive ids\n",
    "# positive_preference_ids = df_slice[\"s3_id\"].to_json(orient='values')\n",
    "# with open('/home/tony/Data/Preference/7b_v2/interesting_clips_20240421_prev_model.json', 'w') as file:\n",
    "#     file.write(positive_preference_ids)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T03:36:36.260290Z",
     "start_time": "2024-04-23T03:36:36.205016Z"
    }
   },
   "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": 22,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T03:36:36.387956Z",
     "start_time": "2024-04-23T03:36:36.261684Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "49991"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# don't have continue at\n",
    "df_slice[df_slice[\"continue_at\"].isna()][\"request_id\"].nunique()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T03:36:36.413934Z",
     "start_time": "2024-04-23T03:36:36.389239Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "76880\n"
     ]
    }
   ],
   "source": [
    "final_filtered_requests = df_slice[\"request_id\"].unique()\n",
    "print(len(final_filtered_requests))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T03:36:36.474530Z",
     "start_time": "2024-04-23T03:36:36.415454Z"
    }
   },
   "outputs": [],
   "source": [
    "# df_slice.to_csv(\"/home/tony/Data/Preference/7b_v2/7b_before_recode_20240412\", index=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T03:36:36.880737Z",
     "start_time": "2024-04-23T03:36:36.475942Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "76111 769\n",
      "(152222, 69) (1538, 69)\n"
     ]
    }
   ],
   "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": "markdown",
   "metadata": {},
   "source": [
    "# Actually make"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T03:36:36.883966Z",
     "start_time": "2024-04-23T03:36:36.882464Z"
    }
   },
   "outputs": [],
   "source": [
    "# val_df[[\"request_id\", \"metadata\", \"updated_at\", \"user_id\", \"preference\"]].head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T03:36:43.949050Z",
     "start_time": "2024-04-23T03:36:36.885661Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████| 152222/152222 [00:07<00:00, 21734.99it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3,384 hours of 152222 clips, 4.7569375 nodes\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "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": 28,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T03:37:05.641153Z",
     "start_time": "2024-04-23T03:36:43.951043Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1538/1538 [00:21<00:00, 70.96it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Total 1538 clips\n",
      "17 hours of False\n",
      "17 hours of True\n",
      "Done\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "make_dataset(val_df, OUT_DATA_DIR, is_val=True, npz_dir=NPZ_DIR)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T04:13:27.232895Z",
     "start_time": "2024-04-23T03:37:05.642874Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|████████████████████████████████████████████████████████████████████████████████████████████████████████| 152222/152222 [36:21<00:00, 69.78it/s]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Total 152222 clips\n",
      "1,724 hours of False\n",
      "1,689 hours of True\n",
      "Done\n"
     ]
    }
   ],
   "source": [
    "make_dataset(train_df, OUT_DATA_DIR, is_val=False, npz_dir=NPZ_DIR)"
   ]
  },
  {
   "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": 30,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T04:13:27.258182Z",
     "start_time": "2024-04-23T04:13:27.234583Z"
    }
   },
   "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": 31,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T04:13:27.309252Z",
     "start_time": "2024-04-23T04:13:27.259819Z"
    }
   },
   "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": 32,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T04:13:27.369456Z",
     "start_time": "2024-04-23T04:13:27.310817Z"
    }
   },
   "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": 33,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T04:13:27.428538Z",
     "start_time": "2024-04-23T04:13:27.370429Z"
    }
   },
   "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": 34,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T04:13:27.489405Z",
     "start_time": "2024-04-23T04:13:27.429606Z"
    }
   },
   "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": 35,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T04:13:27.561634Z",
     "start_time": "2024-04-23T04:13:27.490843Z"
    }
   },
   "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": 36,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T04:13:27.628228Z",
     "start_time": "2024-04-23T04:13:27.562777Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "769 0\n"
     ]
    }
   ],
   "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": 37,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T04:13:27.715468Z",
     "start_time": "2024-04-23T04:13:27.629322Z"
    }
   },
   "outputs": [],
   "source": [
    "train_info = read_json(os.path.join(OUT_DATA_DIR, f\"info_tr.json\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T04:13:27.760295Z",
     "start_time": "2024-04-23T04:13:27.716977Z"
    }
   },
   "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": 39,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T04:13:27.838200Z",
     "start_time": "2024-04-23T04:13:27.761287Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "total samples 152222 (152222, 69)\n"
     ]
    }
   ],
   "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": 40,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T04:13:27.905688Z",
     "start_time": "2024-04-23T04:13:27.841311Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 epoch per batch 4, total 1189.234375\n"
     ]
    }
   ],
   "source": [
    "print(\"1 epoch per batch 4, total\", total_iters / 8 / 4 / 4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T04:13:28.249486Z",
     "start_time": "2024-04-23T04:13:27.906637Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Submitted batch job 1528\r\n"
     ]
    }
   ],
   "source": [
    "!cd /home/tony/Work/tony/slurm && sbatch sbatch_ipo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# some gymathtics loading prev data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-23T04:13:28.253262Z",
     "start_time": "2024-04-23T04:13:28.251361Z"
    }
   },
   "outputs": [],
   "source": [
    "# prev_v3_data = \"/app/suno/data/dpo/7v_v20_full/\"\n",
    "\n",
    "# test_val_metas = read_jsonl(os.path.join(prev_v3_data, f\"meta_val.jsonl\"))\n",
    "# test_tr_metas = read_jsonl(os.path.join(prev_v3_data, f\"meta_tr.jsonl\"))\n",
    "\n",
    "# all_ids = set()\n",
    "# for meta in test_val_metas:\n",
    "#     all_ids.add(meta[\"id\"])\n",
    "# for meta in test_tr_metas:\n",
    "#     all_ids.add(meta[\"id\"])\n",
    "# print(len(all_ids), len(test_val_metas) + len(test_tr_metas))\n",
    "\n",
    "# all_ids = list(all_ids)\n",
    "# with open(\"/home/tony/Data/Preference/7b_v2/7v_v20_full_recut_id.json\", \"w\") as fp:\n",
    "#     json.dump(all_ids, fp)"
   ]
  },
  {
   "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
}
