Character AI風アプリの作り方:アーキテクチャ、コード、コスト試算
Updated 2026-07-15
Character AI風アプリは、OpenAI互換のチャットエンドポイントにつながる4つの要素でできています。ペルソナのシステムプロンプト、記憶レイヤー、モデレーションゲート、モデルルーターです。動くプロトタイプは200行未満のPythonで出荷でき、モデル選びさえ間違えなければ月間アクティブユーザー1人あたり1ドルを大きく下回るコストで運用できます。
結論:4要素のアーキテクチャ
モデルを学習・ファインチューニングする必要はありません。今日、市場にある本格的なコンパニオンアプリは、数百万ユーザーにサービスを提供しているものも含めて、すべてホスト型LLM API上の薄いオーケストレーション層です。キャラクターはウェイトの中ではなく、プロンプトとデータベースの中に存在しています。 この後のガイドでは、標準的なOpenAI互換エンドポイントに対して動くコードで各要素を組み立て、そのうえでトークンの計算をたどり、ローンチ前に月間アクティブユーザー1人あたりの実際のコストを把握できるようにします。
- ペルソナのプロンプト:キャラクターが何者で、どう話すかを定義する構造化されたシステムプロンプト(500〜1,000トークン)。
- 記憶:直近のやり取りのローリングウィンドウと、定期的に更新される要約を組み合わせ、コンテキスト上限を超えても会話が続くようにする。
- モデレーション:年齢ゲート、入力の分類器、ルーティング先のモデルに合わせたコンテンツポリシー。
- ルーティング:カジュアルな会話には安価なモデル、長いシーンにはより強力なモデルを選ぶ小さな関数。
要素1:ペルソナのプロンプト
ペルソナのプロンプトこそがプロダクトです。すべてのリクエストに同梱されるシステムメッセージで、通常は5つの要素を含みます。アイデンティティ(名前、年齢、背景)、性格の特徴、2〜3個の例文を伴う話し方、破ってはいけない行動ルール(キャラクターを崩さない、返信の長さに上限を設ける)、そして現在のシナリオです。 500〜1,000トークンの範囲に収めてください。短すぎるペルソナはブレますし、長すぎるものは毎メッセージの入力予算を消費するわりに追従性はほとんど向上しません。ペルソナはデータベースの行として保存し、ユーザーが自分でキャラクターを作成・編集できるようにします。これが Character.AI 風プロダクトの核となるループです。 以下は完全なリクエストの例です。同じ形はどのOpenAI互換バックエンドでも通用します。この例ではマルチモデルのゲートウェイエンドポイントを使っているため、文字列1つを変えるだけでモデルを切り替えられます。
curl https://api.apisrouter.com/v1/chat/completions \
-H "Authorization: Bearer $KEAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4-flash",
"messages": [
{"role": "system", "content": "You are Mira, a sarcastic starship engineer in her 30s. Personality: dry wit, fiercely loyal, hates small talk. Speech style: short technical sentences, occasional teasing. Example: \"The coupling is fried. Again. Did you touch it?\" Rules: never break character, never mention being an AI, keep replies under 120 words."},
{"role": "user", "content": "Mira, the reactor is making that noise again."}
],
"temperature": 0.9,
"max_tokens": 300,
"stream": true
}'要素2:長い会話に耐える記憶
コンパニオンアプリのセッションは長く続きます。3層の記憶スタックがあれば、毎回すべての履歴を送らなくてもコンテキストの一貫性を保てます。 第1層はローリングウィンドウです。直近10〜14ターンをそのまま送ります。第2層は稼働中の要約です。およそ20ターンごとに、安価なモデルが古いメッセージを、名前・関係性の状態・未解決の伏線を追う形で1段落に圧縮します。第3層は固定された事実です。ユーザーの持続的な情報(名前、好み、キャラクターが覚えておくべき過去の出来事)をデータベースへ抽出し、短いシステムメッセージとして挿入します。 これを公式のOpenAI SDKでPythonとして実装すると、全体は次のようになります。
| コンテキストの枠 | 目安のサイズ | 更新の頻度 |
|---|---|---|
| ペルソナのシステムプロンプト | 500〜1,000トークン | キャラクターごとに固定 |
| 固定されたユーザーの事実 | 100〜200トークン | 抽出イベントの発生時 |
| 稼働中の要約 | 300〜500トークン | およそ20ターンごと |
| ローリングウィンドウ(12ターン) | 約1,800〜2,200トークン | 毎メッセージ |
| 新しいユーザーメッセージ | 約100トークン | 毎メッセージ |
from openai import OpenAI
client = OpenAI(
api_key="sk-...",
base_url="https://api.apisrouter.com/v1",
)
def build_context(persona, summary, pinned_facts, recent_turns, user_msg):
facts = "\n".join(f"- {f}" for f in pinned_facts)
return [
{"role": "system", "content": persona},
*([{"role": "system", "content": f"Facts to remember:\n{facts}"}]
if pinned_facts else []),
*([{"role": "system", "content": f"Story so far: {summary}"}]
if summary else []),
*recent_turns[-12:],
{"role": "user", "content": user_msg},
]
def refresh_summary(old_turns, prev_summary):
prompt = (
"Update this running summary of a roleplay chat. Keep names, "
"relationship state, and open plot threads. Max 150 words.\n\n"
f"Current summary: {prev_summary}\n\nNew messages: {old_turns}"
)
resp = client.chat.completions.create(
model="deepseek-v4-flash",
messages=[{"role": "user", "content": prompt}],
max_tokens=400,
)
return resp.choices[0].message.content要素3:モデレーションとコンテンツポリシー
コンパニオンアプリにおけるモデレーションには、明確に異なる3つの役割があり、それらを混同することがローンチ時に最もよくある失敗です。 まず、対象ユーザーをゲートします。アプリがマチュアなフィクションのテーマを許可するなら、成人向けの年齢ゲートの内側に置き、全年齢向けの別のデフォルトを用意してください。App Store と Play Store の審査はどちらもこれを確認し、決済事業者も気にします。 次に、入力をスクリーニングします。ユーザーのメッセージがキャラクターモデルに届く前に安価な分類器を通し、どのプロバイダーも許可しないカテゴリ、つまり未成年に関わる内容、信憑性のある現実世界での害、違法な指示をブロックします。yes/noの判定基準を1つ用意した deepseek-v4-flash の呼び出し1回のコストは1セントに満たず、レイテンシも1秒未満しか増えません。 最後に、コンテンツポリシーをモデルに合わせます。プロバイダーはフィクションの扱いが異なります。xAI の公開ポリシーは成人ユーザー向けのマチュアなフィクションのテーマを明示的に許容し、DeepSeekなどオープンウェイト系のモデルはホスト型ポリシーがフィクションに柔軟なためロールプレイのコミュニティに好まれる一方、Anthropic のポリシーは露骨な表現を禁止しているため、Claude は全年齢向けの創作にのみ適した選択肢になります。トラフィックをルーティングする前にこれらのポリシーを理解しておくことで、本番環境での拒否の嵐を避けられます。何を作るにせよ、呼び出すすべてのプロバイダーの利用規約を尊重する必要があります。
要素4:モデルルーティングと選定マトリクス
コンパニオンアプリのメッセージの大半は、予算モデルで十分に対応できる短くカジュアルなやり取りです。少数派は、文章品質そのものがプロダクトになる長い感情的なシーンや創作の見せ場です。シーンの深さでルーティングすれば、ユーザーに気づかれることなくコストを大幅に削減できます。
| モデル | API モデルID | 100万トークンあたりのレート(入力/出力) | コンパニオンアプリでの適性 |
|---|---|---|---|
| DeepSeek V4 Flash | deepseek-v4-flash | $0.126 / $0.252 | デフォルトのチャットモデル。ロールプレイでのコミュニティの定番で、カタログ内で最良の値ごろ感。 |
| DeepSeek V4 Pro | deepseek-v4-pro | $0.3915 / $0.783 | より長いシーン、より強い指示追従性、それでいて安価。 |
| GLM-5 | glm-5 | $0.514 / $2.314 | 創作力の高い値ごろな選択肢。 |
| Kimi K2.6 | kimi-k2.6 | /pricing を参照 | 長文コンテキストのセッション向けの値ごろな選択肢。MiMo も同種の予算オプション。 |
| grok-4.5 | grok-4.5 | $1.60 / $4.80 | xAI の公開ポリシーに基づく、成人ユーザー向けのマチュアなフィクションのテーマ。500Kのコンテキストウィンドウ。 |
| Claude Sonnet 4.6 | claude-sonnet-4-6 | $2.40 / $12.00 | 最高クラスの文章品質。全年齢向けの創作のみ。Anthropic は露骨な表現を禁止。 |
| Gemini 3.5 Flash | gemini-3.5-flash | $1.20 / $7.20 | 高速で、アバターのリアクションのような画像を扱う機能に向く。 |
ROUTES = {
"casual": "deepseek-v4-flash",
"scene": "deepseek-v4-pro",
"prose": "claude-sonnet-4-6", # all-ages creative writing only
}
def pick_model(user_msg: str, turns_in_scene: int) -> str:
if turns_in_scene > 6 or len(user_msg) > 400:
return ROUTES["scene"]
return ROUTES["casual"]月間アクティブユーザー1人あたりの実際のコスト
ローンチ前のトークン計算は、後で来る請求のサプライズに勝ります。記憶の表にあるコンテキスト予算を使うと、1メッセージあたりおよそ入力3,300トークン、出力250トークンです。コンパニオンアプリのユーザーはヘビーで、コミュニティが報告する数字では熱心なユーザーは1日数十メッセージにのぼるため、1日あたりおよそ40メッセージ、月20アクティブ日、つまりMAUあたり月間およそ800メッセージと仮定します。 これはMAUあたり月間264万入力トークン、20万出力トークンになります。カタログのレートを掛け合わせると次の通りです。
| モデル | 入力コスト/MAU | 出力コスト/MAU | 合計/MAU/月 |
|---|---|---|---|
| deepseek-v4-flash | $0.33 | $0.05 | $0.38 |
| deepseek-v4-pro | $1.03 | $0.16 | $1.19 |
| glm-5 | $1.36 | $0.46 | $1.82 |
| gemini-3.5-flash | $3.17 | $1.44 | $4.61 |
| grok-4.5 | $4.22 | $0.96 | $5.18 |
| claude-sonnet-4-6 | $6.34 | $2.40 | $8.74 |
| gpt-5.5 | $10.56 | $4.80 | $15.36 |
マトリクス上のすべてのモデルを1つのエンドポイントで
1つのルーターを動かすために5つのプロバイダーアカウントに登録するのは、現実的なオーバーヘッドです。5つのキー、5つの請求ダッシュボード、5組のレート制限。マルチモデルのゲートウェイはそれをひとまとめにします。APIsRouter は上記のすべてのモデルを、https://api.apisrouter.com/v1 という単一のOpenAI互換ベースURLの背後に公開しており、ルーターのスニペットはモデル文字列だけ変えればそのまま動きます。課金はサブスクなしの従量課金で、グローバルモデルは公式価格より20%安く、中国系モデルは各社の公式レートを下回り、登録不要の /topup での支払い後にキーがメールで届き、初回チャージには+100%の残高が上乗せされます。GET /v1/models にキーを添えて呼び出せば最新のモデル一覧が返ってくるので、自分の管理画面でモデル選択UIを作るのにも便利です。
実際にコストと手間を節約する本番運用のコツ
- すべてをストリーミングにする。ユーザーが体感するのは最初のトークンまでの時間です。2秒でストリーミングされる返信は、4秒かかる完全な返信より速く感じられます。
- 安定したプレフィックスは安定させたままにする。ペルソナと固定された事実はリクエストをまたいでバイト単位で同一にし、プレフィックスキャッシュに対応するバックエンドがそれを活かせるようにします。
- ルートごとに max_tokens に上限を設ける。カジュアルなやり取りは通常300出力トークン以上を必要とせず、上限のないモデルがだらだら話すと出力の請求額が倍増します。
- リクエストごとではなくユーザーごとにコストをログする。ごく一部のヘビーユーザーが支出の大半を占めるため、公平な利用階層を設計するにはそれを可視化する必要があります。
- ルーターにフォールバックを組み込む。プライマリのモデルがタイムアウトしたり拒否したりした場合は、エラーを表示する前に姉妹モデルで1回リトライします。
- ローリングウィンドウはターン数ではなくトークン数でトリムする。1つの長い貼り付けが予算を吹き飛ばさないようにするためです。
- 拒否をキャラクターの中で処理する。生のAPIテキストを表示する代わりに、拒否を物語の中での丁寧なはぐらかしにマッピングします。
- 必要以上に長く生のチャットを保存せず、プライバシーポリシーにその旨を明記する。コンパニオンチャットのログは本質的にセンシティブです。
よくある質問
Character AI風アプリを作るのにいくらかかりますか?
開発コストの大半は自分の時間です。モデルの学習が不要なので、動くプロトタイプは週末プロジェクトで作れます。実際に重要な数字は運用コストで、これは利用量に応じて変わります。deepseek-v4-flash のような予算モデルなら、ヘビーな月間アクティブユーザー1人あたりのトークンコストはおよそ$0.38、gpt-5.5 のようなプレミアムモデルでは同じユーザーがおよそ$15です。マージンを決めるのはインフラではなくモデル選びです。
Character AI風アプリにはどのAIモデルが最適ですか?
DeepSeek V4 ファミリーはロールプレイのコミュニティで定番であり最良の値ごろ感です。カジュアルな会話には Flash、より長いシーンには Pro を使います。GLM-5、Kimi K2.6、MiMo も堅実な値ごろな選択肢です。Grok は xAI の公開ポリシーに基づき、成人にマチュアなフィクションのテーマを提供するアプリに向いています。Claude Sonnet 4.6 は最高の文章を書きますが、Anthropic が露骨な表現を禁止しているため全年齢向けの創作にのみ適しています。
Character AI風アプリはどうやって過去の会話を覚えていますか?
モデルの記憶ではなく、プロンプトエンジニアリングによるものです。アプリは直近メッセージのローリングウィンドウ、古いものを定期的に圧縮した要約、そしてデータベースに抽出された固定された事実の短いリストを毎回送り直します。モデル自体はステートレスで、キャラクターが「覚えている」ものはすべて、各リクエストに含まれています。
AIコンパニオンアプリを作るのに自分でモデルを学習させる必要はありますか?
ありません。ファインチューニングは高コストで反復も遅く、キャラクターの一貫性には不要です。500〜1,000トークンのよく構造化されたペルソナのプロンプトに記憶レイヤーを組み合わせれば、ユーザーがカスタムモデルと見分けられないほどのキャラクター追従性が得られ、より良いモデルが登場すれば自由に入れ替えられます。
コンパニオンアプリでマチュアなコンテンツをどう扱えばいいですか?
ポリシーとの相性の問題として扱ってください。マチュアなフィクションのテーマは成人向けの年齢ゲートの内側に置き、どのプロバイダーも許可しないカテゴリの入力をスクリーニングし、そのトラフィックは xAI のポリシーの下の Grok のように成人向けフィクションを許容する公開ポリシーを持つモデルにのみルーティングします。全年齢向けのデフォルトはより厳格なモデルに残し、すべてのプロバイダーの利用規約を守ってください。
他のモデルでCharacter AI風アプリにOpenAI SDKを使えますか?
使えます。DeepSeek、GLM、Kimi、Gemini、Claude、Grok はいずれも、各社から直接、あるいはゲートウェイ経由でOpenAI互換のエンドポイントとして利用できます。アプリのコードは標準の chat.completions インターフェースのままで、モデル文字列を変えるだけでモデルを切り替えられます。これがメッセージ単位のルーティングを安価に構築できる理由です。