運営とお金

英会話アプリのAI原価は1回0.01円台。実測から上限を決めた

英会話アプリ「イエタ」で AI を1回呼ぶ原価を測ると0.01円台でした。モデルの切り替えをまたいだ測定の扱い、平均より最悪の1回を基準にした理由、無料とプラス(月480円)の回数と1日のコスト上限の決め方を記録します。

公開日
AI の利用
AI が作業記録をもとに下書きし、記録との照合を行ったうえで、運営者が内容を確認して公開しています。 編集方針

英会話アプリ「イエタ」で、AI を1回呼ぶといくらかかるかを、開発用の環境(dev)で測りました。記録に残った値は14回で約 $0.0015、1回あたり約0.016円です。ただし、この14回には切り替え前と後の2つのモデルが混ざっていました。同じトークン数を採用したモデル(gpt-6-luna)の単価で計算し直すと、1回約0.013円です。分かったのは、平均の原価はごく小さい一方で、長い会話の最悪の1回は平均の10倍を超えることです。そこで、無料プランとプラス(月480円)の回数と上限は、平均ではなく「最悪の場合」を基準に決めました。

何を「1回」と数えたか

イエタの AI は、ブラウザから直接 OpenAI を呼びません。サーバー(Firebase の Cloud Functions)が間に入り、利用者の確認と回数の管理をしてから OpenAI に送ります。このサーバーを1回通る呼び出しを「1回」と数えました。用途は、会話のターン、会話の最初の AI からの話しかけ、ロールプレイ、翻訳やヒントといった補助、会話後のフィードバックです。復習や表現ノートは端末の中で動くので、AI の原価は0円です。

原価は、OpenAI の応答に入っているトークン数(文章を区切った単位の数)に、サーバーの単価表を掛けて出しています。採用した gpt-6-luna の単価は、100万トークンあたり入力 $0.10、出力 $0.50 です。サーバーはこの見積もりを呼び出しのたびに日ごとの集計へ足し、利用者ごとの当日の合計にも足します。

export function estimateOpenAiCostUsd(
  model: string,
  usage: UsageTokens | null,
  fallback: { promptChars: number; maxTokens: number }
): number {
  const pricing = MODEL_PRICING[model] ?? MODEL_PRICING[DEFAULT_MODEL];
  const tokens = usage ?? { promptTokens: fallback.promptChars, completionTokens: fallback.maxTokens };
  return (
    (tokens.promptTokens * pricing.inputPer1M + tokens.completionTokens * pricing.outputPer1M) /
    1_000_000
  );
}

時間切れでトークン数が分からないときは、課金されている可能性があるので、回数を戻さず、入力1文字を1トークン・出力を上限いっぱいとした最大の見積もりを記録します。

つまり「実測」は、実際のトークン数に公開単価を掛けた推定です。請求書の金額そのものではありません。請求画面の金額との突き合わせは、まだしていません。

2026-10-04 の14回と、混ざっていたモデル

測ったのは 2026-10-04 の dev の日ごとの集計です。この日の呼び出しは14回で、内訳は会話の開始4回、会話ターン7回、フィードバック3回でした。入力は合わせて5,092トークン、出力は1,447トークン、推定原価は $0.00148635 です。

この日は、モデルを切り替えた日でもありました。まず gpt-4o-mini のまま新しいサーバーを dev に出し、アプリを自動で操作して本物の AI と2往復話し、フィードバックまで受け取る確認(D1)を流しました。そのあと gpt-6-luna へ切り替え、確認の呼び出しと D1 をもう一度流しています。

戦略のメモには、この値を「gpt-6-luna で14回」と書いていました。この記事の下書きを別の評価者が記録と照らし合わせたとき、切り替えの前後にまたがっていると分かりました。日ごとの集計には回数・トークン数・原価・用途はありますが、モデル名が無いので、どの呼び出しがどちらのモデルだったかは分けられません。そこで、同じトークン数をモデルごとの単価で計算し直しました。

計算のしかた14回の合計1回あたり円(1ドル150円)
記録の値(2つのモデルが混在)$0.00149$0.000106約0.016円
すべて gpt-6-luna の単価で計算$0.00123$0.000088約0.013円
すべて gpt-4o-mini の単価で計算$0.00163$0.000117約0.017円

採算の見積もりに使った0.016円は、gpt-6-luna だけの値より少し高めでした。見積もりとしては安全側にずれていたことになります。gpt-6-luna だけの日の集計では、まだ測っていません。

平均より「最悪の1回」を見る

dev で動かした D1 は、2往復だけの短い会話です。会話では毎回それまでの履歴を送り直すので、会話が長くなるほど1回の入力が増えます。サーバーは入力の上限を、会話は40件・8,000字まで、フィードバックは16,000字までとし、超えたら受け付けません。出力の上限も用途ごとに決めていて、会話は400トークン、フィードバックは550トークンです。

この上限いっぱいの1回を、1文字1トークンとして多めに見積もった結果が次の表です。

1回の呼び出し原価(USD)円(1ドル150円)
平均(gpt-6-luna で計算し直した値)約 $0.000088約0.013円
会話の最悪(入力8,000字・出力400トークン)約 $0.001約0.15円
フィードバックの最悪(入力16,000字・出力550トークン)約 $0.0019約0.28円

最悪の1回は平均の約11〜21倍です。回数の上限だけでは原価を抑えきれません。そこで回数とは別に、1人1日の推定原価にも上限を置きました。超えると、その日は AI を呼べなくなります。

モデルは単価より品質で選んだ

モデルを選ぶ前の 2026-10-02 の調べでは、候補どうしの単価の差は1人あたり月3円ほどでした。差がこれだけ小さいので、単価ではなく品質と長く使えるかで選ぶことにしました。

2026-10-04 に、それまでの gpt-4o-mini と候補の gpt-6-luna を、固定の問題で比べました。会話16件を3回ずつ、フィードバック4件を2回ずつ生成し、別のモデル(gpt-4.1-mini)が採点します。会話の点数はどちらも満点近くで、差はありませんでした。差が出たのはフィードバックです。採点役が「誤った訂正」と判定した数は、1件あたり0.38から0になりました。日本語の説明の分かりやすさは、5点満点で4.25から4.63に上がりました。

誤った訂正の例は、誤りが1つも無い会話でした。学習者が「I eat it every week. It is very delicious.」と答えた会話に、gpt-4o-mini は2回とも訂正を付けました。採点役のコメントは「'It is very delicious'は自然な表現なので、修正は不要です。」でした。イエタでは、フィードバックで指摘された表現は表現ノートに入り、日を空けて復習に出てきます。誤った訂正は、正しい英語を間違いとして覚えさせることになります。差が出たのがこの誤った訂正と日本語の説明だったので、乗り換えを決めました。

単価も gpt-6-luna のほうが安くなります。評価の仕組みは改善ループのゲート設計についての制作ノートに書きます。

旧 Pro は最悪で赤字になる設計だった

以前のプランは、無料(1日5ターン、広告を見ると増える)、ベーシック(月480円)、Pro(月980円)の3つでした。サーバーで上限を強制するように作り直したとき、Pro の1日の推定原価の上限は $0.50 でした。上限まで30日使われると、$0.50 × 30日 × 150円 で月約2,250円です。月980円の売上を超えます。

ふつうの使い方なら、ここまでは届きません。ただ、上限は「届いてもよい」と認めた額なので、届いたら赤字になる上限は設計として間違っています。2026-10-05 に、プランを無料と有料1本(プラス、月480円)に作り直しました。

無料プラス(月480円)
会話1日10往復1日100往復
シナリオ(ロールプレイ)1日1回1日5回
翻訳・ヒント1日10回1日50回
1人1日の原価の上限$0.02$0.08

無料の10往復は「1日1レッスン」です。フィードバックまで含めた1レッスンの原価は約0.3円と見積もっています。

コスト上限は $0.05 で決め、G3 のあとで $0.08 に緩めた

Stripe の手数料(カード3.6%、Billing 0.7%)を引くと、480円の手取りは約459円です。戦略のメモでは、最初の条件を「1人1日の上限 × 30日 が手取りの半分以下」にしていました。そこから決めたのが1日 $0.05 で、上限まで毎日使われても月約225円です。

ところが、変更を別のエージェントに敵対的にレビューさせたところ(G3)、「basic のコスト上限 $0.05 が、宣伝している回数より先に効く可能性がある(宣伝と実装の食い違い)」という指摘が出ました。basic はプラスの内部名です。

ここで、宣伝した回数を守ることを優先しました。条件を「手取りの半分以下」から「手取りを超えない(赤字にならない)」まで緩め、上限を $0.08 にしています。上限まで30日使われると月約360円で、手取りとの差は最悪の月で約99円です。

あわせて、回数を使い切るほど重く使っても、先にコスト上限で止まらないことをテストで確かめるようにしました。

const heavyDailyCost = (plan: keyof typeof PLAN_LIMITS) => {
  const l = PLAN_LIMITS[plan];
  return (
    l.turn * call(2000, 150) +
    l.roleplay * call(2000, 150) +
    l.feedback * call(3000, 400) +
    l.aux * call(400, 100) +
    l.opener * call(400, 80) +
    l.coaching * call(3000, 600)
  );
};

call(入力, 出力) は、トークン数から1回の原価を出す関数です。会話とロールプレイは、毎回の履歴が上限近くの約8,000字まで伸びた場合を想定しています。英語の会話を前提に、約4文字を1トークンとして約2,000トークンと見積もりました。この式でプラスを計算すると次のとおりです。

種類プラスの1日の回数1回の想定(入力 / 出力トークン)小計(USD)
会話ターン1002,000 / 1500.0275
ロールプレイ75(5シナリオ×15回)2,000 / 1500.0206
フィードバック203,000 / 4000.0100
翻訳などの補助50400 / 1000.0045
会話の開始30400 / 800.0024
週次コーチング23,000 / 6000.0012
合計約0.066

約 $0.066 なので、$0.05 では先に上限に当たります。$0.08 なら、英語中心の会話では重い使い方でも宣伝した回数を使えます。ただし、日本語の多い長い会話では1文字がほぼ1トークンになるので、100往復の前にコスト上限に当たることがあります。1回を最悪の約 $0.001 とすると、会話だけで約80往復です。無料は同じ式で約 $0.012 で上限 $0.02 に届かず、上限まで使われても月約90円です。

上限は何重にも置いた

1人あたりの上限のほかにも、止める仕組みを重ねています。

仕組み値超えたとき
1回の入力と出力の長さ会話は入力8,000字・出力400トークンまで など入力は断り、出力は上限で切る
用途ごとの1日の回数無料は会話10往復、プラスは100往復 などその日は断る
1人1日の推定原価無料 $0.02、プラス $0.08その日は断る
全体の1日の予算無料の利用者の合計と、有料の利用者の合計で別々そのグループの新しい呼び出しを止める
Google Cloud の予算アラート本番 月1,000円、開発 月500円知らせるだけで止めない
OpenAI の自動チャージオフ入れた残高を使い切ると API が止まる

全体の予算を無料と有料に分けたのは、無料の利用が想定を超えて増えても、払っている人まで止めないためです。無料の回数には、まだ対策中の抜け道があります。その場合も、無料全体の予算で1日の費用の上限は決まっています。

予算アラートが見るのは Google Cloud 側の費用だけです。OpenAI は別の請求なので、自動チャージをオフにしたプリペイドの残高を最後の柵にしました(2026-10-05 に確認)。

これから測るもの

1回の原価は dev の短い会話で測った値で、本番の利用者がどんな長さで話すかはまだ分かりません。サーバーの記録だけを読む週次の集計は 2026-10-05 に本番で初めて動かしましたが、公開前なので数字はほぼ0でした。

公開後は、1人あたりの実際の原価が見積もり(記録の値の0.016円をもとにした、よく使う人で月約20円)に近いかを見ます。あわせて、日本語の多い会話でコスト上限に当たる人がいないかも確かめます。無料の補助の回数や全体の予算は、まだ暫定の値です。実際の数字を見て直します。

制作ノートの一覧へ