Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add token counting for OpenAI tools/tool_choice #4716

Merged
merged 5 commits into from
Jul 16, 2024

Conversation

pamelafox
Copy link
Contributor

Title

This PR implements token counting for OpenAI calls that include tools and tool_choice parameter, based on the approach I use in https://github.com/pamelafox/openai-messages-token-helper

I don't know if any other LLMs support tools/tool_choice at this point, and if so, I don't know how to count tokens for other LLMs yet, so this is OpenAI-specific.

I brought in my test cases that have been verified with OpenAI, and also fixed an issue that I saw with counting tokens for images.

I can also expand on the current documentation to mention tools/tool_choice, if this approach looks good.

Relevant issues

Fixes #4664

Type

🆕 New Feature
🐛 Bug Fix
✅ Test

Changes

  • Addition of tools/tool_choice to token_counter function
  • Fixed bug in token_counter with small images

[REQUIRED] Testing

@pamelafox ➜ /workspaces/litellm/litellm/tests (main) $ poetry run pytest test_token_counter.py 
============================================ test session starts =============================================
platform linux -- Python 3.11.9, pytest-7.4.4, pluggy-1.5.0
rootdir: /workspaces/litellm/litellm/tests
plugins: mock-3.14.0, anyio-4.3.0
collected 47 items                                                                                           

test_token_counter.py ...............................................                                  [100%]

============================================== warnings summary ==============================================

Copy link

vercel bot commented Jul 15, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
litellm ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 15, 2024 6:20pm

@@ -3,15 +3,14 @@

import os
import sys
import traceback
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed unused imports

diff = counted_tokens - expected_tokens
assert (
diff >= 0 and diff <= 3
), f"Expected {expected_tokens} tokens, got {counted_tokens}. Counted tokens is only allowed to be off by 3 in the over-counting direction."
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this doesnt do an exact comparison, as I haven't figured out how to get the counts to match exactly, and I don't know if anyone has, since this is all based on reverse-engineering. So I allow over-counting by 3.

@@ -401,6 +401,18 @@ class ChatCompletionToolParam(TypedDict):
function: ChatCompletionToolParamFunctionChunk


class Function(TypedDict, total=False):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that you replicate the types from the openai package? I'm not sure why that's done (versus directly importing from openai), but I copied the types here.

@pamelafox
Copy link
Contributor Author

By the way, it appears that token_counter repeats the message-token-calculation twice- once before it knows what tokenizer it will use, and then again when it decide to use openAI tokenizer. It'd be more efficient if we avoided the first calculation for openai.

num_tokens += 9 # Additional tokens for function definition of tools
# If there's a system message and tools are present, subtract four tokens
if tools and includes_system_message:
num_tokens -= 4
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interesting is there any doc / openai reference for this? @pamelafox

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, not as far as I know. I found this logic from OpenAI discussion forum threads (like https://community.openai.com/t/how-to-calculate-the-tokens-when-using-function-call/266573/59) and other packages, such as https://github.com/forestwanglin/openai-java/blob/main/jtokkit/src/main/java/xyz/felh/openai/jtokkit/utils/TikTokenUtils.java (which I reference in a docstring in this file).

I then verified it by running my test calls against live OpenAI. For basic functions, it gets it exactly correct, but it over-counts by up to 3 tokens for fancier function definitions.

@krrishdholakia krrishdholakia merged commit 0fb88e5 into BerriAI:main Jul 16, 2024
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature]: Token counting for function calling and image requests for OpenAI
2 participants