BEACHSIDE BLOG

Azure と GitHub と C# が好きなエンジニアの個人メモ ( ・ㅂ・)و ̑̑

OpenAI: 文章のトークン数を数える (C#, Python, Node)

OpenAI / Azure OpenAI でとりあえずトークン数を数えることってちょいちょいありますよね。今回は C#, TypeScript のついでに Python もメモしておこうかなという話です。

はじめに: トークンとは

トークンとはなんじゃって改めて感じた場合は、 以下の OpenAI のドキュメントを読むと参考になります (なるかな...)。

と雑にふれたところで、さっそく各言語での実装を見ていきます。

Python: tiktoken

これは言うまでもなくtiktoken ですね。サンプルはこんな感じ。

import tiktoken

def count_token(text: str, model_name: str) -> int:
    encoding = tiktoken.encoding_for_model(model_name)
    token_count = len(encoding.encode(text))
    return token_count

count = count_token("こんにちは、猫さん", "gpt-3.5-turbo")
print(f"{count=}")


model 名から encoding のオブジェクトを作ることが多いですが、参考までに encoding 名からもできます。各 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 (davinci とか)

で、コード。

import tiktoken

def count_token_from_encoding_name(text: str, encoding_name: str) -> int:
  encoding = tiktoken.get_encoding(encoding_name)
  token_count = len(encoding.encode(text))
  return token_count

count = count_token_from_encoding_name("こんにちわ、猫さん", "cl100k_base")
print(f"{count=}")

余談ですが「こんにちは」じゃなくて間違った日本語である「こんにちわ」にするとトークンが増えますね。

C#

Tokenizer

Microsoft が OSS として公開している Tokenizer でトークン数を数えれます。tiktoken の実装をベースにしてるみたいですね。

NuGet で Microsoft.DeepDev.TokenizerLib をインストールしてあとはこんな感じ。実際にトークン数えてるのは26-32行目のメソッド。

`

補足をいくつか書いておきます。

  • 28行目の tokenizer をインスタンス化する TokenizerBuilder.CreateByModelNameAsync はちょっとコストがかかるのでモデルが決まりきっててトークン数を数える回数も多いなら singleton で保持しておいた方がよさそう。
  • 31行目は、トークンを数えるテキストに対して29行目でトークンを追加しているので、その分で2を引いています。
  • TokenizerBuilder.CreateByEncoderNameAsync メソッドを使って encoder name で tokenizer の初期化もできます。
  • model name や encoder name は実装から一覧をみて書いた方がよさそう。
    • Tokenizer/Tokenizer_C#/TokenizerLib/TokenizerBuilder.cs
    • これ書いてる時点だと、model 名が OpenAI の方の名称をベースにしている。そのため Azure AI Studio で表示される model name: gpt-35-turbo だとエラー、OpenAI での model name: gpt-3.5-turbo としないとあかんとか微妙な点があるため。

Semantic Kernel: GPT3Tokenizer

Semantic Kernel の中に GPT3Tokenizer ってのがあってこんな感じでサクッと使えます。

using Microsoft.SemanticKernel.Connectors.AI.OpenAI.Tokenizers;

const string sampleText = "";
var tokenCount = GPT3Tokenizer.Encode(sampleText);

実装を見るとまだこのひとつしかないみたい。これは p50k_base のエンコーダーで、で足りているので、text-davinci-003 や code-davinci-002 で使われているやつ。つまり、gpt-4, gpt-3.5-turbo や text-embedding-ada-002 で使われている cl100k_base とは異なる古いやつなので、積極的に使えるものでなない。ということで、Tokenizer 使いましょうって話になります。

TypeScript (JavaScript)

Tokenizer

TypeScript は、先述の C# と同じ repo で Microsoft が OSS として公開している Tokenizer でやれます。

GitHub Packages Registry を使ってるのでそこから package をダウンロードしつつ C# と似た実装で処理するって感じです。C# とあまり変わらないので参考リンクだけにしておきます (C# と Python は私が使ってるで書いたけど、TS は今のとこ使う予定無いのでメモだけでいいやと雑に扱いました)。

GPT-3-Encoder

GPT-3-Encoder もあるけど、最近更新されてないから Tokenizer 使った方が無難です。

www.npmjs.com

参考

github.com