無料枠の使用回数を数える設計と、時差でずれた話
生成AIの無料枠を使い切らないよう、この端末から送ったリクエスト数を自前で数えています。日付の区切りが現地時間ではなかったこと、複数タブで二重に数えたことなど、実装で踏んだ点を書きます。
無料枠の中で動かすアプリでは、あと何回使えるのかが利用者にとって重要な情報になります。 上限に達したときに「なぜ動かないのか分からない」状態になるのが、いちばん困るためです。
そこで、この端末から実際に送ったリクエスト数を自前で数えて画面に出しています。 設計としては単純に見えたのですが、実際には3か所で間違えました。
1. 日付の区切りが現地時間ではなかった
最初は端末の現地時間で「今日」を判定していました。 日本時間の0時に使用回数がリセットされる、という実装です。
これが合いませんでした。 利用している生成AIの日次枠は、太平洋時間で区切られていたためです。
日本時間で朝を迎えても枠は戻っておらず、 逆に夕方に突然リセットされる、という挙動になります。 利用者から見ると「昨日の分がまだ残っている」「急に使えるようになった」と映ります。
直し方は、日付の判定を太平洋時間で行うことです。 端末のタイムゾーン設定に依存せず、明示的にその地域の日付を求めるようにしました。 サマータイムの切り替えも考慮する必要があるため、 自前でオフセットを引くのではなく、標準の日時フォーマッタに地域を指定して日付部分を取り出しています。
外部サービスの枠を数えるなら、区切りはそのサービスの基準に合わせる。 当たり前のようでいて、自分の端末の時計を基準にしてしまう間違いは起きやすいところです。
2. 複数のタブで二重に数えた
記録は端末内(localStorage)に置いています。 ところが同じアプリを2つのタブで開くと、両方が同じ記録を読み書きします。
タブAが「12回」を読み、同時にタブBも「12回」を読み、 それぞれが1を足して「13回」を書く。2回送ったのに13回にしかならないという状態です。
対処は2段構えにしました。
書き込みそのものは、ブラウザが提供するロックの仕組みで直列化します。 これによって読み書きの競合を防ぎます。
そのうえで、更新があったことを別のタブへ知らせる必要があります。 片方のタブで使ったのに、もう片方の画面が古い数字を表示していると、 利用者は「どちらが正しいのか」で混乱します。 タブ間の通知チャネルを使い、更新を受け取ったタブが表示を更新するようにしました。
ロックの仕組みに対応していないブラウザもあるため、 その場合は従来どおり単純な書き込みに落ちます。 対応していない環境で壊れるより、精度が少し落ちるほうがましという判断です。
3. 何を1回として数えるか
最初は「解答ボタンを押した回数」を数えていました。 これは実際の送信回数と合いません。
一時的な障害で自動的に再送した場合、送信は2回発生しています。 図形問題では、図を写し取る呼び出しと解く呼び出しで2回になることがあります。 答えの検証を行えば、そこでも1回使います。
利用者が知りたいのは「あと何回使えるか」なので、 画面上の操作回数ではなく、実際にAPIへ送った回数を数える必要があります。 内部の再送も含めて記録するようにしました。
さらに、枠はモデルごとに異なります。 軽いモデルと高性能なモデルでは1日に使える回数が違うので、 用途別だけでなくモデル別にも集計しています。 これがないと「まだ余裕がある」と思っていたのに、 特定のモデルだけ先に上限へ達する、ということが起きます。
記録は7日分だけ残す
過去の記録を無制限に貯めても使い道がありません。 7日分を超えたものは自動的に捨てています。
端末内のデータは利用者のものなので、 必要以上に持たないほうが説明も簡単になります。 「7日より前の使用履歴は残していません」と書けるのは、 プライバシーポリシーを短くするうえでも効きます。
この数字が保証しないこと
ここで数えているのは、この端末から送った回数だけです。
同じAPIキーを別の端末でも使っていれば、実際の消費はこれより多くなります。 枠の残量を提供元へ問い合わせているわけではないので、 表示は目安であって正確な残量ではありません。
この点は画面上にも書いています。 数字が出ていると正確なものだと受け取られるため、 何を数えていないのかを明示するほうが、後から誤解を生みません。
関連する記事
- 月額ゼロで実用アプリを配る構成と、無料枠の現実的な制約
個人が作ったアプリを、サーバー代もストアの年会費も払わずに配っています。実際に使っている構成と、無料枠ゆえに起きる問題への対処を書きます。
- APIキーを利用者に持ち込んでもらう設計と責任
生成AIのAPIキーをアプリに埋め込まず、利用者が各自で用意する形にしています。課金が利用者持ちになるぶん、呼び出し回数の設計が機能の一部になりました。
- AIアプリの精度を毎日自動で測り差分で見つける
LLMを使うアプリは同じ入力でも出力が変わるため、通常の回帰テストが効きません。毎日ベンチを回して正答率だけをテキストに追記し、コミットして差分で気付けるようにした構成を書きます。
最終更新日: