From 6300497f77272dee42afeb62d1009f4dbf4fc4c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20BONIFACE?= Date: Tue, 29 Oct 2024 20:31:21 +0100 Subject: [PATCH 1/2] Move file to correct folder --- {climateguard => notebooks/latvia}/scrap_LSM.ipynb | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {climateguard => notebooks/latvia}/scrap_LSM.ipynb (100%) diff --git a/climateguard/scrap_LSM.ipynb b/notebooks/latvia/scrap_LSM.ipynb similarity index 100% rename from climateguard/scrap_LSM.ipynb rename to notebooks/latvia/scrap_LSM.ipynb From d73ba1ff71a8b8b25def39094314d61498ed836c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20BONIFACE?= Date: Tue, 29 Oct 2024 20:34:16 +0100 Subject: [PATCH 2/2] Add cost estimation notebook --- notebooks/hackathon_ecf/estimate_cost.ipynb | 581 ++++++++++++++++++++ pyproject.toml | 8 +- uv.lock | 56 ++ 3 files changed, 643 insertions(+), 2 deletions(-) create mode 100644 notebooks/hackathon_ecf/estimate_cost.ipynb diff --git a/notebooks/hackathon_ecf/estimate_cost.ipynb b/notebooks/hackathon_ecf/estimate_cost.ipynb new file mode 100644 index 0000000..1a8a77d --- /dev/null +++ b/notebooks/hackathon_ecf/estimate_cost.ipynb @@ -0,0 +1,581 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Estimate the cost of using closed-source models on the MediaTree dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "# https://openai.com/api/pricing/\n", + "# https://www.anthropic.com/pricing#anthropic-api\n", + "pricing = {\n", + " 'gpt-4o-mini': {\n", + " 'input': 0.15,\n", + " 'output': 0.6,\n", + " 'cache_discount': 0.5\n", + " },\n", + " 'claude-3.5-haiku': {\n", + " 'input': 0.25,\n", + " 'output': 1.25,\n", + " 'cache_discount': 0.1\n", + " },\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
startplaintextchannel_namechannel_titlechannel_radionum_charactersnum_wordsnum_tokensnum_tokens_approx
02023-09-13 06:02:00avec un pronostic vital plus que engagé l' inc...itelei>TéléFalse2317443516590
12023-09-13 04:58:00amour un peu de love et de tendresse finalemen...itelei>TéléFalse1804341398454
22023-09-13 06:04:00autre sont en réanimation suite à des cas de b...itelei>TéléFalse2264431506574
32023-09-13 04:14:00d' être avec nous dans un instant valeo au euh...itelei>TéléFalse1418285322380
42023-09-13 06:42:00un gros tiers aux élections professionnelles m...itelei>TéléFalse2199407472542
\n", + "
" + ], + "text/plain": [ + " start plaintext \\\n", + "0 2023-09-13 06:02:00 avec un pronostic vital plus que engagé l' inc... \n", + "1 2023-09-13 04:58:00 amour un peu de love et de tendresse finalemen... \n", + "2 2023-09-13 06:04:00 autre sont en réanimation suite à des cas de b... \n", + "3 2023-09-13 04:14:00 d' être avec nous dans un instant valeo au euh... \n", + "4 2023-09-13 06:42:00 un gros tiers aux élections professionnelles m... \n", + "\n", + " channel_name channel_title channel_radio num_characters num_words \\\n", + "0 itele i>Télé False 2317 443 \n", + "1 itele i>Télé False 1804 341 \n", + "2 itele i>Télé False 2264 431 \n", + "3 itele i>Télé False 1418 285 \n", + "4 itele i>Télé False 2199 407 \n", + "\n", + " num_tokens num_tokens_approx \n", + "0 516 590 \n", + "1 398 454 \n", + "2 506 574 \n", + "3 322 380 \n", + "4 472 542 " + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = pd.read_parquet('mediatree_raw_1year.parquet') # download from https://drive.google.com/drive/folders/1d0idkOmMIXabj7ajYhvkitMMHnH_woSN\n", + "df.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Nombres de passages de 2 min : 354189\n", + "Nombre de chaînes : 2\n" + ] + }, + { + "data": { + "text/plain": [ + "array(['itele', 'sud-radio'], dtype=object)" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "print(\"Nombres de passages de 2 min :\", len(df))\n", + "print(\"Nombre de chaînes :\", df.channel_name.nunique())\n", + "df.channel_name.unique()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Nombre moyen de tokens : 474.4648676271708\n" + ] + } + ], + "source": [ + "avg_tokens = df.num_tokens.mean()\n", + "print(\"Nombre moyen de tokens :\", avg_tokens)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [], + "source": [ + "def get_cost(input_tokens: int, output_tokens: int, prompt_tokens: int, model: str) -> dict:\n", + " prices = pricing[model]\n", + " it_cost = input_tokens * prices['input'] / 1e6\n", + " ot_cost = output_tokens * prices['output'] / 1e6\n", + " prompt_cost = prompt_tokens * prices['input'] * prices['cache_discount'] / 1e6\n", + " return {\n", + " 'total_cost': it_cost + ot_cost + prompt_cost,\n", + " 'input_cost': it_cost,\n", + " 'output_cost': ot_cost,\n", + " 'prompt_cost': prompt_cost,\n", + " 'model': model\n", + " }" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "import tiktoken\n", + "encoding = tiktoken.encoding_for_model('gpt-4o-mini')" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "636" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "EXAMPLE_PROMPT = \"\"\"\n", + "Tu es expert en désinformation sur les sujets environnementaux, expert en science climatique et sachant tout sur le GIEC. Je vais te donner un extrait d'une retranscription de 2 minutes d'un flux TV ou Radio. \n", + "A partir de cet extrait liste moi tous les faits/opinions environnementaux (claim) uniques qu'il faudrait factchecker. Et pour chaque claim, donne une première analyse si c'est de la désinformation ou non, un score si c'est de la désinformation, ainsi qu'une catégorisation de cette allégation.\n", + "Ne sélectionne que les claims sur les thématiques environnementales (changement climatique, transition écologique, énergie, biodiversité, pollution, pesticides, ressources (eau, minéraux, ..) et pas sur les thématiques sociales et/ou économiques\n", + "Renvoie le résultat en json sans autre phrase d'introduction ou de conclusion avec à chaque fois les champs suivants : \n", + "\n", + "- \"claim\" - l'allégation à potentiellement vérifier\n", + "- \"context\" - reformulation du contexte dans laquelle cette allégation a été prononcée (maximum 1 paragraphe)\n", + "- \"analysis\" - première analyse du point de vue de l'expert sur le potentiel de désinformation de cette allégation en fonction du contexte\n", + "- \"disinformation_score\" - le score de désinformation (voir plus bas)\n", + "- \"disinformation_category\" - la catégorie de désinformation (voir plus bas)\n", + "- \"pro_anti\" - si l'allégation est plutôt anti-écologie ou pro-écologie\n", + "- \"speaker\" - nom et fonction de la personne qui a prononcé l'allégation si on a l'information (sinon \"N/A\")\n", + "- \"contradiction\" - si l'allégation a été contestée dans un dialogue, résume la contradiction (sinon \"N/A\")\n", + "- \"quote\" - la citation exacte qui correspond à l'allégation\n", + "\n", + "Pour les scores \"disinformation_score\"\n", + "- \"very low\" = pas de problème, l'allégation n'est pas trompeuse ou à risque. pas besoin d'investiguer plus loin\n", + "- \"low\" = allégation qui nécessiterait une vérification et une interrogation, mais sur un sujet peu important et significatif dans le contexte des enjeux écologiques (exemple : les tondeuses à gazon, \n", + "- \"medium\" = allégation problématique sur un sujet écologique important (scientifique, impacts, élections, politique, transport, agriculture, énergie, alimentation, démocratie ...) , qui nécessiterait vraiment d'être vérifiée, déconstruite, débunkée et interrogée. En particulier pour les opinions fallacieuses\n", + "- \"high\" = allégation grave, en particulier si elle nie le consensus scientifique\n", + "\n", + "Pour les catégories de désinformation \"disinformation_category\": \n", + "- \"consensus\" = négation du consensus scientifique\n", + "- \"facts\" = fait à vérifier, à préciser ou contextualiser\n", + "- \"narrative\" = narratif fallacieux ou opinion qui sème le doute (par exemple : \"les écolos veulent nous enlever nos libertés\")\n", + "- \"other\"\n", + "\n", + "\"\"\"\n", + "\n", + "prompt_tokens = len(encoding.encode(EXAMPLE_PROMPT))\n", + "prompt_tokens" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "216355980" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "N_CHANNELS = 19\n", + "N_HOURS = 800\n", + "SAMPLE_LENGTH_MIN = 2\n", + "\n", + "n_samples_per_hour = 60 / SAMPLE_LENGTH_MIN\n", + "total_samples = N_CHANNELS * N_HOURS * n_samples_per_hour\n", + "total_input_tokens = round(total_samples * avg_tokens)\n", + "total_input_tokens" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
total_costinput_costoutput_costprompt_costmodel
056.94059732.4533972.73621.7512gpt-4o-mini
167.03939554.0889955.7007.2504claude-3.5-haiku
267.88459732.45339713.68021.7512gpt-4o-mini
389.83939554.08899528.5007.2504claude-3.5-haiku
481.56459732.45339727.36021.7512gpt-4o-mini
5118.33939554.08899557.0007.2504claude-3.5-haiku
6108.92459732.45339754.72021.7512gpt-4o-mini
7175.33939554.088995114.0007.2504claude-3.5-haiku
8191.00459732.453397136.80021.7512gpt-4o-mini
9346.33939554.088995285.0007.2504claude-3.5-haiku
10273.08459732.453397218.88021.7512gpt-4o-mini
11517.33939554.088995456.0007.2504claude-3.5-haiku
12327.80459732.453397273.60021.7512gpt-4o-mini
13631.33939554.088995570.0007.2504claude-3.5-haiku
\n", + "
" + ], + "text/plain": [ + " total_cost input_cost output_cost prompt_cost model\n", + "0 56.940597 32.453397 2.736 21.7512 gpt-4o-mini\n", + "1 67.039395 54.088995 5.700 7.2504 claude-3.5-haiku\n", + "2 67.884597 32.453397 13.680 21.7512 gpt-4o-mini\n", + "3 89.839395 54.088995 28.500 7.2504 claude-3.5-haiku\n", + "4 81.564597 32.453397 27.360 21.7512 gpt-4o-mini\n", + "5 118.339395 54.088995 57.000 7.2504 claude-3.5-haiku\n", + "6 108.924597 32.453397 54.720 21.7512 gpt-4o-mini\n", + "7 175.339395 54.088995 114.000 7.2504 claude-3.5-haiku\n", + "8 191.004597 32.453397 136.800 21.7512 gpt-4o-mini\n", + "9 346.339395 54.088995 285.000 7.2504 claude-3.5-haiku\n", + "10 273.084597 32.453397 218.880 21.7512 gpt-4o-mini\n", + "11 517.339395 54.088995 456.000 7.2504 claude-3.5-haiku\n", + "12 327.804597 32.453397 273.600 21.7512 gpt-4o-mini\n", + "13 631.339395 54.088995 570.000 7.2504 claude-3.5-haiku" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "output_tokens_range = [10, 50, 100, 200, 500, 800, 1000]\n", + "costs = [get_cost(total_input_tokens, ot * total_samples, prompt_tokens * total_samples, model) for ot in output_tokens_range for model in pricing.keys()]\n", + "costs = pd.DataFrame(costs)\n", + "costs" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABb4AAAIjCAYAAADMRA1rAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAACLhklEQVR4nOzdeXxTdb7/8XcKZdW2wAAVRUV0FFxGR7xaHccNxWWcYQbXyx1BvS4MuM5IAdlVRFxwQ1BHARU3VBCRpIWytEAp+75L0n2lbUL3NDm/P+ZHrhWQFtp+2+T1fDz6eJhzTnLeae6Z++mbk3NslmVZAgAAAAAAAAAgSISZDgAAAAAAAAAAQH2i+AYAAAAAAAAABBWKbwAAAAAAAABAUKH4BgAAAAAAAAAEFYpvAAAAAAAAAEBQofgGAAAAAAAAAAQVim8AAAAAAAAAQFCh+AYAAAAAAAAABBWKbwAAAAAAAABAUKH4BgA0GpvNpvHjx5/Qc88++2wNHjy4XvMAAAAgeC1fvlw2m03Lly9v9H27XC7ZbDbNmjWr0ffdUA7/Pr/55pt6e83x48fLZrPVWGaz2TRs2LB62weA0EXxDQBNyOrVqzV+/HgVFxef0PN/+ukntWnTRjabTevXr6/fcAAAAACM2bFjh+6++26dc845ateunX7zm9/oj3/8o3744YdaPX/WrFmy2WxH/cnJyWng9ADQ+FqaDgAA+D+rV6/WhAkTNHjwYEVFRdX5+c8884xatmypysrK+g9XD8rLy9Wy5Yn9v549e/YoLIx/rwUAAEBoSk1N1aFDhzRo0CB169ZNZWVl+vbbb/XnP/9Z77//vh599NFavc7EiRPVo0ePGstO5G+P+jB69GiNGDHCyL4BBD+KbwAIEnFxcYqLi9Pw4cP14osvmo5zVG3atDnh57Zu3boekwAAAADNy+23367bb7+9xrJhw4bp8ssv1xtvvFHr4vu2225Tnz59GiJinbVs2fKET4wBgOPh1DkAOEnLly9Xnz591KZNG/Xs2VPvv//+EdeqO3ydujlz5uj8889XmzZtdPnllysxMTGwzfjx4/Xcc89Jknr06BH42qHL5TpuBq/Xq6eeekpPPfWUevbsecztli5dqmuvvVbt27dXVFSU/vKXv2jXrl21ep+Hvxq5cuVKPfnkk+rcubOioqL02GOPqaqqSsXFxXrggQfUoUMHdejQQcOHD5dlWTVe45fX+D78e9q/f3/gLPfIyEg9+OCDKisrq/FcrvENAACAX8rMzNTDDz+sbt26qXXr1urRo4eGDBmiqqqqo26flJSku+++W2eeeaZat26t7t2765lnnlF5eXmN7a6//npdf/31Rzx/8ODBOvvss2ssKy4u1uDBgxUZGamoqCgNGjTomJcu3L17t+666y517NhRbdq0UZ8+fbRgwYITeeuSpBYtWqh79+51vlTioUOH5PP5Tmiffr9fL730ks444wy1adNGN910k/bv319jm9r+no92je+jefHFFxUWFqZ33nlH0rH/NjjW5wYgNPHPagBwEjZt2qRbb71Vp512miZMmCCfz6eJEyeqc+fOR2y7YsUKffXVV3ryySfVunVrvffee7r11lu1du1aXXTRRfrb3/6mvXv36osvvtDUqVP1m9/8RpKO+lq/9Oabb6qoqEijR4/Wd999d9RtlixZottuu03nnHOOxo8fr/Lycr3zzju65pprtHHjxiMG+GN54oknFB0drQkTJmjNmjX64IMPFBUVpdWrV+vMM8/UpEmTtGjRIr366qu66KKL9MADDxz3Ne+55x716NFDL7/8sjZu3Kh///vf6tKli1555ZVaZQIAAEDoycrK0n/913+puLhYjz76qC644AJlZmbqm2++OeIkisPmzp2rsrIyDRkyRJ06ddLatWv1zjvvKCMjQ3Pnzq1zBsuy9Je//EUrV67U448/rl69emnevHkaNGjQEdvu2LFD11xzjU4//XSNGDFC7du319dff63+/fvr22+/1V//+tda7bO0tFTl5eVyu91asGCB7Ha77r333lpnvuGGG1RSUqJWrVqpX79+ev3113XeeefV+vmTJ09WWFiY/vWvf8ntdmvKlCkaOHCgUlJSAtvU5+959OjRmjRpkt5//3098sgjdXougBBnAQBO2J133mm1a9fOyszMDCzbt2+f1bJlS+vn/xMryZJkrV+/PrAsNTXVatOmjfXXv/41sOzVV1+1JFlOp7PWGbKzs61TTz3Vev/99y3LsqyZM2dakqx169bV2O7SSy+1unTpYh08eDCwbMuWLVZYWJj1wAMPHHc/h1+3X79+lt/vDyyPiYmxbDab9fjjjweWVVdXW2eccYZ13XXX1XgNSda4ceMCj8eNG2dJsh566KEa2/31r3+1OnXq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O2W32wOXYOzZs6eSkpJUVVUVuAzMwoULlZ6eTvENIIDiGwBOwvjx4xUfH69rrrlGQ4YMkc/n07vvvquLLrpImzdvrrHtRRddpH79+unJJ59U69at9d5770mSJkyYENjmcMH9/PPP67777lN4eLjuvPPOQCH+S7fccssRyw6X5tddd12NPwBeffVV3XbbbYqJidHDDz+s8vJyvfPOO4qMjKzx1UUAAACgOZg0aZLi4+N13XXX6dFHH1WvXr2UnZ2tuXPnauXKlUdsf8EFF6hnz57617/+pczMTEVEROjbb7896n1pHnroIb3xxhvq16+fHn74YeXl5WnGjBm68MILa9yA/c4779Q111yjESNGyOVyqXfv3vruu++Oevb1tGnT9Ic//EEXX3yxHnnkEZ1zzjnKzc1VcnKyMjIytGXLll99v4899pg8Ho/++Mc/6vTTT1dOTo7mzJmj3bt36/XXX69xxvnIkSM1e/ZsOZ1OnX322ZKkq6++Wpdddpn69OmjyMhIbdy4UR9//LG6d++uUaNG1fbXflx1+T0fz1VXXaXvv/9et99+u+666y7Nnz9f4eHh+t///V998803uvXWW3XPPffop59+0meffaaePXvW2/sA0Pwd+05oAIDjuvzyy2W329WhQweNGTNGH330kSZOnKibbrpJbdq0qbHtddddpzfffFOffvqpxo4dq44dO8put+uSSy4JbHPFFVfohRde0JYtWzR48GDdf//9R9zc5kT17dtXDodDnTp10tixY/Xaa6/pqquu0qpVq456qRQAAACgKTv99NOVkpKiu+66S3PmzNGTTz6pTz75RNdff73atWt3xPbh4eH64YcfdOmll+rll1/WhAkTdN555+mTTz45YttevXrpk08+kdvt1rPPPqsFCxbo008/DXx787CwsDAtWLBAAwcO1Geffabnn39ep59+umbPnn3Ea/bu3Vvr16/XHXfcoVmzZmno0KGaMWOGwsLCNHbs2OO+33vvvVdhYWGaPn26hgwZojfeeENnnHGGvv/+ez377LO1ev6+ffs0adIkPfHEE3I4HHrkkUe0bt06de3a9bjPr626/J5r48Ybb9TXX3+t+Ph4/f3vf5ff71e/fv30+uuva+/evXr66aeVnJyshQsX6owzzqi39wGg+bNZ3DkMAOpd//79tWPHjsB1vW02m4YOHap3333XcDIAAAAAAIDgxxnfAHCSfn7jF+k/N7FctGjRr955HQAAAAAAAA2Ha3wDwEk655xzNHjwYJ1zzjlKTU3V9OnT1apVKw0fPtx0NAAAAAAAgJBE8Q0AJ+nWW2/VF198oZycHLVu3VoxMTGaNGmSzjvvPNPRAAAAAAAAQhLX+AYAAAAAAAAABBWu8Q0AAAAAAAAACCoU3wAAAAAAAACAoMI1viX5/X5lZWXp1FNPlc1mMx0HAAAA9cSyLB06dEjdunVTWBjnfIQSZnwAAIDgVNsZn+JbUlZWlrp37246BgAAABpIenq6zjjjDNMx0IiY8QEAAILb8WZ8im9Jp556qqT//LIiIiIMpwEAAEB98Xg86t69e2DeQ+hgxgcAAGgYZd4yTd0wVT8c+EE9Inroiz990aj7r+2MT/EtBb76GBERwVAMAAAQhLjURehhxgcAAKh/Ow7u0IjEEXJ5XGrRtoXC24Ubm7WON+NTfAMAAAAAAAAAjsmyLH28/WO9u/ldVfurTcepFYpvAAAAAAAAAMBR5ZXladTKUUrJTjEdpU4ovgEAAAAAAAAAR0hIS9D41eNVXFlsOkqdUXwDAACcIMuyVF1dLZ/PZzpKyGrRooVatmzJNbxxQnw+n7xer+kYIY1jGACApqm8ulxT1k3RN3u/MR3lhFF8AwAAnICqqiplZ2errKzMdJSQ165dO5122mlq1aqV6ShoRkpKSpSRkSHLskxHCXkcwwAANC27C3dreOJwOd1O01FOCsU3AABAHfn9fjmdTrVo0ULdunVTq1atOFvRAMuyVFVVpfz8fDmdTp133nkKCwszHQvNgM/nU0ZGhtq1a6fOnTtz/BrCMQwAQNNiWZY+2fmJ3tr4lrz+5v+tOIpvAACAOqqqqpLf71f37t3Vrl0703FCWtu2bRUeHq7U1FRVVVWpTZs2piOhGfB6vbIsS507d1bbtm1NxwlpHMMAADQNBeUFGpU0SsnZyaaj1BuKbwAAgBPEmYlNA58DThRnejcNHMMAAJi1PH25xq4aq6LKItNR6hXFNwAAAAAAAACEmIrqCr22/jV9tecr01EaBMU3AAAAAAAAAISQvUV7FZsYq/3F+01HaTAU3wAAAPXk7BE/Nur+XJPvaNT9AcGOYxgAAAQ7y7I0Z9ccTd0wVVX+KtNxGhQXUwMAAAghgwcPls1mk81mU6tWrXTuuedq4sSJqq6uNh3tCMuXL5fNZlNxcbHpKECTwPELAABORkF5gf6R8A+9su6VoC+9Jc74BgAACDm33nqrZs6cqcrKSi1atEhDhw5VeHi4Ro4cWWO7qqoqtWrVylBKAEfD8QsAAE5EUkaSRq8arcKKQtNRGg1nfAMAAISY1q1bKzo6WmeddZaGDBmivn37asGCBRo8eLD69++vl156Sd26ddP5558vSdq2bZtuvPFGtW3bVp06ddKjjz6qkpKSwOsdft6kSZPUtWtXRUVFBc5Cfe6559SxY0edccYZmjlzZuA5LpdLNptNX375pa6++mq1adNGF110kVasWBFYf8MNN0iSOnToIJvNpsGDBzfeLwloojh+AQBAXVT5qjR57WQNTRgaUqW3RPENAAAQ8tq2bauqqv981TEhIUF79uzR4sWLtXDhQpWWlqpfv37q0KGD1q1bp7lz52rJkiUaNmxYjddYunSpsrKylJiYqDfeeEPjxo3Tn/70J3Xo0EEpKSl6/PHH9dhjjykjI6PG85577jn985//1KZNmxQTE6M777xTBw8eVPfu3fXtt99Kkvbs2aPs7Gy99dZbjfMLAZoRjl8AAHAs+4v2674f79OcXXNkyTIdp9FRfAMAAIQoy7K0ZMkSxcXF6cYbb5QktW/fXv/+97914YUX6sILL9Tnn3+uiooKffLJJ7rooot044036t1339Wnn36q3NzcwGt17NhRb7/9ts4//3w99NBDOv/881VWVqZRo0bpvPPO08iRI9WqVSutXLmyRoZhw4ZpwIAB6tWrl6ZPn67IyEh99NFHatGihTp27ChJ6tKli6KjoxUZGdl4vxygieP4BQAAv+aL3V/ovh/v076ifaajGGO8+M7MzNT//M//qFOnTmrbtq0uvvhirV+/PrDesiyNHTtWp512mtq2bau+fftq376aH1hhYaEGDhyoiIgIRUVF6eGHH67x9T0AAAD8n4ULF+qUU05RmzZtdNttt+nee+/V+PHjJUkXX3xxjesC79q1S7/73e/Uvn37wLJrrrlGfr9fe/bsCSy78MILFRb2f6Nl165ddfHFFwcet2jRQp06dVJeXl6NLDExMYH/btmypfr06aNdu3bV23tF42O+b1gcvwAA4NcUVhTqiYQnNCllkip9labjGGW0+C4qKtI111yj8PBw2e127dy5U6+//ro6dOgQ2GbK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DpfL4zIdBfUkzHQAAAAANK709HQ99NBD6tatm1q1aqWzzjpLTz31lA4ePFjr13C5XLLZbNq8eXODZLTZbJo/f36DvDbQ3HEMAwBQfyzL0qztszRw0UBK7yBD8Q0AABBCDhw4oD59+mjfvn364osvtH//fs2YMUMJCQmKiYlRYWGh6YgAfgXHMAAA9Se/LF+PLX5Mr294XV6/13Qc1DOKbwAAgBAydOhQtWrVSvHx8bruuut05pln6rbbbtOSJUuUmZmp559/XtLRz9aMiorSrFmzJEk9evSQJF122WWy2Wy6/vrrJUmDBw9W//79NWHCBHXu3FkRERF6/PHHVVVVFXids88+W2+++WaN17700ks1fvz4wHpJ+utf/yqbzRZ4DIBjGACA+rIsbZkGLBig5Oxk01HQQCi+AQAAQkRhYaHi4uL0j3/8Q23btq2xLjo6WgMHDtRXX30ly7KO+1pr166VJC1ZskTZ2dn67rvvAusSEhK0a9cuLV++XF988YW+++47TZgwodY5161bJ0maOXOmsrOzA4+BUMcxDADAyauortCLa17Uk8ueVFFlkek4aEAU3wAAACFi3759sixLvXr1Our6Xr16qaioSPn5+cd9rc6dO0uSOnXqpOjoaHXs2DGwrlWrVvr444914YUX6o477tDEiRP19ttvy+/31yrn4deOiopSdHR04DEQ6jiGAQA4OXsK9+i+hffpqz1fmY6CRkDxDQAAEGJqczboyfjd736ndu3aBR7HxMSopKRE6enpDbpfIFRwDAMAUDeWZenTnZ/qv3/8b/3k/sl0HDQSim8AAIAQce6558pms2nXrl1HXb9r1y516NBBnTt3ls1mO6Jc83rr54Y/YWFhDfbaQDDjGAYAoO4Kygs0JGGIpqyboip/1fGfgKBB8Q0AABAiOnXqpJtvvlnvvfeeysvLa6zLycnRnDlzdO+998pms6lz587Kzs4OrN+3b5/KysoCj1u1aiVJ8vl8R+xny5YtNV5/zZo1OuWUU9S9e3dJOuK1PR6PnE5njdcIDw8/6msDoYxjGACAuknMSNSABQO0KnOV6SgwgOIbAAAghLz77ruqrKxUv379lJiYqPT0dDkcDt188806/fTT9dJLL0mSbrzxRr377rvatGmT1q9fr8cff1zh4eGB1+nSpYvatm0rh8Oh3Nxcud3uwLqqqio9/PDD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6mrl2Pbt2/HZZ5/hwoULiI6ORlpaGsLDwwEAPXv2hJeXF5YvX46LFy9i7969eP/99xuMXVlZiZSUFNy6dQtVVVUm12JqDkFBQcrPwenTp5GWloaZM2dizJgx8Pf3b3At9u7dCysrK0yYMAGVlZXo3bs3QkJCMHPmTOzYsQMFBQVIS0tDTEwM9u7d26hrXFBQgKioKKSmpuLatWv46quvcPHiReU/B0RERETUOMz3T8Z8r74WzPdE1Fjc+CYis7Ny5coGf6rYr18/fPzxx9iwYQMGDRqEtLS07/1E9GcRGxuL2NhYDBo0CMeOHcPu3bvh5uYGAMpdHHV1dRg3bhx8fX2xaNEi6PV61fsNNsaCBQuwePFiREREwNfXF0lJSdi9ezd69er11POdOnUqZsyYgSFDhuDSpUs4cOAAXFxcADx8D7vPP/8c+/btg6+vLxISErB8+XLVGFOnTsX48ePx05/+FO7u7khISFCOrVixAomJiRg4cCD+9re/ISEhQbkbw9raGgkJCcjLy8PAgQMRFxeHP/zhD6qxR4wYgXnz5mHatGlwd3fHmjVrTK7D1Bx0Oh2++OILuLi4YPTo0QgKCkL37t2xbds2k2M4OTlh//79EBFMnDgR9+7dQ3x8PGbOnImIiAj06dMHU6ZMQXp6Ory9vRt1fR0cHJCXl4epU6eid+/emDt3LsLCwvD666836vlERERE9C3m+8bNl/n+IeZ7ImosnXz3TaCIiIgeQ6fTYefOnZgyZUprT4WIiIiIiH4g5nsi0ire8U1EREREREREREREmsKNbyIiIiIiIiIiIiLSFL7VCRERERERERERERFpCu/4JiIiIiIiIiIiIiJN4cY3EREREREREREREWkKN76JiIiIiIiIiIiISFO48U1EREREREREREREmsKNbyIiIiIiIiIiIiLSFG58ExEREREREREREZGmcOObiIiIiIiIiIiIiDSFG99EREREREREREREpCn/B1JtpO65r5A5AAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, axes = plt.subplots(1, 2, figsize=(18, 6))\n", + "\n", + "for ax, model in zip(axes, pricing.keys()):\n", + " tmp = costs[costs.model == model]\n", + " ax.stackplot(output_tokens_range, tmp.prompt_cost, tmp.input_cost, tmp.output_cost, labels=[\"Prompt\", \"Input\", \"Output\"])\n", + " ax.set_xlabel(\"Number of output tokens\")\n", + " ax.set_ylabel('Cost in USD')\n", + " ax.set_title(model)\n", + " ax.set_ylim(0, costs.total_cost.max())\n", + " ax.legend()\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "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.6" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/pyproject.toml b/pyproject.toml index a147e08..b1189ad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,8 +16,12 @@ dependencies = [ "gdeltdoc>=1.5.0", "lxml-html-clean>=0.2.2", "jupyter>=1.1.1", - "plotly>=5.24.1", # Plotting - "kaleido>=0.2.1", # Render plotly charts as static figures + "plotly>=5.24.1", + # Plotting + "kaleido>=0.2.1", + "tiktoken>=0.8.0", + "pyarrow>=18.0.0", + # Render plotly charts as static figures ] requires-python = ">=3.12" diff --git a/uv.lock b/uv.lock index 46fd50e..9e095a2 100644 --- a/uv.lock +++ b/uv.lock @@ -272,8 +272,10 @@ dependencies = [ { name = "newspaper3k" }, { name = "openai" }, { name = "plotly" }, + { name = "pyarrow" }, { name = "python-dotenv" }, { name = "requests" }, + { name = "tiktoken" }, ] [package.metadata] @@ -290,8 +292,10 @@ requires-dist = [ { name = "newspaper3k", specifier = ">=0.2.8" }, { name = "openai", specifier = ">=1.51.0" }, { name = "plotly", specifier = ">=5.24.1" }, + { name = "pyarrow", specifier = ">=18.0.0" }, { name = "python-dotenv", specifier = ">=1.0.1" }, { name = "requests", specifier = ">=2.26.0" }, + { name = "tiktoken", specifier = ">=0.8.0" }, ] [[package]] @@ -1664,6 +1668,34 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842 }, ] +[[package]] +name = "pyarrow" +version = "18.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ec/41/6bfd027410ba2cc35da4682394fdc4285dc345b1d99f7bd55e96255d0c7d/pyarrow-18.0.0.tar.gz", hash = "sha256:a6aa027b1a9d2970cf328ccd6dbe4a996bc13c39fd427f502782f5bdb9ca20f5", size = 1118457 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e4/ea/a7f77688e6c529723b37589af4db3e7179414e223878301907c5bd49d6bc/pyarrow-18.0.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:e7ab04f272f98ebffd2a0661e4e126036f6936391ba2889ed2d44c5006237802", size = 29493113 }, + { url = "https://files.pythonhosted.org/packages/79/8a/a3af902af623a1cf4f9d4d27d81e634caf1585a819b7530728a8147e391c/pyarrow-18.0.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:03f40b65a43be159d2f97fd64dc998f769d0995a50c00f07aab58b0b3da87e1f", size = 30833386 }, + { url = "https://files.pythonhosted.org/packages/46/1e/f38b22e12e2ce9ee7c9d805ce234f68b23a0568b9a6bea223e3a99ca0068/pyarrow-18.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be08af84808dff63a76860847c48ec0416928a7b3a17c2f49a072cac7c45efbd", size = 39170798 }, + { url = "https://files.pythonhosted.org/packages/f8/fb/fd0ef3e0f03227ab183f8dc941f4ef59636d8c382e246954601dd29cf1b0/pyarrow-18.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c70c1965cde991b711a98448ccda3486f2a336457cf4ec4dca257a926e149c9", size = 40103326 }, + { url = "https://files.pythonhosted.org/packages/7c/bd/5de139adba486db5ccc1b7ecab51e328a9dce354c82c6d26c2f642b178d3/pyarrow-18.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:00178509f379415a3fcf855af020e3340254f990a8534294ec3cf674d6e255fd", size = 38583592 }, + { url = "https://files.pythonhosted.org/packages/8d/1f/9bb3b3a644892d631dbbe99053cdb5295092d2696b4bcd3d21f29624c689/pyarrow-18.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:a71ab0589a63a3e987beb2bc172e05f000a5c5be2636b4b263c44034e215b5d7", size = 40043128 }, + { url = "https://files.pythonhosted.org/packages/74/39/323621402c2b1ce7ba600d03c81cf9645b862350d7c495f3fcef37850d1d/pyarrow-18.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:fe92efcdbfa0bcf2fa602e466d7f2905500f33f09eb90bf0bcf2e6ca41b574c8", size = 25075300 }, + { url = "https://files.pythonhosted.org/packages/13/38/4a8f8e97301adbb51c0bae7e0bc39e6878609c9337543bbbd2e9b1b3046e/pyarrow-18.0.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:907ee0aa8ca576f5e0cdc20b5aeb2ad4d3953a3b4769fc4b499e00ef0266f02f", size = 29475921 }, + { url = "https://files.pythonhosted.org/packages/11/75/43aad9b0678dfcdf5cc4d632f0ead92abe5666ce5b5cc985abab75e0d410/pyarrow-18.0.0-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:66dcc216ebae2eb4c37b223feaf82f15b69d502821dde2da138ec5a3716e7463", size = 30811777 }, + { url = "https://files.pythonhosted.org/packages/1e/b7/477bcba6ff7e65d8045d0b6c04b36f12051385f533189617a652f551e742/pyarrow-18.0.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc1daf7c425f58527900876354390ee41b0ae962a73ad0959b9d829def583bb1", size = 39163582 }, + { url = "https://files.pythonhosted.org/packages/c8/a7/37be6828370a98b3ed1125daf41dc651b27e2a9506a3682da305db757f32/pyarrow-18.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:871b292d4b696b09120ed5bde894f79ee2a5f109cb84470546471df264cae136", size = 40095799 }, + { url = "https://files.pythonhosted.org/packages/5a/a0/a4eb68c3495c5e72b404c9106c4af2d02860b0a64bc9450023ed9a412c0b/pyarrow-18.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:082ba62bdcb939824ba1ce10b8acef5ab621da1f4c4805e07bfd153617ac19d4", size = 38575191 }, + { url = "https://files.pythonhosted.org/packages/95/1f/6c629156ed4b8e2262da57868930cbb8cffba318b8413043acd02db9ad97/pyarrow-18.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:2c664ab88b9766413197733c1720d3dcd4190e8fa3bbdc3710384630a0a7207b", size = 40031824 }, + { url = "https://files.pythonhosted.org/packages/00/4f/5add0884b3ee6f4f1875e9cd0e69a30905798fa1497a80ab6df4645b54b4/pyarrow-18.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:dc892be34dbd058e8d189b47db1e33a227d965ea8805a235c8a7286f7fd17d3a", size = 25068305 }, + { url = "https://files.pythonhosted.org/packages/84/f7/fa53f3062dd2e390b8b021ce2d8de064a141b4bffc2add05471b5b2ee0eb/pyarrow-18.0.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:28f9c39a56d2c78bf6b87dcc699d520ab850919d4a8c7418cd20eda49874a2ea", size = 29503390 }, + { url = "https://files.pythonhosted.org/packages/2b/d3/03bc8a5356d95098878c0fa076e69992c6abc212898cd7286cfeab0f2c60/pyarrow-18.0.0-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:f1a198a50c409ab2d009fbf20956ace84567d67f2c5701511d4dd561fae6f32e", size = 30806216 }, + { url = "https://files.pythonhosted.org/packages/75/04/3b27d1352d3252abf42b0a83a2e7f6fcb7665cc98a5d3777f427eaa166bc/pyarrow-18.0.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5bd7fd32e3ace012d43925ea4fc8bd1b02cc6cc1e9813b518302950e89b5a22", size = 39086243 }, + { url = "https://files.pythonhosted.org/packages/30/97/861dfbe3987156f817f3d7e6feb239de1e085a6b576f62454b7bc42c2713/pyarrow-18.0.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:336addb8b6f5208be1b2398442c703a710b6b937b1a046065ee4db65e782ff5a", size = 40055188 }, + { url = "https://files.pythonhosted.org/packages/25/3a/14f024a1c8fb5ff67d79b616fe218bbfa06f23f198e762c6a900a843796a/pyarrow-18.0.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:45476490dd4adec5472c92b4d253e245258745d0ccaabe706f8d03288ed60a79", size = 38511444 }, + { url = "https://files.pythonhosted.org/packages/92/a2/81c1dd744b322c0c548f793deb521bf23500806d754128ddf6f978736dff/pyarrow-18.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:b46591222c864e7da7faa3b19455196416cd8355ff6c2cc2e65726a760a3c420", size = 40006508 }, +] + [[package]] name = "pycparser" version = "2.22" @@ -2178,6 +2210,30 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6a/9e/2064975477fdc887e47ad42157e214526dcad8f317a948dee17e1659a62f/terminado-0.18.1-py3-none-any.whl", hash = "sha256:a4468e1b37bb318f8a86514f65814e1afc977cf29b3992a4500d9dd305dcceb0", size = 14154 }, ] +[[package]] +name = "tiktoken" +version = "0.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "regex" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/37/02/576ff3a6639e755c4f70997b2d315f56d6d71e0d046f4fb64cb81a3fb099/tiktoken-0.8.0.tar.gz", hash = "sha256:9ccbb2740f24542534369c5635cfd9b2b3c2490754a78ac8831d99f89f94eeb2", size = 35107 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/22/34b2e136a6f4af186b6640cbfd6f93400783c9ef6cd550d9eab80628d9de/tiktoken-0.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:881839cfeae051b3628d9823b2e56b5cc93a9e2efb435f4cf15f17dc45f21586", size = 1039357 }, + { url = "https://files.pythonhosted.org/packages/04/d2/c793cf49c20f5855fd6ce05d080c0537d7418f22c58e71f392d5e8c8dbf7/tiktoken-0.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fe9399bdc3f29d428f16a2f86c3c8ec20be3eac5f53693ce4980371c3245729b", size = 982616 }, + { url = "https://files.pythonhosted.org/packages/b3/a1/79846e5ef911cd5d75c844de3fa496a10c91b4b5f550aad695c5df153d72/tiktoken-0.8.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9a58deb7075d5b69237a3ff4bb51a726670419db6ea62bdcd8bd80c78497d7ab", size = 1144011 }, + { url = "https://files.pythonhosted.org/packages/26/32/e0e3a859136e95c85a572e4806dc58bf1ddf651108ae8b97d5f3ebe1a244/tiktoken-0.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2908c0d043a7d03ebd80347266b0e58440bdef5564f84f4d29fb235b5df3b04", size = 1175432 }, + { url = "https://files.pythonhosted.org/packages/c7/89/926b66e9025b97e9fbabeaa59048a736fe3c3e4530a204109571104f921c/tiktoken-0.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:294440d21a2a51e12d4238e68a5972095534fe9878be57d905c476017bff99fc", size = 1236576 }, + { url = "https://files.pythonhosted.org/packages/45/e2/39d4aa02a52bba73b2cd21ba4533c84425ff8786cc63c511d68c8897376e/tiktoken-0.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:d8f3192733ac4d77977432947d563d7e1b310b96497acd3c196c9bddb36ed9db", size = 883824 }, + { url = "https://files.pythonhosted.org/packages/e3/38/802e79ba0ee5fcbf240cd624143f57744e5d411d2e9d9ad2db70d8395986/tiktoken-0.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:02be1666096aff7da6cbd7cdaa8e7917bfed3467cd64b38b1f112e96d3b06a24", size = 1039648 }, + { url = "https://files.pythonhosted.org/packages/b1/da/24cdbfc302c98663fbea66f5866f7fa1048405c7564ab88483aea97c3b1a/tiktoken-0.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c94ff53c5c74b535b2cbf431d907fc13c678bbd009ee633a2aca269a04389f9a", size = 982763 }, + { url = "https://files.pythonhosted.org/packages/e4/f0/0ecf79a279dfa41fc97d00adccf976ecc2556d3c08ef3e25e45eb31f665b/tiktoken-0.8.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b231f5e8982c245ee3065cd84a4712d64692348bc609d84467c57b4b72dcbc5", size = 1144417 }, + { url = "https://files.pythonhosted.org/packages/ab/d3/155d2d4514f3471a25dc1d6d20549ef254e2aa9bb5b1060809b1d3b03d3a/tiktoken-0.8.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4177faa809bd55f699e88c96d9bb4635d22e3f59d635ba6fd9ffedf7150b9953", size = 1175108 }, + { url = "https://files.pythonhosted.org/packages/19/eb/5989e16821ee8300ef8ee13c16effc20dfc26c777d05fbb6825e3c037b81/tiktoken-0.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5376b6f8dc4753cd81ead935c5f518fa0fbe7e133d9e25f648d8c4dabdd4bad7", size = 1236520 }, + { url = "https://files.pythonhosted.org/packages/40/59/14b20465f1d1cb89cfbc96ec27e5617b2d41c79da12b5e04e96d689be2a7/tiktoken-0.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:18228d624807d66c87acd8f25fc135665617cab220671eb65b50f5d70fa51f69", size = 883849 }, +] + [[package]] name = "tinycss2" version = "1.3.0"