{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:14:21.933894Z",
     "start_time": "2024-04-20T18:14:20.683961Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_2930484/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-20T18:14:21.968783Z",
     "start_time": "2024-04-20T18:14:21.935353Z"
    }
   },
   "outputs": [],
   "source": [
    "OUT_DATA_DIR = \"/app/suno/data/dpo/7v_r2_v3_ipo/\"\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\"\n",
    "NPZ_DIR = \"/app/suno/data/dpo/7b_recycle_npz\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:14:21.997951Z",
     "start_time": "2024-04-20T18:14:21.969796Z"
    }
   },
   "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-20T18:18:39.240500Z",
     "start_time": "2024-04-20T18:14:21.999445Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(7052956, 43)"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df = pd.read_csv(\"/home/tony/Data/Preference/7b_v2/interesting_clips_20240415.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-20T18:18:43.839658Z",
     "start_time": "2024-04-20T18:18:39.242035Z"
    }
   },
   "outputs": [],
   "source": [
    "df[\"is_7b\"] = df[\"model_name\"].str.contains(\"v3\")\n",
    "df[\"is_7b\"].value_counts()\n",
    "df = df[df[\"is_7b\"] == True]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# LET's do the data prep"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:18:43.842570Z",
     "start_time": "2024-04-20T18:18:43.840902Z"
    }
   },
   "outputs": [],
   "source": [
    "date_cut = '2024-03-22 04:30:00'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:18:51.908893Z",
     "start_time": "2024-04-20T18:18:43.843594Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "preference  model_name         \n",
      "False       chirp-v3-engine-i      2659807\n",
      "            chirp-v3-engine-v0      431998\n",
      "            chirp-v3-engine-d       364471\n",
      "            chirp-v3-engine-s        64673\n",
      "            chirp-v3-engine-i-d       5499\n",
      "True        chirp-v3-engine-i      2674870\n",
      "            chirp-v3-engine-d       500928\n",
      "            chirp-v3-engine-v0      291482\n",
      "            chirp-v3-engine-s        54217\n",
      "            chirp-v3-engine-i-d       4951\n",
      "Name: count, dtype: int64\n",
      "(7052898, 44)\n",
      "(5181287, 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\"])]\n",
    "# df = df[(df[\"model_name\"].isin([\"chirp-v3-engine-i\", \"chirp-v3-engine-v0\"])) & (df[\"created_at\"] > date_cut)]\n",
    "df = df[(df[\"created_at\"] >= date_cut)]\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": "markdown",
   "metadata": {},
   "source": [
    "## download data here...faster"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:18:53.168893Z",
     "start_time": "2024-04-20T18:18:51.910240Z"
    }
   },
   "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": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:18:53.171791Z",
     "start_time": "2024-04-20T18:18:53.170275Z"
    }
   },
   "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": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:18:53.232781Z",
     "start_time": "2024-04-20T18:18:53.173967Z"
    }
   },
   "outputs": [],
   "source": [
    "# _ = download_s3_files(unfinished_s3_paths, unfinished_paths, n_cores=64)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:18:53.292007Z",
     "start_time": "2024-04-20T18:18:53.233766Z"
    }
   },
   "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": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:18:53.349281Z",
     "start_time": "2024-04-20T18:18:53.292890Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Finish downloads\n"
     ]
    }
   ],
   "source": [
    "print(\"Finish downloads\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:19:22.347864Z",
     "start_time": "2024-04-20T18:18:53.350241Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "977082\n"
     ]
    }
   ],
   "source": [
    "converted_paths = os.listdir(NPZ_DIR)\n",
    "print(len(converted_paths))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:19:22.724403Z",
     "start_time": "2024-04-20T18:19:22.349080Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "977082\n"
     ]
    }
   ],
   "source": [
    "converted_paths = set([f.replace(\".npz\", \"\") for f in converted_paths])\n",
    "print(len(converted_paths))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:19:27.667891Z",
     "start_time": "2024-04-20T18:19:22.725695Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "pre-downloaded df (5181287, 44)\n",
      "downloaded df (692888, 44)\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": 16,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:19:27.670772Z",
     "start_time": "2024-04-20T18:19:27.669200Z"
    }
   },
   "outputs": [],
   "source": [
    "# BREAK"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Proceed!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:22:07.097993Z",
     "start_time": "2024-04-20T18:19:27.671842Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "unique_requests 354458\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": 18,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:22:09.962805Z",
     "start_time": "2024-04-20T18:22:07.131188Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "unique_requests 354458\n",
      "unique_requests 354458\n"
     ]
    }
   ],
   "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()\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": 19,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:22:17.403104Z",
     "start_time": "2024-04-20T18:22:09.964016Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "77340\n",
      "good_continue_at\n",
      "True     692741\n",
      "False       147\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": 20,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:22:18.908540Z",
     "start_time": "2024-04-20T18:22:17.404294Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(692888, 68)\n",
      "(676860, 68)\n",
      "preference  model_name       \n",
      "False       chirp-v3-engine-i    338430\n",
      "True        chirp-v3-engine-i    338430\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": 21,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:22:19.952573Z",
     "start_time": "2024-04-20T18:22:18.909719Z"
    }
   },
   "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": 22,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:22:19.969161Z",
     "start_time": "2024-04-20T18:22:19.954455Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "concat_in_playlist\n",
       "False    61069\n",
       "True     48474\n",
       "Name: count, dtype: int64"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df[\"concat_in_playlist\"].value_counts()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:22:21.343818Z",
     "start_time": "2024-04-20T18:22:19.970230Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "negative 120289 positive 235013\n",
      "total pair requests 338430 selected pair requests 117082 frac 0.346\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\n",
    "    # & (df[\"reaction_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",
    "    & (\n",
    "        (df[\"is_in_playlist\"] != True) & (df[\"concat_in_playlist\"] != True)\n",
    "    )  # can't be part of a playlist -- otherwise there are some like signal in it?\n",
    "    & (\n",
    "        (df[\"dislike_count\"].astype(int) >= 1)\n",
    "        | (df[\"deleted\"] == True)\n",
    "        | (df[\"flag_count\"].astype(int) >= 1)\n",
    "    )  # this is kinda strict\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[\"reaction_play_count\"] >= 1) & (df[\"is_7b\"] == True))\n",
    "        | ((df[\"reaction_play_count\"] >= 10) & (df[\"is_7b\"] == False))\n",
    "    )\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\"].astype(int) == 0)  # can't have dislikes\n",
    "    & (df[\"flag_count\"].astype(int) == 0)  # can't have issues\n",
    "    & (df[\"user_n_clips\"] >= 40)  # user needs to have genereated at least 20\n",
    "    & (df[\"upvote_count\"].astype(int) >= 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": 24,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:22:21.876386Z",
     "start_time": "2024-04-20T18:22:21.345037Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "requests 117082 clips 234164 total khrs 6.269; N gpus for 1000 iters 7.318; n unique users 33127\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": 25,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:22:21.946232Z",
     "start_time": "2024-04-20T18:22:21.877681Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "positive in playlist (16046, 70)\n",
      "negative in playlist (0, 70)\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)\n",
    "\n",
    "test_mask = (df_slice[\"preference\"] == False) & (\n",
    "    (df_slice[\"is_in_playlist\"] == True) | (df_slice[\"concat_in_playlist\"] == True)\n",
    ")\n",
    "print(\"negative in playlist\", df_slice[test_mask].shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:22:22.001404Z",
     "start_time": "2024-04-20T18:22:21.947455Z"
    }
   },
   "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 = (\n",
    "    df_slice[\"downvoted\"] == False\n",
    ")  # & (df_slice[\"dislike_count\"] < 1)\n",
    "interesting_clips_mask = (\n",
    "    interesting_clips_must_be_positive_mask\n",
    "    & interesting_clips_must_be_not_negative_mask\n",
    ")\n",
    "assert interesting_clips_mask.eq(df_slice[\"preference\"]).all()"
   ]
  },
  {
   "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": 27,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:22:22.252723Z",
     "start_time": "2024-04-20T18:22:22.002548Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "97810"
      ]
     },
     "execution_count": 27,
     "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": 28,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:22:22.298802Z",
     "start_time": "2024-04-20T18:22:22.255986Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "117082\n"
     ]
    }
   ],
   "source": [
    "final_filtered_requests = df_slice[\"request_id\"].unique()\n",
    "print(len(final_filtered_requests))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:22:23.227876Z",
     "start_time": "2024-04-20T18:22:22.300005Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "115911 1171\n",
      "(231822, 71) (2342, 71)\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": "code",
   "execution_count": 30,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:22:23.230600Z",
     "start_time": "2024-04-20T18:22:23.229150Z"
    }
   },
   "outputs": [],
   "source": [
    "# preference_ids = df_slice[\"s3_id\"].to_json(orient='values')\n",
    "# with open('/home/tony/Data/Preference/7b_v2/7v_r2_v3_ipo.json', 'w') as file:\n",
    "#     file.write(preference_ids)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:22:23.752062Z",
     "start_time": "2024-04-20T18:22:23.231600Z"
    }
   },
   "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[31], 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": "markdown",
   "metadata": {},
   "source": [
    "# Actually make"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:22:23.753074Z",
     "start_time": "2024-04-20T18:22:23.753065Z"
    }
   },
   "outputs": [],
   "source": [
    "# val_df[[\"request_id\", \"metadata\", \"updated_at\", \"user_id\", \"preference\"]].head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:23:41.879540Z",
     "start_time": "2024-04-20T18:23:31.383702Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████| 231822/231822 [00:10<00:00, 22096.43it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6,206 hours of 231822 clips, 7.2444375 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": 33,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T18:24:17.894249Z",
     "start_time": "2024-04-20T18:23:41.880974Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████| 2342/2342 [00:35<00:00, 65.47it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Total 2342 clips\n",
      "32 hours of False\n",
      "32 hours of True\n",
      "Done\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "make_dataset(val_df, OUT_DATA_DIR, is_val=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T19:23:26.589902Z",
     "start_time": "2024-04-20T18:24:42.470277Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|████████████████████████████████████████████████████████████████████████████████████████████████████████| 231822/231822 [58:43<00:00, 65.79it/s]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Total 231822 clips\n",
      "3,117 hours of False\n",
      "3,133 hours of True\n",
      "Done\n"
     ]
    }
   ],
   "source": [
    "make_dataset(train_df, OUT_DATA_DIR, 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": 45,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T19:23:26.625196Z",
     "start_time": "2024-04-20T19:23:26.591435Z"
    }
   },
   "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": 46,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T19:23:26.658152Z",
     "start_time": "2024-04-20T19:23:26.626937Z"
    }
   },
   "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": 47,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T19:23:26.715182Z",
     "start_time": "2024-04-20T19:23:26.659230Z"
    }
   },
   "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": 48,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T19:23:26.770389Z",
     "start_time": "2024-04-20T19:23:26.716794Z"
    }
   },
   "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": 49,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T19:23:26.823366Z",
     "start_time": "2024-04-20T19:23:26.771279Z"
    }
   },
   "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": 50,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T19:23:26.879827Z",
     "start_time": "2024-04-20T19:23:26.824363Z"
    }
   },
   "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": 51,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T19:23:26.944485Z",
     "start_time": "2024-04-20T19:23:26.881205Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1171 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": 52,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T19:23:27.018163Z",
     "start_time": "2024-04-20T19:23:26.945496Z"
    }
   },
   "outputs": [],
   "source": [
    "train_info = read_json(os.path.join(OUT_DATA_DIR, f\"info_tr.json\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T19:23:27.057416Z",
     "start_time": "2024-04-20T19:23:27.019653Z"
    }
   },
   "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": 54,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T19:23:27.122042Z",
     "start_time": "2024-04-20T19:23:27.058440Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "total samples 231822 (231822, 71)\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": 55,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T19:23:27.179166Z",
     "start_time": "2024-04-20T19:23:27.123068Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 epoch per batch 4, total 1811.109375\n"
     ]
    }
   ],
   "source": [
    "print(\"1 epoch per batch 4, total\", total_iters / 8 / 4 / 4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-20T19:23:28.449032Z",
     "start_time": "2024-04-20T19:23:27.180146Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Submitted batch job 1493\r\n"
     ]
    }
   ],
   "source": [
    "!cd /home/tony/Work/tony/slurm && sbatch sbatch_ipo"
   ]
  },
  {
   "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
}
