# OpenAI Python API - Cost Estimation With TikToken

**URL:** https://vip.studycamp.tw/t/openai-python-api-cost-estimation-with-tiktoken/6159
**Category:** OpenAI Python API 共學課程
**Created:** [2023年六月14日 00:12 UTC](https://vip.studycamp.tw/t/openai-python-api-cost-estimation-with-tiktoken/6159 "2023-06-14T00:12:37Z")
**Posts on this page:** 1
**Page:** 1

<div class="post-metadata">

### Author: ![sky](https://vip.studycamp.tw/user_avatar/vip.studycamp.tw/sky/32/8098_2.png) [@sky](https://vip.studycamp.tw/u/sky)
#### Post date: [2023年六月14日 00:12 UTC](https://vip.studycamp.tw/t/openai-python-api-cost-estimation-with-tiktoken/6159/1 "2023-06-14T00:12:38Z")

</div>

最簡單的 token 計算，當然是之前介紹的 [**Tokenizer**](https://platform.openai.com/tokenizer)。

把你想計算的文字，直接複製貼上，網頁就告訴你結果。

不過，實際應用上，當然還是呼叫程式計算。

## OpenAi 官方教學

官方教學有一些額外資訊，感興趣的朋友請參考（Jupyter Notebook 格式）：

[**How to count tokens with tiktoken?**](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb)

## tiktoken

為了避免看到帳單時嚇一跳，用程式預先計算，將花費控制在可接受的範圍。

> **[GitHub - openai/tiktoken: tiktoken is a fast BPE tokeniser for use with...](https://github.com/openai/tiktoken)**
>
> tiktoken is a fast BPE tokeniser for use with OpenAI's models.

## BPE (Byte Pair Encoding)

tiktoken 使用 **[BPE 演算法](https://en.wikipedia.org/wiki/Byte_pair_encoding)**。

- 1994年，首先公開發表於 Philip Gage 的 _[C Users Journal](https://en.wikipedia.org/wiki/C_Users_Journal)_ 著作。

- 2015年，開始被應用在 [natural language processing](https://en.wikipedia.org/wiki/Natural_language_processing) (NLP) 中的 [tokenization](https://en.wikipedia.org/wiki/Lexical_analysis)。

BPN 演算法，主要是把重覆出現的字串，用另新的字串代替，依此類推。例如：

1. 原始字串

2. 第一次壓縮 Z = aa  
aaabdaaabac 會成為

3. 第二次壓縮 Y=ab  
ZabdZabac 會成為

4. 第三次壓縮 X=ZY  
ZYdZYac 會成為

到無法再壓縮時，就算壓縮完成。

要解壓時，把上述程式倒過來即可。

我們看看 OpenAI 在 github 中，如何描述 BPE：

1. 可逆且無損壓縮，因此可以將標記轉換回原始文件。

2. 適用於任意文件，甚至是不在標記器訓練數據中的文件。

3. 壓縮文件：令牌序列（token sequence）比原始文件短。實際上，每個令牌（token）平均對應大約 4 個 bytes。

4. 它試圖讓模型看到常見的子詞（subwords）。

## 編碼方式

tiktoken 有三種編碼方式，不同 model 對應的 encoding 如下表：

| Encoding name | OpenAI models |
| --- | --- |
| `cl100k_base` | `gpt-4`, `gpt-3.5-turbo`, `text-embedding-ada-002` |
| `p50k_base` | Codex models, `text-davinci-002`, `text-davinci-003` |
| `r50k_base` (or `gpt2`) | GPT-3 models like `davinci` |

GPT-4 和 GPT-3.X 的比較，這篇這的蠻詳細：

> **[GPT 3 vs. GPT 4. Open AI Language Models Comparison](https://neoteric.eu/blog/gpt-4-vs-gpt-3-openai-models-comparison)**
>
> Compare the GPT 3 vs. GPT 4 and GPT 3.5. Learn the similarities and key differences between these Open AI language models.

## 實際應用

就是把 OpenAI 的 `num_tokens_from_messages` 直接拿來用即可。

以下計算 token 函式來自 OpenAI github - **[How to count tokens with tiktoken](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb)**

更新日期：2023年5月6日

```python
def num_tokens_from_messages(messages, model="gpt-3.5-turbo-0301"):
    """Returns the number of tokens used by a list of messages."""
    try:
        encoding = tiktoken.encoding_for_model(model)
    except KeyError:
        print("Warning: model not found. Using cl100k_base encoding.")
        encoding = tiktoken.get_encoding("cl100k_base")
    if model == "gpt-3.5-turbo":
        print("Warning: gpt-3.5-turbo may change over time. Returning num tokens assuming gpt-3.5-turbo-0301.")
        return num_tokens_from_messages(messages, model="gpt-3.5-turbo-0301")
    elif model == "gpt-4":
        print("Warning: gpt-4 may change over time. Returning num tokens assuming gpt-4-0314.")
        return num_tokens_from_messages(messages, model="gpt-4-0314")
    elif model == "gpt-3.5-turbo-0301":
        tokens_per_message = 4 # every message follows <|start|>{role/name}\n{content}<|end|>\n
        tokens_per_name = -1 # if there's a name, the role is omitted
    elif model == "gpt-4-0314":
        tokens_per_message = 3
        tokens_per_name = 1
    else:
        raise NotImplementedError(f"""num_tokens_from_messages() is not implemented for model {model}. See https://github.com/openai/openai-python/blob/main/chatml.md for information on how messages are converted to tokens.""")
    num_tokens = 0
    for message in messages:
        num_tokens += tokens_per_message
        for key, value in message.items():
            num_tokens += len(encoding.encode(value))
            if key == "name":
                num_tokens += tokens_per_name
    num_tokens += 3 # every reply is primed with <|start|>assistant<|message|>
    return num_tokens

```

不過我們實際使用時，不需要（也不應該）自己把上面這段 code 複製到自己的程式中，因為 OpenAI 可能會不定期版本更新。使用的方法如下：

```python
import tiktoken

def num_tokens_from_string(string: str, encoding_name: str) -> int:
    """Returns the number of tokens in a text string."""
    encoding = tiktoken.get_encoding(encoding_name)
    num_tokens = len(encoding.encode(string))
    return num_tokens

num_tokens_from_string("tiktoken is great!", "cl100k_base")

```

以上示範程式來自 OpenAI 官網 - [ **How can I tell how many tokens a string has before I embed it?**  
 ](https://platform.openai.com/docs/guides/embeddings/how-can-i-tell-how-many-tokens-a-string-has-before-i-embed-it)

> 補充：你可以從 [**前面表格（tiktoken 的編碼方式）**](https://vip.studycamp.tw/t/topic/6159#tiktoken-4) 中左側的「Encoding name」或右側的「OpenAI models」選擇編碼方式：
> 
> encoding = tiktoken.get\_encoding(“cl100k\_base”)
> 
> encoding = tiktoken.encoding\_for\_model(“gpt-4”)

## 延伸閱讀

1. 找資料的過程中，看到一段說明，提及 tiktoken 的 `_educational` 能提供更視覺化的演算法理解。原文找不到了，這裡是 github 中的程式碼：

> <https://github.com/openai/tiktoken/blob/main/tiktoken/_educational.py>

1. 關於 Token Count，這裡有另一堂共學課程的參考： **[1️⃣ Section 10. 文字嵌入（Text Embedding）](https://vip.studycamp.tw/t/topic/5931#token-count-19)**
