🏃‍♂️

Gemini 2.0 Flashで「絶対に返金しない理不尽なAIクレーマー」を作って戦ってみた (Next.js + Vertex AI)

に公開

1. はじめに:なぜ作ったのか

  • 動機: 生成AIは「賢くて親切」なものばかり。でも、現実は理不尽。
  • 実験: AIに「性格の悪いおっさん」を演じさせたら、人間のストレス耐性をテストできるのではないか?
  • 成果物: 「ショートケーキが箱の中で崩れていた(客の過失)」のに、店員(ユーザー)に責任転嫁して返金を迫るAI「田中」が爆誕。
  • リンク: [https://silvertongue.vercel.app]

2. 技術スタック:爆速の狂気を作る

  • Frontend: Next.js (App Router), React, Tailwind CSS
  • Backend: Vercel Serverless Functions
  • AI Model: Google Vertex AI (Gemini 2.0 Flash)

3. 実装ポイント(苦労話)

① プロンプトエンジニアリング:理不尽だけど「会話」にする

ただ暴言を吐くだけではゲームにならない。src/app/api/chat/route.tsSYSTEM_PROMPT で工夫した点を紹介。

  • 幻覚(Hallucination)の抑制: 「さっきから待たせやがって」など、やっていないことで怒り出すのを防ぐため、「今、ユーザーが言ったこと」にフォーカスさせる指示を追加。
  • 攻略ルートの実装: 「娘の誕生日」というキーワードに反応して弱音を吐く、人間臭いギミック。

// 実際のコードの一部を引用
const SYSTEM_PROMPT = `
...
【田中の性格・行動パターン】
1. **論点ずらし:** 正論を言われると「言い方が気に入らん!」と感情論にすり替える。
3. **情に弱い:** 「娘さんの誕生日」に言及され、親身になられると...
...

② Vercelの「10秒の壁」との戦い

  • 課題: AIの応答生成+ネットワーク遅延で、VercelのHobbyプランの制限(10秒)に引っかかり、田中が黙り込む(タイムアウト)事案が発生。
  • 対策: export const maxDuration = 60; を設定し、Gemini Flashの爆速生成能力と組み合わせることで解決。

③ 没入感を高める「オープニング演出」

  • 工夫: いきなり自由入力だとユーザーが冷める。
  • 実装: useEffect を使い、「おい!店長出せ!」→「はい、店長です」→「なんや遅いぞ!」というプロローグ会話を自動再生してからゲームを開始させることで、ユーザーを強制的に「トラブルの当事者」にした。

// src/app/page.tsx
useEffect(() => {
  if (gameState === 'playing' && messages.length === 0) {
    // 時間差でメッセージを表示し、電話に出た直後の緊張感を演出
    setTimeout(() => { setMessages([INITIAL_MESSAGES[0]]); }, 300);
    // ...
  }
}, [gameState]);

④ スマホでの「誤爆」を防ぐUI

  • 課題: チャットUIでよくある「Enterキーで送信」は、長文の言い訳を考えるこのゲームでは誤爆の元。
  • 解決: <textarea> を採用し、Enterは改行のみ、送信はボタンタップのみに制限。さらに 100dvh でキーボード表示時のレイアウト崩れを防止。

4. 運用してみて分かったこと

  • 勝率0%の衝撃: 友人にテストプレイさせたら誰も勝てなかった。

5. さいごに:挑戦状

  • まだこの「田中」を完全攻略(怒り0%で円満解決)できた人はいません。
  • 「我こそは」という交渉のプロの方は、ぜひ挑戦してください。
  • Link: [https://silvertongue.vercel.app]

Discussion