キャッシング生成的LLMs | APIコストの節約
キャッシング生成的LLMs | APIコストの節約' Condensed 'キャッシング生成的LLMs | APIコストの節約
はじめに
生成AIは非常に広まっており、私たちのほとんどは、画像生成器または有名な大規模言語モデルなど、生成AIモデルを使用したアプリケーションの開発に取り組んでいるか、既に取り組んでいます。私たちの多くは、特にOpenAIなどのクローズドソースの大規模言語モデルを使用して、彼らが開発したモデルの使用に対して支払いをする必要があります。もし私たちが十分注意を払えば、これらのモデルを使用する際のコストを最小限に抑えることができますが、どういうわけか、価格はかなり上昇してしまいます。そして、この記事では、つまり大規模言語モデルに送信される応答/ API呼び出しをキャッチすることについて見ていきます。Caching Generative LLMsについて学ぶのが楽しみですか?
学習目標
- Cachingとは何か、そしてそれがどのように機能するかを理解する
- 大規模言語モデルをキャッシュする方法を学ぶ
- LangChainでLLMをキャッシュするための異なる方法を学ぶ
- Cachingの潜在的な利点とAPIコストの削減方法を理解する
この記事は、Data Science Blogathonの一部として公開されました。
Cachingとは何か?なぜ必要なのか?
キャッシュとは、データを一時的に保存する場所であり、このデータの保存プロセスをキャッシングと呼びます。ここでは、最も頻繁にアクセスされるデータがより速くアクセスできるように保存されます。これはプロセッサのパフォーマンスに劇的な影響を与えます。プロセッサが計算時間がかかる集中的なタスクを実行する場合を想像してみてください。今度は、プロセッサが同じ計算を再度実行する状況を想像してみてください。このシナリオでは、前回の結果をキャッシュしておくと非常に役立ちます。タスクが実行された時に結果がキャッシュされていたため、計算時間が短縮されます。
上記のタイプのキャッシュでは、データはプロセッサのキャッシュに保存され、ほとんどのプロセスは組み込みのキャッシュメモリ内にあります。しかし、これらは他のアプリケーションには十分ではない場合があります。そのため、これらの場合はキャッシュをRAMに保存します。RAMからのデータアクセスはハードディスクやSSDからのアクセスよりもはるかに高速です。キャッシュはAPI呼び出しのコストも節約することができます。例えば、Open AIモデルに類似のリクエストを送信した場合、各リクエストに対して請求がされ、応答時間も長くなります。しかし、これらの呼び出しをキャッシュしておくと、モデルに類似のリクエストをキャッシュ内で検索し、キャッシュ内に類似のリクエストがある場合は、APIを呼び出す代わりにデータ、つまりキャッシュから応答を取得することができます。
- ジニ係数の解説:経済学が機械学習に影響を与えた方法
- 「コードを使用して、大規模な言語モデルを使って、どんなPDFや画像ファイルでもチャットする方法」
- ライトオンAIは、Falcon-40Bをベースにした新しいオープンソースの言語モデル(LLM)であるAlfred-40B-0723をリリースしました
大規模言語モデルのキャッシュ
私たちは、GPT 3.5などのクローズドソースのモデル(OpenAIなど)が、ユーザーにAPI呼び出しの料金を請求していることを知っています。請求額または関連する費用は、渡されるトークンの数に大きく依存します。トークンの数が多いほど、関連するコストも高くなります。これは大金を支払うことを避けるために慎重に扱う必要があります。
さて、APIを呼び出すコストを解決する/削減する方法の一つは、プロンプトとそれに対応する応答をキャッシュすることです。最初にモデルにプロンプトを送信し、それに対応する応答を取得したら、それをキャッシュに保存します。次に、別のプロンプトが送信される際には、モデルに送信する前に、つまりAPI呼び出しを行う前に、キャッシュ内の保存されたプロンプトのいずれかと類似しているかどうかをチェックします。もし類似している場合は、モデルにプロンプトを送信せずに(つまりAPI呼び出しを行わずに)キャッシュから応答を取得します。
これにより、モデルに類似のプロンプトを要求するたびにコストを節約することができ、さらに、応答時間も短縮されます。なぜなら、キャッシュから直接データを取得するため、モデルにリクエストを送信してから応答を取得する必要がないからです。この記事では、モデルからの応答をキャッシュするための異なる方法を見ていきます。
LangChainのInMemoryCacheを使用したキャッシュ
はい、正しく読みました。LangChainライブラリを使用して、応答とモデルへの呼び出しをキャッシュすることができます。このセクションでは、キャッシュメカニズムの設定方法と、結果がキャッシュされており、類似のクエリに対する応答がキャッシュから取得されていることを確認するための例を見ていきます。必要なライブラリをダウンロードして開始しましょう。
!pip install langchain openai
まず、LangChainとOpenAIのライブラリをpip installします。OpenAIモデルで作業し、API呼び出しの価格設定方法とキャッシュの使用方法を確認します。さあ、コードを始めましょう。
import os
import openai
from langchain.llms import OpenAI
os.environ["OPENAI_API_KEY"] = "あなたのAPIトークン"
llm = OpenAI(model_name="text-davinci-002", openai_api_key=os.environ["OPENAI_API_KEY"])
llm("誰が最初に宇宙に行った人ですか?")
- ここでは、OpenAIモデルを設定しています。os.environ[]にOpenAI APIキーを指定する必要があります。
- 次に、LangChainのLLMラッパーをインポートします。ここで使用しているモデルは「text-davinci-002」であり、OpenAI()関数にはAPIキーを含む環境変数も渡しています。
- モデルが動作するかをテストするために、簡単な質問でAPIを呼び出し、LLMにクエリを送信することができます。
- 上記の画像でLLMによって生成された回答が表示されます。これにより、モデルが稼働しており、モデルにリクエストを送信し、生成された応答を受け取ることができることが確認されます。
LangChainを介したキャッシング
次に、LangChainを介したキャッシングについて見てみましょう。
import langchain
from langchain.cache import InMemoryCache
from langchain.callbacks import get_openai_callback
langchain.llm_cache = InMemoryCache()
- LangChainライブラリには、InMemoryCacheというキャッシングのための組み込み関数があります。LLMのキャッシングにはこの関数を使用します。
- LangChainでキャッシングを開始するためには、InMemoryCache()関数をlangchain.llm_cacheに渡します。
- ここでは、まずLangChainでLLMキャッシュを作成しています。
- 次に、InMemoryCache(キャッシング手法)を取得し、langchain.llm_cacheに渡します。
- これにより、LangChainでInMemoryCacheが作成されます。別のキャッシュメカニズムを使用する場合は、InMemoryCacheを使用するキャッシュと置き換えることができます。
- get_openai_callbackもインポートしています。これにより、API呼び出しが行われた際にモデルに渡されるトークンの数、かかるコスト、応答トークンの数、応答時間に関する情報を取得できます。
LLMへのクエリ
次に、LLMにクエリを行い、レスポンスをキャッシュし、類似の質問がされた場合にキャッシュからレスポンスが取得されるかどうかを確認します。
%%time
import time
with get_openai_callback() as cb:
start = time.time()
result = llm("地球と月の距離は何ですか?")
end = time.time()
print("レスポンスにかかった時間:", end-start)
print(cb)
print(result)
時間計測関数
上記のコードでは、%%timeline関数を使用してセルの実行時間を表示します。また、API呼び出しと応答の受信にかかる時間を取得するためにtime関数もインポートしています。ここでもget_openai_callback()を使用していることに注意してください。モデルにクエリを渡した後にこの関数を通過させると、渡されたトークンの数、API呼び出しの処理コスト、所要時間が表示されます。以下に出力を示します。
上記の出力は、リクエストの処理にかかる時間は0.8秒であることを示しています。送信したプロンプトクエリのトークン数が9であり、生成された出力のトークン数が21であることもわかります。また、API呼び出しの処理コストが生成されたコールバックで表示され、$0.0006であることもわかります。CPU時間は9ミリ秒です。同じクエリでコードを再実行して、生成される出力を確認してみましょう。
ここでは、レスポンスにかかった時間の大きな違いが見られます。0.0003秒であり、最初に実行したときの2666倍速いです。コールバックの出力でも、プロンプトトークンの数は0で、コストは$0で、出力トークンも0です。成功したリクエストも0に設定されており、モデルへのAPI呼び出し/リクエストが行われなかったことを示しています。代わりに、キャッシュから取得されました。
これにより、LangChainが以前に同じプロンプトで実行されたときにOpenAIの大規模言語モデルによってキャッシュされたプロンプトと生成された応答をキャッシュしたことがわかります。これは、LangChainのInMemoryCache()関数を使用してLLMをキャッシュする方法です。
SQLiteCacheを使用したキャッシュ
プロンプトと大規模言語モデルの応答をキャッシュするもう一つの方法は、SQLiteCacheを使用することです。それについてのコードを始めましょう
from langchain.cache import SQLiteCache
langchain.llm_cache = SQLiteCache(database_path=".langchain.db")
ここでは、以前に定義したLLMキャッシュを同じ方法でLangChainで定義しています。ただし、ここでは異なるキャッシュ方法を指定しています。私たちはSQLiteCacheで作業しており、データベースのプロンプトと大規模言語モデルの応答を保存しています。これらのプロンプトと応答を保存するデータベースのパスも指定しています。ここではlangchain.dbになります。
それでは、以前にテストしたようにキャッシュメカニズムを試してみましょう。OpenAIの大規模言語モデルにクエリを2回実行し、2回目の実行で生成される出力を観察してデータがキャッシュされているかどうかを確認します。これに対するコードは次のとおりです
%%time
import time
start = time.time()
result = llm("原子爆弾は誰が作りましたか?")
end = time.time()
print("レスポンスにかかった時間:", end-start)
print(result)
%%time
import time
start = time.time()
result = llm("原子爆弾は誰が作りましたか?")
end = time.time()
print("レスポンスにかかった時間:", end-start)
print(result)
最初の出力では、大規模言語モデルへのクエリを最初に実行したとき、モデルにリクエストを送信してレスポンスを取得するまでの時間は0.7秒かかります。しかし、同じクエリを大規模言語モデルに実行しようとすると、レスポンスにかかる時間は0.002秒になります。これは、「原子爆弾は誰が作りましたか?」というクエリが最初に実行されたとき、プロンプトと大規模言語モデルによって生成された応答がSQLiteCacheデータベースにキャッシュされたことを証明しています。
その後、同じクエリを2回目に実行すると、最初にキャッシュを検索し、使用可能な場合はOpenAIのモデルにリクエストを送信してレスポンスを取得する代わりに、キャッシュから対応する応答を取得します。これは、大規模言語モデルをキャッシュする別の方法です。
キャッシュの利点
コストの削減
大規模言語モデルと連携する際に、キャッシュはAPIコストを大幅に削減します。APIコストは、モデルにリクエストを送信してその応答を受け取ることに関連しています。つまり、生成型の大規模言語モデルに対して送信するリクエストが多いほど、コストも大きくなります。同じクエリを2回目に実行したとき、クエリの応答がモデルにリクエストを送信する代わりにキャッシュから取得されることを確認しました。これは、大規模言語モデルに対して多くの類似のクエリが送信されるようなアプリケーションで非常に役立ちます。
パフォーマンスの向上/レスポンス時間の短縮
はい、キャッシュはパフォーマンス向上に役立ちます。直接ではなく、間接的にですが。パフォーマンスの向上は、プロセッサが計算にかなりの時間を費やした回答をキャッシュし、再計算する必要がある場合です。しかし、キャッシュしていれば、再計算する代わりに回答に直接アクセスできます。したがって、プロセッサは他の活動に時間を費やすことができます。
言語モデルのキャッシュに関しては、Promptと応答の両方をキャッシュします。したがって、類似のクエリを繰り返す場合、応答はモデルにリクエストを送る代わりにキャッシュから取得されます。これにより、応答時間が大幅に短縮されます。応答はキャッシュから直接取得されるため、モデルにリクエストを送信して応答を受け取る必要がありません。私たちは例を使って応答速度もチェックしました。
結論
この記事では、LangChainでのキャッシュの動作について学びました。キャッシュとは何か、そしてその目的は何かについて理解を深めました。キャッシュを使用することの潜在的な利点についても見てきました。LangChainでの大規模言語モデルのキャッシュの異なる方法(InMemoryCacheとSQLiteCache)を見てきました。例を通じて、キャッシュの利点、アプリケーションのコスト削減、迅速な応答の確保方法を発見しました。
キーポイント
このガイドの主なポイントは次のとおりです:
- キャッシュは情報を保存し、後で取り出す方法です。
- 大規模言語モデルはキャッシュできます。保存されるのはPromptと生成された応答です。
- LangChainでは、InMemoryCache、SQLiteCache、Redisなど、さまざまなキャッシュ技術が利用できます。
- 大規模言語モデルをキャッシュすることで、モデルへのAPI呼び出し数が減り、APIのコストが削減され、迅速な応答が得られます。
よくある質問
この記事で表示されているメディアはAnalytics Vidhyaの所有ではなく、著者の裁量で使用されています。
We will continue to update VoAGI; if you have any questions or suggestions, please contact us!
Was this article helpful?
93 out of 132 found this helpful
Related articles