paint-brush
チャットボットは単語を読んでいるのではなく、トークンを数えているのです@paulr
2,546 測定値
2,546 測定値

チャットボットは単語を読んでいるのではなく、トークンを数えているのです

9m2025/02/05
Read on Terminal Reader

長すぎる; 読むには

トークン化は、生のテキストを GPT などの大規模言語モデル (LLM) で使用できる形式に変換するためのゲートウェイです。これは、人間が読めるコンテンツとモデルが処理する数値データの間の橋渡しとして機能します。テキストをトークン化する方法は、モデルがデータを処理できる効率に直接影響します。
featured image - チャットボットは単語を読んでいるのではなく、トークンを数えているのです
undefined HackerNoon profile picture

トークン化は、生のテキストを GPT などの大規模言語モデル (LLM) で使用できる形式に変換するためのゲートウェイです。これは、人間が読めるコンテンツとモデルが処理する数値データの間の橋渡しとして機能します。モデルが一貫したテキストを理解したり生成したりする前に、入力をトークンと呼ばれる小さな単位に分割する必要があります。


GPT アーキテクチャでは、トークン化はモデルのパフォーマンスと機能の基本であり、効率、コンテキスト ウィンドウの使用、および出力品質に影響します。トークン化とは、テキストをトークンと呼ばれる小さな単位に分割するプロセスです。トークンは、単語、サブワード、文字、さらには特殊記号を表すことができます。これらのトークンは、モデルが処理する基本的な構成要素です。テキストをトークン化する方法は、モデルがデータを処理できる効率、コンテキスト ウィンドウ内に収まる情報の量、およびモデルが生成する応答の品質に直接影響します。


コンテキスト ウィンドウとは、モデルが 1 回の操作で処理できるトークンの最大数であり、入力と生成された出力の両方が含まれます。たとえば、32,000 トークンのコンテキスト ウィンドウを持つモデルでは、入力テキスト、システム命令、モデルの応答など、すべてがこの制限内に収まる必要があります。効率的なトークン化により、特定のテキストを表すために必要なトークンの数が減り、制限を超えずに、より多くのコンテンツを含めたり、より長く充実した出力を取得したりできるようになります。一方、トークン化が不十分だと、トークン数が不必要に膨らんでコンテキスト ウィンドウの貴重なスペースが無駄になり、より長いタスクでのモデルの使いやすさが制限される可能性があります。


テキストがトークン化されると、各トークンは数値埋め込みに変換されます。数値埋め込みは、高次元空間 (多くの場合、数百または数千の次元) における数学的表現です。この埋め込みは、語彙全体のコンテキストにおけるトークンの意味と関係性を捉えます。たとえば、「run」や「running」などの類似した単語のトークンは、「run」や「table」などの無関係なトークンよりもこの空間に近い位置に配置されます。これらの埋め込みにより、モデルはトークンのシーケンスを理解し、テキスト生成中に最も可能性の高い次のトークンを予測できます。このプロセスにより、クエリへの応答、文の完成、クリエイティブなコンテンツの生成など、GPT は一貫性があり、コンテキストに関連した出力を生成できます。

本質的に、トークン化は単なる前処理ステップではなく、GPT モデルが効率的に機能し、高品質の結果を提供するための重要な要素です。


トークン化の仕組み

トークン化は、万能のプロセスではありません。テキストをトークンと呼ばれる管理可能な単位に分割するように設計された、事前定義されたルールまたはアルゴリズムに応じて異なります。


仕組みを詳しく見てみましょう:


分割

これには、テキストを単語、サブワード、文字などの小さな単位に分割することが含まれます。現代の LLM は、効率性と堅牢性のバランスが取れることから、サブワード トークン化に頼ることがよくあります。このバランスは、サブワード トークン化によって、まれな単語や未知の単語をより小さく一般的なコンポーネントに分割しながら、頻繁に使用される単語を単一のトークンとしてエンコードできるため実現します。



unhappinessという単語を考えてみましょう。サブワードのトークン化を使用すると、次のように分割される可能性があります。

  • unhappiness

このアプローチにより、次のことが保証されます。

  • 効率性: unnessなどの共通要素はさまざまな単語間で再利用され、語彙のサイズが削減されます。
  • 堅牢性: unhappinessなどのまれな単語も、既知のサブコンポーネントに分割することで処理でき、語彙不足の問題を回避できます。


実際には、これにより、語彙を過度に増やすことなく、さまざまなテキスト入力にわたってモデルをより適切に一般化できるようになります。


エンコーディング

エンコーディングでは、定義済みの語彙(モデルが認識できるすべてのトークンのコレクション)に基づいて、各トークンに一意の整数が割り当てられます。GPT や同様のモデルのコンテキストでは、語彙はトレーニング中に作成され、モデルがテキストを理解して生成するために使用するサブワード (または文字) のセットを表します。


たとえば、GPT の場合:

  • helloという単語は、 1356のような整数表現を持つ単一のトークンである可能性があります。
  • micropaleontologyのような珍しい用語は、 micropaleontologyなどのサブワード トークンに分割され、それぞれに整数が含まれる場合があります。


ChatGPT の場合、ユーザーがテキストを入力すると、トークナイザーはモデルの語彙に基づいて入力文字列を整数のシーケンスにマッピングします。このシーケンスはニューラル ネットワークによって処理されます。語彙のサイズはモデルのメモリ使用量と計算効率に影響し、複雑な言語構造の処理とシステムのパフォーマンス維持のバランスをとります。


デコード

デコードは逆のプロセスで、トークン整数のシーケンスを人間が読めるテキストに変換します。サブワードのトークン化の場合、可能な場合はサブワードを完全な単語に再構成します。


仕組み

  1. モデルは出力時に整数 (トークン) のシーケンスを生成します。
  2. デコーダーは語彙内の各整数を検索し、対応するサブワードまたは文字を取得します。
  3. サブワードは連結されて単語を形成し、一貫性を確保するためのルールが適用されます (例: サブワードの周囲の不要なスペースを削除する)。



モデルがunhappinessのトークンを生成するとします。デコードにより、サブワードを連結してunhappinessに再構築されます。スペースを適切に処理することで、 unが別の単語として扱われないようにします。


このシステムにより、サブワードベースのモデルは、まれな用語や複雑な用語を正しく表現する機能を維持しながら、効率的にテキストを生成できます。


開発者としてなぜ気にする必要があるのでしょうか?

ChatGPT API はトークン化を自動的に処理しますが、開発者はtiktoken直接使用して、アプリケーションをより細かく制御できます。これにより、トークン制限を事前にチェックおよび管理して、入力テキストと応答がモデルの制約内に収まるようにすることができます。これは、長い会話やドキュメントを扱うときにエラーを回避するために特に重要です。さらに、開発者は入力をトリミングまたは要約することでトークンの使用を最適化し、API コストを削減できます。


tiktokenトークン化の問題のデバッグにも役立ち、テキストがどのようにトークン化されデコードされるかについて透明性を提供します。長い入力を処理するために、 tiktokenテキストを小さなチャンクに分割し、大きなドキュメントを部分的に処理できるようにします。最後に、埋め込みやトークン レベルの操作などの高度なユース ケースでは、 tiktokenトークンの生成方法と処理方法を正確に制御します。

 import openai import tiktoken openai.api_key = "your-api-key" # Initialize tokenizer for GPT-4 encoding = tiktoken.get_encoding("cl100k_base") # Function to count tokens def count_tokens(text): return len(encoding.encode(text)) # Example input user_input = "Explain the theory of relativity in detail with examples." conversation_history = [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "What is the theory of relativity?"} ] # Combine inputs for token counting conversation_text = "".join([msg["content"] for msg in conversation_history]) + user_input # Pre-check input token limit (Use Case 1) token_limit = 4096 if count_tokens(conversation_text) > token_limit: print("Trimming conversation to fit within token limit.") conversation_history = conversation_history[1:] # Trim oldest message # Optimize input by summarizing if too long (Use Case 2) def summarize_if_needed(text, max_tokens=500): if count_tokens(text) > max_tokens: print("Input too long, summarizing...") response = openai.ChatCompletion.create( model="gpt-3.5-turbo", messages=[ {"role": "system", "content": "Summarize the following text."}, {"role": "user", "content": text} ], max_tokens=200 ) return response.choices[0].message["content"] return text long_text = "A very long text input that exceeds the desired token limit ... (more text)" optimized_text = summarize_if_needed(long_text, max_tokens=500) # Debug tokenization (Use Case 3) tokens = encoding.encode("OpenAI's ChatGPT is amazing!") print("Tokenized:", tokens) for token in tokens: print(f"Token ID: {token}, Token: '{encoding.decode([token])}'") # Handle long documents by splitting into chunks (Use Case 4) def split_into_chunks(text, chunk_size): tokens = encoding.encode(text) for i in range(0, len(tokens), chunk_size): yield encoding.decode(tokens[i:i + chunk_size]) document = "A very long document... (more text)" chunks = list(split_into_chunks(document, chunk_size=1000)) # Process each chunk separately responses = [] for chunk in chunks: response = openai.ChatCompletion.create( model="gpt-3.5-turbo", messages=[{"role": "user", "content": chunk}], max_tokens=300 ) responses.append(response.choices[0].message["content"]) full_response = " ".join(responses) # Advanced token manipulation (Use Case 5) custom_text = "Analyze the sentiment of this text." tokens = encoding.encode(custom_text) response = openai.ChatCompletion.create( model="gpt-3.5-turbo", messages=[{"role": "user", "content": encoding.decode(tokens)}], max_tokens=100 ) print("Final Response:", response.choices[0].message["content"])

コードのハイライト:

  1. トークン制限を事前にチェックすることで、入力がモデルの制約内に収まるようになり、切り捨てやエラーを回避できます。
  2. 入力要約により、長いテキストを扱うときにトークンの使用量が削減されます。
  3. トークン化をデバッグすると、トークンがどのようにエンコードおよびデコードされるかについての透明性が提供されます。
  4. 長いドキュメントを管理しやすいチャンクに分割すると、大量の入力が効率的に処理されます。
  5. 高度なトークン操作は、トークン化された入力を正確に制御します。


このアプローチにより、ChatGPT API 上に構築する際の最適なパフォーマンスとコスト効率の両方が保証されます。

3. tiktokenの探索:GPTのトークナイザー

OpenAI のtiktokenライブラリは、効率的にトークン化し、GPT モデルの制約を理解するように設計されています。その仕組みを見てみましょう。

使用例

以下は、 tiktokenを使用してテキストをトークン化する方法の Python の例です。私は、Python ノートブックを実行するためにhttps://colab.research.google.com/を使用しています。


 import tiktoken # Choose a model-specific tokenizer encoding = tiktoken.get_encoding("o200k_base") # Input text text = "Tokenization is crucial for GPT models." # Tokenize text tokens = encoding.encode(text) print("Tokens:", tokens) # Decode back to text decoded_text = encoding.decode(tokens) print("Decoded Text:", decoded_text)

出力

Tokens: [4421, 2860, 382, 19008, 395, 174803, 7015, 13] Decoded Text: Tokenization is crucial for GPT models.

4. ChatGPT API におけるトークン化のための開発者向けレバー

ChatGPT API を使用する場合、トークン化を理解すると、次の点を最適化できます。

  1. 入力効率:
    • 入力は簡潔にしてください。トークンごとに処理能力が消費され、トークン制限に影響します (例: GPT-3.5 の場合は 8k、GPT-4 の場合は 32k)。
    • 重要な情報のみを保持することで、コンテキストを効果的に再利用します。
  2. モデル選択:
    • GPT モデルによってトークン化の動作は異なります。コンテキスト ウィンドウが大きいモデルでは、より広範な入力が可能になりますが、コストが高くなります。
  3. プロンプトの構造化:
    • 不要なトークンを最小限に抑えるために、書式設定とフレーズを試してみてください。冗長性を減らすことで、意味を失うことなくトークンの予算を最大化できます。
  4. 微調整とトークン操作:
    • パディングや切り捨てなどのトークン レベルの操作を使用して、アプリケーション間で入力が均一になるようにします。

5. Pythonでのサンプル実装

ChatGPT API をクエリするときにトークンの使用量を計算する実用的な例を次に示します。

 import tiktoken import openai def calculate_tokens(api_input, model="gpt-3.5-turbo"): encoding = tiktoken.encoding_for_model(model) tokens = encoding.encode(api_input) return len(tokens) # Example API call with token usage calculation api_input = "Explain the significance of tokenization in LLMs." model = "gpt-4" token_count = calculate_tokens(api_input, model) print(f"Token count for input: {token_count}") response = openai.ChatCompletion.create( model=model, messages=[{"role": "user", "content": api_input}] ) print("API Response:", response['choices'][0]['message']['content'])

このコードは、コストとパフォーマンスの最適化に不可欠なトークンの使用状況を監視するのに役立ちます。


6. まとめ

トークン化を理解することは、AI アプリケーションを構築するエンジニアにとって不可欠です。これは、トークン化が言語モデルによるテキストデータの処理方法に直接影響するためです。トークン化では、生のテキストを単語、サブワード、文字などのより小さく意味のある単位に分解します。これらの単位は、これらのモデルの基本的な入力です。このプロセスにより、開発者は入力サイズを正確に管理し、不要なトークンの使用を減らすことでコストを最適化し、文脈上の意味を保持する方法でテキストをセグメント化することでモデルのパフォーマンスを向上させることができます。さらに、トークン化をクライアント側のコードに直接組み込むと、データ転送のオーバーヘッドとレイテンシが削減され、操作が合理化され、より効率的なキャッシュとより高速な前処理が可能になります。トークン化を習得することで、エンジニアは堅牢でコスト効率の高い AI システムを構築でき、最終的にはアプリケーションの応答性とスケーラビリティが向上します。