diff --git a/check_logits_hidden_layers.ipynb b/check_logits_hidden_layers.ipynb new file mode 100644 index 00000000..a9c55b2f --- /dev/null +++ b/check_logits_hidden_layers.ipynb @@ -0,0 +1,400 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "from fast_llm.data.dataset.gpt.memmap import GPTMemmapDataset\n", + "from pathlib import Path\n", + "import numpy as np\n", + "from transformers import AutoTokenizer\n", + "import torch\n", + "import pickle\n", + "\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": 139, + "metadata": {}, + "outputs": [], + "source": [ + "files_root = Path(\"/mnt/datasets/tests/denis/tensors_f32/\")\n", + "#files_root = Path(\"/mnt/datasets/tests/denis/tensors/\")" + ] + }, + { + "cell_type": "code", + "execution_count": 140, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1000" + ] + }, + "execution_count": 140, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fm_files = {int(file.stem.split(\"tensor\")[1]): file for file in (files_root / \"fast_llm/logits/\").glob(\"tensor*.pt\")}\n", + "hf_files = {int(file.stem.split(\"tensor\")[1]): file for file in (files_root / \"hf/logits\").glob(\"tensor*.pt\")}\n", + "assert len(fm_files) == len(hf_files)\n", + "len(fm_files)" + ] + }, + { + "cell_type": "code", + "execution_count": 141, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/tmp/ipykernel_14929/1685567046.py:7: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.\n", + " fm_data = torch.load(fm_files[i])\n", + "/tmp/ipykernel_14929/1685567046.py:8: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.\n", + " hf_data = torch.load(hf_files[i])\n" + ] + }, + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 141, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "hf_tokens = []\n", + "fm_tokens = []\n", + "max_adiff = []\n", + "mean_adiff = []\n", + "sum_adiff = []\n", + "for i in range(len(fm_files)):\n", + " fm_data = torch.load(fm_files[i])\n", + " hf_data = torch.load(hf_files[i])\n", + " \n", + " hf_tokens.append(hf_data[0, -1, :].argmax().item())\n", + " fm_tokens.append(fm_data[0, -1, :].argmax().item())\n", + "\n", + " adiff = torch.abs(hf_data[0, -1, :] - fm_data[0, -1, :])\n", + " max_adiff.append(adiff.max().item())\n", + " mean_adiff.append(adiff.mean().item())\n", + " sum_adiff.append(adiff.sum().item())\n", + " \n", + "all(a == b for a, b in zip(hf_tokens, fm_tokens))" + ] + }, + { + "cell_type": "code", + "execution_count": 129, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "107" + ] + }, + "execution_count": 129, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "min(len(hf_tokens)+1 if ab[0] == ab[1] else i for i, ab in enumerate(zip(hf_tokens, fm_tokens)))" + ] + }, + { + "cell_type": "code", + "execution_count": 130, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABKUAAAHqCAYAAADVi/1VAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvc2/+5QAAAAlwSFlzAAAPYQAAD2EBqD+naQABAABJREFUeJzsnXd4FNX6x7+zJY0k9CIdQUABUVARsYBSBMSGDVEQEb0WLoperx1Rr4iKyk8Br14F7IBdOiJI771DIIQSEkhIL9vm98dmd2dmp+/Mzm7yfp4nT3Znzpxz5syZ2XO+877vYViWZUEQBEEQBEEQBEEQBEEQUcRmdQUIgiAIgiAIgiAIgiCImgeJUgRBEARBEARBEARBEETUIVGKIAiCIAiCIAiCIAiCiDokShEEQRAEQRAEQRAEQRBRh0QpgiAIgiAIgiAIgiAIIuqQKEUQBEEQBEEQBEEQBEFEHRKlCIIgCIIgCIIgCIIgiKhDohRBEARBEARBEARBEAQRdUiUIgiCIAiCIAiCIAiCIKIOiVIEUU1YuXIlGIbBypUrra5KTPLQQw8hNTU1qmVmZmaCYRjMmjUrquUajdR5LF68GJdddhmSkpLAMAwKCgoAAF9//TU6duwIp9OJOnXqRL2+BEEQBBFP0BhFPzRGIYj4h0QpIu6ZNWsWGIYBwzBYs2ZN2H6WZdGiRQswDINbbrnFghrGFtWxvbxeL5o2bQqGYbBo0SKrq2MIZWVleP31100RGQPXn2EYOBwO1KtXD927d8e4ceOwb98+VXnk5eXhnnvuQXJyMqZNm4avv/4atWrVwoEDB/DQQw+hbdu2+Pzzz/HZZ58ZXn+CIAii5rJ7927cddddaNWqFZKSktCsWTP069cPH3/8sdVVE4XGKNqgMQpB1DwcVleAIIwiKSkJ3333Ha699lre9r///hsnT55EYmKiRTWLTapTe/3111/Izs5G69at8e2332LgwIFWVyliysrKMHHiRABA7969Dc+/X79+GDFiBFiWRWFhIXbu3InZs2dj+vTpmDx5MsaPHx9M26pVK5SXl8PpdAa3bd68GcXFxXjzzTfRt2/f4PaVK1fC5/Nh6tSpaNeuneH1JgiCIGou69atQ58+fdCyZUuMGTMGTZo0wYkTJ7BhwwZMnToVY8eOtbqKYdAYRTs0RiGImgWJUkS1YdCgQZg3bx7+7//+Dw5HqGt/99136N69O86dO2dh7WKP6tRe33zzDbp164aRI0fipZdeQmlpKWrVqmV1tWKa9u3b44EHHuBte+eddzBkyBA8++yz6NixIwYNGgTA/9YyKSmJlzY3NxcAwkzfpbZHAl1PgiAIAgD+85//oHbt2ti8ebPk70+sQWMU7dAYhSBqFuS+R1Qbhg0bhry8PCxbtiy4zeVy4ccff8T9998vesz777+Pa665BvXr10dycjK6d++OH3/8kZdm5syZYBgGX375JW/722+/DYZhsHDhQtl6/fbbbxg8eDCaNm2KxMREtG3bFm+++Sa8Xi8vXe/evdG5c2fs27cPffr0QUpKCpo1a4Z33303LM+TJ0/i9ttvR61atdCoUSM888wzqKyslK2HED3t5fP58NFHH6FTp05ISkpC48aN8dhjj+H8+fOmn7MU5eXl+OWXX3DffffhnnvuQXl5OX777TfJ9EePHsWAAQNQq1YtNG3aFG+88QZYluWl+eGHH9C9e3ekpaUhPT0dXbp0wdSpU8Pyufvuu1GvXj2kpKTg6quvxoIFCxTr27t3b9G3ig899BBat24NwB8foWHDhgCAiRMnBs3YX3/99WD6AwcO4K677kK9evWQlJSEK664Ar///rti+XLUr18fP/zwAxwOB/7zn/8EtwvjNfTu3RsjR44EAFx55ZVgGCZY/wkTJgAAGjZsGFbnRYsW4brrrkOtWrWQlpaGwYMHY+/evWHtkJqaioyMDAwaNAhpaWkYPnw4APX9r3Xr1rjllluwZs0aXHXVVUhKSsKFF16Ir776KuycCwoK8Mwzz6B169ZITExE8+bNMWLECJ4oW1lZiQkTJqBdu3ZITExEixYt8Pzzz2u+5wiCIIjIyMjIQKdOnURFhUaNGgU/y8VLEv42vf7662AYBocOHcIDDzyA2rVro2HDhnj11VfBsixOnDiB2267Denp6WjSpAmmTJmiur40RqExCo1RCEIZEqWIakPr1q3Rs2dPfP/998FtixYtQmFhIe677z7RY6ZOnYrLL78cb7zxBt5++204HA7cfffdvB/uUaNG4ZZbbsH48eNx4sQJAP54BhMnTsTo0aODb2qkmDVrFlJTUzF+/HhMnToV3bt3x2uvvYYXXnghLO358+dx8803o2vXrpgyZQo6duyIf//737wYBOXl5bjpppuwZMkSPPXUU3j55ZexevVqPP/886a312OPPYZ//etf6NWrF6ZOnYpRo0bh22+/xYABA+B2u007Zzl+//13lJSU4L777kOTJk3Qu3dvfPvtt6JpvV4vbr75ZjRu3BjvvvsuunfvjgkTJgQHKQCwbNkyDBs2DHXr1sXkyZPxzjvvoHfv3li7dm0wTU5ODq655hosWbIETzzxBP7zn/+goqICt956K3755RdV9ZajYcOGmDFjBgDgjjvuwNdff42vv/4ad955JwBg7969uPrqq7F//3688MILmDJlCmrVqoXbb7894vJbtmyJG264ARs2bEBRUZFompdffhmPPvooAOCNN97A119/jcceewwfffQR7rjjDgDAjBkzeHX++uuvMXjwYKSmpmLy5Ml49dVXsW/fPlx77bXIzMzk5e/xeDBgwAA0atQI77//PoYOHQpAff8DgCNHjuCuu+5Cv379MGXKFNStWxcPPfQQb4BZUlKC6667Dh9//DH69++PqVOn4h//+AcOHDiAkydPAvAPMm+99Va8//77GDJkCD7++GPcfvvt+PDDD3HvvfdG1NYEQRCENlq1aoWtW7diz549hud97733wufz4Z133kGPHj3w1ltv4aOPPkK/fv3QrFkzTJ48Ge3atcNzzz2HVatWqcqTxig0RqExCkGogCWIOGfmzJksAHbz5s3sJ598wqalpbFlZWUsy7Ls3Xffzfbp04dlWZZt1aoVO3jwYN6xgXQBXC4X27lzZ/bGG2/kbc/Ozmbr1avH9uvXj62srGQvv/xytmXLlmxhYaFi/YRlsCzLPvbYY2xKSgpbUVER3HbDDTewANivvvoquK2yspJt0qQJO3To0OC2jz76iAXAzp07N7ittLSUbdeuHQuAXbFihWx99LbX6tWrWQDst99+y8tv8eLFYduNPmc5brnlFrZXr17B75999hnrcDjY3NxcXrqRI0eyANixY8cGt/l8Pnbw4MFsQkICe/bsWZZlWXbcuHFseno66/F4JMt8+umnWQDs6tWrg9uKi4vZNm3asK1bt2a9Xi/Lsix77NgxFgA7c+ZM3jnfcMMNYXmOHDmSbdWqVfD72bNnWQDshAkTwtLedNNNbJcuXXht6fP52GuuuYa96KKLJOsdAAD75JNPSu4fN24cC4DduXOn5Hlw+xGXCRMmsACC7cmy/rapU6cOO2bMGF7aM2fOsLVr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EZHLsShFREREREREREQux6IUERERERERERG5HItSRERERERERETkcixKERERERERERGRyxm07oCzCSEAABkZGU45fkFBAXJycpCRkQGj0eiU+6CSMf7aYvy1xfhrj8+BtpwZf0veYMkjajPmUjUb468txl9bjL+2GH9tOTv+juZSNb4olZmZCQAIDw/XuCdERERU3WRmZsLPz0/rbmiKuRQRERFVVFm5lCRq+L8AzWYz/vjjD/j4+ECSpEo/fkZGBsLDw3H16lX4+vpW+vGpdIy/thh/bTH+2uNzoC1nxl8IgczMTNSvXx86Xe1e7YC5VM3G+GuL8dcW468txl9bzo6/o7lUjR8ppdPp0LBhQ6ffj6+vL/+QNMT4a4vx1xbjrz0+B9pyVvxr+wgpC+ZStQPjry3GX1uMv7YYf205M/6O5FK1+19/RERERERERESkCRaliIiIiIiIiIjI5ViUukvu7u5YsGAB3N3dte5KrcT4a4vx1xbjrz0+B9pi/GsGPo/aYvy1xfhri/HXFuOvraoS/xq/0DkREREREREREVU9HClFREREREREREQux6IUERERERERERG5HItSRERERERERETkcixK3YUPP/wQjRs3hoeHB3r06IEDBw5o3aUaYcmSJejWrRt8fHwQHByM4cOH48yZM1ZtcnNzMWXKFAQGBsLb2xuPPPIIrl27ZtXmypUrGDJkCLy8vBAcHIzZs2ejsLDQlQ+lRli6dCkkScL06dOVbYy/c/3+++94/PHHERgYCE9PT7Rv3x6HDh1S9gshMH/+fISFhcHT0xPR0dE4d+6c1THS0tIQGxsLX19f+Pv7Y+LEicjKynL1Q6l2TCYTXnnlFTRp0gSenp5o1qwZXnvtNaiXX2T8K9ePP/6Ihx9+GPXr14ckSdi0aZPV/sqK99GjR3HvvffCw8MD4eHhePPNN5390MgBzKWcg7lU1cJcyvWYS2mHuZRr1Yg8SlCFbNiwQbi5uYnVq1eLEydOiEmTJgl/f39x7do1rbtW7cXExIg1a9aI48ePi8TERDF48GAREREhsrKylDbPPvusCA8PF/Hx8eLQoUOiZ8+e4p577lH2FxYWinbt2ono6Ghx5MgR8b///U8EBQWJuXPnavGQqq0DBw6Ixo0biw4dOohp06Yp2xl/50lLSxONGjUSTz75pNi/f7+4ePGi+P7778X5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5TjmUkRUHBc6JyKHDR48GJ999hkSEhLwwAMPKNuzsrKwaNEijBw50uY2Hh4eyuXiw70lSYLZbC71PmNjYzFv3jx4enoiLCwMOp3jtfSFCxfiL3/5C7777jts3boVCxYswIYNGzBixAiHj1ERFXmclX2MrKws6PV6HD582CqpA6wXYk1NTcXZs2eh1+tx7tw5DBw4sFz9JCIiIscxl3IMcymi2oMjpYhqOV9fX9SvXx979+612r537160adPGattzzz2HpUuXYujQodi9e7eyvXPnzjhz5gyaN29u81OexMcePz8/NG/eHA0aNLA6VuvWrXH16lVcvXpV2Xby5Emkp6db9TsyMhIzZszA9u3bMXLkSKxZs8bu/bi5ucFkMpXal9atWyMpKQnZ2dnKtr1790Kn01n9Z83ZmjVrBqPRiP379yvbbt68aXVa5k6dOsFkMiE1NdXmOVGfBWfChAlo37491q1bhxdffNHmP7pERERUOuZSMuZSzKWIKoIjpYgIs2fPxoIFC9CsWTN07NgRa9asQWJiItavX2/T9m9/+xtMJhMeeughbN26FX369MH8+fPx0EMPISIiAo8++ih0Oh2SkpJw/Phx/OMf/3BKn6Ojo9G+fXvExsbi3XffRWFhISZPnoy+ffuia9euuH37NmbPno1HH30UTZo0wW+//YaDBw/ikUcesXu8xo0b49KlS0hMTETDhg3h4+MDd3d3qzaxsbFYsGABxo8fj4ULF+LPP//E3/72NzzxxBMICQlxyuO0x9vbGxMnTsTs2bMRGBiI4OBgzJs3zyrRjIyMRGxsLMaNG4dly5ahU6dO+PPPPxEfH48OHTpgyJAh+PDDD5GQkICjR48iPDwc3333HWJjY7Fv3z64ubm57PEQERFVd8ylmEsxlyKqGI6UIiI8//zzmDlzJmbNmoX27dtj27Zt+Pbbb9GiRQu77adPn45FixZh8ODB+PnnnxETE4MtW7Zg+/bt6NatG3r27Il//vOfaNSokdP6LEkSNm/ejICAANx3332Ijo5G06ZN8eWXXwIA9Ho9bty4gXHjxiEyMhKjR4/GoEGDsGjRIrvHe+SRRzBw4EDcf//9qFevHr744gubNl5eXvj++++RlpaGbt264dFHH0X//v2xfPlypz3Okrz11lu499578fDDDyM6Ohp9+vRBly5drNqsWbMG48aNw6xZs9CyZUsMHz4cBw8eREREBE6fPo3Zs2djxYoVyloSK1aswPXr1/HKK6+4/PEQERFVZ8ylmEsBzKWIKkISQgitO0FERERERERERLULR0oREREREREREZHLsShFREREREREREQux6IUERERERERERG5HItSRERERERERETkcixKERERERERERGRy7EoRURERERERERELseiFBERERERERERuRyLUkRERERERERE5HIsShERERERERERkcuxKEVERERERERERC7HohQREREREREREbkci1JERERERERERORy/x/5iPH7VCCmugAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, axes = plt.subplots(1, 2, figsize=(12, 5), sharex=True)\n", + "\n", + "# Left plot: max and mean absolute differences\n", + "axes[0].plot(max_adiff, label='max')\n", + "axes[0].plot(mean_adiff, label='mean')\n", + "axes[0].set_title('Max and Mean Absolute Difference')\n", + "axes[0].set_xlabel('Token Position Index')\n", + "axes[0].set_ylabel('Absolute Difference')\n", + "axes[0].legend()\n", + "axes[0].grid(True)\n", + "\n", + "# Right plot: sum absolute difference\n", + "axes[1].plot(sum_adiff, label='sum', color='tab:orange')\n", + "axes[1].set_title('Sum Absolute Difference')\n", + "axes[1].set_xlabel('Token Position Index')\n", + "axes[1].set_ylabel('Absolute Difference')\n", + "axes[1].legend()\n", + "axes[1].grid(True)\n", + "\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 131, + "metadata": {}, + "outputs": [], + "source": [ + "fm_hidden_files = {int(file.stem.split(\"data\")[1]): file for file in (files_root / \"fast_llm/hidden_states/\").glob(\"data*.pickle\")}\n", + "hf_hidden_files = {int(file.stem.split(\"data\")[1]): file for file in (files_root / \"hf/hidden_states\").glob(\"data*.pickle\")}" + ] + }, + { + "cell_type": "code", + "execution_count": 132, + "metadata": {}, + "outputs": [], + "source": [ + "def mad(new_token_index, fm_hidden_files, hf_hidden_files):\n", + " with fm_hidden_files[new_token_index].open(\"rb\") as f:\n", + " fm_data = pickle.load(f)\n", + " with hf_hidden_files[new_token_index].open(\"rb\") as f:\n", + " hf_data = pickle.load(f)\n", + " max_adiffs_hidden_layers = []\n", + " for i in range(len(hf_data)):\n", + " max_adiff = torch.abs(hf_data[i][0,-1,:]-fm_data[i]['tensor'][0,-1,:]).max().item()\n", + " max_adiffs_hidden_layers.append(max_adiff)\n", + " return max_adiffs_hidden_layers\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 133, + "metadata": {}, + "outputs": [], + "source": [ + "new_token_index = 107\n", + "new_token_index1 = 108\n", + "max_adiffs_hidden_layers = mad(0, fm_hidden_files, hf_hidden_files)\n", + "max_adiffs_hidden_layers2 = mad(new_token_index, fm_hidden_files, hf_hidden_files)\n", + "max_adiffs_hidden_layers3 = mad(new_token_index1, fm_hidden_files, hf_hidden_files)" + ] + }, + { + "cell_type": "code", + "execution_count": 134, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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1auXep+oqChRsmRJ4erqKr788kvx448/itq1awsrKyuxefNm9X6RkZECgFi1apXGObds2TLH/pUrV04IIURSUpJYunSpACC6d+8u1qxZI9asWSMiIiKEEEJcvnxZuLu7i2rVqok5c+aIRYsWiRYtWgiZTKZx/NwAECNHjsz18TZt2ggrKysRHx+f43ns2bNHDB8+XAAQM2bMEGvWrBHHjh0TW7ZsEd27dxcAxNKlSzX6/NtvvwmZTCY6duwo/ve//4k5c+aIwMBA4eHhISIjIzXGwd7eXlSoUEEMHDhQLFu2TPz2229CiIK//8qVKyeqVKkiSpYsKb744guxaNEiUa9ePSGTycTly5fV+yUmJooaNWoIa2tr8cEHH4ilS5eKmTNnigYNGojz588LIYRQKBSiffv2wsnJSYwdO1YsX75cjBo1StjY2Ii3334737EmIjI1WecBWS1YsEAAEMuWLRNCCPH1118LmUwm3n33XbFkyRIRFhYmfHx8RGBgoHjx4oX6eS1bthR+fn6iRIkS4pNPPhHLly8XW7duzfX45cqVEwMHDlTfP336tKhQoYKYNGmSWL58uZgxY4YoXbq0cHd3F48ePVLv995774mSJUuKzMxMjfa+++47IZPJxL1794QQQiQnJ4tatWoJb29v8cUXX4hly5aJAQMGCJlMJsaMGaN+nvTZVq1aNVG+fHnx7bffinnz5qnbya3vnTt3Vs8Vbt26pX6sTp064sMPP8xxfOfOnSuaN28uZsyYIVasWCHGjBkjHB0dRcOGDYVSqVTvd+LECWFtbS0+/fRT9bY+ffoIR0dHcf369Vz7lVXHjh1FmzZthBBC3Lt3T8hkMvHHH39k2w+AqFGjhvDx8REzZswQc+bMEeXKlROOjo7i0qVL6v369esn7OzsxLhx48TPP/8s5syZI7p27SrWrl2r3kc65wYNGoh58+aJSZMmCUdHx2zvlWnTpomsf47mNE/K2r9p06YJIYSIiIgQffv2FQDEvHnz1POipKQkIUTB36s5ye3fg+TBgwcCgOjZs2eO55GUlCTWrFkjgoODRZkyZdR9i4qKEmvWrBE+Pj6iTp06Gn3WZm4BQFStWlWUKFFChIWFicWLF4vz58+LqKgoUaZMGREQECBmzJghli5dKt566y31GEn2798vAIi6deuKkJAQMW/ePDF9+nTh5OQkGjZs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eDHeeOMN1KxZEx988AHKly+P6OhoHD9+HA8fPkRERES+43fjxg2sXbsWQggkJCQgIiICGzduRFJSkvrfhb64ublh6dKl6N+/P+rVq4c+ffqgRIkSuH//Pv755x80a9ZMI1iYk4K+/7QxYcIEbNq0Cb169cKQIUMQEhKC58+fY9u2bVi2bBlq166N/v37448//sBHH32E/fv3o1mzZlAoFLh27Rr++OMP7N69O9f0FyIic1WhQgV8/fXXmDx5Mu7evYtu3brB1dUVkZGR2LJlC4YPH47x48fr5VhdunRRrwxq2rQpLl26hHXr1uWaft+vXz9MnDgRW7ZswYgRI7LVDJowYQK2bduGLl26YNCgQQgJCUFycjIuXbqETZs24e7du9lWYBVWuXLlMH369Dz3cXNzQ4sWLfDdd99BLpejdOnS2LNnT44ryKU6p3v37oWrqytq1aqFr776ClOmTEHPnj0RGhqa4zFOnjyJW7duaVzMJavSpUujXr16WLduHT7//HP19ho1aqBDhw4YPXo07O3t1cGgsLAwAKoLnpQpUwY9e/ZE7dq14eLign///RenT59WB+JsbW0xZ84cDB48GC1btkTfvn0RHR2NBQsWIDAwMN+A2rBhw/Dtt99i2LBhqF+/Pg4dOpTjl75SYPPLL79Enz59YGtri65du+rtvbpz505cu3YNmZmZiI6Oxr59+xAeHo5y5cph27ZtGkXcdaWPucW3336L/fv3o1GjRvjggw9QrVo1PH/+HOfOncO///6L58+fa9UnKysrLF26FF27dkWdOnUwePBglCpVCteuXcOVK1fUQd6CzkGrVauGVq1aISQkBF5eXjhz5gw2bdqU63uUipmiucgfUdEpyKVchcj5kqwrV64UlSpVEvb29iI4OFisWrUq22Ve33nnHeHq6iru3r2r8dy//vpLABBz5szJ87hHjx4VjRs3Fo6OjsLf319MnDhRfVnj/fv3q/fL7VKyAwcOFOXKldPYdu/ePfHWW28JJycn4ePjI8aMGSN27dqVrc2c6DJeQgixYsUKERISIhwdHYWrq6uoWbOmmDhxonj8+LFBzzmrs2fPCgBi6tSpue5z9+5dAUB8+umn6jadnZ3F7du3Rfv27YWTk5MoWbKkmDZtmsalqDdt2iTat28vfH19hZ2dnShbtqz48MMPxZMnTzTav337tujZs6fw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jV8g/ptUZq5VlXOnbt2gUycbc+bsYdSoroSEVPu/l/qMfm54RuPnGY2fZzR+ntH4ecbseZPV689cAaGhofTs2ZOUlBT3MYfDQUpKCv369SvzMf369St1PjiX653sfBEREZGaqjJzLREREZGqYvqfoyZMmMC4ceM488wz6d27Ny+88AL5+fnuHWKuueYamjZtytSpUwG48847Oeecc3juuec477zz+PTTT/ntt9944403zHwZIiIiIn7pdHMtEREREbOYnpS67LLLOHDgAA8//DAZGRl069aNuXPnuhty7ty5E6v12IKu/v378/HHH/Pggw9y//3306ZNG7755hs6d+5s1ksQERER8Vunm2uJiIiImMX0pBTA+PHjGT9+fJn3LVq06IRj//jHP/jHP/7h46hEREREqodTzbVEREREzGJqTykREREREREREamZlJQSEREREREREZEqp6SUiIiIiIiIiIhUOSWlRERERERERESkyikpJSIiIiIiIiIiVU5JKRERERERERERqXJKSomIiIiIiIiISJVTUkpERERERERERKqcklIiIiIiIiIiIlLllJQSEREREREREZEqp6SUiIiIiIiIiIhUuWCzA6hqhmEAkJOT45Pr22w2CgoKyMnJISQkxCfPUZ1p/Dyj8fOMxs9zGkPPaPw84+vxc80dXHOJmkJzJ/+m8fOMxs8zGj/PaPw8o/HzjL/Mm2pcUio3NxeA5s2bmxyJiIiIBKLc3FxiY2PNDqPKaO4kIiIilXW6eZPFqGF/7nM4HOzdu5fo6GgsFovXr5+Tk0Pz5s3ZtWsXMTExXr9+dafx84zGzzMaP89pDD2j8fOMr8fPMAxyc3Np0qQJVmvN6YCguZN/0/h5RuPnGY2fZzR+ntH4ecZf5k01bqWU1WqlWbNmPn+emJgYfWN4QOPnGY2fZzR+ntMYekbj5xlfjl9NWiHlorlTYND4eUbj5xmNn2c0fp7R+HnG7HlTzfkzn4iIiIiIiIiI+A0lpUREREREREREpMopKeVlYWFhPPLII4SFhZkdSkDS+HlG4+cZjZ/nNIae0fh5RuMXmPTv5hmNn2c0fp7R+HlG4+cZjZ9n/GX8alyjcxERERERERERMZ9WSomIiIiIiIiISJVTUkpERERERERERKqcklIiIiIiIiIiIlLllJTysunTp5OQkEB4eDh9+vThl19+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zJuqbJ+/GuLll182WrRoYYSGhhq9e/c2VqxYYXZIAeGyyy4zGjdubISGhhpNmzY1LrvsMmPbtm1mh+W3Fi5caAAnfIwbN84wDOf2xg899JDRsGFDIywszEhKSjK2bt1qbtB+5FTjV1BQYAwfPtyoX7++ERISYsTHxxs33XSTkZGRYXbYfqOssQOMd999133O0aNHjVtvvdWoXbu2ERkZaVx88cXGvn37zAvaj5xu/Hbu3GkMHDjQqFOnjhEWFma0bt3auPfee43s7GxzA/cT119/vREfH2+EhoYa9evXN5KSkox58+a579d7L7Bo3lQ5mjdVjOZNntPcqfI0b/KM5k2eCYR5k8UwDMM36S4REREREREREZGyqaeUiIiIiIiIiIhUOSWlRERERERERESkyikpJSIiIiIiIiIiVU5JKRERERERERERqXJKSomIiIiIiIiISJVTUkpERERERERERKqcklIiIiIiIiIiIlLllJQSEREREREREZEqp6SUiFTIzJkziYuLO+U5jz76KN26dTvlOddeey2jR4/2WlzilJaWhsViYe3atWaHIiIiUuNp3uTfNG8SMZ+SUiICnHyys2jRIiwWC1lZWQBcdtll/PHHH1UbnAcsFgvffPON2WGUy6BBg7jrrrvMDkNEREROQ/Mm82neJFI9BJsdgIgEloiICCIiIswOI6DZbDZCQkLMDkNERER8TPMmz2neJFK9aaWUiFRIWcvQn3rqKRo2bEh0dDQ33HADhYWFpe632+1MmDCBuLg46taty8SJEzEMo9Q5DoeDqVOnkpiYSEREBF27duXLL7903+/6y2NKSgpnnnkmkZGR9O/fn61bt1b6tRw6dIgrrriCpk2bEhkZyRlnnMEnn3zivv/999+nbt26FBUVlXrc6NGjufrqq91ff/vtt/To0YPw8HBatmzJ5MmTKSkpcd9vsVh47bXXuPDCC6lVqxZTpkwpV3wJCQk8+eSTXH/99URHR9OiRQveeOONUuf88ssvdO/enfDwcM4880zWrFlzwnU2bNjAyJEjiYqKomHDhlx99dUcPHgQcI5raGgoP/30k/v8Z555hgYNGpCZmVmuOEVERKRsmjdp3iQip2GIiBiGMW7cOOOiiy464fjChQsNwDhy5IhhGIbx7rvvGrGxse77P/vsMyMsLMx46623jC1bthgPPPCAER0dbXTt2tV9ztNPP23Url3b+Oqrr4xNmzYZN9xwgxEdHV3q+Z544gmjffv2xty5c43t27cb7777rhEWFmYsWrSoVBx9+vQxFi1aZGzcuNEYMGCA0b9//1O+LsCYNWtWmfft3r3bePbZZ401a9YY27dvN1566SUjKCjIWLlypWEYhlFQUGDExsYan3/+ufsxmZmZRnBwsLFgwQLDMAxjyZIlRkxMjDFz5kxj+/btxrx584yEhATj0UcfLRVDgwYNjHfeecfYvn27kZ6eXmY855xzjnHnnXe6v46Pjzfq1KljTJ8+3fjzzz+NqVOnGlar1diyZYthGIaRm5tr1K9f37jyyiuNDRs2GN99953RsmVLAzDWrFljGIZhHDlyxKhfv74xadIkY/Pmzcbq1auNYcOGGYMHD3Y/z7333mvEx8cbWVlZxurVq43Q0FDj22+/PeW4ioiI1GSaN2nepHmTiHcoKSUihmE4J1dBQUFGrVq1Sn2Eh4efcnLVr18/49Zbby11rT59+pSaXDVu3Nh45pln3F/bbDajWbNm7slVYWGhERkZaSxbtqzUdW644QbjiiuuMAzj2ORq/vz57vtnz55tAMbRo0dP+rpONbkqy3nnnWfcc8897q9vueUWY+TIke6vn3vuOaNly5aGw+EwDMMwkpKSjCeffLLUNT744AOjcePGpWK46667TvvcZU2urrrqKvfXDofDaNCggfHaa68ZhmEYr7/+ulG3bt1Sr/+1114rNbl6/PHHjeHDh5d6nl27dhmAsXXrVsMwDKOoqMjo1q2bcemllxodO3Y0brrpptPGKiIiUpNp3uSkeZPmTSKeUk8pEXEbPHgwr732WqljK1eu5KqrrjrpYzZv3sy///3vUsf69evHwoULAcjOzmbfvn306dPHfX9wcDBnnnmmeyn6tm3bKCgoYNiwYaWuU1xcTPfu3Usd69Kli/t248aNAdi/fz8tWrQo78t0s9vtPPnkk3z++efs2bOH4uJiioqKiIyMdJ9z00030atXL/bs2UPTpk2ZOXMm1157LRaLBYB169bx888/l1pabrfbKSwspKCgwH2tM888s8Lx/f31WiwWGjVqxP79+wHn2Hfp0oXw8HD3Of369Sv1+HXr1rFw4UKioqJOuPb27dtp27YtoaGhfPTRR3Tp0oX4+HimTZtWqVhFRERqEs2bNG/SvEnEc0pKiYhbrVq1aN26dalju3fv9vnz5uXlATB79myaNm1a6r6wsLBSXx/f6NI1wXE4HJV63meffZYXX3yRF154gTPOOINatWpx1113UVxc7D6ne/fudO3alffff5/hw4ezceNGZs+eXSr2yZMnM2bMmBOuf/ykp1atWpWK8e+NPS0WS4Veb15eHhdccAFPP/30Cfe5JqcAy5YtA+Dw4cMcPny40vGKiIjUFJo3ad6keZOI55SUEhGPdOjQgZUrV3LNNde4j61YscJ9OzY2lsaNG7Ny5UoGDhwIQElJCatWraJHjx4AdOzYkbCwMHbu3Mk555xTZbH//PPPXHTRRe6/aDocDv744w86duxY6rwbb7yRF154gT179jB06FCaN2/uvq9Hjx5s3br1hElpVejQoQMffPABhYWF7onc8WPviu+rr74iISGB4OCyf+Rv376du+++mzfffJPPPvuMcePGMX/+fKxW7YUhIiLiTZo3ad4kIqXpO0dEPHLnnXfyzjvv8O677/LHH3/wyCOPsHHjxhPOeeqpp/jmm2/YsmULt956K1lZWe77o6Oj+c9//sPdd9/Ne++9x/bt21m9ejUvv/wy7733nscxpqamsnbt2lIf+fn5tGnThuTkZJYtW8bmzZv517/+VebOKVdeeSW7d+/mzTff5Prrry9138MPP8z777/P5MmT2bhxI5s3b+bTTz/lwQcf9Dju07nyyiuxWCzcdNNNbNq0iTlz5vB///d/pc657bbbOHz4MFdccQW//vor27dv58cff+S6667Dbrdjt9u56qqrGDFiBNdddx3vvvsuv//+O88995zP4xcREalpNG/SvElEStNKKRHxyGWXXcb27duZOHEihYWFjB07lltuuYUff/zRfc4999zDvn37GDduHFarleuvv56LL76Y7Oxs9zmPP/449evXZ+rUqezYsYO4uDh69OjB/fff73GMEyZMOOHYTz/9xIMPPsiOHTsYMWIEkZGR3HzzzYwePbpUXOD8q+XYsWOZPXs2o0ePLnXfiBEj+P7773nsscd4+umnCQkJoX379tx4440ex306UVFRfPfdd/z73/+me/fudOzYkaeffpqxY8e6z2nSpAk///wz9913H8OHD6eoqIj4+HjOPfdcrFYrjz/+OOnp6Xz//feAc2n6G2+8wRVXXMHw4cPp2rWrz1+HiIhITaF5k+ZNIlKaxXB1zBMRkZNKSkqiU6dOvPTSS2aHIiIiIuLXNG8SkfJSUkpE5BSOHDnCokWLuOSSS9i0aRPt2rUzOyQRERERv6R5k4hUlMr3REROoXv37hw5coSnn35aEysRERGRU9C8SUQqSiulRERERERERESkymn3PRERERERERERqXJKSomIiIiIiIiISJVTUkpERERERERERKqcklIiIiIiIiIiIlLllJQSEREREREREZEqp6SUiIiIiIiIiIhUOSWlRERERERERESkyikpJSIiIiIiIiIiVU5JKRERERERERERqXL/D/oId8DX+mDYAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, axes = plt.subplots(1, 2, figsize=(12, 5), sharex=True)\n", + "\n", + "axes[0].plot(max_adiffs_hidden_layers, label='new_token_0', color='blue')\n", + "axes[0].plot(max_adiffs_hidden_layers2, label=f'new_token_{new_token_index}', color='green')\n", + "axes[0].set_title('Max and Mean Absolute Difference')\n", + "axes[0].set_xlabel('Hidden Layer Index')\n", + "axes[0].set_ylabel('Max Absolute Difference')\n", + "axes[0].legend()\n", + "axes[0].grid(True)\n", + "\n", + "axes[1].plot(max_adiffs_hidden_layers, label='new_token_0', color='blue')\n", + "axes[1].plot(max_adiffs_hidden_layers3, label=f'new_token_{new_token_index1}', color='green')\n", + "axes[1].set_title('Max and Mean Absolute Difference')\n", + "axes[1].set_xlabel('Hidden Layer Index')\n", + "axes[1].set_ylabel('Max Absolute Difference')\n", + "axes[1].legend()\n", + "axes[1].grid(True)\n", + "\n", + "\n", + "\n", + "plt.title('Per-layer Max Absolute Differences')\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 144, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2389, 28, 527, 26648, 357, 2258, 260, 3712, 282, 260, 635, 4062, 12903, 30]\n", + "[2389, 284, 260, 1439, 357, 3593, 30, 378, 540, 6207, 260, 1569, 28, 260]\n" + ] + } + ], + "source": [ + "print(hf_tokens_bf16[106:120])\n", + "print(fm_tokens_b16[106:120])" + ] + }, + { + "cell_type": "code", + "execution_count": 145, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2389, 284, 260, 1439, 357, 3593, 30, 378, 540, 6207, 260, 1569, 28, 260]\n", + "[2389, 284, 260, 1439, 357, 3593, 30, 378, 540, 6207, 260, 1569, 28, 260]\n" + ] + } + ], + "source": [ + "print(hf_tokens[106:120])\n", + "print(fm_tokens[106:120])" + ] + }, + { + "cell_type": "code", + "execution_count": 136, + "metadata": {}, + "outputs": [], + "source": [ + "hf_tokens_bf16 = hf_tokens\n", + "fm_tokens_b16 = fm_tokens" + ] + }, + { + "cell_type": "code", + "execution_count": 152, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1001" + ] + }, + "execution_count": 152, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "min(len(hf_tokens)+1 if ab[0] == ab[1] else i for i, ab in enumerate(zip(hf_tokens, fm_tokens)))" + ] + }, + { + "cell_type": "code", + "execution_count": 153, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "107" + ] + }, + "execution_count": 153, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "min(len(hf_tokens)+1 if ab[0] == ab[1] else i for i, ab in enumerate(zip(hf_tokens, hf_tokens_bf16)))" + ] + }, + { + "cell_type": "code", + "execution_count": 154, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "174" + ] + }, + "execution_count": 154, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "min(len(hf_tokens)+1 if ab[0] == ab[1] else i for i, ab in enumerate(zip(fm_tokens, fm_tokens_b16)))" + ] + }, + { + "cell_type": "code", + "execution_count": 151, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1001" + ] + }, + "execution_count": 151, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "min(len(hf_tokens)+1 if ab[0] == ab[1] else i for i, ab in enumerate(zip(hf_tokens, fm_tokens)))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "fastllm", + "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": 2 +} diff --git a/classes_fast_llm.jpg b/classes_fast_llm.jpg new file mode 100644 index 00000000..ea418943 Binary files /dev/null and b/classes_fast_llm.jpg differ diff --git a/examples/qwen_evaluate.yaml b/examples/qwen_evaluate.yaml new file mode 100644 index 00000000..c1890ad0 --- /dev/null +++ b/examples/qwen_evaluate.yaml @@ -0,0 +1,77 @@ +training: + train_iters: 100_000 + logs: + interval: 10 + evaluations: + gsm8k: + type: lm_eval + cli_args: + - --tasks + - gsm8k + - --output_path + - /mnt/checkpoints/test/denis/qwen_eval_experiment/lm_eval + # stack_3b: + # iterations: 10 + # interval: 10 + # fineweb: + # iterations: 10 + # interval: 10 + checkpoint: + interval: 1000 + keep: 5 + test_iters: 0 + export: # (1)! + format: llama + interval: 20_000 +batch: + micro_batch_size: 16 + sequence_length: 4096 + batch_size: 16 +data: + tokenizer: + path: /mnt/checkpoints/pretrained_models/Qwen2-1.5B-Instruct + bos_token: "<|endoftext|>" + datasets: + # Bad dataset they are tokenized with different tokenizer, then llama + training: + type: file + path: /mnt/datasets/test/denis/fineweb_the_stack_3b.yaml + stack_3b: + type: memmap + path: /mnt/datasets/data_collections/the_stack_3b/tokens/stack_3b/default/train/99 + fineweb: + type: memmap + path: /mnt/datasets/data_collections/standalone_datasets/tokens/HuggingFaceFW/fineweb/default/train/9_1000 +optimizer: + weight_decay: 0.1 + beta_1: 0.9 + beta_2: 0.95 + learning_rate: + base: 1.0e-04 # (3)! + minimum: 1.0e-05 + decay_style: cosine + decay_iterations: 100_000 + warmup_iterations: 2000 +pretrained: # (4)! + format: qwen2 + path: /mnt/checkpoints/pretrained_models/Qwen2-1.5B-Instruct + model_weights: yes # (5)! +model: + base_model: + transformer: + use_flash_attention: yes + cross_entropy_impl: fused + multi_stage: + zero_stage: 2 + distributed: + training_dtype: bf16 + +run: + experiment_dir: "/mnt/checkpoints/test/denis/qwen_eval_experiment" + +# training: +# logs: +# interval: 10 +# wandb: +# project_name: ${job.project_name} +# group_name: ${job.project_version} \ No newline at end of file diff --git a/examples/smol_evaluate.yaml b/examples/smol_evaluate.yaml new file mode 100644 index 00000000..7c06ffed --- /dev/null +++ b/examples/smol_evaluate.yaml @@ -0,0 +1,77 @@ +training: + train_iters: 100_000 + logs: + interval: 10 + evaluations: + gsm8k: + type: lm_eval + cli_args: + - --tasks + - gsm8k + - --output_path + - /mnt/checkpoints/test/denis/smol_eval_experiment/lm_eval + # stack_3b: + # type: loss + # iterations: 10 + # interval: 10 + # fineweb: + # iterations: 10 + # interval: 10 + checkpoint: + interval: 1000 + keep: 5 + test_iters: 0 + export: # (1)! + format: llama + interval: 20_000 +batch: + micro_batch_size: 16 + sequence_length: 4096 + batch_size: 16 +data: + tokenizer: + path: /mnt/checkpoints/pretrained_models/SmolLM2-135M-Instruct + datasets: + # Bad dataset they are tokenized with different tokenizer, then llama + training: + type: file + path: /mnt/datasets/test/denis/fineweb_the_stack_3b.yaml + stack_3b: + type: memmap + path: /mnt/datasets/data_collections/the_stack_3b/tokens/stack_3b/default/train/99 + fineweb: + type: memmap + path: /mnt/datasets/data_collections/standalone_datasets/tokens/HuggingFaceFW/fineweb/default/train/9_1000 +optimizer: + weight_decay: 0.1 + beta_1: 0.9 + beta_2: 0.95 + learning_rate: + base: 1.0e-04 # (3)! + minimum: 1.0e-05 + decay_style: cosine + decay_iterations: 100_000 + warmup_iterations: 2000 +pretrained: # (4)! + format: llama + path: /mnt/checkpoints/pretrained_models/SmolLM2-135M-Instruct/ + model_weights: yes # (5)! +model: + base_model: + transformer: + use_flash_attention: yes + cross_entropy_impl: fused + multi_stage: + zero_stage: 2 + distributed: + training_dtype: bf16 + +run: + experiment_dir: "/mnt/checkpoints/test/denis/smol_eval_experiment" + +# training: +# logs: +# interval: 10 +# wandb: +# project_name: ${job.project_name} +# group_name: ${job.project_version} \ No newline at end of file diff --git a/fast_llm/data/config.py b/fast_llm/data/config.py index 1586d370..4c041945 100644 --- a/fast_llm/data/config.py +++ b/fast_llm/data/config.py @@ -34,3 +34,8 @@ class TokenizerConfig(Config): desc="Path to the tokenizer file.", hint=FieldHint.core, ) + bos_token: str | None = Field( + default=None, + desc="BOS token to use if the tokenizer doesn't define one; must be an existing token.", + hint=FieldHint.core, + ) diff --git a/fast_llm/data/tokenizer.py b/fast_llm/data/tokenizer.py index 28e105ee..bc801ed0 100644 --- a/fast_llm/data/tokenizer.py +++ b/fast_llm/data/tokenizer.py @@ -1,6 +1,6 @@ import numpy as np import torch -from transformers import PreTrainedTokenizerFast +from transformers import PreTrainedTokenizerFast, AutoTokenizer from fast_llm.data.config import TokenizerConfig from fast_llm.engine.config_utils.run import log_main_rank @@ -13,9 +13,18 @@ class Tokenizer: def __init__(self, config: TokenizerConfig): log_main_rank(f"> loading tokenizer from {config.path} ...") - self.tokenizer: PreTrainedTokenizerFast = PreTrainedTokenizerFast.from_pretrained( - pretrained_model_name_or_path=config.path, errors="replace", max_len=None + # self.tokenizer: PreTrainedTokenizerFast = PreTrainedTokenizerFast.from_pretrained( + # pretrained_model_name_or_path=config.path, errors="replace", max_len=None + # ) + self.tokenizer = AutoTokenizer.from_pretrained( + pretrained_model_name_or_path=config.path, + errors="replace", + max_len=None, + trust_remote_code=True, + use_fast=True, # This is the flag you're asking about ) + if config.bos_token is not None: + self.tokenizer.bos_token = config.bos_token if self.tokenizer.eos_token_id is None: raise ValueError("Tokenizer does not have an EOS token.") if self.tokenizer.bos_token_id is None: diff --git a/fast_llm/engine/inference/config.py b/fast_llm/engine/inference/config.py index d4b46bcc..c18daa48 100644 --- a/fast_llm/engine/inference/config.py +++ b/fast_llm/engine/inference/config.py @@ -91,7 +91,8 @@ def __eq__(self, other) -> bool: def to_dict(self) -> dict[str, typing.Any]: out = super().to_dict() - out["fast_llm_config"] = self.fast_llm_config.to_dict(verbose=FieldVerboseLevel.everything) + if self.fast_llm_config is not None: + out["fast_llm_config"] = self.fast_llm_config.to_dict(verbose=FieldVerboseLevel.everything) return out def to_diff_dict(self) -> dict[str, typing.Any]: diff --git a/fast_llm/engine/inference/huggingface.py b/fast_llm/engine/inference/huggingface.py index 196310b4..a39345a3 100644 --- a/fast_llm/engine/inference/huggingface.py +++ b/fast_llm/engine/inference/huggingface.py @@ -2,16 +2,22 @@ import pathlib import typing +import torch import transformers.modeling_outputs +import transformers.generation.utils from fast_llm.engine.checkpoint.config import CheckpointLoadConfig, FastLLMCheckpointFormat from fast_llm.engine.inference.config import HuggingfaceModelConfig from fast_llm.engine.inference.runner import InferenceRunner from fast_llm.engine.multi_stage.config import StageMode from fast_llm.engine.multi_stage.fast_llm_model import FastLLMModel +from fast_llm.engine.schedule.config import BatchConfig, ScheduleConfig +from fast_llm.engine.schedule.runner import ScheduleRunner +from fast_llm.engine.schedule.schedule import Schedule +from fast_llm.engine.training.config import TrainerConfig -class HuggingfacePreTrainedModel(transformers.PreTrainedModel): +class HuggingfaceBaseModelForCausalLM(transformers.PreTrainedModel, transformers.generation.utils.GenerationMixin): config_class: typing.ClassVar[type[HuggingfaceModelConfig]] = HuggingfaceModelConfig runner_class: typing.ClassVar[type[InferenceRunner]] = InferenceRunner config: HuggingfaceModelConfig @@ -20,31 +26,84 @@ class HuggingfacePreTrainedModel(transformers.PreTrainedModel): # _supports_cache_class = False # _tied_weights_keys = [] - def __init__(self, config: HuggingfaceModelConfig, fast_llm_model: FastLLMModel, **kwargs): + def __init__( + self, + config: HuggingfaceModelConfig, + fast_llm_model: FastLLMModel, + trainer_config: TrainerConfig | None = None, + runner: ScheduleRunner | None = None, + **kwargs, + ): + """ + Initializes the HuggingfaceBaseModelForCausalLM either in standalone mode (single GPU inference) + or integrated training mode (with runner from training loop). + + - If `trainer_config` and `runner` are both provided → assumes training mode. + - If both are omitted → assumes standalone mode with default configs. + - Any other combination will raise. + """ assert self.runner_class.model_class.config_class is config.model_config_class assert config.fast_llm_config is fast_llm_model.config assert isinstance(config, self.config_class) + # The HF constructor performs a deep copy of the config, + # but config.fast_llm_config may contain non-picklable items like process groups. + # Temporarily remove it before the call and restore it afterward. + fast_llm_config = config.fast_llm_config + config.fast_llm_config = None super().__init__(config, **kwargs) + config.fast_llm_config = fast_llm_config + + self._inference_runner = self.runner_class(fast_llm_model, trainer_config, runner) - self._inference_runner = self.runner_class(fast_llm_model) - if not fast_llm_model.is_setup: - fast_llm_model.setup(mode=StageMode.inference) + # A model can be created from pretrained which setup it in the current HF wrapper api + # or set from training loop and also is setup, so, do not accept not setup model + assert fast_llm_model.is_setup + # if not fast_llm_model.is_setup: + # fast_llm_model.setup(distributed=distributed, mode=StageMode.inference) self._inference_runner.setup() + # Transformers needs to be able to inspect the base model. self.fast_llm_base_model = fast_llm_model.base_model - # TODO: Support distributed models? - assert fast_llm_model.config.distributed.world_size == 1 + # # TODO: Support distributed models? + # assert fast_llm_model.config.distributed.world_size == 1 with transformers.modeling_utils.no_init_weights(): self.post_init() + def forward( + self, + input_ids: torch.Tensor | None = None, + attention_mask: torch.Tensor | None = None, + position_ids: torch.Tensor | None = None, + past_key_values=None, + inputs_embeds: torch.FloatTensor | None = None, + labels: torch.LongTensor | None = None, + use_cache: bool | None = None, + output_attentions: bool | None = None, + output_hidden_states: bool | None = None, + return_dict: bool | None = None, + ) -> tuple | transformers.modeling_outputs.CausalLMOutputWithPast: + # Meant to be overridden in derived classes + raise NotImplementedError() + + @classmethod + def from_fast_llm_model_in_training( + cls, fast_llm_model: FastLLMModel, trainer_config: TrainerConfig, runner: ScheduleRunner, **kwargs + ): + config = cls.config_class(fast_llm_model.config) + return cls(config, fast_llm_model, trainer_config=trainer_config, runner=runner, **kwargs) + @classmethod def from_pretrained( cls, pretrained_model_name_or_path: str | os.PathLike | CheckpointLoadConfig, - *, - mode: StageMode = StageMode.inference, + *updates: dict[str | tuple[str, ...], typing.Any], + optimizer_state_names: tuple[str, ...] | None = None, + # setup: bool = True, + mode: StageMode = StageMode.training, + use_cpu: bool = False, + stage_filter: set | None = None, **kwargs, ) -> typing.Self: # Pretrained config. @@ -54,18 +113,23 @@ def from_pretrained( format=FastLLMCheckpointFormat, ) - updates = {} - torch_dtype = kwargs.pop("torch_dtype", None) - if torch_dtype is not None: - updates[("distributed", "training_dtype")] = torch_dtype - # Create the model + # always set up model and crate distributed instance internally for now fast_llm_model = cls.runner_class.model_class.from_pretrained( - pretrained_model_name_or_path, updates, mode=mode + pretrained_model_name_or_path, + *updates, + optimizer_state_names=optimizer_state_names, + # setup=setup, + mode=mode, + use_cpu=use_cpu, + stage_filter=stage_filter, ) - config = cls.config_class(fast_llm_model.config) + config = cls.config_class(fast_llm_model.config) return cls(config, fast_llm_model, **kwargs) def _init_weights(self, module) -> None: raise NotImplementedError(module) + + def can_generate(self): + return True diff --git a/fast_llm/engine/inference/runner.py b/fast_llm/engine/inference/runner.py index 30f836b7..7e608e23 100644 --- a/fast_llm/engine/inference/runner.py +++ b/fast_llm/engine/inference/runner.py @@ -7,27 +7,46 @@ from fast_llm.engine.schedule.config import BatchConfig, ScheduleConfig from fast_llm.engine.schedule.runner import ScheduleRunner from fast_llm.engine.schedule.schedule import Schedule +from fast_llm.engine.training.config import TrainerConfig class InferenceRunner(abc.ABC): model_class: typing.ClassVar[type[FastLLMModel]] = FastLLMModel batch_config_class: typing.ClassVar[type[BatchConfig]] = BatchConfig - def __init__(self, fast_llm_model: FastLLMModel): + def __init__( + self, + fast_llm_model: FastLLMModel, + trainer_config: TrainerConfig | None = None, + runner: ScheduleRunner | None = None, + ): + has_training_args = trainer_config is not None and runner is not None + has_partial_args = (trainer_config is None) != (runner is None) + if has_partial_args: + raise ValueError("Both trainer_config and runner must be provided together or not at all.") + assert isinstance(fast_llm_model, self.model_class) self._fast_llm_model = fast_llm_model - # We only need a basic schedule and don't care about dimensions. - self._schedule_config = ScheduleConfig() - # TODO: Sort things out. - with NoAutoValidate(): - self._batch_config = self.batch_config_class() - self._batch_config.setup(self._fast_llm_model.config.distributed) - self._batch_config.validate() - self._runner = ScheduleRunner( - config=self._schedule_config, - multi_stage=self._fast_llm_model, - distributed_config=self._fast_llm_model.config.distributed, - ) + if has_training_args: + self._trainer_config = trainer_config + self._schedule_config = self._trainer_config.schedule + self._batch_config = self._trainer_config.batch + self._runner = runner + # External runner from training loop must be already setup + assert runner._is_setup + else: + # We only need a basic schedule and don't care about dimensions. + self._schedule_config = ScheduleConfig() + # TODO: Sort things out. + with NoAutoValidate(): + self._batch_config = self.batch_config_class() + self._batch_config.setup(self._fast_llm_model.config.distributed) + self._batch_config.validate() + self._runner = ScheduleRunner( + config=self._schedule_config, + multi_stage=self._fast_llm_model, + distributed_config=self._fast_llm_model.config.distributed, + ) # TODO: Random state? (Distributed.set_step) self._schedule = Schedule( multi_stage=self._fast_llm_model, @@ -42,7 +61,8 @@ def fast_llm_model(self) -> FastLLMModel: return self._fast_llm_model def setup(self): - self._runner.setup(self._fast_llm_model.distributed) + if not self._runner._is_setup: + self._runner.setup(self._fast_llm_model.distributed) def forward( self, input_, kwargs: dict, *, iteration: int = 1, return_metrics: bool = False diff --git a/fast_llm/engine/multi_stage/config.py b/fast_llm/engine/multi_stage/config.py index 69bf3695..174f4a56 100644 --- a/fast_llm/engine/multi_stage/config.py +++ b/fast_llm/engine/multi_stage/config.py @@ -30,7 +30,7 @@ from fast_llm.utils import Assert if typing.TYPE_CHECKING: - from fast_llm.engine.inference.model import HuggingfacePreTrainedModel + from fast_llm.engine.inference.model import HuggingfaceBaseModelForCausalLM from fast_llm.engine.multi_stage.fast_llm_model import FastLLMModel logger = logging.getLogger(__name__) @@ -247,7 +247,7 @@ def get_model_class(cls) -> type["FastLLMModel"]: raise NotImplementedError @classmethod - def get_huggingface_model_class(cls) -> type["HuggingfacePreTrainedModel"]: + def get_huggingface_model_for_causal_lm_class(cls) -> type["HuggingfaceBaseModelForCausalLM"]: raise NotImplementedError @classmethod diff --git a/fast_llm/engine/multi_stage/stage.py b/fast_llm/engine/multi_stage/stage.py index 675e878b..eb37c292 100644 --- a/fast_llm/engine/multi_stage/stage.py +++ b/fast_llm/engine/multi_stage/stage.py @@ -13,6 +13,9 @@ from fast_llm.tensor import ParameterMeta, TensorMeta, accumulate_gradient from fast_llm.utils import Assert +if typing.TYPE_CHECKING: + from fast_llm.core.distributed import ProcessGroup + logger = logging.getLogger(__name__) @@ -111,6 +114,15 @@ def forward( metrics, ) self._log_layer_forward(output, kwargs, i) + + # TODO: very slow and memory consuming, only use for debugging for now + # TODO: decide if and how we want to return + # HF transformer style details from forward properly + if "output_hidden_states" in kwargs and kwargs["output_hidden_states"]: + kwargs["hidden_states"][self._layer_range[i]] = { + "layer_type": type(layer).__name__, + "tensor": self._get_global_output_tensor(i, output), + } return None if output is None else output.detach(), (input_, output) def backward( @@ -185,6 +197,16 @@ def invalidate_buffer(self) -> None: for fsdp in self._fsdps: fsdp.invalidate_buffer() + @torch._dynamo.disable # noqa + def _get_global_output_tensor( + self, + i: int, + tensor: torch.Tensor, + ) -> typing.Tuple[torch.Tensor, bool]: + meta = self._meta_outputs[i] + tensor, _ = meta.local_to_global(tensor, distributed=self._distributed) + return tensor + def _log_layer_forward(self, output: torch.Tensor, kwargs: dict[str, typing.Any], i: int) -> None: if ( self._config.debug_tensor_parallel diff --git a/fast_llm/engine/schedule/runner.py b/fast_llm/engine/schedule/runner.py index 8eca4559..94991915 100644 --- a/fast_llm/engine/schedule/runner.py +++ b/fast_llm/engine/schedule/runner.py @@ -396,8 +396,11 @@ def _recv(self, context: BatchContext, step: Step) -> None: self._record_event(context, EventType.compute_wait_pipe, step) def _forward(self, context: BatchContext, step: Step) -> None: + input = self._get_forward_input(context, step) + if not "hidden_states" in context.batch[step.data_index]: + context.batch[step.data_index]["hidden_states"] = {} output, grad_context = self._stages[step.stage].forward( - self._get_forward_input(context, step), + input, context.batch[step.data_index], losses=context.losses, metrics=context.metrics, diff --git a/fast_llm/engine/training/config.py b/fast_llm/engine/training/config.py index 8b4cadc3..8373397e 100644 --- a/fast_llm/engine/training/config.py +++ b/fast_llm/engine/training/config.py @@ -28,11 +28,12 @@ from fast_llm.engine.optimizer.config import OptimizerConfig from fast_llm.engine.schedule.config import BatchConfig, ScheduleConfig from fast_llm.profile import ProfilingConfig -from fast_llm.utils import Assert +from fast_llm.utils import Assert, Registry if typing.TYPE_CHECKING: from fast_llm.engine.inference.runner import InferenceRunner from fast_llm.engine.training.trainer import Trainer + from fast_llm.engine.training.evaluator import Evaluation, EvaluationLoss, EvaluationHarness @config_class() @@ -154,6 +155,75 @@ class WandbConfig(Config): @config_class() class EvaluationConfig(IntervalConfig): + _abstract: typing.ClassVar[bool] = True + # TODO: Generalize dynamic types? + _registry: typing.ClassVar[Registry[str, type["EvaluationConfig"]]] = Registry[str, type["EvaluationConfig"]]( + "evaluation_class", {} + ) + type_: typing.ClassVar[str | None] = None + type: str | None = Field( + default=None, + desc="The type of evaluation.", + hint=FieldHint.core, + ) + + @classmethod + def get_evaluation_class(cls) -> "Evaluation": + raise NotImplementedError + + def _validate(self) -> None: + if self.type is None: + self.type = self.type_ + # Should be handled in `from_dict`, but can fail if instantiating directly. + Assert.eq(self.type, self.__class__.type_) + super()._validate() + + @classmethod + def _from_dict( + cls, + default: dict[str, typing.Any], + strict: bool = True, + flat: bool = False, + ) -> typing.Self: + type_ = default.get("type") + if type_ is None: + # TODO: Remove in version 0.* — this is for backward compatibility. + # If 'type' is not provided, it falls back to 'loss'. + type_ = "loss" + default["type"] = type_ + actual_cls = EvaluationLossConfig + # actual_cls = cls + else: + if type_ not in cls._registry: + raise ValueError( + f"Unknown {cls._registry.name} type {type_}." f" Available types: {list(cls._registry.keys())}" + ) + actual_cls = cls._registry[type_] + Assert.custom(issubclass, actual_cls, cls) + if actual_cls == cls: + return super()._from_dict(default, strict=strict, flat=flat) + else: + return actual_cls._from_dict(default, strict=strict, flat=flat) + + def __init_subclass__(cls) -> None: + if cls._abstract and cls.type_ is not None: + # Abstract classes should not have a `type_` + raise ValueError(f"Abstract class {cls.__name__} has type = {cls.type_}, expected None.") + if cls.type_ is not None: + if cls.type_ in cls._registry: + raise ValueError( + f"Registry {cls._registry.name} already contains type {cls.type_}." + f" Make sure all classes either have a unique or `None` type." + ) + EvaluationConfig._registry[cls.type_] = cls + super().__init_subclass__() + + +@config_class() +class EvaluationLossConfig(EvaluationConfig): + _abstract: typing.ClassVar[bool] = False + type_: typing.ClassVar[str | None] = "loss" + interval = FieldUpdate( desc="The number of training iterations between each evaluation phase." " Setting to None will disable evaluation." @@ -170,6 +240,59 @@ def get_iteration_count(self, training_iterations: int, extra_evaluations: int = # Number of completed validation iterations return (self.get_count(training_iterations) + extra_evaluations) * self.iterations if self.enabled() else 0 + @classmethod + def get_evaluation_class(cls) -> type["EvaluationLoss"]: + from fast_llm.engine.training.evaluator import EvaluationLoss + + return EvaluationLoss + + +@config_class() +class EvaluationHarnessConfig(EvaluationConfig): + _abstract: typing.ClassVar[bool] = False + type_: typing.ClassVar[str | None] = "lm_eval" + + interval = FieldUpdate( + desc="The number of training iterations between each evaluation phase." + " Setting to None will disable evaluation." + ) + offset = FieldUpdate(desc="Offset for the first evaluation phase.") + + cli_args: list[str] = Field( + default_factory=lambda: [], + desc="lm_eval CLI arguments, excluding those related to model, wandb, batch sizes, and device.", + ) + + truncation: bool = Field( + default=False, + desc="Whether to use truncation during tokenization (useful when inputs exceed model's max length);" + " passed to the Fast-LLM lm_eval model wrapper.", + ) + + logits_cache: bool = Field( + default=True, + desc="Whether to enable logits caching for speedup and avoiding recomputation during repeated evaluations;" + " passed to the Fast-LLM lm_eval model wrapper.", + ) + + add_bos_token: bool = Field( + default=False, + desc="Whether to prepend a beginning-of-sequence (BOS) token, required for some models like LLaMA;" + " passed to the Fast-LLM lm_eval model wrapper.", + ) + + prefix_token_id: int | None = Field( + default=None, + desc="Token ID to use as a prefix to the input (e.g., for control codes or prompts);" + " passed to the Fast-LLM lm_eval model wrapper.", + ) + + @classmethod + def get_evaluation_class(cls) -> type["EvaluationHarness"]: + from fast_llm.engine.training.evaluator import EvaluationHarness + + return EvaluationHarness + @config_class() class TrainingCheckpointBaseConfig(IntervalConfig): diff --git a/fast_llm/engine/training/evaluator.py b/fast_llm/engine/training/evaluator.py new file mode 100644 index 00000000..0abf2115 --- /dev/null +++ b/fast_llm/engine/training/evaluator.py @@ -0,0 +1,419 @@ +import abc +import logging +import math +import pathlib +import shutil +import time +import typing + +import torch + +from fast_llm.config import Configurable +from fast_llm.core.distributed import safe_barrier +from fast_llm.data.data.abstract import Data +from fast_llm.engine.config_utils.run import Run, is_main_rank, log_main_rank, log_pipeline_parallel_main_rank +from fast_llm.engine.distributed.config import PhaseType +from fast_llm.engine.distributed.distributed import Distributed +from fast_llm.engine.multi_stage.fast_llm_model import FastLLMModel + +from fast_llm.engine.schedule.runner import ScheduleRunner +from fast_llm.engine.schedule.schedule import Schedule +from fast_llm.engine.training.config import ( + TrainerConfig, + EvaluationConfig, + EvaluationLossConfig, + EvaluationHarnessConfig, +) +from fast_llm.engine.training.wandb import Wandb +from fast_llm.logging import format_metrics, get_memory_usage_mib, log_memory_usage +from fast_llm.utils import Assert +from fast_llm.engine.training.lm_eval.fast_llm_wrapper import FastLLMWrapper +from fast_llm.engine.training.lm_eval.utils import prepare_lm_eval_simple_eval_params, process_lm_eval_results + +# from fast_llm.engine.training.lm_eval.evaluator import simple_evaluate as lm_eval_simple_evaluate +from lm_eval.evaluator import simple_evaluate as lm_eval_simple_evaluate + +logger = logging.getLogger(__name__) + + +class Evaluation[ConfigType: EvaluationConfig](Configurable[ConfigType], abc.ABC): + config_class: typing.ClassVar[type[EvaluationConfig]] = EvaluationConfig + + _is_setup: bool = False + + @classmethod + def build( + cls, + name: str, + eval_config: EvaluationLossConfig, + trainer_config: TrainerConfig, + get_tflops_func: callable, + ) -> "Evaluation": + return cls( + name=name, + eval_config=eval_config, + trainer_config=trainer_config, + get_tflops_func=get_tflops_func, + ) + + def setup( + self, + distributed: Distributed, + run: Run, + multi_stage: FastLLMModel, + runner: ScheduleRunner, + data: Data, + ) -> None: + # TODO: check if objects passed are actually set up themselves, if appropriate + self._distributed = distributed + self._run = run + self._runner = runner + self._multi_stage = multi_stage + self._data = data + + @abc.abstractmethod + def run( + self, + done: bool, + completed_steps: int, + consumed_samples: int, + consumed_tokens: int, + ) -> tuple[dict[str, any], str | None]: ... + + @abc.abstractmethod + def get_dataset_samples(self) -> tuple[str, int] | None: + """ + Returns the name and number of required samples in a dataset, + or None if the evaluation does not rely on Fast-LLM data or + if the evaluation is skipped for this run. + """ + + +class EvaluationLoss[ConfigType: EvaluationLossConfig](Evaluation[ConfigType]): + config_class: typing.ClassVar[type[EvaluationLossConfig]] = EvaluationLossConfig + + def __init__( + self, + name: str, + eval_config: EvaluationLossConfig, + trainer_config: TrainerConfig, + get_tflops_func: callable, + ): + self._name = name + self._eval_config = eval_config + self._trainer_config = trainer_config + self._get_tflops_func = get_tflops_func + + steps = self._eval_config.get_iteration_count( + self._trainer_config.training.train_iters, + # There may be an extra evaluation after the last training step. + not self._eval_config.enabled(self._trainer_config.training.train_iters), + ) + + self._samples = self._trainer_config.batch.batch_size * steps if steps > 0 else None + + self._evaluation_iterator = None + + def setup( + self, + distributed: Distributed, + run: Run, + multi_stage: FastLLMModel, + runner: ScheduleRunner, + data: Data, + ) -> None: + super().setup(distributed, run, multi_stage, runner, data) + self._loss_defs = self._multi_stage.base_model.loss_defs + # Setup the schedule + self._schedule = Schedule( + multi_stage=self._multi_stage, + batch_config=self._trainer_config.batch, + schedule_config=self._trainer_config.schedule, + distributed_config=self._trainer_config.model.distributed, + phase=PhaseType.validation, + ) + + self._is_setup = True + + def get_dataset_samples(self) -> tuple[str, int] | None: + if self._samples is None: + return None + return self._name, self._samples + + def run( + self, + done: bool, + completed_steps: int, + consumed_samples: int, + consumed_tokens: int, + ) -> tuple[dict[str, any], str | None]: + assert self._is_setup + metrics = {} + formatted_metrics = None + if self._samples is not None and (done or self._eval_config.enabled(completed_steps)): + + if self._evaluation_iterator is None: + self._evaluation_iterator = self._get_data_iterator( + self._get_completed_evaluation_steps(completed_steps) + ) + # TODO: formatting metric category as Validation.evaluation_dataset_name + # maybe format each metric with evaluation_dataset_name prefix instead? + # TODO: setting performance metrics per evaluation dataset + # maybe to set aggregate performance metrics for all evaluations datasets? + metric_key = f"{PhaseType.validation.value}.{self._name}" + metrics[metric_key] = self._evaluate_loss( + data_iterator=self._evaluation_iterator, + phase=PhaseType.validation, + num_iters=self._eval_config.iterations, + begin_iter=self._get_completed_evaluation_steps(completed_steps), + completed_steps=completed_steps, + consumed_samples=consumed_samples, + consumed_tokens=consumed_tokens, + ) + formatted_metrics = format_metrics( + metrics[metric_key], + self._loss_defs, + PhaseType.validation, + dataset_name=self._name, + ) + + return metrics, formatted_metrics + + def _evaluate_loss( + self, + *, + data_iterator: typing.Iterator, + phase: PhaseType, + num_iters: int, + completed_steps: int, + consumed_samples: int, + consumed_tokens: int, + begin_iter: int = 0, + ) -> dict[str, float | int]: + full_phase_name = f"{phase.value}_{self._name}" + safe_barrier(self._distributed.world_group, f"{full_phase_name} begin") + begin_time = time.perf_counter() + total_losses = {loss_def.name: 0.0 for loss_def in self._loss_defs} + for iter_ in range(num_iters): + iter_losses, _, _ = self._runner.run_step(data_iterator, self._schedule, iteration=begin_iter + iter_) + for name, value in iter_losses.items(): + total_losses[name] += value + self._run.save_logged_tensors(f"{full_phase_name}_{completed_steps}_{iter_}") + + safe_barrier( + self._distributed.world_group, + f"{full_phase_name} end", + ) + end_time = time.perf_counter() + time_per_iteration = (end_time - begin_time) / num_iters + model_tflops, hardware_tflops = self._get_tflops_func(phase, time_per_iteration) + # TODO add other relevant eval metrics + metrics = { + "train_iters": self._trainer_config.training.train_iters, + "batch_size": self._trainer_config.batch.batch_size, + "iteration": completed_steps, + **{name: (value / num_iters) for name, value in total_losses.items()}, + "consumed_samples": consumed_samples, + "consumed_tokens": consumed_tokens, + "step_time_ms": time_per_iteration * 1000, + "model_tflops": model_tflops, + "hardware_tflops": hardware_tflops, + "tokens_per_sec_per_gpu": ( + (self._trainer_config.batch.sequence_length * self._trainer_config.batch.batch_size) + / self._trainer_config.model.distributed.world_size + / time_per_iteration + ), + **get_memory_usage_mib(), + } + + return metrics + + def _get_completed_evaluation_steps(self, completed_steps: int) -> int: + # Number of evaluations steps performed before the current step + return self._eval_config.get_iteration_count(completed_steps - 1) + + def _get_data_iterator( + self, completed_steps: int = 0, prefetch_factor: int | None = None + ) -> typing.Iterator[typing.Any]: + return self._data.get_iterator( + self._trainer_config.batch, + self._name, + consumed_samples=completed_steps * self._trainer_config.batch.batch_size, + num_workers=self._trainer_config.training.num_workers, + prefetch_factor=prefetch_factor, + ) + + +class EvaluationHarness[ConfigType: EvaluationHarnessConfig](Evaluation[ConfigType]): + config_class: typing.ClassVar[type[EvaluationHarnessConfig]] = EvaluationHarnessConfig + + def __init__( + self, + name: str, + eval_config: EvaluationHarnessConfig, + trainer_config: TrainerConfig, + get_tflops_func: callable, + ): + self._name = name + self._eval_config = eval_config + self._trainer_config = trainer_config + self._get_tflops_func = get_tflops_func + + def setup( + self, + distributed: Distributed, + run: Run, + multi_stage: FastLLMModel, + runner: ScheduleRunner, + data: Data, + ) -> None: + super().setup(distributed, run, multi_stage, runner, data) + + # TODO: pass mini and batch size of the same length for lm_eval not to crash during training + # or implement min batch sequential awareness in fas_llm_wrapper for lm_eval + self._hf_model = ( + self._multi_stage.config_class.get_huggingface_model_for_causal_lm_class().from_fast_llm_model_in_training( + self._multi_stage, self._trainer_config, self._runner + ) + ) + + # For reporting purposes, just to indicate it is from Fast-LLM + # as lm_eval.simple_evaluate will take it for results['config']['model'] + self._hf_model.config.name_or_path = type(self._hf_model).__name__ + + self._flm_wrapper = FastLLMWrapper( + model=self._hf_model, + tokenizer=self._data.tokenizer.tokenizer, + truncation=self._eval_config.truncation, + logits_cache=self._eval_config.logits_cache, + add_bos_token=self._eval_config.add_bos_token, + prefix_token_id=self._eval_config.prefix_token_id, + ) + self._is_setup = True + + def run( + self, + done: bool, + completed_steps: int, + consumed_samples: int, + consumed_tokens: int, + ) -> tuple[dict[str, any], str | None]: + assert self._is_setup + if not (done or self._eval_config.enabled(completed_steps)): + return {}, None + + # completed_steps is added to output_path like output_path/runs/run_index/completed_steps/ + + if self._run.is_main_rank: + args, simple_eval_kwargs = prepare_lm_eval_simple_eval_params( + self._eval_config.cli_args, completed_steps, self._run.index + ) + simple_eval_kwargs["model"] = self._flm_wrapper + + # Needed for reporting as batch_size is set from args not lm for reporting in evaluate + simple_eval_kwargs["batch_size"] = self._flm_wrapper.batch_size + simple_eval_kwargs["max_batch_size"] = self._flm_wrapper.max_batch_size + + # As of lm_eval commit 758c5ed891b1ca48acd8d3a0d309a827215796b7 + # Expected to be a string even if empty and not None in simple_evaluate + simple_eval_kwargs["model_args"] = "" + + results = lm_eval_simple_evaluate(**simple_eval_kwargs) + self._flm_wrapper.stop_workers() + + # Evaluation_tracker save expects model to be either string, but if model is passed + # LM wrapper needs to be deep copyable and json serializable + simple_eval_kwargs["evaluation_tracker"].general_config_tracker.model_source = ( + self._hf_model.config.name_or_path + ) + + if results is not None: + process_lm_eval_results( + args, + results, + simple_eval_kwargs["evaluation_tracker"], + completed_steps, + consumed_samples, + consumed_tokens, + ) + else: + self._flm_wrapper.worker_model_invoke() + + # TODO: do we need it here as self._flm_wrapper.stop_workers() and self._flm_wrapper.worker_model_invoke() + # already have barrier + safe_barrier(self._distributed.world_group, f"Evaluation Harness Run end") + + # lm_eval logs to disc, wandb and prints to screen itself + return {}, None + + def get_dataset_samples(self) -> tuple[str, int] | None: + return None + + +# NOTE: This is not a standalone runnable; it's a submodule of Trainer used for code encapsulation. +class Evaluator: + _is_setup: bool = False + + def __init__( + self, + config: TrainerConfig, + get_tflops_func: callable, + ): + self._config = config + self._evaluations = [ + eval_config.get_evaluation_class().build( + name=name, + eval_config=eval_config, + trainer_config=config, + get_tflops_func=get_tflops_func, + ) + for name, eval_config in config.training.evaluations.items() + ] + + def setup( + self, + distributed: Distributed, + run: Run, + multi_stage: FastLLMModel, + runner: ScheduleRunner, + data: Data, + wandb: Wandb, + ) -> None: + self._wandb = wandb + for evaluation in self._evaluations: + evaluation.setup(distributed, run, multi_stage, runner, data) + self._is_setup = True + + def get_datasets_samples(self) -> dict[str:int]: + return { + el[0]: el[1] + for el in (evaluation.get_dataset_samples() for evaluation in self._evaluations) + if el is not None + } + + def run( + self, + metrics: dict[str:any], + done: bool, + completed_steps: int, + consumed_samples: int, + consumed_tokens: int, + ): + assert self._is_setup + formatted_metrics = [] + for evaluation in self._evaluations: + this_metrics, this_formatted_metrics = evaluation.run( + done, completed_steps, consumed_samples, consumed_tokens + ) + if len(this_metrics) == 0: + continue + for k, v in this_metrics.items(): + metrics[k] = v + if this_formatted_metrics is not None: + formatted_metrics.append(this_formatted_metrics) + + if len(formatted_metrics) > 0: + formatted_metrics = "\n".join(formatted_metrics) + log_main_rank(formatted_metrics) + if self._config.training.wandb.alert.enabled(completed_steps): + self._wandb.alert("Validation results", formatted_metrics, "INFO") diff --git a/fast_llm/engine/training/lm_eval/evaluator.py b/fast_llm/engine/training/lm_eval/evaluator.py new file mode 100644 index 00000000..d1312b28 --- /dev/null +++ b/fast_llm/engine/training/lm_eval/evaluator.py @@ -0,0 +1,765 @@ +import itertools +import json +import logging +import random +import time +from collections import defaultdict +from typing import TYPE_CHECKING, List, Optional, Union + +import numpy as np +import torch + +import lm_eval.api.metrics +import lm_eval.api.registry +import lm_eval.api.task +import lm_eval.models +from lm_eval.caching.cache import delete_cache +from lm_eval.evaluator_utils import ( + consolidate_group_results, + consolidate_results, + get_sample_size, + get_subtask_list, + get_task_list, + prepare_print_tasks, + print_writeout, + run_task_tests, +) +from lm_eval.loggers import EvaluationTracker +from lm_eval.loggers.utils import add_env_info, add_tokenizer_info, get_git_commit_hash +from lm_eval.tasks import TaskManager, get_task_dict +from lm_eval.utils import ( + handle_non_serializable, + hash_string, + positional_deprecated, + setup_logging, + simple_parse_args_string, +) + + +if TYPE_CHECKING: + from lm_eval.api.model import LM + from lm_eval.api.task import Task + +eval_logger = logging.getLogger(__name__) + + +@positional_deprecated +def simple_evaluate( + model, + model_args: Optional[Union[str, dict]] = None, + tasks: Optional[List[Union[str, dict, object]]] = None, + num_fewshot: Optional[int] = None, + batch_size: Optional[Union[int, str]] = None, + max_batch_size: Optional[int] = None, + device: Optional[str] = None, + use_cache: Optional[str] = None, + cache_requests: bool = False, + rewrite_requests_cache: bool = False, + delete_requests_cache: bool = False, + limit: Optional[Union[int, float]] = None, + samples: Optional[dict] = None, + bootstrap_iters: int = 100000, + check_integrity: bool = False, + write_out: bool = False, + log_samples: bool = True, + evaluation_tracker: Optional[EvaluationTracker] = None, + system_instruction: Optional[str] = None, + apply_chat_template: Union[bool, str] = False, + fewshot_as_multiturn: bool = False, + gen_kwargs: Union[str, dict, None] = None, + task_manager: Optional[TaskManager] = None, + verbosity=None, + predict_only: bool = False, + random_seed: int = 0, + numpy_random_seed: int = 1234, + torch_random_seed: int = 1234, + fewshot_random_seed: int = 1234, + confirm_run_unsafe_code: bool = False, + metadata: Optional[dict] = None, +): + """Instantiate and evaluate a model on a list of tasks. + + :param model: Union[str, LM] + Name of model or LM object, see lm_eval.models.get_model + :param model_args: Optional[str, dict] + String or dict arguments for each model class, see LM.create_from_arg_string and LM.create_from_arg_object. + Ignored if `model` argument is a LM object. + :param tasks: list[Union[str, dict, Task]] + List of task names or Task objects. Task objects will be taken to have name task.EVAL_HARNESS_NAME if defined and type(task).__name__ otherwise. + :param num_fewshot: int + Number of examples in few-shot context + :param batch_size: int or str, optional + Batch size for model + :param max_batch_size: int, optional + Maximal batch size to try with automatic batch size detection + :param device: str, optional + PyTorch device (e.g. "cpu" or "cuda:0") for running models + :param use_cache: str, optional + A path to a sqlite db file for caching model responses. `None` if not caching. + :param cache_requests: bool, optional + Speed up evaluation by caching the building of dataset requests. `None` if not caching. + :param rewrite_requests_cache: bool, optional + Rewrites all the request cache if set to `True`. `None` if not desired. + :param delete_requests_cache: bool, optional + Deletes all the request cache if set to `True`. `None` if not desired. + :param limit: int or float, optional + Limit the number of examples per task (only use this for testing), If <1, limit is a percentage of the total number of examples. + :param samples: dictionary, optional + Dictionary indicating which examples should be tested in each task, e.g., {"mmlu_astronomy":[0,3,6],"mmlu_anatomy":[1,4,7,10]}. + :param bootstrap_iters: + Number of iterations for bootstrap statistics, used when calculating stderrs. set to 0 for no stderr calculations to be performed. + :param check_integrity: bool + Whether to run the relevant part of the test suite for the tasks + :param write_out: bool + If True, write out an example document and model input for checking task integrity + :param log_samples: bool + If True, write out all model outputs and documents for per-sample measurement and post-hoc analysis + :param system_instruction: str + System instruction to be applied to the prompt + :param apply_chat_template: Union[bool, str] + Specifies whether to apply a chat template to the prompt. + - If set to True, the default chat template is applied. + - If set to a string, applies the specified chat template by name. + Defaults to False (no chat template applied). + :param fewshot_as_multiturn: bool + Whether to provide the fewshot examples as a multiturn conversation or a single user turn. + :param gen_kwargs: dict or comma-separated string + Arguments for model generation + Ignored for all tasks with loglikelihood output_type + :param verbosity: str + Verbosity level for logging + :param predict_only: bool + If true only model outputs will be generated and returned. Metrics will not be evaluated + :param random_seed: int + Random seed for python's random module. If set to None, the seed will not be set. + :param numpy_random_seed: int + Random seed for numpy. If set to None, the seed will not be set. + :param torch_random_seed: int + Random seed for torch. If set to None, the seed will not be set. + :param fewshot_random_seed: int + Random seed for fewshot sampler random generator. If set to None, the seed of generator will be set to None. + :param metadata: dict + Additional metadata to be added to the task manager. Will get passed to the download function of the task. + + return + Dictionary of results + """ + if verbosity is not None: + setup_logging(verbosity=verbosity) + start_date = time.time() + + if limit is not None and samples is not None: + raise ValueError( + "Either 'limit' or 'samples' must be None, but both are not None." + ) + + if isinstance(model_args, str) and ( + "instruct" in model_args and not apply_chat_template + ): + eval_logger.warning( + "Instruct model detected, but chat template not applied. Recommend setting `apply_chat_template` (optionally `fewshot_as_multiturn`)." + ) + + if delete_requests_cache: + eval_logger.info("Deleting requests cache...") + delete_cache() + + seed_message = [] + if random_seed is not None: + # See https://github.com/EleutherAI/lm-evaluation-harness/pull/1412 + seed_message.append(f"Setting random seed to {random_seed}") + random.seed(random_seed) + + if numpy_random_seed is not None: + seed_message.append(f"Setting numpy seed to {numpy_random_seed}") + np.random.seed(numpy_random_seed) + + if torch_random_seed is not None: + seed_message.append(f"Setting torch manual seed to {torch_random_seed}") + torch.manual_seed(torch_random_seed) + + if fewshot_random_seed is not None: + seed_message.append(f"Setting fewshot manual seed to {fewshot_random_seed}") + + if seed_message: + eval_logger.info(" | ".join(seed_message)) + + if tasks is None: + tasks = [] + if len(tasks) == 0: + raise ValueError( + "No tasks specified, or no tasks found. Please verify the task names." + ) + + if gen_kwargs is not None: + if isinstance(gen_kwargs, str): + gen_kwargs = simple_parse_args_string(gen_kwargs) + eval_logger.warning( + f"generation_kwargs: {gen_kwargs} specified through cli, these settings will update set parameters in yaml tasks. " + "Ensure 'do_sample=True' for non-greedy decoding!" + ) + if not gen_kwargs: + gen_kwargs = None + + if isinstance(model, str): + if model_args is None: + eval_logger.warning("model_args not specified. Using defaults.") + model_args = "" + + if isinstance(model_args, dict): + eval_logger.info( + f"Initializing {model} model, with arguments: {model_args}" + ) + lm = lm_eval.api.registry.get_model(model).create_from_arg_obj( + model_args, + { + "batch_size": batch_size, + "max_batch_size": max_batch_size, + "device": device, + }, + ) + + else: + eval_logger.info( + f"Initializing {model} model, with arguments: {simple_parse_args_string(model_args)}" + ) + lm = lm_eval.api.registry.get_model(model).create_from_arg_string( + model_args, + { + "batch_size": batch_size, + "max_batch_size": max_batch_size, + "device": device, + }, + ) + else: + if not isinstance(model, lm_eval.api.model.LM): + raise TypeError( + f"The value of `model` passed to simple_evaluate() was of type {type(model)}, but is required to be a subclass of lm_eval.api.model.LM . This may be because you are passing an initialized Hugging Face PreTrainedModel without having wrapped it in `lm_eval.models.huggingface.HFLM(pretrained=my_model)` first." + ) + eval_logger.info("Using pre-initialized model") + lm = model + + if use_cache is not None: + eval_logger.info(f"Using cache at {use_cache + '_rank' + str(lm.rank) + '.db'}") + lm = lm_eval.api.model.CachingLM( + lm, + use_cache + # each rank receives a different cache db. + # necessary to avoid multiple writes to cache at once + + "_rank" + + str(lm.rank) + + ".db", + ) + + if task_manager is None: + metadata = ( + simple_parse_args_string(model_args) + if isinstance(model_args, str) + else model_args + if isinstance(model_args, dict) + else {} + ) | (metadata or {}) + task_manager = TaskManager(metadata=metadata) + + task_dict = get_task_dict( + tasks, + task_manager, + ) + + # helper function to recursively apply config overrides to leaf subtasks, skipping their constituent groups. + # (setting of num_fewshot ; bypassing metric calculation ; setting fewshot seed) + def _adjust_config(task_dict): + adjusted_task_dict = {} + for task_name, task_obj in task_dict.items(): + if isinstance(task_obj, dict): + adjusted_task_dict = { + **adjusted_task_dict, + **{task_name: _adjust_config(task_obj)}, + } + + else: + if task_obj.get_config("output_type") == "generate_until": + if gen_kwargs is not None: + task_obj.set_config( + key="generation_kwargs", value=gen_kwargs, update=True + ) + eval_logger.info( + f"{task_obj.config.task}: Using gen_kwargs: {task_obj.config.generation_kwargs}" + ) + + if predict_only: + eval_logger.info( + f"Processing {task_name} in output-only mode. Metrics will not be calculated!" + ) + # we have to change the class properties post-hoc. This is pretty hacky. + task_obj.override_metric(metric_name="bypass") + + # override tasks' fewshot values to the provided num_fewshot arg value + # except if tasks have it set to 0 manually in their configs--then we should never overwrite that + if num_fewshot is not None: + if (default_num_fewshot := task_obj.get_config("num_fewshot")) == 0: + eval_logger.info( + f"num_fewshot has been set to 0 for {task_name} in its config. Manual configuration will be ignored." + ) + else: + eval_logger.warning( + f"Overwriting default num_fewshot of {task_name} from {default_num_fewshot} to {num_fewshot}" + ) + task_obj.set_config(key="num_fewshot", value=num_fewshot) + else: + # if num_fewshot not provided, and the task does not define a default one, default to 0 + if ( + default_num_fewshot := task_obj.get_config("num_fewshot") + ) is None: + task_obj.set_config(key="num_fewshot", value=0) + # fewshot_random_seed set for tasks, even with a default num_fewshot (e.g. in the YAML file) + task_obj.set_fewshot_seed(seed=fewshot_random_seed) + + adjusted_task_dict[task_name] = task_obj + + return adjusted_task_dict + + task_dict = _adjust_config(task_dict) + + if check_integrity: + run_task_tests(task_list=tasks) + + if evaluation_tracker is not None: + evaluation_tracker.general_config_tracker.log_experiment_args( + model_source=model, + model_args=model_args, + system_instruction=system_instruction, + chat_template=lm.chat_template(apply_chat_template) + if apply_chat_template + else None, + fewshot_as_multiturn=fewshot_as_multiturn, + ) + + results = evaluate( + lm=lm, + task_dict=task_dict, + limit=limit, + samples=samples, + cache_requests=cache_requests, + rewrite_requests_cache=rewrite_requests_cache, + bootstrap_iters=bootstrap_iters, + write_out=write_out, + log_samples=True if predict_only else log_samples, + system_instruction=system_instruction, + apply_chat_template=apply_chat_template, + fewshot_as_multiturn=fewshot_as_multiturn, + verbosity=verbosity, + confirm_run_unsafe_code=confirm_run_unsafe_code, + ) + if verbosity is not None: + setup_logging(verbosity=verbosity) + + if lm.rank == 0: + if isinstance(model, str): + model_name = model + elif hasattr(model, "config") and hasattr(model.config, "_name_or_path"): + model_name = model.config._name_or_path + else: + model_name = type(model).__name__ + + # add info about the model and few shot config + results["config"] = { + "model": model_name, + "model_args": model_args, + } + # add more detailed model info if available + if isinstance(lm, lm_eval.models.huggingface.HFLM): + results["config"].update(lm.get_model_info()) + # add info about execution + results["config"].update( + { + "batch_size": batch_size, + "batch_sizes": ( + list(lm.batch_sizes.values()) if hasattr(lm, "batch_sizes") else [] + ), + "device": device, + "use_cache": use_cache, + "limit": limit, + "bootstrap_iters": bootstrap_iters, + "gen_kwargs": gen_kwargs, + "random_seed": random_seed, + "numpy_seed": numpy_random_seed, + "torch_seed": torch_random_seed, + "fewshot_seed": fewshot_random_seed, + } + ) + results["git_hash"] = get_git_commit_hash() + results["date"] = start_date + add_env_info(results) # additional environment info to results + add_tokenizer_info(results, lm) # additional info about tokenizer + return results + else: + return None + + +@positional_deprecated +def evaluate( + lm: "LM", + task_dict, + limit: Optional[int] = None, + samples: Optional[dict] = None, + cache_requests: bool = False, + rewrite_requests_cache: bool = False, + bootstrap_iters: Optional[int] = 100000, + write_out: bool = False, + log_samples: bool = True, + system_instruction: Optional[str] = None, + apply_chat_template: Union[bool, str] = False, + fewshot_as_multiturn: bool = False, + verbosity: str = "INFO", + confirm_run_unsafe_code: bool = False, +): + """Instantiate and evaluate a model on a list of tasks. + + :param lm: obj + Language Model + :param task_dict: dict[str, Task] + Dictionary of tasks. Tasks will be taken to have name type(task).config.task . + :param limit: int, optional + Limit the number of examples per task (only use this for testing) + :param samples: dictionary, optional + Dictionary indicating which examples should be tested in each task, e.g., {"mmlu_astronomy":[0,3,6],"mmlu_anatomy":[1,4,7,10]}. + :param cache_requests: bool, optional + Speed up evaluation by caching the building of dataset requests. + :param rewrite_requests_cache: bool, optional + Rewrites all the request cache if set to `True`. + :param bootstrap_iters: + Number of iterations for bootstrap statistics, used when calculating stderr. Set to 0 for skipping all stderr calculations. + :param write_out: bool + If True, write out an example document and model input for checking task integrity + :param log_samples: bool + If True, write out all model outputs and documents for per-sample measurement and post-hoc analysis + :param system_instruction: str + System instruction to be applied to the prompt + :param apply_chat_template: Union[bool, str] + Specifies whether to apply a chat template to the prompt. + - If set to True, the default chat template is applied. + - If set to a string, applies the specified chat template by name. + Defaults to False (no chat template applied). + :param fewshot_as_multiturn: bool + Whether to provide the fewshot examples as a multiturn conversation or a single user turn. + :param verbosity: str + Verbosity level for logging + :param confirm_run_unsafe_code: bool + Whether to confirm running tasks marked as unsafe. + :return + Dictionary of results + """ + + if limit is not None and samples is not None: + raise ValueError( + "Either 'limit' or 'samples' must be None, but both are not None." + ) + if samples is not None: + eval_logger.info(f"Evaluating examples for tasks {list(samples.keys())}") + if apply_chat_template: + eval_logger.warning( + "Chat template formatting change affects loglikelihood and multiple-choice tasks. See docs/chat-template-readme.md for details." + ) + # tracks all Instances/requests a model must generate output on. + requests = defaultdict(list) + # stores the amount to pad out reqs per req. type so that + # number of fwd passes per distributed rank is equal + padding_requests = defaultdict(int) + + # get lists of group hierarchy and each type of request + eval_tasks = get_task_list(task_dict) + if not log_samples: + if not all( + "bypass" not in getattr(task_output.task, "_metric_fn_list", {}).keys() + for task_output in eval_tasks + ): + raise ValueError("log_samples must be True for 'bypass' metric-only tasks") + + # validation checks: + # 1.are we running multimodal task <-> non-multimodal model class, or vice-versa. + # 2.are we running code that is marked as unsafe. + incompatible_tasks = [] + for task_output in eval_tasks: + task: Task = task_output.task + + if getattr(lm, "MULTIMODAL", False) != getattr(task, "MULTIMODAL", False): + incompatible_tasks.append(task_output.task_name) + elif getattr(task, "UNSAFE_CODE", False) and not confirm_run_unsafe_code: + raise ValueError( + f"Attempted to run task: {task_output.task_name} which is marked as unsafe. Set confirm_run_unsafe_code=True to run this task." + ) + if len(incompatible_tasks) > 0: + if not getattr(lm, "MULTIMODAL", False): + raise ValueError( + f"Attempted to run tasks: {incompatible_tasks} which require multimodal input, but the selected model type does not currently implement this. Multimodal support is currently restricted to the ['hf-multimodal', 'vllm-vlm'] model type." + ) + else: + raise ValueError( + f"Attempted to run tasks: {incompatible_tasks} which are text-only, but used a model type which only currently supports multimodal tasks." + ) + # end validation check + + # Cache the limit arg. + limit_arg = limit + limits = [] + for task_output in eval_tasks: + task: Task = task_output.task + + limit = get_sample_size(task, limit_arg) + limits.append(limit) + task.build_all_requests( + limit=limit, + samples=samples.get(task_output.task_name, None) + if samples is not None + else samples, + rank=lm.rank, + world_size=lm.world_size, + cache_requests=cache_requests, + rewrite_requests_cache=rewrite_requests_cache, + system_instruction=system_instruction, + apply_chat_template=bool(apply_chat_template), + fewshot_as_multiturn=fewshot_as_multiturn, + chat_template=getattr(lm, "apply_chat_template") + if apply_chat_template + else None, + tokenizer_name=getattr(lm, "tokenizer_name", "") + if apply_chat_template + else "", + ) + eval_logger.debug( + f"Task: {task_output.task_name}; number of requests on this rank: {len(task.instances)}" + ) + if write_out: + print_writeout(task) + # aggregate Instances by LM method requested to get output. + for instance in task.instances: + reqtype = instance.request_type + requests[reqtype].append(instance) + + if lm.world_size > 1: + instances_rnk = torch.tensor(len(task._instances), device=lm.device) + gathered_item = ( + lm.accelerator.gather(instances_rnk).cpu().detach().numpy().tolist() + ) + # "multiple_choice" task types dispatch (several) "loglikelihood" request types + reqtype = ( + "loglikelihood" + if task.OUTPUT_TYPE == "multiple_choice" + else task.OUTPUT_TYPE + ) + # compute number of pseudo-batches to pad with (FSDP/DDP require even batches among ranks) + numpad = max(gathered_item) - gathered_item[lm.rank] + # todo: may not account for padding in cases like SquadV2 which has multiple req types + padding_requests[reqtype] += numpad + + ### Run LM on inputs, get all outputs ### + # execute each type of request + for reqtype, reqs in requests.items(): + eval_logger.info(f"Running {reqtype} requests") + # create `K` copies of each request `req` based off `K = req.repeats` + cloned_reqs = [] + for req in reqs: + cloned_reqs.extend([req] * req.repeats) + + if (lm.world_size > 1) and (padding_requests[reqtype] > 0): + for _ in range(padding_requests[reqtype]): + cloned_reqs.extend([req] * req.repeats) + + # run requests through model + resps = getattr(lm, reqtype)(cloned_reqs) + + # put responses from model into a list of length K for each request. + for x, req in zip(resps, cloned_reqs): + req.resps.append(x) + + if lm.world_size > 1: + lm.accelerator.wait_for_everyone() + + RANK = lm.rank + WORLD_SIZE = lm.world_size + ### Postprocess outputs ### + # TODO: del model here, maybe (idea: allow user to specify device of e.g. reward model separately) + for task_output, limit in zip(eval_tasks, limits): + task = task_output.task + task.apply_filters() + + ### Collect values of metrics on all datapoints ### + # # unpack results and sort back in order and return control to Task + # TODO: make it possible to use a different metric per filter + # Pre-process task.instances to group by doc_id + instances_by_doc_id = defaultdict(list) + for instance in task.instances: + instances_by_doc_id[instance.doc_id].append(instance) + # Sort instances within each group + for instances in instances_by_doc_id.values(): + instances.sort(key=lambda x: x.idx) + # iterate over different filters used + for filter_key in task.instances[0].filtered_resps.keys(): + indices = ( + samples.get(task_output.task_name, None) + if samples is not None + else None + ) + doc_iterator = task.doc_iterator( + rank=RANK, + limit=limit, + world_size=WORLD_SIZE, + samples=indices, + ) + for doc_id, doc in doc_iterator: + if indices: + doc_id_true = indices[doc_id] + else: + doc_id_true = doc_id + requests = instances_by_doc_id[doc_id] + metrics = task.process_results( + doc, [req.filtered_resps[filter_key] for req in requests] + ) + if log_samples: + target = task.doc_to_target(doc) + example = { + "doc_id": doc_id_true, + "doc": doc, + "target": target, + "arguments": [req.args for req in requests], + "resps": [req.resps for req in requests], + "filtered_resps": [ + req.filtered_resps[filter_key] for req in requests + ], + "filter": filter_key, + "metrics": list(metrics.keys()), + "doc_hash": hash_string( + json.dumps( + requests[0].doc, + indent=2, + default=handle_non_serializable, + ensure_ascii=False, + ) + ), + "prompt_hash": hash_string(requests[0].arguments[0]), + "target_hash": hash_string(str(target)), + } + example.update(metrics) + task_output.logged_samples.append(example) + for metric, value in metrics.items(): + task_output.sample_metrics[(metric, filter_key)].append(value) + + if WORLD_SIZE > 1: + # if multigpu, then gather data across all ranks to rank 0 + # first gather logged samples across all ranks + for task_output in eval_tasks: + if log_samples: + # for task_name, task_samples in list(samples.items()): + full_samples = [None] * WORLD_SIZE if RANK == 0 else None + torch.distributed.gather_object( + obj=task_output.logged_samples, + object_gather_list=full_samples, + dst=0, + ) + + if RANK == 0: + task_output.logged_samples = list( + itertools.chain.from_iterable(full_samples) + ) + + # then collect metrics across all ranks + for metrics in task_output.sample_metrics: + metric_list = [None] * WORLD_SIZE if RANK == 0 else None + torch.distributed.gather_object( + obj=task_output.sample_metrics[metrics], + object_gather_list=metric_list, + dst=0, + ) + if RANK == 0: + task_output.sample_metrics[metrics] = list( + itertools.chain.from_iterable(metric_list) + ) + + if RANK == 0: + ### Aggregate results over all datapoints ### + # aggregate results ; run bootstrap CIs + for task_output in eval_tasks: + task_output.calculate_aggregate_metric(bootstrap_iters=bootstrap_iters) + ( + results, + samples, + configs, + versions, + num_fewshot, + higher_is_better, + ) = consolidate_results(eval_tasks) + + ### Calculate group metrics ### + if bool(results): + results, versions, show_group_table, *_ = consolidate_group_results( + results, versions, task_dict + ) + + results_agg, group_agg = prepare_print_tasks(task_dict, results) + subtask_list = get_subtask_list(task_dict) + + # collect all higher_is_better values for metrics + # in the group's subtasks. + # TODO: clean this up ; unify with the below metric_list loop? + _higher_is_better = {} + for group, task_list in subtask_list.items(): + if ( + len(task_list) != 0 + ): # subtask list will list "task_name": [] for solo tasks + for task in task_list: + for m, h in higher_is_better[task].items(): + if m not in _higher_is_better.keys(): + _higher_is_better[m] = h + + if ( + m in _higher_is_better + and _higher_is_better[m] is not None + and _higher_is_better[m] != h + ): + eval_logger.warning( + f"Higher_is_better values for metric {m} in group {group} are not consistent. Defaulting to None." + ) + _higher_is_better[m] = None + higher_is_better[group] = _higher_is_better + + results_dict = { + "results": dict(results_agg.items()), + **( + {"groups": dict(group_agg.items())} + if (bool(group_agg) & show_group_table) + else {} + ), + "group_subtasks": dict(reversed(subtask_list.items())), + "configs": dict(sorted(configs.items())), + "versions": dict(sorted(versions.items())), + "n-shot": dict(sorted(num_fewshot.items())), + "higher_is_better": dict(sorted(higher_is_better.items())), + "n-samples": { + task_output.task_name: { + "original": len(task_output.task.eval_docs), + "effective": min( + limit if limit else len(task_output.task.eval_docs), + len(task_output.task.eval_docs), + ), + } + for task_output, limit in zip(eval_tasks, limits) + }, + } + if log_samples: + results_dict["samples"] = dict(samples) + + return results_dict + + else: + return None + + +def request_caching_arg_to_dict(cache_requests: str) -> dict: + request_caching_args = { + "cache_requests": cache_requests in {"true", "refresh"}, + "rewrite_requests_cache": cache_requests == "refresh", + "delete_requests_cache": cache_requests == "delete", + } + + return request_caching_args diff --git a/fast_llm/engine/training/lm_eval/fast_llm_wrapper.py b/fast_llm/engine/training/lm_eval/fast_llm_wrapper.py new file mode 100644 index 00000000..43204206 --- /dev/null +++ b/fast_llm/engine/training/lm_eval/fast_llm_wrapper.py @@ -0,0 +1,896 @@ +import logging +import pathlib +import copy +import jinja2 + +from typing import Optional, Union, Any, List, Tuple, Dict + +import transformers +from tqdm.auto import tqdm +import torch +import torch.nn.functional as F +import torch.distributed as dist + + +# make lazy +from lm_eval import utils +from lm_eval.api.model import TemplateLM +from lm_eval.api.instance import Instance +from lm_eval.api.model import CacheHook +from lm_eval.models.utils import ( + Collator, + configure_pad_token, + handle_stop_sequences, + pad_and_concat, + stop_sequences_criteria, +) + +from fast_llm.core.distributed import safe_barrier +from fast_llm.engine.checkpoint.config import CheckpointLoadConfig +from fast_llm.engine.multi_stage.config import FastLLMModelConfig +from fast_llm.models.auto import model_registry +from fast_llm.engine.inference.huggingface import HuggingfaceBaseModelForCausalLM +from fast_llm.engine.distributed.distributed import Distributed +from fast_llm.engine.distributed.config import DistributedConfig + + +eval_logger = logging.getLogger(__name__) + + +# move to fast_llm +class FastLLMWrapper(TemplateLM): + _DEFAULT_MAX_LENGTH = 2048 + + def __init__( + self, + model: HuggingfaceBaseModelForCausalLM, + tokenizer: transformers.PreTrainedTokenizer | transformers.PreTrainedTokenizerFast, + truncation: Optional[bool] = False, + logits_cache: bool = True, + add_bos_token: Optional[bool] = False, + prefix_token_id: Optional[int] = None, + ): + super().__init__() + # This is for lm_eval sake, we always run lm_eval on one main rank + self._rank = 0 + self._world_size = 1 + + self._distributed: Distributed = model._inference_runner._fast_llm_model.distributed + dist_config: DistributedConfig = self._distributed.config + # get batch_data_parallel group leaders + if dist_config.sequence_data_rank == 0 and dist_config.pipeline_rank == 0 and dist_config.tensor_rank == 0: + self.group = self._distributed.batch_data_group + else: + self.group = dist.GroupMember.NON_GROUP_MEMBER + + # TODO: clean code which does not used parts from HFLM + backend = "causal" + revision = "main" + gguf_file = None + delta = None + peft = None + + # set some inputs which are expected in HFLM but are set by our model config + # TODO: do _batch_config public read only property + max_length = model._inference_runner._batch_config.sequence_length + # batch_size = model._batch_config.micro_batch_size + batch_size = model._inference_runner._batch_config.batch_size + max_batch_size = batch_size + + self.backend = backend + + # set tokenizer object + assert isinstance(tokenizer, transformers.PreTrainedTokenizer) or isinstance( + tokenizer, transformers.PreTrainedTokenizerFast + ) + self.tokenizer = tokenizer + + # initialize model fields + self._model = model + self._device = self._model.device + self._config = self._model.config + + # access self._model through self.model property outside this method + if isinstance(self.model, torch.nn.Module): + self.model.eval() + self.model.tie_weights() + + self.truncation = truncation + self.logits_cache = logits_cache + self.vocab_size = self.tokenizer.vocab_size + # select (or create) a pad token to use + self.tokenizer = configure_pad_token(self.tokenizer, model_config=self.config) + + self.add_bos_token = add_bos_token + # TODO: do we support gemma models? + if "gemma" in getattr(self.config, "model_type", ""): + self.add_bos_token = True + eval_logger.info( + f"Model type is '{self.config.model_type}', part of the Gemma family--a BOS" + " token will be used as Gemma underperforms without it." + ) + + self._max_length = max_length + self.pretrained = model + self.delta = delta + self.peft = peft + self.revision = revision + self.batch_schedule = 1 + self.batch_sizes = {} + self.max_batch_size = max_batch_size + + if str(batch_size).startswith("auto"): + batch_size = batch_size.split(":") + self.batch_size_per_gpu = batch_size[0] + self.batch_schedule = float(batch_size[1]) if len(batch_size) > 1 else 1 + else: + self.batch_size_per_gpu = int(batch_size) + + self.custom_prefix_token_id = prefix_token_id + if prefix_token_id is not None: + eval_logger.info(f"Loglikelihood prefix token id used in evaluation: {self.prefix_token_id}") + + def _model_invoke( + self, inputs, attn_mask, labels, max_length, stop, generate: bool, continue_generate: bool, **generation_kwargs + ): + if self.group is None or (world_size := self.group.size()) == 1: + # Must not be called with continue_generate false on one process + assert continue_generate + return self._model_invoke_inner(inputs, attn_mask, labels, max_length, stop, generate, **generation_kwargs) + + rank = self.group.rank() + assert rank == 0 + + if continue_generate: + assert inputs is not None + if generate: + assert max_length is not None and stop is not None + + step = len(inputs) // world_size + + inputs = [inputs[i * step : (i + 1) * step] for i in range(world_size)] + attn_mask = [ + attn_mask[i * step : (i + 1) * step] if attn_mask is not None else None for i in range(world_size) + ] + labels = [labels[i * step : (i + 1) * step] if labels is not None else None for i in range(world_size)] + + scatter_list = [ + [inputs[i], attn_mask[i], labels[i], max_length, stop, generate, continue_generate, generation_kwargs] + for i in range(world_size) + ] + else: + scatter_list = [[None, None, None, None, None, None, False, None] for _ in range(world_size)] + + obj_list = [None] + dist.scatter_object_list( + obj_list, + scatter_list, + # TODO: figure out how to get proper global rank as Fast-llm groups crash here with + # Group is not registered, please create group with torch.distributed.new_group API + # src=dist.get_global_rank(self.group, 0), + src=0, + group=self.group, + ) + inputs, attn_mask, labels, max_length, stop, generate, continue_generate, generation_kwargs = tuple( + obj_list[0] + ) + + if continue_generate == False: + return + + res = self._model_invoke_inner(inputs, attn_mask, labels, max_length, stop, generate, **generation_kwargs) + + gather_list = [None] * world_size + dist.gather_object( + res, + gather_list, + # TODO: make proper rank mapping + # dst=dist.get_global_rank(self.group, 0), + dst=0, + group=self.group, + ) + + return gather_list + + def worker_model_invoke(self): + assert self.group is not None + print(self.group) + # if isinstance(self.group, dist.ProcessGroup): + if not isinstance(self.group, int): + assert self.group.size() > 1 and self.group.rank() != 0 + # on worker ranks the function need to wait to be called multiple times + while True: + scatter_list = None + obj_list = [None] + dist.scatter_object_list( + obj_list, + scatter_list, + # TODO: figure out how to get proper global rank as Fast-llm groups crash here with + # Group is not registered, please create group with torch.distributed.new_group API + # src=dist.get_global_rank(self.group, 0), + src=0, + group=self.group, + ) + inputs, attn_mask, labels, max_length, stop, generate, continue_generate, generation_kwargs = tuple( + obj_list[0] + ) + + if continue_generate == False: + break + + res = self._model_invoke_inner( + inputs, attn_mask, labels, max_length, stop, generate, **generation_kwargs + ) + + gather_list = None + dist.gather_object( + res, + gather_list, + # TODO: make proper rank mapping + # dst=dist.get_global_rank(self.group, 0), + dst=0, + group=self.group, + ) + else: + # TODO: implement distributed model support + assert self.group == dist.GroupMember.NON_GROUP_MEMBER + safe_barrier(self._distributed.world_group, "lm_eval_end") + + def stop_workers(self): + if self.group is None or (world_size := self.group.size()) == 1: + return + self._model_invoke(None, None, None, None, None, None, continue_generate=False) + safe_barrier(self._distributed.world_group, "lm_eval_end") + + def _model_invoke_inner(self, inputs, attn_mask, labels, max_length, stop, generate: bool, **generation_kwargs): + if generate: + return self._model_generate_inner(inputs, max_length, stop, **generation_kwargs) + else: + return self._model_call_inner(inputs, attn_mask, labels) + + def _model_call(self, inps, attn_mask=None, labels=None): + return self._model_invoke(inps, attn_mask, labels, None, None, generate=False, continue_generate=True) + + def _model_generate(self, context, max_length, stop, **generation_kwargs): + return self._model_invoke( + context, None, None, max_length, stop, generate=True, continue_generate=True, **generation_kwargs + ) + + def _model_call_inner(self, inps, attn_mask=None, labels=None): + """ + :param inps: torch.Tensor + A torch tensor of shape [batch, (sequence_ctx + sequence_cont)] or of shape + [batch, sequence_ctx]. the size of sequence may vary from call to call + :param attn_mask: torch.Tensor, optional + A torch tensor of shape [batch, (sequence_ctx + sequence_cont)]. Only passed + (and must be passed) if self.AUTO_MODEL_CLASS is transformers.AutoModelForSeq2SeqLM + :param labels: torch.Tensor, optional + A torch tensor of shape [batch, (sequence_ctx + sequence_cont)]. Only passed + (and must be passed) if self.AUTO_MODEL_CLASS is transformers.AutoModelForSeq2SeqLM + :return + A torch tensor of shape [batch, sequence, vocab] with the + logits returned from the model's decoder + """ + # TODO: do we need no_grad for our model? + with torch.no_grad(): + if attn_mask is not None or labels is not None: + assert attn_mask is not None and labels is not None + return self.model( + input_ids=inps, + attention_mask=attn_mask, + labels=labels, + position_ids=None, + past_key_values=None, + inputs_embeds=None, + use_cache=False, + output_attentions=False, + output_hidden_states=False, + return_dict=True, + ).logits + else: + return self.model( + input_ids=inps, + attention_mask=None, + position_ids=None, + past_key_values=None, + inputs_embeds=None, + labels=None, + use_cache=False, + output_attentions=False, + output_hidden_states=False, + return_dict=True, + ).logits + + def _model_generate_inner(self, context, max_length, stop, **generation_kwargs): + # temperature = 0.0 if not set + # if do_sample is false and temp==0.0: + # remove temperature, as do_sample=False takes care of this + # and we don't want a warning from HF + generation_kwargs["temperature"] = generation_kwargs.get("temperature", 0.0) + do_sample = generation_kwargs.get("do_sample", None) + + # The temperature has to be a strictly positive float -- if it is 0.0, use greedy decoding strategies + if generation_kwargs.get("temperature") == 0.0 and do_sample is None: + generation_kwargs["do_sample"] = do_sample = False + + if do_sample is False and generation_kwargs.get("temperature") == 0.0: + generation_kwargs.pop("temperature") + # build stopping criteria + stopping_criteria = stop_sequences_criteria(self.tokenizer, stop, context.shape[1], context.shape[0]) + return self.model.generate( + input_ids=context, + max_length=max_length, + stopping_criteria=stopping_criteria, + pad_token_id=self.tokenizer.pad_token_id, + use_cache=False, + **generation_kwargs, + ) + + @property + def config(self): + # return the associated transformers.AutoConfig for the given pretrained model. + return self._config + + @property + def model(self): + # returns the model, unwrapping it if using Accelerate + if hasattr(self, "accelerator"): + return self.accelerator.unwrap_model(self._model) + else: + return self._model + + @property + def eot_token_id(self): + # we use EOT because end of *text* is more accurate for what we're doing than end of *sentence* + return self.tokenizer.eos_token_id + + @property + def prefix_token_id(self): + # it is used as prefix for loglikelihood + if self.custom_prefix_token_id is not None: + return self.custom_prefix_token_id + if self.tokenizer.bos_token_id is not None: + return self.tokenizer.bos_token_id + return self.tokenizer.eos_token_id + + @property + def max_length(self): + if self._max_length: # if max length manually set, return it + return self._max_length + seqlen_config_attrs = ("n_positions", "max_position_embeddings", "n_ctx") + for attr in seqlen_config_attrs: + if hasattr(self.model.config, attr): + return getattr(self.model.config, attr) + if hasattr(self.tokenizer, "model_max_length"): + if self.tokenizer.model_max_length == 1000000000000000019884624838656: + return self._DEFAULT_MAX_LENGTH + return self.tokenizer.model_max_length + return self._DEFAULT_MAX_LENGTH + + @property + def max_gen_toks(self) -> int: + return 256 + + @property + def batch_size(self): + return self.batch_size_per_gpu + + @property + def device(self): + return self._device + + @property + def rank(self): + return self._rank + + @property + def world_size(self): + return self._world_size + + @property + def tokenizer_name(self) -> str: + return self.tokenizer.name_or_path.replace("/", "__") + + def tok_encode(self, string: str, left_truncate_len=None, add_special_tokens=None) -> List[int]: + """ """ + # default for None - empty dict, use predefined tokenizer param + # used for all models except for CausalLM or predefined value + special_tokens_kwargs = {} + + # by default for CausalLM - false or self.add_bos_token is set + if add_special_tokens is None: + if self.backend == "causal": + special_tokens_kwargs = {"add_special_tokens": False or self.add_bos_token} + # otherwise the method explicitly defines the value + else: + special_tokens_kwargs = {"add_special_tokens": add_special_tokens} + + encoding = self.tokenizer.encode(string, **special_tokens_kwargs) + + # left-truncate the encoded context to be at most `left_truncate_len` tokens long + if left_truncate_len: + encoding = encoding[-left_truncate_len:] + + return encoding + + def tok_batch_encode( + self, + strings: List[str], + padding_side: str = "left", + left_truncate_len: int = None, + truncation: bool = False, + ) -> Tuple[torch.Tensor, torch.Tensor]: + # encode a batch of strings. converts to tensors and pads automatically, unlike tok_encode. + old_padding_side = self.tokenizer.padding_side + self.tokenizer.padding_side = padding_side + + add_special_tokens = {} + if self.backend == "causal": + add_special_tokens = {"add_special_tokens": False or self.add_bos_token} + + encoding = self.tokenizer( + strings, + truncation=truncation, + padding="longest", + return_tensors="pt", + **add_special_tokens, + ) + if left_truncate_len: + original_lengths = encoding["input_ids"].size(1) + if original_lengths > left_truncate_len: + eval_logger.warn( + f"Left truncation applied. Original sequence length was {original_lengths}, " + f"truncating to last {left_truncate_len} tokens. Some content will be lost.", + ) + encoding["input_ids"] = encoding["input_ids"][:, -left_truncate_len:] + encoding["attention_mask"] = encoding["attention_mask"][:, -left_truncate_len:] + self.tokenizer.padding_side = old_padding_side + + return encoding["input_ids"], encoding["attention_mask"] + + def tok_decode(self, tokens, skip_special_tokens=True): + return self.tokenizer.decode(tokens, skip_special_tokens=skip_special_tokens) + + def _select_cont_toks(self, logits: torch.Tensor, contlen: int = None, inplen: int = None) -> torch.Tensor: + if self.backend == "causal": + assert contlen and inplen, "Must pass input len and cont. len to select scored logits for causal LM" + # discard right-padding. + # also discard the input/context tokens. we'll only score continuations. + logits = logits[inplen - contlen : inplen] + elif self.backend == "seq2seq": + assert contlen and not inplen, "Selecting scored logits for Seq2SeqLM requires only cont. len" + # only discard right-padding. + # the logits input to this fn only contain decoder-side tokens. + logits = logits[:contlen] + + return logits + + def loglikelihood_rolling(self, requests: List[Instance], disable_tqdm: bool = False) -> List[float]: + adaptive_batch_size = None + if self.batch_size == "auto": + # using rolling window with maximum context + print("Passed argument batch_size = auto. Detecting largest batch size") + batch_size = self._detect_batch_size() + print(f"Determined Largest batch size: {batch_size}") + adaptive_batch_size = batch_size + + # First, collect all windows from all requests + all_windows = [] # List of (request_idx, window) tuples + request_window_counts = [] # Track number of windows per request + + for req_idx, (string,) in enumerate( + tqdm( + [req.args for req in requests], + disable=(disable_tqdm or (self.rank != 0)), + ) + ): + rolling_token_windows: List[Tuple[List[int], List[int]]] = list( + map( + utils.make_disjoint_window, + utils.get_rolling_token_windows( + token_list=self.tok_encode(string), + prefix_token=self.prefix_token_id, + max_seq_len=self.max_length, + context_len=1, + ), + ) + ) + + # TODO: Right now, we pass single EOT token to the Encoder and the full context to the decoder, in seq2seq case + windows = [(None,) + x for x in rolling_token_windows] + + # Store windows with their request index + all_windows.extend((req_idx, window) for window in windows) + request_window_counts.append(len(windows)) + + # Handle distributed case padding + pad_amnt = 0 + if self.world_size > 1: + mytensor = torch.tensor(len(all_windows), device=self.device) + gathered = self.accelerator.gather(mytensor).cpu().detach().numpy().tolist() + pad_amnt = max(gathered) - gathered[self.rank] + if pad_amnt > 0: + all_windows += pad_amnt * [all_windows[0]] + + all_nlls = [] + batch_size = adaptive_batch_size or self.batch_size + for i in range(0, len(all_windows), batch_size): + batch = all_windows[i : i + batch_size] + # Extract just the windows for processing, keeping track of request indices + batch_indices, batch_windows = zip(*batch) + + batch_nlls = self._loglikelihood_tokens( + requests=batch_windows, + disable_tqdm=False, + override_bs=len(batch_windows), + ) + # Store results with their request indices + all_nlls.extend(zip(batch_indices, batch_nlls)) + + # Remove padding if necessary + if (self.world_size > 1) and (pad_amnt > 0): + all_nlls = all_nlls[:-pad_amnt] + + # Reconstruct per-request loglikelihoods + loglikelihoods = [] + current_idx = 0 + for window_count in request_window_counts: + # Get all nlls for this request + request_nlls = all_nlls[current_idx : current_idx + window_count] + # Sum up the nlls for this request (discarding is_greedy) + request_total = sum(nll[0] for _, nll in request_nlls) + loglikelihoods.append(request_total) + current_idx += window_count + + string = requests[len(loglikelihoods) - 1].args[0] + self.cache_hook.add_partial("loglikelihood_rolling", (string,), request_total) + + return loglikelihoods + + def _batch_scheduler(self, pos, n_reordered_requests): + sched = pos // int(len(n_reordered_requests) / self.batch_schedule) + if sched in self.batch_sizes: + return self.batch_sizes[sched] + if (len(self.batch_sizes) > 1) and (self.batch_sizes[sched - 1] == self.max_batch_size): + # if previous batch size is already maximal, skip recomputation + self.batch_sizes[sched] = self.max_batch_size + return self.batch_sizes[sched] + print(f"Passed argument batch_size = auto:{self.batch_schedule}. Detecting largest batch size") + self.batch_sizes[sched] = self._detect_batch_size(n_reordered_requests, pos) + print(f"Determined largest batch size: {self.batch_sizes[sched]}") + return self.batch_sizes[sched] + + def _loglikelihood_tokens( + self, + requests: List[Tuple[Tuple[str, str], List[int], List[int]]], + disable_tqdm: bool = False, + override_bs: int = None, + ) -> List[Tuple[float, bool]]: + # TODO: implement some kind of efficient-request-middleware that lumps together requests with the same context + res = [] + + def _collate(req: Tuple[Tuple[str, str], List[int], List[int]]): + """Defines the key for the sorted method""" + # the negative sign on len(toks) sorts descending - this has a few advantages: + # - time estimates will always be over not underestimates, which is more useful for planning + # - to know the size of a batch when going through the list, you know the first one is always the batch + # padded context length. this is useful to simplify the batching logic and more importantly to make + # automatic adaptive batches much much easier to implement + # - any OOMs will happen right away rather than near the end + + toks = req[1] + req[2] + return -len(toks), tuple(toks) + + def _lookup_one_token_cont(req: Tuple[Tuple[str, str], List[int], List[int]]): + """Defines the key to group and lookup one-token continuations""" + # Use with group_by="contexts" (optional)" + # allows for the creation of a lookup, so we can reuse logits in case of one-token continuations. + # speeds up some multiple-choice tasks proportionally to the number of choices. + # groups requests by context+continuation[:-1] and infer on one request/group. + return req[-2] + req[-1][:-1] + + re_ord = Collator( + requests, + sort_fn=_collate, + group_by="contexts" if self.backend == "causal" and self.logits_cache else None, + group_fn=_lookup_one_token_cont, + ) + + # automatic (variable) batch size detection for vectorization + # pull longest context sample from request + n_reordered_requests = len(re_ord) + batch_size = self.batch_size if self.batch_size != "auto" else override_bs if override_bs is not None else 0 + batch_fn = ( + self._batch_scheduler + if self.batch_size == "auto" and n_reordered_requests > 0 and not override_bs + else None + ) + + chunks = re_ord.get_batched(n=batch_size, batch_fn=batch_fn) + pbar = tqdm( + total=len(requests), + disable=(disable_tqdm or (self.rank != 0)), + desc="Running loglikelihood requests", + ) + for chunk in chunks: + inps = [] + cont_toks_list = [] + inplens = [] + + conts = [] + encoder_attns = [] + + padding_len_inp = None + padding_len_cont = None + # because vectorizing is annoying, we first convert each (context, continuation) pair to padded + # tensors, then we pack them together into a batch, call the model, and then pick it all apart + # again because vectorizing is annoying + + for _, context_enc, continuation_enc in chunk: + # sanity check + assert len(context_enc) > 0 + assert len(continuation_enc) > 0 + assert len(continuation_enc) <= self.max_length + + # how this all works (illustrated on a causal decoder-only setup): + # CTX CONT + # inp 0 1 2 3|4 5 6 7 8 9 <- last token is deleted by inp[:, :-1] + # model \ \ + # logits 1 2 3|4 5 6 7 8 9 <- the ctx half gets tossed out by the + # cont_toks 4 5 6 7 8 9 [:, -len(continuation_enc):, :self.vocab_size] slice + + # when too long to fit in context, truncate from the left + if self.backend == "causal": + total_length = len(context_enc) + len(continuation_enc) + if total_length > self.max_length + 1: + eval_logger.warn( + f"Combined length of context ({len(context_enc)}) and continuation ({len(continuation_enc)}) " + f"exceeds model's maximum length ({self.max_length}). " + f"Truncating {total_length - self.max_length + 1} tokens from the left." + ) + inp = torch.tensor( + (context_enc + continuation_enc)[-(self.max_length + 1) :][:-1], + dtype=torch.long, + device=self.device, + ) + (inplen,) = inp.shape + elif self.backend == "seq2seq": + inp = torch.tensor( + (context_enc)[-self.max_length :], + dtype=torch.long, + device=self.device, + ) + (inplen,) = inp.shape + + # build encoder attn masks + encoder_attns.append(torch.ones_like(inp)) + + cont = torch.tensor( + (continuation_enc)[-self.max_length :], + # TODO: left-shift these? + # TODO: our code assumes we never end up truncating conts for either model type + dtype=torch.long, + device=self.device, + ) + (contlen,) = cont.shape + + conts.append(cont) + + padding_len_cont = max(padding_len_cont, contlen) if padding_len_cont is not None else contlen + + padding_len_inp = max(padding_len_inp, inplen) if padding_len_inp is not None else inplen + + inps.append(inp) # [1, inp_length] + cont_toks_list.append(continuation_enc) + inplens.append(inplen) + + # create encoder attn mask and batched conts, if seq2seq + call_kwargs = {} + if self.backend == "causal": + batched_inps = pad_and_concat(padding_len_inp, inps, padding_side="right") # [batch, padding_len_inp] + elif self.backend == "seq2seq": + # TODO: left-pad encoder inps and mask? + batched_inps = pad_and_concat(padding_len_inp, inps) # [batch, padding_len_inp] + batched_conts = pad_and_concat(padding_len_cont, conts) # [batch, padding_len_cont] + batched_encoder_mask = pad_and_concat(padding_len_inp, encoder_attns) # [batch, padding_len_inp] + call_kwargs = { + "attn_mask": batched_encoder_mask, + "labels": batched_conts, + } + + multi_logits = F.log_softmax( + self._model_call(batched_inps, **call_kwargs), dim=-1 + ) # [batch, padding_length (inp or cont), vocab] + + for (request_str, ctx_tokens, _), logits, inplen, cont_toks in zip( + chunk, multi_logits, inplens, cont_toks_list + ): + # Slice to original seq length + contlen = len(cont_toks) + # take only logits in the continuation + # (discard context toks if decoder-only ; discard right-padding) + # also discards + checks for "virtual tokens" in the causal LM's input window + # from prompt/prefix tuning tokens, if applicable + ctx_len = inplen + (logits.shape[0] - padding_len_inp) if self.backend == "causal" else None + logits = self._select_cont_toks(logits, contlen=contlen, inplen=ctx_len) + logits = logits.unsqueeze(0) # [1, seq, vocab] + + # Check if per-token argmax is exactly equal to continuation + greedy_tokens = logits.argmax(dim=-1) + + # check for one-token continuation cache hits. + # noop in case group_by != "contexts" or no cache hit and returns the + # original args. Otherwise, expands the logits batch dimension and yields each + # batch along with matching continuation tokens and prompt strings. + # logits -> [1, seq, vocab] + for request_str, cont_toks, logits in re_ord.get_cache( + req_str=request_str, + cxt_toks=ctx_tokens, + cont_toks=cont_toks, + logits=logits, + ): + cont_toks = torch.tensor(cont_toks, dtype=torch.long, device=self.device).unsqueeze(0) # [1, seq] + max_equal = (greedy_tokens == cont_toks).all() + + # Obtain log-probs at the corresponding continuation token indices + # last_token_slice = logits[:, -1, :].squeeze(0).tolist() + logits = torch.gather(logits, 2, cont_toks.unsqueeze(-1)).squeeze(-1) # [1, seq] + + # Answer: (log prob, is-exact-match) + answer = (float(logits.sum()), bool(max_equal)) + + res.append(answer) + + if request_str is not None: + # special case: loglikelihood_rolling produces a number of loglikelihood requests + # all with cache key None. instead do add_partial on the per-example level + # in the loglikelihood_rolling() function for those. + self.cache_hook.add_partial("loglikelihood", request_str, answer) + pbar.update(1) + + pbar.close() + + return re_ord.get_original(res) + + def generate_until(self, requests: List[Instance], disable_tqdm: bool = False) -> List[str]: + res = [] + + def _collate(req: Tuple[str, dict]): + """Defines the key for the sorted method""" + # the negative sign on len(toks) sorts descending - this has a few advantages: + # - time estimates will always be over not underestimates, which is more useful for planning + # - to know the size of a batch when going through the list, you know the first one is always the batch + # padded context length. this is useful to simplify the batching logic and more importantly to make + # automatic adaptive batches much much easier to implement + # - any OOMs will happen right away rather than near the end + toks = self.tok_encode(req[0]) + return -len(toks), req[0] + + pbar = tqdm( + total=len(requests), + disable=(disable_tqdm or (self.rank != 0)), + desc="Running generate_until requests", + ) + adaptive_batch_size = None + if self.batch_size == "auto": + # using rolling window with maximum context + print("Passed argument batch_size = auto. Detecting largest batch size") + batch_size = self._detect_batch_size() + print(f"Determined Largest batch size: {batch_size}") + adaptive_batch_size = batch_size + # for each different set of kwargs, we execute all requests, by batch. + batch_size = ( + self.batch_size + if self.batch_size != "auto" + else adaptive_batch_size if adaptive_batch_size is not None else 0 + ) + batch_fn = self._batch_scheduler if self.batch_size == "auto" and not adaptive_batch_size else None + + # we group requests by their generation_kwargs, + # so that we don't try to execute e.g. greedy sampling and temp=0.8 sampling + # in the same batch. + # group_fn=lambda x: x[1] -> x=(context, gen_kwargs) + re_ords = Collator( + [reg.args for reg in requests], + sort_fn=_collate, + group_by="gen_kwargs", + group_fn=lambda x: x[1], + ) + chunks = re_ords.get_batched(n=batch_size, batch_fn=batch_fn) + eos = self.tok_decode(self.eot_token_id, skip_special_tokens=False) + for chunk in chunks: + contexts, all_gen_kwargs = zip(*chunk) + # we assume all gen kwargs in the batch are the same + # this is safe to assume because the `grouper` object ensures it. + gen_kwargs = all_gen_kwargs[0] + # unpack our keyword arguments. + if isinstance(gen_kwargs, dict): + kwargs = copy.deepcopy(gen_kwargs) # edge case for repeats > 1 + # add EOS token to stop sequences + until = handle_stop_sequences(kwargs.pop("until", None), eos=eos) + else: + raise ValueError(f"Expected `kwargs` to be of type `dict` but got {type(gen_kwargs)}") + if "max_gen_toks" in kwargs.keys(): + max_gen_toks = kwargs.pop("max_gen_toks") + else: + max_gen_toks = self.max_gen_toks + + # set the max length in tokens of inputs ("context_enc") + if self.backend == "causal": + # max len for inputs = max length, minus room to generate the max new tokens + max_ctx_len = self.max_length - max_gen_toks + assert ( + max_ctx_len > 0 + ), f"Invalid configuration: requested max tokens to generate ({max_gen_toks}) must be less than model's maximum sequence length ({self.max_length})." + elif self.backend == "seq2seq": + # max len for inputs = encoder's whole max_length + max_ctx_len = self.max_length + + # encode, pad, and truncate contexts for this batch + context_enc, attn_masks = self.tok_batch_encode( + contexts, + left_truncate_len=max_ctx_len, + truncation=self.truncation, + ) + context_enc = context_enc.to(self.device) + attn_masks = attn_masks.to(self.device) + + if "max_length" not in kwargs: + kwargs["max_length"] = context_enc.shape[1] + max_gen_toks + + # perform batched generation + cont = self._model_generate( + context=context_enc, + attention_mask=attn_masks, + stop=until, + **kwargs, + ) + + cont_toks_list = cont.tolist() + for cont_toks, context in zip(cont_toks_list, contexts): + # discard context + left-padding toks if using causal decoder-only LM + if self.backend == "causal": + cont_toks = cont_toks[context_enc.shape[1] :] + + s = self.tok_decode(cont_toks) + + # use secondary stop seqs to cut off should-have-been-stopped content post-hoc + for term in until: + if len(term) > 0: + # ignore '' separator, + # for seq2seq case where self.tok_decode(self.eot_token_id) = '' + s = s.split(term)[0] + + res.append(s) + + self.cache_hook.add_partial("generate_until", (context, gen_kwargs), s) + pbar.update(1) + # reorder this group of results back to original unsorted form + res = re_ords.get_original(res) + + pbar.close() + + return res + + def apply_chat_template(self, chat_history: List[Dict[str, str]], add_generation_prompt: bool = True) -> str: + """ + Method to apply a chat template to a list of chat history between user and model. + """ + try: + chat_templated = self.tokenizer.apply_chat_template( + chat_history, + tokenize=False, + add_generation_prompt=add_generation_prompt, + continue_final_message=not add_generation_prompt, + ) + except jinja2.exceptions.TemplateError: + eval_logger.warning("Failed to apply chat template. removing the system role in chat history.") + chat_history = [msg for msg in chat_history if msg["role"] != "system"] + chat_templated = self.tokenizer.apply_chat_template( + chat_history, + tokenize=False, + add_generation_prompt=add_generation_prompt, + continue_final_message=not add_generation_prompt, + ) + + return chat_templated diff --git a/fast_llm/engine/training/lm_eval/utils.py b/fast_llm/engine/training/lm_eval/utils.py new file mode 100644 index 00000000..c9366189 --- /dev/null +++ b/fast_llm/engine/training/lm_eval/utils.py @@ -0,0 +1,544 @@ +import argparse +import json +import logging +import os +import pathlib +import sys +from functools import partial +from pathlib import Path +from typing import Union, Optional + +from lm_eval import utils +from lm_eval.evaluator import request_caching_arg_to_dict +from lm_eval.loggers import EvaluationTracker, WandbLogger +from lm_eval.tasks import TaskManager +from lm_eval.utils import handle_non_serializable, make_table, simple_parse_args_string + + +from lm_eval.api.model import LM + +eval_logger = logging.getLogger(__name__) + + +def try_parse_json(value: str) -> Union[str, dict, None]: + if value is None: + return None + try: + return json.loads(value) + except json.JSONDecodeError: + if "{" in value: + raise argparse.ArgumentTypeError(f"Invalid JSON: {value}. Hint: Use double quotes for JSON strings.") + return value + + +def _int_or_none_list_arg_type(min_len: int, max_len: int, defaults: str, value: str, split_char: str = ","): + def parse_value(item): + item = item.strip().lower() + if item == "none": + return None + try: + return int(item) + except ValueError: + raise argparse.ArgumentTypeError(f"{item} is not an integer or None") + + items = [parse_value(v) for v in value.split(split_char)] + num_items = len(items) + + if num_items == 1: + # Makes downstream handling the same for single and multiple values + items = items * max_len + elif num_items < min_len or num_items > max_len: + raise argparse.ArgumentTypeError(f"Argument requires {max_len} integers or None, separated by '{split_char}'") + elif num_items != max_len: + logging.warning( + f"Argument requires {max_len} integers or None, separated by '{split_char}'. " + "Missing values will be filled with defaults." + ) + default_items = [parse_value(v) for v in defaults.split(split_char)] + items.extend(default_items[num_items:]) # extend items list with missing defaults + + return items + + +def check_argument_types(parser: argparse.ArgumentParser): + """ + Check to make sure all CLI args are typed, raises error if not + """ + for action in parser._actions: + if action.dest != "help" and not action.const: + if action.type is None: + raise ValueError(f"Argument '{action.dest}' doesn't have a type specified.") + else: + continue + + +def setup_parser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter) + parser.add_argument("--model", "-m", type=str, default="hf", help="Name of model e.g. `hf`") + parser.add_argument( + "--tasks", + "-t", + default=None, + type=str, + metavar="task1,task2", + help="Comma-separated list of task names or task groupings to evaluate on.\nTo get full list of tasks, use one of the commands `lm-eval --tasks {{list_groups,list_subtasks,list_tags,list}}` to list out all available names for task groupings; only (sub)tasks; tags; or all of the above", + ) + parser.add_argument( + "--model_args", + "-a", + default="", + type=try_parse_json, + help="""Comma separated string or JSON formatted arguments for model, e.g. `pretrained=EleutherAI/pythia-160m,dtype=float32` or '{"pretrained":"EleutherAI/pythia-160m","dtype":"float32"}'""", + ) + parser.add_argument( + "--num_fewshot", + "-f", + type=int, + default=None, + metavar="N", + help="Number of examples in few-shot context", + ) + parser.add_argument( + "--batch_size", + "-b", + type=str, + default=1, + metavar="auto|auto:N|N", + help="Acceptable values are 'auto', 'auto:N' or N, where N is an integer. Default 1.", + ) + parser.add_argument( + "--max_batch_size", + type=int, + default=None, + metavar="N", + help="Maximal batch size to try with --batch_size auto.", + ) + parser.add_argument( + "--device", + type=str, + default=None, + help="Device to use (e.g. cuda, cuda:0, cpu).", + ) + parser.add_argument( + "--output_path", + "-o", + default=None, + type=str, + metavar="DIR|DIR/file.json", + help="The path to the output file where the result metrics will be saved. If the path is a directory and log_samples is true, the results will be saved in the directory. Else the parent directory will be used.", + ) + parser.add_argument( + "--limit", + "-L", + type=float, + default=None, + metavar="N|0 argparse.Namespace: + check_argument_types(parser) + return parser.parse_args(args) + + +def prepare_lm_eval_simple_eval_params( + cli_args: list[str], + completed_steps: int, + run_index: int, +) -> tuple[argparse.Namespace, dict[str, any]]: + """ + Parses CLI arguments for an LM evaluation run and prepares keyword arguments + for the `evaluate` function. + + This function wraps argument parsing, environment configuration, task resolution, + and metadata setup needed for evaluation with Fast-LLM's `lm_eval` wrapper. It also + handles special cases like hub token injection, dynamic sample loading, and task + listing commands. + + Args: + cli_args (list[str]): Command-line arguments, excluding the program name. + completed_steps (int): Current number of completed training steps, used to + uniquely tag evaluation output paths. + run_index (int): index of the current run of Fast-LLM experiment + + Returns: + tuple: + - argparse.Namespace: Parsed CLI arguments. + - dict: Keyword arguments to pass into `simple_evaluate`, including task list, + tracker, cache settings, random seeds, and generation parameters. + + Raises: + ValueError: If required fields like `--tasks` or `--output_path` are missing + when needed, or if misconfigured combinations are detected. + SystemExit: If special task listing flags are used. + """ + parser = setup_parser() + args = parse_eval_args(parser, cli_args) + + # NOTE: all this args are set by fast_llm on the model directly or not used here + assert not args.wandb_args # default empty string + assert not args.wandb_config_args # default empty string + assert args.model == "hf" # default value of 'hf' + assert not args.model_args # default empty string + assert args.batch_size == 1 # default value of 1 + assert args.max_batch_size is None + assert args.device is None + # if args.wandb_args: + # wandb_args_dict = simple_parse_args_string(args.wandb_args) + # wandb_config_args_dict = simple_parse_args_string(args.wandb_config_args) + # wandb_logger = WandbLogger(wandb_args_dict, wandb_config_args_dict) + + # TODO: change logging levels from fast_llm to lm_eval and then back? + # utils.setup_logging(args.verbosity) + # eval_logger = logging.getLogger(__name__) + + os.environ["TOKENIZERS_PARALLELISM"] = "false" + + # update the evaluation tracker args with the output path and the HF token + if args.output_path: + args.output_path = str(pathlib.Path(args.output_path) / f"runs/{run_index}/{completed_steps}") + args.hf_hub_log_args += f",output_path={args.output_path}" + if os.environ.get("HF_TOKEN", None): + args.hf_hub_log_args += f",token={os.environ.get('HF_TOKEN')}" + evaluation_tracker_args = simple_parse_args_string(args.hf_hub_log_args) + evaluation_tracker = EvaluationTracker(**evaluation_tracker_args) + + if args.predict_only: + args.log_samples = True + if (args.log_samples or args.predict_only) and not args.output_path: + raise ValueError("Specify --output_path if providing --log_samples or --predict_only") + + if args.fewshot_as_multiturn and args.apply_chat_template is False: + raise ValueError( + "When `fewshot_as_multiturn` is selected, `apply_chat_template` must be set (either to `True` or to the chosen template name)." + ) + + if args.include_path is not None: + eval_logger.info(f"Including path: {args.include_path}") + metadata = ( + simple_parse_args_string(args.model_args) + if isinstance(args.model_args, str) + else args.model_args if isinstance(args.model_args, dict) else {} + ) | (args.metadata if isinstance(args.metadata, dict) else simple_parse_args_string(args.metadata)) + + task_manager = TaskManager(include_path=args.include_path, metadata=metadata) + + if "push_samples_to_hub" in evaluation_tracker_args and not args.log_samples: + eval_logger.warning( + "Pushing samples to the Hub requires --log_samples to be set. Samples will not be pushed to the Hub." + ) + + if args.limit: + eval_logger.warning( + " --limit SHOULD ONLY BE USED FOR TESTING." "REAL METRICS SHOULD NOT BE COMPUTED USING LIMIT." + ) + if args.samples: + assert args.limit is None, "If --samples is not None, then --limit must be None." + if (samples := Path(args.samples)).is_file(): + args.samples = json.loads(samples.read_text()) + else: + args.samples = json.loads(args.samples) + + if args.tasks is None: + eval_logger.error("Need to specify task to evaluate.") + sys.exit() + elif args.tasks == "list": + print(task_manager.list_all_tasks()) + sys.exit() + elif args.tasks == "list_groups": + print(task_manager.list_all_tasks(list_subtasks=False, list_tags=False)) + sys.exit() + elif args.tasks == "list_tags": + print(task_manager.list_all_tasks(list_groups=False, list_subtasks=False)) + sys.exit() + elif args.tasks == "list_subtasks": + print(task_manager.list_all_tasks(list_groups=False, list_tags=False)) + sys.exit() + else: + if os.path.isdir(args.tasks): + import glob + + task_names = [] + yaml_path = os.path.join(args.tasks, "*.yaml") + for yaml_file in glob.glob(yaml_path): + config = utils.load_yaml_config(yaml_file) + task_names.append(config) + else: + task_list = args.tasks.split(",") + task_names = task_manager.match_tasks(task_list) + for task in [task for task in task_list if task not in task_names]: + if os.path.isfile(task): + config = utils.load_yaml_config(task) + task_names.append(config) + task_missing = [ + task for task in task_list if task not in task_names and "*" not in task + ] # we don't want errors if a wildcard ("*") task name was used + + if task_missing: + missing = ", ".join(task_missing) + eval_logger.error( + f"Tasks were not found: {missing}\n" + f"{utils.SPACING}Try `lm-eval --tasks list` for list of available tasks", + ) + raise ValueError( + f"Tasks not found: {missing}. Try `lm-eval --tasks {{list_groups,list_subtasks,list_tags,list}}` to list out all" + " available names for task groupings; only (sub)tasks; tags; or all of the above, or pass '--verbosity DEBUG'" + " to troubleshoot task registration issues." + ) + + # Respect user's value passed in via CLI, otherwise default to True and add to comma-separated model args + if args.trust_remote_code: + eval_logger.info( + "Passed `--trust_remote_code`, setting environment variable `HF_DATASETS_TRUST_REMOTE_CODE=true`" + ) + # HACK: import datasets and override its HF_DATASETS_TRUST_REMOTE_CODE value internally, + # because it's already been determined based on the prior env var before launching our + # script--`datasets` gets imported by lm_eval internally before these lines can update the env. + import datasets + + datasets.config.HF_DATASETS_TRUST_REMOTE_CODE = True + + args.model_args = args.model_args + ",trust_remote_code=True" + ( + eval_logger.info(f"Selected Tasks: {task_names}") + if eval_logger.getEffectiveLevel() >= logging.INFO + else print(f"Selected Tasks: {task_names}") + ) + + request_caching_args = request_caching_arg_to_dict(cache_requests=args.cache_requests) + + eval_kwargs = dict( + tasks=task_names, + num_fewshot=args.num_fewshot, + # batch_size=args.batch_size, + # max_batch_size=args.max_batch_size, + # device=args.device, + use_cache=args.use_cache, + limit=args.limit, + samples=args.samples, + check_integrity=args.check_integrity, + write_out=args.write_out, + log_samples=args.log_samples, + evaluation_tracker=evaluation_tracker, + system_instruction=args.system_instruction, + apply_chat_template=args.apply_chat_template, + fewshot_as_multiturn=args.fewshot_as_multiturn, + gen_kwargs=args.gen_kwargs, + task_manager=task_manager, + predict_only=args.predict_only, + random_seed=args.seed[0], + numpy_random_seed=args.seed[1], + torch_random_seed=args.seed[2], + fewshot_random_seed=args.seed[3], + confirm_run_unsafe_code=args.confirm_run_unsafe_code, + metadata=metadata, + **request_caching_args, + ) + + return args, eval_kwargs + + +def process_lm_eval_results( + args: argparse.Namespace, + results: dict[str, any], + evaluation_tracker: EvaluationTracker, + completed_steps: int, + consumed_samples: int, + consumed_tokens: int, +) -> None: + if results is not None: + import wandb + + if args.log_samples: + samples = results.pop("samples") + dumped = json.dumps(results, indent=2, default=handle_non_serializable, ensure_ascii=False) + if args.show_config: + print(dumped) + + batch_sizes = ",".join(map(str, results["config"]["batch_sizes"])) + + # Add W&B logging if we have the run to log to + # we expect the rest of the fast_llm code will finish the run. + if wandb.run is not None: + try: + wandb_logger = WandbLogger(init_args={"step": completed_steps}) + wandb_logger.post_init(results) + wandb_logger.log_eval_result() + if args.log_samples: + wandb_logger.log_eval_samples(samples) + except Exception as e: + eval_logger.info(f"Logging to Weights and Biases failed due to {e}") + + evaluation_tracker.save_results_aggregated(results=results, samples=samples if args.log_samples else None) + + if args.log_samples: + for task_name, config in results["configs"].items(): + evaluation_tracker.save_results_samples(task_name=task_name, samples=samples[task_name]) + + if evaluation_tracker.push_results_to_hub or evaluation_tracker.push_samples_to_hub: + evaluation_tracker.recreate_metadata_card() + + # TODO: convert to logging entries instead? + print( + f"{results["config"]["model"]}, gen_kwargs: ({args.gen_kwargs}), limit: {args.limit}, num_fewshot: {args.num_fewshot}, " + f"batch_size: {results["config"]["batch_size"]}{f' ({batch_sizes})' if batch_sizes else ''}" + ) + print(make_table(results)) + if "groups" in results: + print(make_table(results, "groups")) diff --git a/fast_llm/engine/training/trainer.py b/fast_llm/engine/training/trainer.py index 66f1ad86..a984a681 100644 --- a/fast_llm/engine/training/trainer.py +++ b/fast_llm/engine/training/trainer.py @@ -18,11 +18,13 @@ from fast_llm.engine.distributed.distributed import Distributed from fast_llm.engine.inference.runner import InferenceRunner from fast_llm.engine.multi_stage.config import StageMode +from fast_llm.engine.multi_stage.fast_llm_model import FastLLMModel from fast_llm.engine.optimizer.config import ParamGroup from fast_llm.engine.optimizer.optimizer import Optimizer from fast_llm.engine.schedule.runner import ScheduleRunner from fast_llm.engine.schedule.schedule import Schedule from fast_llm.engine.training.config import TrainerConfig, TrainingCheckpointBaseConfig, TrainingCheckpointConfig +from fast_llm.engine.training.evaluator import Evaluator from fast_llm.engine.training.wandb import Wandb from fast_llm.logging import format_metrics, get_memory_usage_mib, log_memory_usage from fast_llm.utils import Assert @@ -41,13 +43,20 @@ class Trainer[ConfigType: TrainerConfig](Configurable[ConfigType], abc.ABC): _completed_steps: int + _is_evaluation_only: bool + + _evaluator: Evaluator + def __init__(self, config: TrainerConfig): super().__init__(config) + + self._is_evaluation_only = config.training.train_iters == 0 + self._data = self._get_data() log_main_rank("Creating model...") self._multi_stage = self._config.model.get_model_class()( self._config.model, - optimizer_state_names=self._config.optimizer.state_names(), + optimizer_state_names=self._config.optimizer.state_names() if not self._is_evaluation_only else (), ) self._reference_models = {} for name, reference_config in self._config.reference_models.items(): @@ -65,45 +74,46 @@ def __init__(self, config: TrainerConfig): multi_stage=self._multi_stage, distributed_config=self._config.model.distributed, ) - steps_per_split = { - PhaseType.training: {PhaseType.training.value.lower(): self._config.training.train_iters}, - PhaseType.validation: { - dataset_name: self._config.training.evaluations[dataset_name].get_iteration_count( - self._config.training.train_iters, - # There may be an extra evaluation after the last training step. - not self._config.training.evaluations[dataset_name].enabled(self._config.training.train_iters), - ) - for dataset_name in self._config.training.evaluations.keys() - }, - PhaseType.test: {PhaseType.test.value.lower(): self._config.training.test_iters}, - } - self._samples_per_split = { - phase: { - dataset_name: self._config.batch.batch_size * steps - for dataset_name, steps in datasets.items() - if steps > 0 - } - for phase, datasets in steps_per_split.items() - } - # Prune empty phases. - self._samples_per_split = {k: v for k, v in self._samples_per_split.items() if len(v) > 0} - self._loss_defs = self._multi_stage.base_model.loss_defs - # Setup the schedules - self._schedule = { - phase: { - dataset_name: Schedule( - multi_stage=self._multi_stage, - batch_config=self._config.batch, - schedule_config=self._config.schedule, - distributed_config=self._config.model.distributed, - phase=phase, - ) - for dataset_name in datasets + if not self._is_evaluation_only: + steps_per_split = { + PhaseType.training: {PhaseType.training.value.lower(): self._config.training.train_iters}, + PhaseType.test: {PhaseType.test.value.lower(): self._config.training.test_iters}, } - for phase, datasets in self._samples_per_split.items() - } + + self._samples_per_split = { + phase: { + dataset_name: self._config.batch.batch_size * steps + for dataset_name, steps in datasets.items() + if steps > 0 + } + for phase, datasets in steps_per_split.items() + } + # Prune empty phases. + self._samples_per_split = {k: v for k, v in self._samples_per_split.items() if len(v) > 0} + + # Setup the schedules + self._schedule = { + phase: { + dataset_name: Schedule( + multi_stage=self._multi_stage, + batch_config=self._config.batch, + schedule_config=self._config.schedule, + distributed_config=self._config.model.distributed, + phase=phase, + ) + for dataset_name in datasets + } + for phase, datasets in self._samples_per_split.items() + } + else: + self._samples_per_split = {} + + self._evaluator = Evaluator( + config=self._config, + get_tflops_func=self.get_tflops, + ) def setup(self, distributed: Distributed, run: Run) -> None: assert distributed.config is self._config.model.distributed @@ -121,18 +131,23 @@ def setup(self, distributed: Distributed, run: Run) -> None: reference_model.fast_llm_model.setup(distributed, StageMode.inference) reference_model.setup() + # TODO: Check with Joel if this will be enought not to allocate grad buffers. # Setup the optimizer. - param_groups, grads_for_norm = self._multi_stage.get_param_groups(ParamGroup) - self._optimizer = self._config.optimizer.optimizer_cls( - self._config.optimizer, - param_groups=param_groups, - grads_for_norm=grads_for_norm, - distributed=self._distributed, - ) + if self._is_evaluation_only: + self._optimizer = None + else: + param_groups, grads_for_norm = self._multi_stage.get_param_groups(ParamGroup) + self._optimizer = self._config.optimizer.optimizer_cls( + self._config.optimizer, + param_groups=param_groups, + grads_for_norm=grads_for_norm, + distributed=self._distributed, + ) # Setup the schedules. with torch.no_grad(): self._runner.setup(distributed, self._optimizer) + # Setup the datasets. log_main_rank("Preparing datasets...") self._data.setup( @@ -141,10 +156,25 @@ def setup(self, distributed: Distributed, run: Run) -> None: dataset_name: self._get_sampling_parameters({"num_samples": samples}) for datasets in self._samples_per_split.values() for dataset_name, samples in datasets.items() + } + | { + dataset_name: self._get_sampling_parameters({"num_samples": samples}) + for dataset_name, samples in self._evaluator.get_datasets_samples().items() }, None if run.experiment_directory is None else run.experiment_directory / "dataset_cache", timeout=self._config.training.timeout, ) + + # Must be called with all arguments set up + self._evaluator.setup( + distributed=self._distributed, + run=self._run, + multi_stage=self._multi_stage, + runner=self._runner, + data=self._data, + wandb=self._wandb, + ) + self._is_setup = True @abc.abstractmethod @@ -166,21 +196,21 @@ def _consumed_tokens(self) -> int: assert self._is_setup return self._consumed_samples * self._config.batch.sequence_length - def _get_completed_evaluation_steps(self, dataset_name) -> int: - # Number of evaluations steps performed before the current step - return self._config.training.evaluations[dataset_name].get_iteration_count(self._completed_steps - 1) - def run(self) -> None: assert self._is_setup with self._wandb: self._run_training() def _run_training(self) -> None: - self._prepare_training_state() + self._prepare_model_state() + log_main_rank("done with setup ...") log_pipeline_parallel_main_rank(lambda: log_memory_usage(f"After initial setup", str)) self._run.save_logged_tensors("init") + if self._is_evaluation_only: + assert len(self._samples_per_split) == 0 + if PhaseType.training in self._samples_per_split: done = self._completed_steps >= self._config.training.train_iters if done: @@ -189,13 +219,21 @@ def _run_training(self) -> None: else: done, metrics = self._train() else: - done, metrics = True, {} + metrics = {} + done = True + self._evaluator.run( + metrics=metrics, + done=done, + completed_steps=0, + consumed_samples=0, + consumed_tokens=0, + ) if done and PhaseType.test in self._samples_per_split: log_main_rank(lambda: f"Running test phase ...") test_iterator = self._get_data_iterator(PhaseType.test.value.lower()) metrics_key = PhaseType.test.value - metrics[metrics_key] = self._evaluate( + metrics[metrics_key] = self._evaluate_loss( data_iterator=test_iterator, phase=PhaseType.test, num_iters=self._config.training.test_iters, @@ -223,7 +261,6 @@ def _train(self) -> tuple[bool, dict[PhaseType, dict[str, typing.Any]]]: self._completed_steps, self._config.training.prefetch_factor, ) - evaluation_iterators = {name: None for name in self._config.training.evaluations.keys()} log_main_rank("Training ...") @@ -323,49 +360,16 @@ def _train(self) -> tuple[bool, dict[PhaseType, dict[str, typing.Any]]]: done = self._completed_steps >= self._config.training.train_iters # TODO: Signal-based stop. stop = done or self._config.training.shutdown.enabled(self._completed_steps) + # Evaluation # TODO: Adjust valid iterator length. - if PhaseType.validation in self._samples_per_split and ( - done - or any( - evaluation_conf.enabled(self._completed_steps) - for evaluation_conf in self._config.training.evaluations.values() - ) - ): - formatted_metrics = [] - for dataset_name, evaluation_conf in self._config.training.evaluations.items(): - if not evaluation_conf.enabled(self._completed_steps): - continue - if evaluation_iterators[dataset_name] is None: - evaluation_iterators[dataset_name] = self._get_data_iterator( - dataset_name, self._get_completed_evaluation_steps(dataset_name) - ) - # TODO: formatting metric category as Validation.evaluation_dataset_name - # maybe format each metric with evaluation_dataset_name prefix instead? - # TODO: setting performance metrics per evaluation dataset - # maybe to set aggregate performance metrics for all evaluations datasets? - metric_key = f"{PhaseType.validation.value}.{dataset_name}" - metrics[metric_key] = self._evaluate( - data_iterator=evaluation_iterators[dataset_name], - phase=PhaseType.validation, - num_iters=evaluation_conf.iterations, - begin_iter=self._get_completed_evaluation_steps(dataset_name), - dataset_name=dataset_name, - ) - formatted_metrics.append( - format_metrics( - metrics[metric_key], - self._loss_defs, - PhaseType.validation, - dataset_name=dataset_name, - ) - ) - - if len(formatted_metrics) > 0: - formatted_metrics = "\n".join(formatted_metrics) - log_main_rank(formatted_metrics) - if self._config.training.wandb.alert.enabled(self._completed_steps): - self._wandb.alert("Validation results", formatted_metrics, "INFO") + self._evaluator.run( + metrics=metrics, + done=done, + completed_steps=self._completed_steps, + consumed_samples=self._consumed_samples, + consumed_tokens=self._consumed_tokens, + ) if is_main_rank() and metrics: self._wandb.log_metrics(self._completed_steps, metrics) @@ -379,55 +383,6 @@ def _train(self) -> tuple[bool, dict[PhaseType, dict[str, typing.Any]]]: profiler.step() return done, metrics - def _evaluate( - self, - *, - data_iterator: typing.Iterator, - phase: PhaseType, - num_iters: int, - begin_iter: int = 0, - dataset_name: str | None = None, - ) -> dict[str, float | int]: - full_phase_name = phase.value if dataset_name is None else f"{phase.value}_{dataset_name}" - safe_barrier(self._distributed.world_group, f"{full_phase_name} begin") - begin_time = time.perf_counter() - total_losses = {loss_def.name: 0.0 for loss_def in self._loss_defs} - for iter_ in range(num_iters): - iter_losses, _, _ = self._runner.run_step( - data_iterator, self._schedule[phase][dataset_name], iteration=begin_iter + iter_ - ) - for name, value in iter_losses.items(): - total_losses[name] += value - self._run.save_logged_tensors(f"{full_phase_name}_{self._completed_steps}_{iter_}") - - safe_barrier( - self._distributed.world_group, - f"{full_phase_name} end", - ) - end_time = time.perf_counter() - time_per_iteration = (end_time - begin_time) / num_iters - model_tflops, hardware_tflops = self.get_tflops(phase, time_per_iteration) - # TODO add other relevant eval metrics - metrics = { - "train_iters": self._config.training.train_iters, - "batch_size": self._config.batch.batch_size, - "iteration": self._completed_steps, - **{name: (value / num_iters) for name, value in total_losses.items()}, - "consumed_samples": self._consumed_samples, - "consumed_tokens": self._consumed_tokens, - "step_time_ms": time_per_iteration * 1000, - "model_tflops": model_tflops, - "hardware_tflops": hardware_tflops, - "tokens_per_sec_per_gpu": ( - (self._config.batch.sequence_length * self._config.batch.batch_size) - / self._config.model.distributed.world_size - / time_per_iteration - ), - **get_memory_usage_mib(), - } - - return metrics - def _get_data_iterator( self, dataset_name, completed_steps: int = 0, prefetch_factor: int | None = None ) -> typing.Iterator[typing.Any]: @@ -440,7 +395,7 @@ def _get_data_iterator( timeout=self._config.training.timeout, ) - def _prepare_training_state(self) -> None: + def _prepare_model_state(self) -> None: # Setup the training state. if (last_iteration := self._get_last_checkpoint()) is None: if (path := self._config.pretrained.path) is not None and self._config.pretrained.model_weights: @@ -451,9 +406,15 @@ def _prepare_training_state(self) -> None: ) self._multi_stage.load_checkpoint(self._config.pretrained) else: + if self._is_evaluation_only: + raise ValueError( + "Evaluation mode, model need to be trained first or pretrained checkpoint is provided for loading" + ) log_main_rank(f"Initializing training state from scratch...") self._multi_stage.initialize_weights() - self._optimizer.reset_state() + + if not self._is_evaluation_only: + self._optimizer.reset_state() self._completed_steps = 0 else: log_main_rank(lambda: f"Loading checkpoint from iteration {last_iteration}...") diff --git a/fast_llm/layers/language_model/head.py b/fast_llm/layers/language_model/head.py index 3b476f6a..5dd6e7b6 100644 --- a/fast_llm/layers/language_model/head.py +++ b/fast_llm/layers/language_model/head.py @@ -5,7 +5,7 @@ from torch.distributed import all_reduce from fast_llm.config import Configurable -from fast_llm.core.ops import split_op +from fast_llm.core.ops import gather_op, split_op from fast_llm.engine.base_model.base_model import Layer from fast_llm.engine.config_utils.tensor_space import DefaultDimNames, TensorDim, TensorSpace from fast_llm.engine.distributed.config import DistributedDimNames @@ -168,6 +168,14 @@ def _forward_backward( with torch.enable_grad(): ln_output = self.final_norm(input_) + if "output_hidden_states" in kwargs and kwargs["output_hidden_states"]: + # The last hidden layer output is returned normalized in the HF Transformers-style output, at least for LLama style models. + # So, if needed, we gather the data after normalization and set it as the output of the previous layer. + group = self._tensor_space.distributed.tensor_group if self._parallel_embeddings else None + sequence_parallel = self._sequence_parallel and self._parallel_embeddings + hidden_state = gather_op(ln_output.detach(), group, dim=0) if sequence_parallel else ln_output.detach() + kwargs["hidden_states"][len(kwargs["hidden_states"]) - 1]["tensor"] = hidden_state + grad_output = kwargs[TransformerKwargs.grad_output] / ( self._group_size if self._sequence_parallel_logits else 1 ) diff --git a/fast_llm/layers/transformer/preprocessing.py b/fast_llm/layers/transformer/preprocessing.py index 2415a2f9..1e07c1c1 100644 --- a/fast_llm/layers/transformer/preprocessing.py +++ b/fast_llm/layers/transformer/preprocessing.py @@ -239,7 +239,7 @@ def preprocess(self, batch, kwargs: dict[str, typing.Any]) -> None: ] if (sequence_lengths := kwargs.get(TransformerKwargs.sequence_lengths, None)) is not None: seq_ids = torch.stack( - [torch.cat([torch.arange(x) for x in sample_lens]) for sample_lens in sequence_lengths] + [torch.cat([torch.full((x,), i) for i, x in enumerate(sample_lens)]) for sample_lens in sequence_lengths] ) document_mask = (seq_ids[:, None, :] == seq_ids[:, :, None]).to(self._tensor_space.distributed.device) kwargs[TransformerKwargs.attention_mask] = ( diff --git a/fast_llm/models/custom/config.py b/fast_llm/models/custom/config.py index 1c82b59e..5c87a4ca 100644 --- a/fast_llm/models/custom/config.py +++ b/fast_llm/models/custom/config.py @@ -47,7 +47,7 @@ def get_model_class(cls) -> type["CustomModel"]: return CustomModel @classmethod - def get_huggingface_model_class(cls) -> type["HuggingfaceCustomModelForCausalLM"]: + def get_huggingface_model_for_causal_lm_class(cls) -> type["HuggingfaceCustomModelForCausalLM"]: from fast_llm.models.custom.huggingface import HuggingfaceCustomModelForCausalLM return HuggingfaceCustomModelForCausalLM diff --git a/fast_llm/models/gpt/config.py b/fast_llm/models/gpt/config.py index 18809419..30f3a4ff 100644 --- a/fast_llm/models/gpt/config.py +++ b/fast_llm/models/gpt/config.py @@ -161,7 +161,7 @@ def get_model_class(cls) -> type["GPTModel"]: return GPTModel @classmethod - def get_huggingface_model_class(cls) -> type["HuggingfaceGPTModelForCausalLM"]: + def get_huggingface_model_for_causal_lm_class(cls) -> type["HuggingfaceGPTModelForCausalLM"]: from fast_llm.models.gpt.huggingface import HuggingfaceGPTModelForCausalLM return HuggingfaceGPTModelForCausalLM diff --git a/fast_llm/models/gpt/huggingface.py b/fast_llm/models/gpt/huggingface.py index 0da4acbb..3f7e43ca 100644 --- a/fast_llm/models/gpt/huggingface.py +++ b/fast_llm/models/gpt/huggingface.py @@ -5,10 +5,11 @@ import torch import transformers.modeling_outputs + from fast_llm.data.data.gpt.data import GPTBatch from fast_llm.engine.distributed.config import PhaseType from fast_llm.engine.inference.config import HuggingfaceModelConfig -from fast_llm.engine.inference.huggingface import HuggingfacePreTrainedModel +from fast_llm.engine.inference.huggingface import HuggingfaceBaseModelForCausalLM from fast_llm.layers.transformer.config import TransformerKwargs from fast_llm.models.gpt.config import GPTModelConfig from fast_llm.models.gpt.model import GPTBaseModel, GPTInferenceRunner @@ -22,7 +23,7 @@ class HuggingfaceGPTModelConfig(HuggingfaceModelConfig): fast_llm_config: GPTModelConfig -class HuggingfaceGPTModelForCausalLM(HuggingfacePreTrainedModel): +class HuggingfaceGPTModelForCausalLM(HuggingfaceBaseModelForCausalLM): config_class = HuggingfaceGPTModelConfig config: HuggingfaceGPTModelConfig runner_class: typing.ClassVar[type[GPTInferenceRunner]] = GPTInferenceRunner @@ -55,21 +56,33 @@ def forward( if output_attentions: raise NotImplementedError() - if output_hidden_states: - raise NotImplementedError() - if attention_mask is not None: - raise NotImplementedError() - if position_ids is not None: - raise NotImplementedError() if inputs_embeds is not None: raise NotImplementedError() if labels is not None: raise NotImplementedError() + # NOTE: We are ignoring position_ids as we reconstruct them from attention_mask via sequence_lenghts. + if attention_mask is not None: + + # First non zero indexes or zero index if the row is all zeros (invalid row) + first_non_zero_indexes = attention_mask.argmax(dim=1) + + # Check if the sequence is left-padded and if the remaining ones are continuous 1-ns + assert (attention_mask.sum(axis=1) == (attention_mask.shape[1] - first_non_zero_indexes)).all() + + sequence_lenghts = [ + torch.tensor( + [attention_mask.shape[1]] if el == 0 else [el, attention_mask.shape[1] - el], dtype=torch.int64 + ) + for el in first_non_zero_indexes.tolist() + ] + else: + sequence_lenghts = None + # Iteration serves as a random seed, using random module because it's not seeded by Fast LLM iteration = random.randint(0, 2**32) batch = self.fast_llm_base_model.preprocess( - GPTBatch(input_ids), phase=PhaseType.inference, iteration=iteration + GPTBatch(input_ids, sequence_lengths=sequence_lenghts), phase=PhaseType.inference, iteration=iteration ) ((input_, kwargs),) = batch @@ -82,23 +95,39 @@ def forward( # The transformers will save the present keys and values to this list. kwargs[TransformerKwargs.presents] = [] + if output_hidden_states: + kwargs["output_hidden_states"] = True + else: + kwargs["output_hidden_states"] = False + self._inference_runner.forward(input_, kwargs, iteration=iteration) # TODO: Make a proper way of returning the model output. logits = kwargs["logits"] + # TODO: convert hidden state form dict to list to be the same as with HFs + hidden_states = None + if output_hidden_states: + hidden_states = kwargs["hidden_states"] + if not return_dict: - outputs = (logits,) + # TODO: check hidden state go before past in the tuple + if output_hidden_states: + outputs = (logits, hidden_states) + else: + outputs = (logits,) + if use_cache: outputs += (kwargs[TransformerKwargs.presents],) return outputs return transformers.modeling_outputs.CausalLMOutputWithPast( logits=logits, + hidden_states=hidden_states, past_key_values=kwargs[TransformerKwargs.presents], ) - def prepare_inputs_for_generation( - self, input_ids, past_key_values=None, attention_mask=None, inputs_embeds=None, **kwargs - ): - raise NotImplementedError() + # def prepare_inputs_for_generation( + # self, input_ids, past_key_values=None, attention_mask=None, inputs_embeds=None, **kwargs + # ): + # raise NotImplementedError() diff --git a/fast_llm/tools/cli.py b/fast_llm/tools/cli.py index 0cc02f42..b36a294d 100644 --- a/fast_llm/tools/cli.py +++ b/fast_llm/tools/cli.py @@ -15,11 +15,13 @@ def fast_llm(args=None): # (Pre-)configure logging configure_logging() parser = argparse.ArgumentParser(add_help=False) - parser.add_argument("subcommand", choices=["train", "convert", "prepare"]) + parser.add_argument("subcommand", choices=["train", "evaluate", "convert", "prepare"]) parsed, unparsed = parser.parse_known_args(args) try: if parsed.subcommand == "train": from fast_llm.tools.train import CliTrainingConfig as Runnable + elif parsed.subcommand == "evaluate": + from fast_llm.tools.evaluate import CliEvaluationConfig as Runnable elif parsed.subcommand == "convert": from fast_llm.tools.convert import ConversionConfig as Runnable elif parsed.subcommand == "prepare": diff --git a/fast_llm/tools/evaluate.py b/fast_llm/tools/evaluate.py new file mode 100644 index 00000000..26a9aa9c --- /dev/null +++ b/fast_llm/tools/evaluate.py @@ -0,0 +1,25 @@ +import argparse + +from fast_llm.engine.config_utils.runnable import RunnableConfig +from fast_llm.models.auto import trainer_registry + + +class CliEvaluationConfig(RunnableConfig): + @classmethod + def _get_parser(cls): + parser = super()._get_parser() + parser.add_argument( + "model_type", + choices=trainer_registry.keys(), + help="The Fast-LLM model type to use. Must be defined in the trainer registry in `fast_llm.models.auto`.", + ) + return parser + + @classmethod + def _from_parsed_args(cls, parsed: argparse.Namespace, unparsed: list[str]): + unparsed += ['training.train_iters=0'] + return trainer_registry[parsed.model_type]._from_parsed_args(parsed, unparsed) + + +if __name__ == "__main__": + CliEvaluationConfig.parse_and_run() diff --git a/test.py b/test.py new file mode 100644 index 00000000..e02fb32d --- /dev/null +++ b/test.py @@ -0,0 +1,216 @@ +import torch + +from pathlib import Path +import shutil +import cloudpickle + +from transformers import AutoTokenizer, AutoModelForCausalLM +from transformers.modeling_outputs import CausalLMOutputWithPast +from fast_llm.models.gpt.huggingface import HuggingfaceGPTModelForCausalLM +from fast_llm.engine.checkpoint.config import CheckpointLoadConfig +from fast_llm.models.gpt.config import LlamaGPTHuggingfaceCheckpointFormat + +import torch + + +def generate(model, input_ids, attention_mask, max_new_tokens, tensors_save_path: Path | None = None): + + if tensors_save_path is not None: + if tensors_save_path.is_dir(): + shutil.rmtree(tensors_save_path, ignore_errors=True) + logits_save_path = tensors_save_path / "logits" + hs_save_path = tensors_save_path / "hidden_states" + logits_save_path.mkdir(exist_ok=True, parents=True) + hs_save_path.mkdir(exist_ok=True, parents=True) + + # assume attention mask is left padded with zeroes if any + mask_step = torch.ones((attention_mask.shape[0], 1), dtype=torch.int64).to(attention_mask.device) + for i in range(max_new_tokens): + output: CausalLMOutputWithPast = model.forward( + input_ids=input_ids, + attention_mask=attention_mask, + position_ids=None, + past_key_values=None, + inputs_embeds=None, + labels=None, + use_cache=False, + output_attentions=False, + output_hidden_states=True, + return_dict=True, + ) + current_ids = output.logits[:, -1, :].argmax(dim=1, keepdim=True) + input_ids = torch.cat([input_ids, current_ids], dim=1) + attention_mask = torch.cat([attention_mask, mask_step], dim=1) + + if tensors_save_path is not None: + logits_file = logits_save_path / f"tensor{i}.pt" + torch.save(output.logits, logits_file) + + hidden_states_file = hs_save_path / f"data{i}.pickle" + with hidden_states_file.open("wb") as f: + cloudpickle.dump(output.hidden_states, f) + + return input_ids + + +def diff_flm_hf(tokenizer, flm_tokens, hf_tokens): + print("+++++++++++++++fast_llm:+++++++++++++++++++++++++++++++++++++++++++++++++") + fllm_str = tokenizer.decode(flm_tokens) + print(fllm_str) + print("---------------hugging_face:---------------------------------------------") + hf_str = tokenizer.decode(hf_tokens) + print(hf_str) + print( + f"==============================({"Same" if fllm_str==hf_str else "Different"})=====================================" + ) + + +def run_test_fast_llm( + attn_implementation, + torch_dtype, + is_batch_size2, + reverse_samples, + tensors_save_path, + num_new_tokens, +): + checkpoint = "/mnt/checkpoints/pretrained_models/SmolLM2-135M-Instruct" + + device = "cuda" # for GPU usage or "cpu" for CPU usage + tokenizer = AutoTokenizer.from_pretrained(checkpoint) + messages = [ + # {"role": "user", "content": "What is gravity?"}, + {"role": "user", "content": "What is gravity?"}, + {"role": "user", "content": "Who is the president of EU?"}, + # {"role": "user", "content": "Who is the president of EU?"}, + ] + if reverse_samples: + messages = list(reversed(messages)) + if not is_batch_size2: + messages = messages[0:1] + + input_text = [tokenizer.apply_chat_template([el], tokenize=False) for el in messages] + + tokenizer.padding_side = "left" + inputs = tokenizer(input_text, padding="longest", return_tensors="pt").to(device) + + fm_kwards = {} + if attn_implementation is not None and attn_implementation == "flash_attention_2": + fm_kwards["attn_implementation"] = "flash_attention_2" + else: + fm_kwards["attn_implementation"] = "fuse" + if torch_dtype is not None and torch_dtype == torch.bfloat16: + fm_kwards["torch_dtype"] = "bf16" + + print("fm_kwards", fm_kwards) + + model_fm = HuggingfaceGPTModelForCausalLM.from_pretrained( + CheckpointLoadConfig( + path=checkpoint, + format=LlamaGPTHuggingfaceCheckpointFormat, + ), + **fm_kwards, + ) + + # outputs_fm = model_fm.generate(**inputs, max_new_tokens=50, use_cache=False) + outputs_fm = generate( + model_fm, **inputs, max_new_tokens=num_new_tokens, tensors_save_path=tensors_save_path / "fast_llm" + ) + + print(tokenizer.decode(outputs_fm[0][inputs["input_ids"].shape[1] :])) + if len(outputs_fm) > 1: + print("--------------------------------------------------------------") + print(tokenizer.decode(outputs_fm[1][inputs["input_ids"].shape[1] :])) + + +def run_test( + attn_implementation, + torch_dtype, + is_batch_size2, + reverse_samples, + tensors_save_path, + num_new_tokens, +): + checkpoint = "/mnt/checkpoints/pretrained_models/SmolLM2-135M-Instruct" + + device = "cuda" # for GPU usage or "cpu" for CPU usage + tokenizer = AutoTokenizer.from_pretrained(checkpoint) + # for multiple GPUs install accelerate and do `model = AutoModelForCausalLM.from_pretrained(checkpoint, device_map="auto")` + hf_kwards = {} + if attn_implementation is not None and attn_implementation == "flash_attention_2": + hf_kwards["attn_implementation"] = "flash_attention_2" + if torch_dtype is not None: + hf_kwards["torch_dtype"] = torch_dtype + + print("hf_kwards", hf_kwards) + model_hf = AutoModelForCausalLM.from_pretrained(checkpoint, **hf_kwards).to(device) + + messages = [ + # {"role": "user", "content": "What is gravity?"}, + {"role": "user", "content": "Who is the president of EU?"}, + {"role": "user", "content": "Who is the president of EU?"}, + ] + if reverse_samples: + messages = list(reversed(messages)) + if not is_batch_size2: + messages = messages[0:1] + + input_text = [tokenizer.apply_chat_template([el], tokenize=False) for el in messages] + + tokenizer.padding_side = "left" + inputs = tokenizer(input_text, padding="longest", return_tensors="pt").to(device) + + # outputs_hf = model_hf.generate(**inputs, max_new_tokens=50, use_cache=False) + outputs_hf = generate( + model_hf, **inputs, max_new_tokens=num_new_tokens, tensors_save_path=tensors_save_path / "hf" + ) + # print(tokenizer.decode(outputs_hf[0])) + + fm_kwards = {} + if attn_implementation is not None and attn_implementation == "flash_attention_2": + fm_kwards["attn_implementation"] = "flash_attention_2" + else: + fm_kwards["attn_implementation"] = "fuse" + if torch_dtype is not None and torch_dtype == torch.bfloat16: + fm_kwards["torch_dtype"] = "bf16" + + print("fm_kwards", fm_kwards) + + model_fm = HuggingfaceGPTModelForCausalLM.from_pretrained( + CheckpointLoadConfig( + path=checkpoint, + format=LlamaGPTHuggingfaceCheckpointFormat, + ), + **fm_kwards, + ) + + # outputs_fm = model_fm.generate(**inputs, max_new_tokens=50, use_cache=False) + outputs_fm = generate( + model_fm, **inputs, max_new_tokens=num_new_tokens, tensors_save_path=tensors_save_path / "fast_llm" + ) + + diff_flm_hf( + tokenizer, outputs_fm[0][inputs["input_ids"].shape[1] :], outputs_hf[0][inputs["input_ids"].shape[1] :] + ) + if len(outputs_fm) > 1: + diff_flm_hf( + tokenizer, outputs_fm[1][inputs["input_ids"].shape[1] :], outputs_hf[1][inputs["input_ids"].shape[1] :] + ) + + +def main(): + run_test_fast_llm( + # run_test( + attn_implementation="flash_attention_2", + # attn_implementation=None, + torch_dtype=torch.bfloat16, + # torch_dtype=None, + is_batch_size2=True, + reverse_samples=False, + # tensors_save_path=Path("/mnt/datasets/tests/denis/tensors_bf16_flash_attention_2_batch_size2/"), + tensors_save_path=Path("/mnt/datasets/tests/denis/tmp/"), + num_new_tokens=100, + ) + + +if __name__ == "__main__": + main() diff --git a/test_distributed.py b/test_distributed.py new file mode 100644 index 00000000..35b84677 --- /dev/null +++ b/test_distributed.py @@ -0,0 +1,55 @@ +# distributed_example.py +import os +import torch +import torch.distributed as dist + +from transformers import AutoTokenizer +from transformers.modeling_outputs import CausalLMOutputWithPast + +from fast_llm.engine.checkpoint.config import CheckpointLoadConfig +from fast_llm.engine.distributed.config import DistributedConfig +from fast_llm.engine.distributed.distributed import Distributed +from fast_llm.models.gpt.config import LlamaGPTHuggingfaceCheckpointFormat, Qwen2GPTHuggingfaceCheckpointFormat +from fast_llm.models.gpt.huggingface import HuggingfaceGPTModelForCausalLM + + +def run( + attn_implementation="flash_attention_2", + torch_dtype=torch.bfloat16, + checkpoint="/mnt/checkpoints/pretrained_models/Qwen2-1.5B-Instruct/", +): + tokenizer = AutoTokenizer.from_pretrained(checkpoint) + + updates = { + ("base_model", "transformer", "use_flash_attention"): attn_implementation is not None + and attn_implementation == "flash_attention_2", + ("distributed", "tensor_parallel"): 2, + ("distributed", "pipeline_parallel"): 1, + ("distributed", "sequence_data_parallel"): 1, + } + + if torch_dtype is not None and torch_dtype == torch.bfloat16: + updates[("distributed", "training_dtype")] = "bf16" + + print("aupdatesgs", updates) + + model_fm = HuggingfaceGPTModelForCausalLM.from_pretrained( + CheckpointLoadConfig( + path=checkpoint, + format=Qwen2GPTHuggingfaceCheckpointFormat, + ), + updates, + ) + + input_ids = torch.randint(1, tokenizer.vocab_size, (10, 100), dtype=torch.int64, generator=torch.Generator().manual_seed(42)) + + res = model_fm.forward(input_ids, use_cache=False) + print(res.logits.shape, res.logits.sum().item()) + + +def main(): + run() + + +if __name__ == "__main__": + main() diff --git a/tests/test_checkpoint.py b/tests/test_checkpoint.py index 8ae30ee4..3ce38c38 100644 --- a/tests/test_checkpoint.py +++ b/tests/test_checkpoint.py @@ -32,7 +32,7 @@ from tests.compare_tensor_logs import CompareConfig, compare_logged_tensor TEST_MODEL_CONFIG_CLS = model_registry[TEST_MODEL_TYPE] -TEST_MODEL_HF_CLS = TEST_MODEL_CONFIG_CLS.get_huggingface_model_class() +TEST_MODEL_HF_CLS = TEST_MODEL_CONFIG_CLS.get_huggingface_model_for_causal_lm_class() TEST_MODEL_CLS = TEST_MODEL_CONFIG_CLS.get_model_class() TEST_BASE_MODEL_CONFIG_CLS = TEST_MODEL_CONFIG_CLS.get_base_model_config_class() TEST_ARCHITECTURE_CONFIG_CLS = TEST_BASE_MODEL_CONFIG_CLS.architecture_class