💰

画像生成AIサービスのお金事情とそのコストカット術

2023/01/14に公開約3,900字

はじめに

こんにちは Nishino です。

お絵描きばりぐっどくんという画像生成 AI を日本語で誰でも気軽に楽しめるサービスを開発しています。今回は画像生成 AI を使ったサービスのお金事情に関するノウハウが溜まってきたので共有します。

https://twitter.com/nishino_0719/status/1563739424617549824?s=20&t=_cUy4gRBY2vfTbomSOuR7A

画像生成 AI サービスの大まかな流れ

お絵描きばりぐっどくんに限らず、日本語対応している画像生成 AI サービスは大まかに以下のフローをとっていると思います。

コストカット前のお金事情

想像はつくかもしれませんが、コスト面は

画像生成 > テキストの翻訳

といった感じになります。
今回は画像生成周りとテキストの翻訳に注目して解説していこうと思います。

画像生成 AI

お絵描きばりぐっどくんのリリース当初、画像生成部分は外部 API を使用しておりました。当時の外部 API は画像生成にかかるコストが1 枚あたり 1.3 ~ 1.5 円かかってしまっていました。
リリース前はこんなにバズるものだとは思っておらず、許容できるレベルでしたがあまりの利用数の増大に早急に対処しなければなりませんでした。

資金をバクバク食い漁るモンスターとなってしまったお絵描きばりぐっどくんは1 週間でサービス終了する話まで出ていたレベルでした。

画像生成におけるコストカット

どうしたものかと考えていたタイミングで、機械学習周りに強いエンジニアさんがチームに加わり、外部 API サービスに頼らず自前で画像生成の演算をやってしまおう!という動きになりました。

結果的に外部 API サービスから、Google Compute Engine で演算する自前 API を作成することで劇的なコストカットにつながりました。

https://cloud.google.com/products/compute

具体的な金額は言えないのですが、画像生成 1 枚あたりのコストは数十分の一にまで落とすことができました。画像生成速度もさらに向上しており、画像生成に 1s 未満のオーダーで生成できるようになりました。

公開情報なので言いますが、お絵描きばりぐっどくんは一ヶ月で3000 万枚の画像を生成しました。これが 1 枚あたり1.3 ~ 1.5 円かかっていたと考えると今でもゾッとしますね。
担当してくれた機械学習エンジニアさんには頭が上がりません。ありがとうございます。

テキストの翻訳

お絵描きばりぐっどくんで動かしている Stable Diffusion は英語にのみ対応しているので、日本語に対応させるためには翻訳する必要があります。翻訳は DeepL を採用しました。

分析したところ、お絵描きばりぐっどくんでは 1 枚の画像を生成あたり平均約 11 文字の文章が入力されていました。
1 ヶ月に 3000 万枚画像を生成したことを考えると 1 ヶ月で およそ 3 億文字(3000 万 \times 11 文字)の翻訳をしていることになりますね。

https://www.deepl.com/ja/pro/change-plan#developer

100 万文字あたり ¥2,500

DeepL は文字数による従量課金を取っているのでこれで大まかな計算ができます。
大体 75 万円(3 億文字 \div 100 万文字 \times 2500 円)も翻訳にかかっていることがわかります。

先ほどコストは画像生成 > テキストの翻訳であると記述しましたが、画像生成周りが劇的にコストカットされたことにより、先月あたりからテキスト翻訳の方がコストがかかっているという事態になってしまいました。

テキスト翻訳におけるコストカット

翻訳は機械学習モデルが公開されていないので、先ほどのように自前 API 化 することはできません。
そこで頭を抱えていると、画像生成は同じ文章が打ち込まれやすい傾向があるのではないかと気づきました。
画像生成にはガチャ要素が伴います。同じ文章でも毎回異なる画像が生成されるので求める画像が出るまで同じ文章でガチャをする傾向(画像生成 AI を触ったことがある人は経験があると思います)がとても強いです。

「ということは一回翻訳した文章は翻訳する必要ないのでは?」

物は試しで、 1 度でも翻訳された文章は DeepL に通さずデータベースから読み取る疑似キャッシュを実装しました。

const getPrompt = async (promptJa: string): Promise<string | null> => {
  const timelinesGroupRef = db.collectionGroup("timeline")
  const docs = await timelinesGroupRef
    .where("prompt_ja", "==", promptJa)
    .limit(1)
    .get()
  if (docs.docs.length === 0) return null
  const timeline = docs.docs[0].data() as TimelineImage
  return timeline.prompt_en
}

ユーザーからの入力を引数に取り、過去に入力しているかどうかの where 句によって一致する可動化のクエリをかき、limit(1)で 1 件のみを取得するようにしています。
firestore の Collection Group Queries を使うことによって全ユーザーを対象としたプロンプトチェックが可能になります。
データ取得も数 ms オーダーで実行ができるので本番環境に投入してみると、効果は絶大的でした。

2022/12/12 時点と 2022/12/18 は画像生成枚数に差がほとんどないことを確認しました。画像生成枚数に変更がないにも関わらず、翻訳している文字数が少なくなっています。


その後の経過を見てみても、確実に疑似キャッシュの効果が表れていることが確認できます。

恩恵を受けたのはコスト面だけでなく、速度面も改善されました。DeepL を通すと数秒かかってしまっていた長文も、キャッシュされていた場合は数 ms オーダーで処理することが可能になりました。

速度面も改善されたことにより、現在僕が確認できる範囲だと国内最速の画像生成 AI サービスになっています。(速い時は 1s で返ってきます)

おわりに

画像生成周りとテキスト翻訳でそれぞれコストカットすることができました。

変更前 変更後
画像生成 外部 API で画像生成 API を自前化して画像生成
テキスト翻訳 都度翻訳 一度翻訳したものは翻訳しない

特にテキスト翻訳に関しては最初から気づいていれば、、と思うほどに盲点で今後同じようなサービスを開発する方にぜひ届いてほしいです。

テキストの翻訳だけでなく、毎回やらなければならない処理か? という疑問を持ってプログラムすれば意外なところにコストカットできる場所が見つかると思いました。

お絵描きばりぐっどくんは僕にとって初めてのサービスのリリースでしたが、実際にリリースしてからは学ぶことがたくさんでとても楽しいです。
今年はたくさん技術記事書こうと思っているのでよろしくお願いいたします!

Discussion

ログインするとコメントできます