a0c8464e58
Build Package / build (ubuntu-latest) (push) Failing after 1s
CodeQL / Analyze (python) (push) Failing after 1s
Core Typecheck / core-typecheck (push) Failing after 1s
Linting / lint (push) Failing after 1s
llama-dev tests / test-llama-dev (push) Failing after 1s
Publish Sub-Package to PyPI if Needed / publish_subpackage_if_needed (push) Has been skipped
Sync Docs to Developer Hub / sync-docs (push) Failing after 0s
Build Package / build (windows-latest) (push) Has been cancelled
411 lines
11 KiB
Plaintext
411 lines
11 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"<a href=\"https://colab.research.google.com/github/run-llama/llama_index/blob/main/docs/examples/observability/TokenCountingHandler.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
|
|
]
|
|
},
|
|
{
|
|
"attachments": {},
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Token Counting Handler\n",
|
|
"\n",
|
|
"This notebook walks through how to use the TokenCountingHandler and how it can be used to track your prompt, completion, and embedding token usage over time."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"If you're opening this Notebook on colab, you will probably need to install LlamaIndex 🦙."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%pip install llama-index-llms-openai"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"!pip install llama-index"
|
|
]
|
|
},
|
|
{
|
|
"attachments": {},
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Setup\n",
|
|
"\n",
|
|
"Here, we setup the callback and the serivce context. We set global settings so that we don't have to worry about passing it into indexes and queries."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import os\n",
|
|
"\n",
|
|
"os.environ[\"OPENAI_API_KEY\"] = \"sk-...\""
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import tiktoken\n",
|
|
"from llama_index.core.callbacks import CallbackManager, TokenCountingHandler\n",
|
|
"from llama_index.llms.openai import OpenAI\n",
|
|
"from llama_index.core import Settings\n",
|
|
"\n",
|
|
"\n",
|
|
"token_counter = TokenCountingHandler(\n",
|
|
" tokenizer=tiktoken.encoding_for_model(\"gpt-3.5-turbo\").encode\n",
|
|
")\n",
|
|
"\n",
|
|
"Settings.llm = OpenAI(model=\"gpt-3.5-turbo\", temperature=0.2)\n",
|
|
"Settings.callback_manager = CallbackManager([token_counter])"
|
|
]
|
|
},
|
|
{
|
|
"attachments": {},
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Token Counting\n",
|
|
"\n",
|
|
"The token counter will track embedding, prompt, and completion token usage. The token counts are __cummulative__ and are only reset when you choose to do so, with `token_counter.reset_counts()`.\n",
|
|
"\n",
|
|
"### Embedding Token Usage\n",
|
|
"\n",
|
|
"Now that the settings is setup, let's track our embedding token usage."
|
|
]
|
|
},
|
|
{
|
|
"attachments": {},
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Download Data"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"!mkdir -p 'data/paul_graham/'\n",
|
|
"!wget 'https://raw.githubusercontent.com/run-llama/llama_index/main/docs/examples/data/paul_graham/paul_graham_essay.txt' -O 'data/paul_graham/paul_graham_essay.txt'"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from llama_index.core import SimpleDirectoryReader\n",
|
|
"\n",
|
|
"documents = SimpleDirectoryReader(\"./data/paul_graham\").load_data()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from llama_index.core import VectorStoreIndex\n",
|
|
"\n",
|
|
"index = VectorStoreIndex.from_documents(documents)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"20723\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"print(token_counter.total_embedding_token_count)"
|
|
]
|
|
},
|
|
{
|
|
"attachments": {},
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"That looks right! Before we go any further, lets reset the counts"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"token_counter.reset_counts()"
|
|
]
|
|
},
|
|
{
|
|
"attachments": {},
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### LLM + Embedding Token Usage\n",
|
|
"\n",
|
|
"Next, let's test a query and see what the counts look like."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"query_engine = index.as_query_engine(similarity_top_k=4)\n",
|
|
"response = query_engine.query(\"What did the author do growing up?\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Embedding Tokens: 8 \n",
|
|
" LLM Prompt Tokens: 4518 \n",
|
|
" LLM Completion Tokens: 45 \n",
|
|
" Total LLM Token Count: 4563 \n",
|
|
"\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"print(\n",
|
|
" \"Embedding Tokens: \",\n",
|
|
" token_counter.total_embedding_token_count,\n",
|
|
" \"\\n\",\n",
|
|
" \"LLM Prompt Tokens: \",\n",
|
|
" token_counter.prompt_llm_token_count,\n",
|
|
" \"\\n\",\n",
|
|
" \"LLM Completion Tokens: \",\n",
|
|
" token_counter.completion_llm_token_count,\n",
|
|
" \"\\n\",\n",
|
|
" \"Total LLM Token Count: \",\n",
|
|
" token_counter.total_llm_token_count,\n",
|
|
" \"\\n\",\n",
|
|
")"
|
|
]
|
|
},
|
|
{
|
|
"attachments": {},
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Token Counting + Streaming!\n",
|
|
"\n",
|
|
"The token counting handler also handles token counting during streaming.\n",
|
|
"\n",
|
|
"Here, token counting will only happen once the stream is completed."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"token_counter.reset_counts()\n",
|
|
"\n",
|
|
"query_engine = index.as_query_engine(similarity_top_k=4, streaming=True)\n",
|
|
"response = query_engine.query(\"What happened at Interleaf?\")\n",
|
|
"\n",
|
|
"# finish the stream\n",
|
|
"for token in response.response_gen:\n",
|
|
" # print(token, end=\"\", flush=True)\n",
|
|
" continue"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Embedding Tokens: 6 \n",
|
|
" LLM Prompt Tokens: 4563 \n",
|
|
" LLM Completion Tokens: 123 \n",
|
|
" Total LLM Token Count: 4686 \n",
|
|
"\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"print(\n",
|
|
" \"Embedding Tokens: \",\n",
|
|
" token_counter.total_embedding_token_count,\n",
|
|
" \"\\n\",\n",
|
|
" \"LLM Prompt Tokens: \",\n",
|
|
" token_counter.prompt_llm_token_count,\n",
|
|
" \"\\n\",\n",
|
|
" \"LLM Completion Tokens: \",\n",
|
|
" token_counter.completion_llm_token_count,\n",
|
|
" \"\\n\",\n",
|
|
" \"Total LLM Token Count: \",\n",
|
|
" token_counter.total_llm_token_count,\n",
|
|
" \"\\n\",\n",
|
|
")"
|
|
]
|
|
},
|
|
{
|
|
"attachments": {},
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Advanced Usage\n",
|
|
"\n",
|
|
"The token counter tracks each token usage event in an object called a `TokenCountingEvent`. This object has the following attributes:\n",
|
|
"\n",
|
|
"- prompt -> The prompt string sent to the LLM or Embedding model\n",
|
|
"- prompt_token_count -> The token count of the LLM prompt\n",
|
|
"- completion -> The string completion received from the LLM (not used for embeddings)\n",
|
|
"- completion_token_count -> The token count of the LLM completion (not used for embeddings)\n",
|
|
"- total_token_count -> The total prompt + completion tokens for the event\n",
|
|
"- event_id -> A string ID for the event, which aligns with other callback handlers\n",
|
|
"\n",
|
|
"These events are tracked on the token counter in two lists:\n",
|
|
"\n",
|
|
"- llm_token_counts\n",
|
|
"- embedding_token_counts\n",
|
|
"\n",
|
|
"Let's explore what these look like!"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Num LLM token count events: 2\n",
|
|
"Num Embedding token count events: 1\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"print(\"Num LLM token count events: \", len(token_counter.llm_token_counts))\n",
|
|
"print(\n",
|
|
" \"Num Embedding token count events: \",\n",
|
|
" len(token_counter.embedding_token_counts),\n",
|
|
")"
|
|
]
|
|
},
|
|
{
|
|
"attachments": {},
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"This makes sense! The previous query embedded the query text, and then made 2 LLM calls (since the top k was 4, and the default chunk size is 1024, two separate calls need to be made so the LLM can read all the retrieved text).\n",
|
|
"\n",
|
|
"Next, let's quickly see what these events look like for a single event."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"prompt: system: You are an expert Q&A system that is trusted around the world.\n",
|
|
"Always answer the query using ...\n",
|
|
"\n",
|
|
"prompt token count: 3873 \n",
|
|
"\n",
|
|
"completion: assistant: At Interleaf, the company had added a scripting language inspired by Emacs and made it a ...\n",
|
|
"\n",
|
|
"completion token count: 95 \n",
|
|
"\n",
|
|
"total token count 3968\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"print(\"prompt: \", token_counter.llm_token_counts[0].prompt[:100], \"...\\n\")\n",
|
|
"print(\n",
|
|
" \"prompt token count: \",\n",
|
|
" token_counter.llm_token_counts[0].prompt_token_count,\n",
|
|
" \"\\n\",\n",
|
|
")\n",
|
|
"\n",
|
|
"print(\n",
|
|
" \"completion: \", token_counter.llm_token_counts[0].completion[:100], \"...\\n\"\n",
|
|
")\n",
|
|
"print(\n",
|
|
" \"completion token count: \",\n",
|
|
" token_counter.llm_token_counts[0].completion_token_count,\n",
|
|
" \"\\n\",\n",
|
|
")\n",
|
|
"\n",
|
|
"print(\"total token count\", token_counter.llm_token_counts[0].total_token_count)"
|
|
]
|
|
}
|
|
],
|
|
"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"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 4
|
|
}
|