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..1934a1c6 --- /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: 32 +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..1e1eb658 --- /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: 32 +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/core/distributed.py b/fast_llm/core/distributed.py index e82e0801..09daa438 100644 --- a/fast_llm/core/distributed.py +++ b/fast_llm/core/distributed.py @@ -6,12 +6,17 @@ Todo: Move all core methods elsewhere (functional?). """ +import collections import contextlib import datetime +import io +import itertools import logging +import pickle import typing import torch +import torch.monitor from torch._C._distributed_c10d import Work from torch.distributed import ( # noqa ProcessGroup, @@ -26,6 +31,117 @@ logger = logging.getLogger(__name__) +def _as_iterable(obj) -> collections.abc.Iterable: + return obj if isinstance(obj, list) else (obj,) + + +def _check_single_tensor(param, param_name) -> None: + """Check that the parameter ``param_name`` is a single tensor.""" + if not isinstance(param, torch.Tensor): + raise TypeError( + f"""Invalid function argument. Expected parameter `{param_name}` of type torch.Tensor + but got {type(param)} instead.""" + ) + + +def _check_tensor_list(param, param_name) -> None: + """Check that the parameter ``param_name`` is a list of tensors.""" + if not isinstance(param, list): + raise TypeError( + f"""Invalid function argument. Expected parameter `{param_name}` of type List[torch.Tensor] + but got {type(param)} instead.""" + ) + elif not all(isinstance(p, torch.Tensor) for p in param): + raise TypeError( + f"""Invalid function argument. Expected parameter `{param_name}` of type List[torch.Tensor] + but got {type(param)} with elements of type {[type(p) for p in param]}.""" + ) + + +def _ensure_all_tensors_same_dtype(*tensors) -> None: + last_dtype = None + for tensor in itertools.chain.from_iterable(map(_as_iterable, tensors)): + tensor_dtype = tensor.dtype + # Mixing complex and its element type is allowed + if tensor_dtype.is_complex: + tensor_dtype = torch.float32 if tensor_dtype == torch.complex64 else torch.complex128 + + if last_dtype is None: + last_dtype = tensor_dtype + else: + if last_dtype != tensor_dtype: + raise ValueError( + "Invalid usage of tensors with different dtypes" f"Found {last_dtype} and {tensor.dtype}" + ) + + +def _rank_not_in_group(group: typing.Optional[ProcessGroup]) -> bool: + """Check if the current process's rank is not in a given group.""" + if group is None: + return False + return group == torch.distributed.GroupMember.NON_GROUP_MEMBER + + +def _warn_not_in_group(op_name) -> None: + # TODO: get global rank + global_rank = -1 + logger.warning(f"Running {op_name} on global rank {global_rank} which does not " "belong to the given group.") + + +_pickler = pickle.Pickler +_unpickler = pickle.Unpickler + + +def _object_to_tensor(obj, device, group): + with torch.monitor._WaitCounter("pytorch.wait_counter.c10d._object_to_tensor").guard(): + f = io.BytesIO() + _pickler(f).dump(obj) + byte_storage = torch.ByteStorage._from_buffer(f.getvalue()) # type: ignore[attr-defined] + # Do not replace `torch.ByteTensor` or `torch.LongTensor` with torch.tensor and specifying dtype. + # Otherwise, it will casue 100X slowdown. + # See: https://github.com/pytorch/pytorch/issues/65696 + byte_tensor = torch.ByteTensor(byte_storage).to(device) + + # TODO: do we need to log this level of details? + # if get_debug_level() == DebugLevel.DETAIL and is_nccl_available(): + # backend = get_backend(group) + # if backend == Backend.NCCL: + # hash = torch._C._distributed_c10d._hash_tensors([byte_tensor]) + # logger.warning( + # "_object_to_tensor size: %s hash value: %s", + # byte_tensor.numel(), + # hash, + # ) + + local_size = torch.LongTensor([byte_tensor.numel()]).to(device) + return byte_tensor, local_size + + +def _tensor_to_object(tensor, tensor_size, group): + with torch.monitor._WaitCounter("pytorch.wait_counter.c10d._tensor_to_object").guard(): + + # TODO: do we need to log this level of details? + # if get_debug_level() == DebugLevel.DETAIL and is_nccl_available(): + # backend = get_backend(group) + # if backend == Backend.NCCL: + # hash = torch._C._distributed_c10d._hash_tensors([tensor]) + # logger.warning( + # "_tensor_to_object size: %s hash value: %s", tensor.numel(), hash + # ) + + tensor = tensor.cpu() + buf = tensor.numpy().tobytes()[:tensor_size] + return _unpickler(io.BytesIO(buf)).load() + + +def _validate_output_list_for_rank(my_rank, dst, gather_list): + if dst == my_rank: + if not gather_list: + raise ValueError("Argument ``gather_list`` must be specified on destination rank.") + elif gather_list: + raise ValueError("Argument ``gather_list`` must NOT be specified on non-destination ranks.") + + def add_ephemeral_timeout(group: ProcessGroup, timeout: float | None = None) -> None: if group is not None and timeout is not None: # TODO: Only works for nccl? @@ -133,3 +249,406 @@ def set_generator(generator: torch.Generator) -> typing.Generator[None, None, No finally: generator.set_state(default_generator.get_state()) default_generator.set_state(old_state) + + +def gather( + tensor: torch.Tensor, + gather_list: typing.Optional[list[torch.Tensor]] = None, + group: typing.Optional[ProcessGroup] = None, + async_op: bool = False, + group_dst: typing.Optional[int] = None, +): + """ + Gathers a list of tensors in a single process. + + This function requires all tensors to be the same size on each process. + + Args: + tensor (Tensor): Input tensor. + gather_list (list[Tensor], optional): List of appropriately, + same-sized tensors to use for gathered data + (default is None, must be specified on the destination rank) + group (ProcessGroup, optional): The process group to work on. + async_op (bool, optional): Whether this op should be an async op + group_dst (int, optional): Destination rank on ``group``. + + Returns: + Async work handle, if async_op is set to True. + None, if not async_op or if not part of the group + + .. note:: Note that all Tensors in gather_list must have the same size. + + Example:: + >>> # xdoctest: +SKIP("no rank") + >>> # We have 2 process groups, 2 ranks. + >>> tensor_size = 2 + >>> device = torch.device(f'cuda:{rank}') + >>> tensor = torch.ones(tensor_size, device=device) + rank + >>> if dist.get_rank() == 0: + >>> gather_list = [torch.zeros_like(tensor, device=device) for i in range(2)] + >>> else: + >>> gather_list = None + >>> dist.gather(tensor, gather_list, dst=0) + >>> # Rank 0 gets gathered data. + >>> gather_list + [tensor([1., 1.], device='cuda:0'), tensor([2., 2.], device='cuda:0')] # Rank 0 + None # Rank 1 + + """ + _check_single_tensor(tensor, "tensor") + + # Parameter ``gather_list`` may be left unspecified on non-dst ranks. + if gather_list: + _check_tensor_list(gather_list, "gather_list") + else: + gather_list = [] + _ensure_all_tensors_same_dtype(tensor, gather_list) + assert group is not None + if _rank_not_in_group(group): + _warn_not_in_group("gather") + return + if group_dst is None: + group_dst = 0 + my_group_rank = group.rank() + _validate_output_list_for_rank(my_group_rank, group_dst, gather_list) + output_tensors = [gather_list] if group_dst == my_group_rank else [] + input_tensors = [tensor] + + opts = torch.distributed.GatherOptions() + opts.rootRank = group_dst + # Absent in ver 2.6 + #opts.asyncOp = async_op + work = group.gather(output_tensors, input_tensors, opts) + + if async_op: + return work + elif work is not None: # Backward compatible with backends that don't sync at CPP level + work.wait() + # Otherwise, the backend has sync'ed at CPP level + + +def scatter( + tensor: torch.Tensor, + scatter_list: typing.Optional[list[torch.Tensor]] = None, + group: typing.Optional[ProcessGroup] = None, + async_op: bool = False, + group_src: typing.Optional[int] = None, +): + """ + Scatters a list of tensors to all processes in a group. + + Each process will receive exactly one tensor and store its data in the + ``tensor`` argument. + + Complex tensors are supported. + + Args: + tensor (Tensor): Output tensor. + scatter_list (list[Tensor]): List of tensors to scatter (default is + None, must be specified on the source rank) + group (ProcessGroup, optional): The process group to work on. + async_op (bool, optional): Whether this op should be an async op + group_src (int, optional): Source rank on ``group``. + + Returns: + Async work handle, if async_op is set to True. + None, if not async_op or if not part of the group + + .. note:: Note that all Tensors in scatter_list must have the same size. + + Example:: + >>> # xdoctest: +SKIP("need process group init") + >>> # Note: Process group initialization omitted on each rank. + >>> import torch.distributed as dist + >>> tensor_size = 2 + >>> device = torch.device(f'cuda:{rank}') + >>> output_tensor = torch.zeros(tensor_size, device=device) + >>> if dist.get_rank() == 0: + >>> # Assumes world_size of 2. + >>> # Only tensors, all of which must be the same size. + >>> t_ones = torch.ones(tensor_size, device=device) + >>> t_fives = torch.ones(tensor_size, device=device) * 5 + >>> scatter_list = [t_ones, t_fives] + >>> else: + >>> scatter_list = None + >>> dist.scatter(output_tensor, scatter_list, src=0) + >>> # Rank i gets scatter_list[i]. + >>> output_tensor + tensor([1., 1.], device='cuda:0') # Rank 0 + tensor([5., 5.], device='cuda:1') # Rank 1 + + """ + _check_single_tensor(tensor, "tensor") + # Parameter ``scatter_list`` may be left unspecified on non-src ranks. + if scatter_list: + _check_tensor_list(scatter_list, "scatter_list") + else: + scatter_list = [] + _ensure_all_tensors_same_dtype(tensor, scatter_list) + assert group is not None + if group_src is None: + group_src = 0 + if _rank_not_in_group(group): + _warn_not_in_group("scatter") + return + scatter_list = [t if not t.is_complex() else torch.view_as_real(t) for t in scatter_list] + tensor = tensor if not tensor.is_complex() else torch.view_as_real(tensor) + + my_group_rank = group.rank() + if group_src == my_group_rank: + if not scatter_list: + raise ValueError("Argument ``scatter_list`` must be specified on source rank.") + input_tensors = [scatter_list] + output_tensors = [tensor] + else: + if scatter_list: + raise ValueError("Argument ``scatter_list`` must NOT be specified on non-source ranks.") + input_tensors = [] + output_tensors = [tensor] + + opts = torch.distributed.ScatterOptions() + opts.rootRank = group_src + opts.asyncOp = async_op + work = group.scatter(output_tensors, input_tensors, opts) + + if async_op: + return work + elif work is not None: # Backward compatible with backends that don't sync at CPP level + work.wait() + # Otherwise, the backend has sync'ed at CPP level + + +def gather_object( + current_device: torch.device | str, + obj: typing.Any, + object_gather_list: typing.Optional[list[typing.Any]] = None, + group: typing.Optional[ProcessGroup] = None, + group_dst: typing.Optional[int] = None, +): + """ + Gathers picklable objects from the whole group in a single process. + + Similar to :func:`gather`, but Python objects can be passed in. Note that the + object must be picklable in order to be gathered. + + Args: + current_device: (torch.device | str): device to use for object serialization to + tensor, must be this process assigned gpu for nccl backend. + obj (Any): Input object. Must be picklable. + object_gather_list (list[Any]): Output list. On the ``dst`` rank, it + should be correctly sized as the size of the group for this + collective and will contain the output. Must be ``None`` on non-dst + ranks. (default is ``None``) + dst (int, optional): Destination rank on global process group (regardless of ``group`` argument). + (If both ``dst`` and ``group_dst`` are None, default is global rank 0) + group: (ProcessGroup, optional): The process group to work on. If None, + the default process group will be used. Default is ``None``. + group_dst (int, optional): Destination rank on ``group``. Invalid to specify both ``dst`` and ``group_dst`` + + Returns: + None. On the ``dst`` rank, ``object_gather_list`` will contain the + output of the collective. + + .. note:: Note that this API differs slightly from the gather collective + since it does not provide an async_op handle and thus will be a blocking + call. + + .. note:: For NCCL-based processed groups, internal tensor representations + of objects must be moved to the GPU device before communication takes + place. In this case, the device used is given by + ``torch.cuda.current_device()`` and it is the user's responsiblity to + ensure that this is set so that each rank has an individual GPU, via + ``torch.cuda.set_device()``. + + .. warning:: + Object collectives have a number of serious performance and scalability + limitations. See :ref:`object_collectives` for details. + + .. warning:: + :func:`gather_object` uses ``pickle`` module implicitly, which is + known to be insecure. It is possible to construct malicious pickle data + which will execute arbitrary code during unpickling. Only call this + function with data you trust. + + .. warning:: + Calling :func:`gather_object` with GPU tensors is not well supported + and inefficient as it incurs GPU -> CPU transfer since tensors would be + pickled. Please consider using :func:`gather` instead. + + Example:: + >>> # xdoctest: +SKIP("need process group init") + >>> # Note: Process group initialization omitted on each rank. + >>> import torch.distributed as dist + >>> # Assumes world_size of 3. + >>> gather_objects = ["foo", 12, {1: 2}] # any picklable object + >>> output = [None for _ in gather_objects] + >>> dist.gather_object( + ... gather_objects[dist.get_rank()], + ... output if dist.get_rank() == 0 else None, + ... dst=0 + ... ) + >>> # On rank 0 + >>> output + ['foo', 12, {1: 2}] + """ + assert group is not None + if group_dst is None: + group_dst = 0 + if _rank_not_in_group(group): + _warn_not_in_group("gather_object") + return + + # Ensure object_gather_list is specified appropriately. + my_group_rank = group.rank() + _validate_output_list_for_rank(my_group_rank, group_dst, object_gather_list) + input_tensor, local_size = _object_to_tensor(obj, current_device, group) + + # Gather all local sizes. This is so that we can find the max size, and index + # until the correct size when deserializing the tensors. + group_size = group.size() + object_sizes_tensor = torch.zeros(group_size, dtype=torch.long, device=current_device) + object_size_list = [object_sizes_tensor[i].unsqueeze(dim=0) for i in range(group_size)] + # Allgather tensor sizes. An all-gather is needed here despite this being a + # gather, since each rank needs to broadcast a tensor of the same (maximal) + # size. + all_gather(object_size_list, local_size, group=group) + max_object_size = int(max(object_size_list).item()) # type: ignore[type-var] + # Resize tensor to max size across all ranks. + input_tensor.resize_(max_object_size) + # Avoid populating output tensors if the result won't be gathered on this rank. + if my_group_rank == group_dst: + coalesced_output_tensor = torch.empty(max_object_size * group_size, dtype=torch.uint8, device=current_device) + # Output tensors are nonoverlapping views of coalesced_output_tensor + output_tensors = [ + coalesced_output_tensor[max_object_size * i : max_object_size * (i + 1)] for i in range(group_size) + ] + # All ranks call gather with equal-sized tensors. + gather( + input_tensor, + gather_list=output_tensors if my_group_rank == group_dst else None, # type: ignore[possibly-undefined] + group_dst=group_dst, + group=group, + ) + if my_group_rank != group_dst: + return + + assert object_gather_list is not None, "Must provide object_gather_list on dst rank" + for i, tensor in enumerate(output_tensors): + tensor = tensor.type(torch.uint8) + tensor_size = object_size_list[i] + object_gather_list[i] = _tensor_to_object(tensor, tensor_size, group) + + +def scatter_object_list( + pg_device: torch.device | str, + scatter_object_output_list: list[typing.Any], + scatter_object_input_list: typing.Optional[list[typing.Any]] = None, + group: typing.Optional[ProcessGroup] = None, + group_src: typing.Optional[int] = None, +): + """ + Scatters picklable objects in ``scatter_object_input_list`` to the whole group. + + Similar to :func:`scatter`, but Python objects can be passed in. On + each rank, the scattered object will be stored as the first element of + ``scatter_object_output_list``. Note that all objects in + ``scatter_object_input_list`` must be picklable in order to be scattered. + + Args: + pg_device: (torch.device | str): device to use for object serialization to + tensor, must be this process assigned gpu for nccl backend. + scatter_object_output_list (List[Any]): Non-empty list whose first + element will store the object scattered to this rank. + scatter_object_input_list (List[Any], optional): List of input objects to scatter. + Each object must be picklable. Only objects on the ``src`` rank will + be scattered, and the argument can be ``None`` for non-src ranks. + group: (ProcessGroup, optional): The process group to work on. + group_src (int, optional): Source rank on ``group``. + + Returns: + ``None``. If rank is part of the group, ``scatter_object_output_list`` + will have its first element set to the scattered object for this rank. + + .. note:: Note that this API differs slightly from the scatter collective + since it does not provide an ``async_op`` handle and thus will be a + blocking call. + + .. warning:: + Object collectives have a number of serious performance and scalability + limitations. See :ref:`object_collectives` for details. + + .. warning:: + :func:`scatter_object_list` uses ``pickle`` module implicitly, which + is known to be insecure. It is possible to construct malicious pickle + data which will execute arbitrary code during unpickling. Only call this + function with data you trust. + + .. warning:: + Calling :func:`scatter_object_list` with GPU tensors is not well supported + and inefficient as it incurs GPU -> CPU transfer since tensors would be + pickled. Please consider using :func:`scatter` instead. + + Example:: + >>> # xdoctest: +SKIP("need process group init") + >>> # Note: Process group initialization omitted on each rank. + >>> import torch.distributed as dist + >>> if dist.get_rank() == 0: + >>> # Assumes world_size of 3. + >>> objects = ["foo", 12, {1: 2}] # any picklable object + >>> else: + >>> # Can be any list on non-src ranks, elements are not used. + >>> objects = [None, None, None] + >>> output_list = [None] + >>> dist.scatter_object_list(output_list, objects, src=0) + >>> # Rank i gets objects[i]. For example, on rank 2: + >>> output_list + [{1: 2}] + """ + assert group is not None + if group_src is None: + group_src = 0 + if _rank_not_in_group(group): + _warn_not_in_group("scatter_object_list") + return + + if not isinstance(scatter_object_output_list, list) or len(scatter_object_output_list) < 1: + raise ValueError("Expected argument scatter_object_output_list to be a list of size at least 1.") + + my_group_rank = group.rank() + if my_group_rank == group_src: + if scatter_object_input_list is None: + raise ValueError("source rank must provide non-None scatter_object_input_list") + tensor_list, tensor_sizes = zip( + *[_object_to_tensor(obj, pg_device, group) for obj in scatter_object_input_list] + ) + tensor_list, tensor_sizes = list(tensor_list), list(tensor_sizes) + + # Src rank broadcasts the maximum tensor size. This is because all ranks are + # expected to call into scatter() with equal-sized tensors. + max_tensor_size = max(tensor_sizes) # type: ignore[possibly-undefined] + for tensor in tensor_list: # type: ignore[possibly-undefined] + tensor.resize_(max_tensor_size) + else: + max_tensor_size = torch.tensor([0], dtype=torch.long, device=pg_device) + broadcast(max_tensor_size, src=group_src, group=group) + + # Scatter actual serialized objects + output_tensor = torch.empty(max_tensor_size.item(), dtype=torch.uint8, device=pg_device) + scatter( + output_tensor, + scatter_list=None if my_group_rank != group_src else tensor_list, # type: ignore[possibly-undefined] + group_src=group_src, + group=group, + ) + + # Scatter per-object sizes to trim tensors when deserializing back to object + obj_tensor_size = torch.tensor([0], dtype=torch.long, device=pg_device) + scatter( + obj_tensor_size, + scatter_list=None if my_group_rank != group_src else tensor_sizes, # type: ignore[possibly-undefined] + group_src=group_src, + group=group, + ) + + # Deserialize back to object + scatter_object_output_list[0] = _tensor_to_object(output_tensor, obj_tensor_size, group) 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..e478061b 100644 --- a/fast_llm/engine/inference/runner.py +++ b/fast_llm/engine/inference/runner.py @@ -7,27 +7,47 @@ 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 False: + #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 +62,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..7b76c77e 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 Evaluator, EvaluatorLoss, EvaluatorLmEval @config_class() @@ -153,7 +154,76 @@ class WandbConfig(Config): @config_class() -class EvaluationConfig(IntervalConfig): +class EvaluatorConfig(IntervalConfig): + _abstract: typing.ClassVar[bool] = True + # TODO: Generalize dynamic types? + _registry: typing.ClassVar[Registry[str, type["EvaluatorConfig"]]] = 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_evaluator_class(cls) -> "Evaluator": + 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 = EvaluatorLossConfig + # 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." + ) + EvaluatorConfig._registry[cls.type_] = cls + super().__init_subclass__() + + +@config_class() +class EvaluatorLossConfig(EvaluatorConfig): + _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_evaluator_class(cls) -> type["EvaluatorLoss"]: + from fast_llm.engine.training.evaluator import EvaluatorLoss + + return EvaluatorLoss + + +@config_class() +class EvaluatorLmEvalConfig(EvaluatorConfig): + _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_evaluator_class(cls) -> type["EvaluatorLmEval"]: + from fast_llm.engine.training.evaluator import EvaluatorLmEval + + return EvaluatorLmEval + @config_class() class TrainingCheckpointBaseConfig(IntervalConfig): @@ -280,7 +403,7 @@ class ShutdownConfig(IntervalConfig): @config_class() class TrainingConfig(Config): - evaluations: dict[str, EvaluationConfig] = Field( + evaluations: dict[str, EvaluatorConfig] = Field( default_factory=dict, desc="A dictionary of evaluation dataset names and their configurations for the validation phase.", hint=FieldHint.core, diff --git a/fast_llm/engine/training/evaluator.py b/fast_llm/engine/training/evaluator.py new file mode 100644 index 00000000..5c7ce6ce --- /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, + EvaluatorConfig, + EvaluatorLossConfig, + EvaluatorLmEvalConfig, +) +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 FastLLMLmEvalWrapper +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 Evaluator[ConfigType: EvaluatorConfig](Configurable[ConfigType], abc.ABC): + config_class: typing.ClassVar[type[EvaluatorConfig]] = EvaluatorConfig + + _is_setup: bool = False + + @classmethod + def build( + cls, + name: str, + eval_config: EvaluatorLossConfig, + trainer_config: TrainerConfig, + get_tflops_func: callable, + ) -> "Evaluator": + 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 EvaluatorLoss[ConfigType: EvaluatorLossConfig](Evaluator[ConfigType]): + config_class: typing.ClassVar[type[EvaluatorLossConfig]] = EvaluatorLossConfig + + def __init__( + self, + name: str, + eval_config: EvaluatorLossConfig, + 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 EvaluatorLmEval[ConfigType: EvaluatorLmEvalConfig](Evaluator[ConfigType]): + config_class: typing.ClassVar[type[EvaluatorLmEvalConfig]] = EvaluatorLmEvalConfig + + def __init__( + self, + name: str, + eval_config: EvaluatorLmEvalConfig, + 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 = FastLLMLmEvalWrapper( + 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 EvaluatorRunner: + _is_setup: bool = False + + def __init__( + self, + config: TrainerConfig, + get_tflops_func: callable, + ): + self._config = config + self._evaluations = [ + eval_config.get_evaluator_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/fast_llm_wrapper.py b/fast_llm/engine/training/lm_eval/fast_llm_wrapper.py new file mode 100644 index 00000000..0c138eda --- /dev/null +++ b/fast_llm/engine/training/lm_eval/fast_llm_wrapper.py @@ -0,0 +1,940 @@ +import logging +import copy +import jinja2 + + +import transformers +from tqdm.auto import tqdm +import torch +import torch.nn.functional as F + + +# make lazy +import lm_eval.api.instance +import lm_eval.models.utils +import lm_eval.api.model +import lm_eval.utils + + +from fast_llm.core.distributed import safe_barrier +from fast_llm.engine.inference.huggingface import HuggingfaceBaseModelForCausalLM +from fast_llm.engine.distributed.distributed import Distributed +from fast_llm.engine.distributed.config import DistributedConfig + +from fast_llm.core.distributed import scatter_object_list, gather_object + + +eval_logger = logging.getLogger(__name__) + + +class FastLLMLmEvalWrapper(lm_eval.api.model.TemplateLM): + _DEFAULT_MAX_LENGTH = 2048 + + def __init__( + self, + model: HuggingfaceBaseModelForCausalLM, + tokenizer: transformers.PreTrainedTokenizer | transformers.PreTrainedTokenizerFast, + truncation: bool | None = False, + logits_cache: bool = True, + add_bos_token: bool | None = False, + prefix_token_id: int | None = 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 = torch.distributed.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 + 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 = lm_eval.models.utils.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 = model._inference_runner._batch_config.sequence_length + self.pretrained = model + self.delta = delta + self.peft = peft + self.revision = revision + + self.batch_schedule = 1 + self.batch_sizes = {} + self.batch_size_per_gpu = 16 # model._inference_runner._batch_config.micro_batch_size + self.batch_size = self.batch_size_per_gpu * dist_config.batch_data_parallel + self.max_batch_size = self.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, + input_ids, + attention_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( + input_ids, attention_mask, labels, max_length, stop, generate, **generation_kwargs + ) + + rank = self.group.rank() + assert rank == 0 + + if continue_generate: + assert input_ids is not None + if generate: + assert max_length is not None and stop is not None + + # always divide by batch_size, if not full batch, some ranks will get less work or not at all + step = self.batch_size // world_size + + input_ids = [input_ids[i * step : (i + 1) * step] for i in range(world_size)] + attention_mask = [ + attention_mask[i * step : (i + 1) * step] if attention_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 = [ + [ + input_ids[i], + attention_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] + scatter_object_list( + self._distributed.device, + obj_list, + scatter_list, + group_src=0, + group=self.group, + ) + input_ids, attention_mask, labels, max_length, stop, generate, continue_generate, generation_kwargs = tuple( + obj_list[0] + ) + + if continue_generate == False: + return + + assert len(input_ids) > 0 + + res = self._model_invoke_inner( + input_ids, attention_mask, labels, max_length, stop, generate, **generation_kwargs + ) + + gather_list = [None] * world_size + gather_object( + self._distributed.device, + res, + gather_list, + group_dst=0, + group=self.group, + ) + + # If it was model generate tensors could be of different length + # so we aggregate results to list instead of a tensor + if generate: + res = sum((el.tolist() for el in gather_list), []) + else: + res = torch.cat(gather_list, dim=0) + + return res + + def worker_model_invoke(self): + assert self.group is not None + # 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] + scatter_object_list( + self._distributed.device, + obj_list, + scatter_list, + group_src=0, + group=self.group, + ) + input_ids, attention_mask, labels, max_length, stop, generate, continue_generate, generation_kwargs = ( + tuple(obj_list[0]) + ) + + if continue_generate == False: + break + + # if some data was received, work, otherwise return empty tensor + if len(input_ids) > 0: + res = self._model_invoke_inner( + input_ids, attention_mask, labels, max_length, stop, generate, **generation_kwargs + ) + else: + res = input_ids + + gather_list = None + gather_object( + self._distributed.device, + res, + gather_list, + group_dst=0, + group=self.group, + ) + else: + # TODO: implement distributed model support + assert self.group == torch.distributed.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, input_ids, attention_mask, labels, max_length, stop, generate: bool, **generation_kwargs + ): + if generate: + return self._model_generate_inner(input_ids, attention_mask, max_length, stop, **generation_kwargs) + else: + return self._model_call_inner(input_ids, attention_mask, labels) + + def _model_call(self, input_ids, attention_mask=None, labels=None): + return self._model_invoke( + input_ids, attention_mask, labels, None, None, generate=False, continue_generate=True + ) + + def _model_generate(self, input_ids, attention_mask, max_length, stop, **generation_kwargs): + return self._model_invoke( + input_ids, + attention_mask, + None, + max_length, + stop, + generate=True, + continue_generate=True, + **generation_kwargs, + ) + + def _model_call_inner(self, input_ids, attention_mask=None, labels=None): + """ + :param input_ids: 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 attention_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 attention_mask is not None or labels is not None: + assert attention_mask is not None and labels is not None + return self.model( + input_ids=input_ids, + attention_mask=attention_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=input_ids, + 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, input_ids, attention_mask, 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 = lm_eval.models.utils.stop_sequences_criteria( + self.tokenizer, stop, input_ids.shape[1], input_ids.shape[0] + ) + if attention_mask is None: + return self.model.generate( + input_ids=input_ids, + max_length=max_length, + stopping_criteria=stopping_criteria, + pad_token_id=self.tokenizer.pad_token_id, + use_cache=False, + **generation_kwargs, + ) + else: + return self.model.generate( + input_ids=input_ids, + attention_mask=attention_mask, + 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 + + # TODO: check removing this does not affect lm_eval + # @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[lm_eval.api.instance.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( + lm_eval.utils.make_disjoint_window, + lm_eval.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 = lm_eval.models.utils.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 = lm_eval.models.utils.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 = lm_eval.models.utils.pad_and_concat(padding_len_inp, inps) # [batch, padding_len_inp] + batched_conts = lm_eval.models.utils.pad_and_concat( + padding_len_cont, conts + ) # [batch, padding_len_cont] + batched_encoder_mask = lm_eval.models.utils.pad_and_concat( + padding_len_inp, encoder_attns + ) # [batch, padding_len_inp] + call_kwargs = { + "attention_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[lm_eval.api.instance.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 = lm_eval.models.utils.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 = lm_eval.models.utils.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 + input_ids, attention_mask = self.tok_batch_encode( + contexts, + left_truncate_len=max_ctx_len, + truncation=self.truncation, + ) + input_ids = input_ids.to(self.device) + attention_mask = attention_mask.to(self.device) + + if "max_length" not in kwargs: + kwargs["max_length"] = input_ids.shape[1] + max_gen_toks + + # perform batched generation + cont = self._model_generate( + input_ids=input_ids, + attention_mask=attention_mask, + stop=until, + **kwargs, + ) + + # cont_toks_list = cont.tolist() + cont_toks_list = cont + + 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[input_ids.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..e608ec7d --- /dev/null +++ b/fast_llm/engine/training/lm_eval/utils.py @@ -0,0 +1,249 @@ +import argparse +import json +import logging +import os +import pathlib +import sys +from pathlib import Path + + +import lm_eval.evaluator +import lm_eval.loggers +import lm_eval.__main__ +import lm_eval.tasks +import lm_eval.utils + + +eval_logger = logging.getLogger(__name__) + + +def parse_eval_args(parser: argparse.ArgumentParser, args: list[str]) -> argparse.Namespace: + lm_eval.__main__.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 = lm_eval.__main__.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__) + + # update the evaluation tracker args with the output path and the HF token + evaluation_tracker_args = "" + if args.output_path: + args.output_path = str(pathlib.Path(args.output_path) / f"runs/{run_index}/{completed_steps}") + evaluation_tracker_args += f",output_path={args.output_path}" + + evaluation_tracker_args = lm_eval.utils.simple_parse_args_string(evaluation_tracker_args) + evaluation_tracker = lm_eval.loggers.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 = ( + lm_eval.utils.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 lm_eval.utils.simple_parse_args_string(args.metadata)) + + task_manager = lm_eval.tasks.TaskManager(include_path=args.include_path, metadata=metadata) + + 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 = lm_eval.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 = lm_eval.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"{lm_eval.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." + ) + + ( + eval_logger.info(f"Selected Tasks: {task_names}") + if eval_logger.getEffectiveLevel() >= logging.INFO + else print(f"Selected Tasks: {task_names}") + ) + + request_caching_args = lm_eval.evaluator.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: lm_eval.loggers.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=lm_eval.utils.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 = lm_eval.loggers.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(lm_eval.utils.make_table(results)) + if "groups" in results: + print(lm_eval.utils.make_table(results, "groups")) diff --git a/fast_llm/engine/training/trainer.py b/fast_llm/engine/training/trainer.py index 66f1ad86..ab8ab9e9 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 EvaluatorRunner 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_runner: EvaluatorRunner + 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_runner = EvaluatorRunner( + 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_runner.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_runner.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_runner.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_runner.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