見出し画像

【HELP ME】Assistants APIで破産しそうになった話

こんにちは、ニケです。
皆さん、Assistatnts APIは使われていますでしょうか?

巷(私の周り)ではGPTsが流行りに流行ってるのでAssistatnts APIを使用されている方はあまり見かけないですが、今回のDevDayで発表された中でもかなり注目度の高いサービスではないかと思っています。

私も過去に以下の記事を書いているので是非ご覧になってください。

で、個人的にもかなり注目しているAssistatnts APIですが、今回はこれに破産させられそうになったという話です。


Assistants API とは?

この説明も3回目です。
下記の公式かnpakaさんの記事がわかりやすいので、そちらを先に読んでもらえると良いかもしれません。

アシスタントAPIは、開発者が多様なタスクを行う強力なAIアシスタントを作れるように設計されています。

  1. アシスタントは、特定の指示を設定することでOpenAIのモデルを呼び出し、その個性や能力を調整することができます。

  2. アシスタントは複数のツールに同時にアクセスできます。これらは、OpenAIが提供するコードインタプリターまたはナレッジ検索等のツール、あるいはユーザーが作成あるいはホストするツール(関数呼び出しを通じて)の両方が含まれます。

  3. アシスタントは永続的なスレッドにアクセスすることができます。スレッドはメッセージの履歴を保持し、会話がモデルのコンテキスト長を超える場合には切り捨て、AIアプリケーション開発を容易にします。一度スレッドが生成されると、ユーザーが返信する際にはメッセージをそこに追加するだけです。

  4. アシスタントは、作成の過程であったりアシスタントとユーザ間のスレッドの一部として、様々な形式のファイルにアクセスできます。ツールを用いる場合、アシスタントはファイル(画像、スプレッドシート等)を作成し、メッセージ作成時に参照するファイルを引用することも可能です。

経緯

私はいくつかのDiscordサーバーで「AIニケちゃん」というbotを無償で運営しています。運営と言ってもOpenAI APIのテスト場みたいなものですが、ありがたいことによく使用してもらっています。

今回、画像を認識できるVision API、画像を生成できるDALL-E APIが追加されたということで、これらをAssistatnts APIを使って早速実装してみることにしました。

Discord bot作成

Assistatnts APIでは、アシスタントというオブジェクトを作成し、これに使用できるToolsを与えてからAPIを実行します。かなり直感的に実装できる点もポイントです。

今回はアシスタントに知識検索と画像認識、画像生成機能などをToolsとして与えました。

アシスタントが画像を認識して新しいイラストを作るテストをしたときの投稿です。このときはまだ余裕がありますね。


内部処理紹介

ちなみに内部的な処理を説明しておくと下記のような感じになります。

  1. アシスタントをOpenAIのマイページ上で作成。

  2. アシスタントのToolsを定義する。

  3. Discordの1つのサーバーに対して1つのスレッドを作成しておく。

  4. Discordからメッセージが送られてきたらスレッドにメッセージを追加する。

  5. アシスタントとスレッドを指定してRunを実行する。

  6. メッセージが返却されたらDiscordに返す。途中で画像生成などしたらそれも返す。

3でスレッドを1つのみに指定していますが、これは下記の記事で紹介したように、Assistatnts APIはかなり古いメッセージも覚えていることができるからです。
実際の処理仕様は不明ですが、すごいなあ…どうやってるんだろ、くらいの感覚でした(そしてたぶんこれが地獄への片道切符)

bot始動

テストもだいたい出来たので、実際にいくつかのサーバーで公開することにしました。

楽しんでます。

公開当初は少し不具合もありましたが、発見しては直してを数回繰り返して稼働させていました。

初日(11日)でもうバグは出なくなったので、その翌日(12日/日曜日)はとくに気にすることもなく過ごしていました。

請求がっ!!

13日になりました。今日もAIニケちゃんチャンネル賑わってるなあと思いながら、そういえばどれくらい使用量達してるのか気になったので見ることにしました。

Discord botは今までも運営していて、そこまで驚く額になったことはなかったですし、今回の発表からGPT-4の値段は下がっています。
画像生成APIを実行しても、1日の送信上限も設定してるし、まあ$20-30くらいかな?という気持ちで見ました。

わらえません。

普通にパニクって急いでbotを停止させました。なんで?????

このまま継続していたらすぐに上限に達するところでした。
気づかず運営し続けて、かつ 上限も$500とかに設定していたらと思うと…

ちゃんと計算する

わけがわからないのでちゃんと計算します。

一番多い日は12日です。この日はOpen Interpreterを使用して色々していたので、GPT-4で請求されている$18はおそらくほぼOpen Interpreterのはずです。

GPT-4 Turboの$51はDiscord Botでしか使用されていないはずなので、これを元に計算します。

GPT-4 Turbo(preview)は245リクエスト送られています。

Tokenは5百万らしいです。

……5ひゃくまん!!!???

計算します。

5M tokens / 245req ≒ 20k tokens
一つのリクエストで約2万トークン送っていることがわかりました。

?????

更に計算します。

5M tokens * $0.01 / 1K tokens ≒ $50

概算ですが、先程のGPT-4 Turboの利用量$51に一致するので、やはりほぼインプット費用のようです。

なんでこんなに送ってるの…???

Assistatnts API…お前…

Assistatnts APIのどこで費用がかかっているのか名言されていませんが、おそらく実行処理の本体であるcreate Run APIでしょう。

先程紹介した私の記事(Assistants APIの記憶性能を調べたらとんでもなかった件)では、メッセージは100件を超えても記憶として残っていました。
そもそもAssistatnts APIのスレッドのメッセージの数に制限は決まっていないと記載されています。

Managing Threads and Messages
Threads and Messages represent a conversation session between an Assistant and a user. There is no limit to the number of Messages you can store in a Thread. Once the size of the Messages exceeds the context window of the model, the Thread will attempt to include as many messages as possible that fit in the context window and drop the oldest messages. Note that this truncation strategy may evolve over time.

スレッドとメッセージの管理
スレッドとメッセージは、アシスタントとユーザー間の会話セッションを表します。スレッドに保存できるメッセージの数に制限はありません。メッセージのサイズがモデルのコンテキスト ウィンドウを超えると、スレッドはコンテキスト ウィンドウに収まるできるだけ多くのメッセージを含めようとし、最も古いメッセージを削除します。この切り捨て戦略は時間の経過とともに進化する可能性があることに注意してください。(日本語訳)

https://platform.openai.com/docs/assistants/how-it-works/managing-threads-and-messages

ちなみに、APIで取得できるスレッドのメッセージの上限値は100件らしいです。

私はこれを好意的に受け取っていて、古いメッセージはよしなに記憶として保存されて必要に応じて呼び出させるのかな?と思っていました。

ここでこれらの画像をもう一度見てください。

11日のリクエスト量は12日より多いのにトークン数は12日のほうが多いです。
ちなみにいくつかのサーバーで公開したと書きましたが、実際には私のbotを使用していたのはほぼ1つのDiscordサーバーです。リクエスト数はほぼそのままこのサーバーが出したものと考えます。

正確に計算したら、下記のようになっていました。
11日:3.14M tokens / 278req ≒ 11k tokens / req
12日:5M tokens / 245req ≒ 20k tokens / req

メッセージの内容にもよりますが、平均して2倍も差がでることはないと思うので、11日よりも12日の方が1リクエストに含まれるメッセージ数が多いことになります。上限100ではなさそうですね。

ここまで来て思ったのですが、

…これもしかして上限(128kトークン)に達するまでスレッドがメッセージを蓄えて続けてるのでは…?
で、毎リクエスト全メッセージ分送信してると…

ちゃんと算出したわけではないので正確なことはわかりませんが、もしかしたらAssistants APIはとんでもない野郎だったかもしれません。

これが本当なら、スレッドからメッセージを削除する機構などが必要かもしれませんね。

この段階では実際の原因を解明することが出来なかったので、どなたかより詳細な真相を知っている方がいたら教えてください。
私の実装が誤っているだけなら良いのですが…。

以上、Assistatnts APIの人柱、ニケちゃんからの報告でした。

追記(解答)

この記事公開してからいろいろな方に反応してもらえたのですが、やはり私の結論は正しいようで、雪だるま式に増えていくみたいです。

なんて仕様だ…。

じゃあ結局いままでと同じように、スレッドに上限メッセージ数を設定して、一定数を超えたら古いやつを削除する、みたいにしないといけないのか〜〜。

???「…ないよ。」

私「…え?」

公式ドキュメント「DELETE messages API ないよ。」

~ Fin ~

この記事が気に入ったらサポートをしてみませんか?