{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b686543b",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "\n",
    "bluejay_filepath = \"/home/tony/Data/Preference/bluejay_t1/interesting_clips_bluejay_t1_20250811_public_only.pkl\"\n",
    "crow_filepath = \"/home/tony/Data/Preference/crow_t1/interesting_clips_crow_t1_20251020_public_only.pkl\"\n",
    "bluejay_df = pd.read_pickle(bluejay_filepath)\n",
    "print(len(bluejay_df))\n",
    "crow_df = pd.read_pickle(crow_filepath)\n",
    "print(len(crow_df))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1a5a4d71",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4166823a",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(len(discogs_title_terms_map))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7aedafe7",
   "metadata": {},
   "outputs": [],
   "source": [
    "# merge bluejay_df and crow_df but track the source, avoiding dataframe fragmentation\n",
    "bluejay_df_copy = bluejay_df.copy()\n",
    "crow_df_copy = crow_df.copy()\n",
    "bluejay_df_copy[\"model\"] = \"bluejay\"\n",
    "crow_df_copy[\"model\"] = \"crow\"\n",
    "df = pd.concat([bluejay_df_copy, crow_df_copy], ignore_index=True)\n",
    "print(len(df))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b1674e18",
   "metadata": {},
   "outputs": [],
   "source": [
    "# create a list of all prompts \n",
    "tags_df = df[\"metadata\"].apply(lambda x: x.get(\"tags\", \"\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "556e7472",
   "metadata": {},
   "outputs": [],
   "source": [
    "# print the index of the df where tags are empty string\n",
    "empty_tags_indices = df[df[\"metadata\"].apply(lambda x: x.get(\"tags\", \"\") == \"\")].index\n",
    "print(empty_tags_indices)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fb06d972",
   "metadata": {},
   "outputs": [],
   "source": [
    "df.iloc[27]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "55ec9466",
   "metadata": {},
   "outputs": [],
   "source": [
    "# for each row, split the string by comma and strip whitespace, but handle None safely\n",
    "tags = tags_df.apply(lambda x: [t.strip() for t in x.split(\",\")] if isinstance(x, str) else [])\n",
    "# flatten the list\n",
    "#\n",
    "# tags = tags.explode()\n",
    "# remove duplicates\n",
    "#tags = tags.unique()\n",
    "print(len(tags))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "182a7ede",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "rand_idx = np.random.randint(0, len(tags_df))  \n",
    "print(tags_list_sorted[rand_idx])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "47d71ef0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# sort tags_df by length of tags, handling None safely\n",
    "tags_list = tags_df.tolist()\n",
    "# filter out None to avoid TypeError\n",
    "tags_list_non_none = [x for x in tags_list if x is not None]\n",
    "# sort the non-None tags_list by length\n",
    "tags_list_sorted = sorted(tags_list_non_none, key=lambda x: len(x), reverse=False)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ddf4a27b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create separate tags lists for model == \"crow\" and model == \"bluejay\"\n",
    "tags_df_crow = df[df[\"model\"] == \"crow\"][\"metadata\"].apply(lambda x: x.get(\"tags\", \"\"))\n",
    "tags_df_bluejay = df[df[\"model\"] == \"bluejay\"][\"metadata\"].apply(lambda x: x.get(\"tags\", \"\"))\n",
    "\n",
    "# Process crow tags\n",
    "tags_list_crow = tags_df_crow.tolist()\n",
    "tags_list_crow_non_none = [x for x in tags_list_crow if x is not None]\n",
    "tags_list_crow_sorted = sorted(tags_list_crow_non_none, key=lambda x: len(x), reverse=False)\n",
    "\n",
    "# Process bluejay tags\n",
    "tags_list_bluejay = tags_df_bluejay.tolist()\n",
    "tags_list_bluejay_non_none = [x for x in tags_list_bluejay if x is not None]\n",
    "tags_list_bluejay_sorted = sorted(tags_list_bluejay_non_none, key=lambda x: len(x), reverse=False)\n",
    "\n",
    "# Plot both as histograms of tag string lengths\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "tags_list_lens_crow = [len(x) for x in tags_list_crow_sorted]\n",
    "tags_list_lens_bluejay = [len(x) for x in tags_list_bluejay_sorted]\n",
    "\n",
    "plt.hist(tags_list_lens_crow, bins=100, alpha=0.5, label=\"crow\", density=True)\n",
    "plt.hist(tags_list_lens_bluejay, bins=100, alpha=0.5, label=\"bluejay\", density=True)\n",
    "plt.legend()\n",
    "plt.title(\"Distribution of tag string lengths by model\")\n",
    "plt.xlabel(\"Tag string length\")\n",
    "plt.ylabel(\"Count\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a6fc5985",
   "metadata": {},
   "outputs": [],
   "source": [
    "tags_list_lens = [len(x) for x in tags_list_sorted]\n",
    "print(tags_list_lens)\n",
    "# plot the distribution of tags_list_lens\n",
    "plt.hist(tags_list_lens, bins=100)\n",
    "plt.show()\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "22ba2aa0",
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "# for each row, count the number of tags\n",
    "tags_count = tags_df.apply(lambda x: len(x) if x is not None else 0)\n",
    "# make a histogram of the number of tags per row\n",
    "#tags_count.value_counts().plot(kind=\"bar\")\n",
    "#plt.show()\n",
    "# sort from highest to lowest\n",
    "tags_count = tags_count.sort_values(ascending=False)\n",
    "# get the top 100 tags\n",
    "tags_count = tags_count.head(100)\n",
    "print(tags_count)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "acfc446a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# plot distrubution of reaction_play_count\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# filter to those with reaction_play_count > 10\n",
    "df = df[(df[\"reaction_play_count\"] > 5)]\n",
    "df = df[df[\"upvoted\"] == True]\n",
    "#df = df[df[\"is_pro_user\"] == True]\n",
    "df = df[df[\"deleted\"] == False]\n",
    "#df = df[df[\"source\"] == \"web\"]\n",
    "df = df[df[\"user_n_clips\"] >= 5]\n",
    "df = df[df[\"flag_count\"] == 0]\n",
    "df = df[df[\"is_public\"] == True]\n",
    "df = df[df[\"task\"].isin([\"cover\", \"\", \"artist_consistency\", \"artist_cover\", \"playlist_condition\"])]\n",
    "df = df[df[\"duration\"] > 60]\n",
    "print(len(df))\n",
    "\n",
    "# and ensure that we have a balanced number of clips per user, \n",
    "# for example, ensure we have no more than 3 clips per user\n",
    "df = df.groupby(\"user_id\").filter(lambda x: len(x) <= 100)\n",
    "print(len(df))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a1ac3d28",
   "metadata": {},
   "outputs": [],
   "source": [
    "df_subset = df.copy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "078df4c4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Sample a total of 200 clips: half English, half balanced among foreign languages\n",
    "\n",
    "total_clips = 50_000\n",
    "n_english = total_clips // 2\n",
    "n_foreign = total_clips - n_english\n",
    "\n",
    "# Get language for each row\n",
    "df[\"lang\"] = df[\"metadata\"].apply(lambda x: x.get(\"lang\", \"\"))\n",
    "\n",
    "# English clips\n",
    "df_en = df[df[\"lang\"] == \"English\"]\n",
    "if len(df_en) >= n_english:\n",
    "    df_en_sample = df_en.sample(n_english, random_state=42)\n",
    "else:\n",
    "    df_en_sample = df_en\n",
    "\n",
    "# Foreign languages\n",
    "foreign_langs = [l for l in df[\"lang\"].unique() if l != \"English\"]\n",
    "n_langs = len(foreign_langs)\n",
    "clips_per_lang = n_foreign // n_langs if n_langs > 0 else 0\n",
    "remainder = n_foreign % n_langs if n_langs > 0 else 0\n",
    "\n",
    "dfs = []\n",
    "for i, lang in enumerate(foreign_langs):\n",
    "    n = clips_per_lang + (1 if i < remainder else 0)\n",
    "    df_lang = df[df[\"lang\"] == lang]\n",
    "    if len(df_lang) >= n:\n",
    "        dfs.append(df_lang.sample(n, random_state=42))\n",
    "    else:\n",
    "        dfs.append(df_lang)\n",
    "\n",
    "df_foreign_sample = pd.concat(dfs) if dfs else pd.DataFrame(columns=df.columns)\n",
    "\n",
    "# Combine and shuffle\n",
    "df_subset = pd.concat([df_en_sample, df_foreign_sample]).sample(frac=1, random_state=42).reset_index(drop=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8c079e1e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# plot the distribution of lang\n",
    "lang_counts = df_subset[\"metadata\"].apply(lambda x: x.get(\"lang\", \"\")).value_counts()\n",
    "plt.figure(figsize=(10, 5))\n",
    "lang_counts.plot(kind=\"bar\")\n",
    "plt.xlabel(\"Language\")\n",
    "plt.ylabel(\"Number of Clips\")\n",
    "plt.title(\"Distribution of Clips by Language\")\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "76c7724f",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f934f73f",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(len(df_subset))\n",
    "# crop to exactly 30_000 rows\n",
    "df_subset = df_subset.sample(100_000, random_state=42)\n",
    "print(len(df_subset))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f8ff9282",
   "metadata": {},
   "outputs": [],
   "source": [
    "# now i need to create a jsonl file that has \n",
    "# text, tags, clip_ids, user_id, \n",
    "from suno_utils.utils.text import write_jsonl\n",
    "\n",
    "# iterate over the dataframe and create a jsonl file\n",
    "metas = []\n",
    "i = 0\n",
    "for index, row in df_subset.iterrows():\n",
    "    meta = {\n",
    "        \"text\": row[\"prompt_text\"],\n",
    "        \"tags\": row[\"metadata\"].get(\"tags\", \"\"),\n",
    "        \"id\": row[\"s3_id\"],\n",
    "        \"user_id\": row[\"user_id\"],\n",
    "        \"lang\" : row[\"metadata\"].get(\"lang\", \"\"),\n",
    "        \"duration\": row[\"duration\"],\n",
    "    }\n",
    "    metas.append(meta)\n",
    "\n",
    "write_jsonl(metas, \"/home/christian/code/christian/metadata/sft/interesting_clips_bluejay_t1_20250811_public_only_100k.jsonl\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bb15cc7e",
   "metadata": {},
   "outputs": [],
   "source": [
    "from suno_utils.utils.text import read_jsonl\n",
    "work_items = read_jsonl(\n",
    "    \"/home/christian/code/christian/metadata/discogs_subset_sampled_metas.jsonl\"\n",
    ")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "10f0ec44",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(len(work_items))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "38707f6d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# how many work items have \"text\" that is non-empty\n",
    "# how many work items have tags list that is non-empty\n",
    "text_count = 0\n",
    "tags_count = 0\n",
    "for item in work_items:\n",
    "    if item[\"text\"] != \"\":\n",
    "        text_count += 1\n",
    "        \n",
    "    if len(item[\"tags\"]) > 0:\n",
    "        tags_count += 1\n",
    "print(text_count)\n",
    "print(tags_count)\n",
    "        \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6919d6a7",
   "metadata": {},
   "outputs": [],
   "source": [
    "# test some of the local data\n",
    "CODEC_FILEPATH = \"s3://suno-data/minz/models/dac_vae_tuned_25hz.pth\"\n",
    "\n",
    "from suno_utils.tasks.dac_vae_fixed_25hz import (\n",
    "    preload_models as preload_codec_models,\n",
    "    decode as codec_decode,\n",
    "    encode as codec_encode,\n",
    "    decode_stream_to_full_audio,\n",
    ")\n",
    "\n",
    "_ = preload_codec_models(CODEC_FILEPATH)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "59d54fe6",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "source_dir = \"/app2/suno/data/christian/outputs/v3-base-data-ctx-discogs-subset-t0\"\n",
    "\n",
    "# get all the dirs in the source_dir\n",
    "dirs = os.listdir(source_dir)\n",
    "\n",
    "# get the dirs that start with \"2025-09-29\"\n",
    "dirs = [d for d in dirs if os.path.isdir(os.path.join(source_dir, d))]\n",
    "print(dirs)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5942cdcf",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "dir_idx = 1500\n",
    "dir_path = os.path.join(source_dir, dirs[dir_idx])\n",
    "model_name = \"16n_25hz_v45_infill_shared_flow_resume_1_75m\"\n",
    "\n",
    "# get all the files in the dir\n",
    "files = os.listdir(dir_path)\n",
    "# get the upsample vae and the origina_vae\n",
    "upsample_vae_filepath = os.path.join(dir_path, f\"{dirs[dir_idx]}_{model_name}_0_upsampled_vae.npz\")\n",
    "original_vae_filepath = os.path.join(dir_path, f\"{dirs[dir_idx]}_original_vae.npz\")\n",
    "\n",
    "upsample_vae = np.load(upsample_vae_filepath)[\"vae_latents\"]\n",
    "original_vae = np.load(original_vae_filepath)[\"vae_latents\"]\n",
    "\n",
    "print(upsample_vae.shape)\n",
    "print(original_vae.shape)\n",
    "\n",
    "# decode both\n",
    "print(\"upsample\")\n",
    "upsample_audio = codec_decode(upsample_vae[:750]).play()\n",
    "print(\"original\")\n",
    "original_audio = codec_decode(original_vae[:750]).play()\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ce9472c5",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "suno_diff",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
