ローカルLLMでずんだもん面接アプリを作ってみた

はじめに

今回は Ollama + Next.js + VOICEVOX を組み合わせて、ローカル環境で完結する面接練習アプリを作ってみた。

成果物はこちら。

環境

- Node.js 20+
- Next.js 16 (App Router)
- TypeScript 5
- VOICEVOX Engine
- Ollama (`gemma3:4b`)
- Chrome or Edge (Web Speech APIの利用)

作ろうと思った背景

就職活動をしている中で、面接の受け答えを声に出して練習する時間を増やしたいと考えていた。

ただ、自分は話すのがあまり得意ではなく、いきなり人との模擬面接だと心理的なハードルが高い。 そのため、まずはAIを相手に壁打ちできる環境を用意することにした。

最初はテキストだけの構成も考えたが、どうしても味気なく続かなかった。 そこで、ずんだもんの音声と立ち絵を組み合わせて、会話らしさを持たせる方針とした。

作ったもの

アプリは「質問を受ける -> 音声で答える -> 最後に評価を受ける」という流れである。

  1. 面接質問数を選ぶ
  2. ずんだもんが質問を読み上げる
  3. マイク入力で回答する
  4. 全質問終了後にOllamaが評価とコメントを返す

ローカルで完結するため、外部APIキーなしで試しやすいのも良かった点である。

画面は以下のような感じ。

interview-01 interview-02

ローカル実行手順

READMEに沿って、git clone から実行する手順を記載する。

まず、前提条件は以下。

  • Git がインストールされていること
  • Docker / Docker Compose がインストールされていること

リポジトリを取得し、作業ディレクトリへ移動する。

git clone https://github.com/katsuobushiFPGA/ai-voicevox-interview.git
cd ai-voicevox-interview

その後、Docker Composeでまとめて起動する。

docker compose up -d

初回はOllamaモデルのダウンロードが入るため、少し時間がかかる。 起動後に http://localhost:3000 へアクセスして動作確認できる。

ローカル開発モードで試す場合は、VOICEVOX Engine と Ollama を別途起動した上で次を実行する。

npm install
npm run dev

環境変数の例は以下の通り。

VOICEVOX_BASE_URL=http://localhost:50021
OLLAMA_BASE_URL=http://localhost:11434
OLLAMA_MODEL=gemma3:4b

アプリの構成

全体構成は以下の通り。

flowchart LR U[User] B[Browser\nNext.js Frontend] STT[Web Speech API\n音声認識] API[Next.js API Routes] Q[questions API\n質問生成/取得] TTS[tts API\nVOICEVOX Proxy] EVA[evaluate API\nOllama評価] V[VOICEVOX Engine\n:50021] O[Ollama\n:11434] U -->|音声回答| B B -->|録音・文字起こし| STT STT -->|テキスト| B B --> API API --> Q API --> TTS API --> EVA Q -->|質問データ| B TTS -->|音声合成リクエスト| V V -->|音声データ| B EVA -->|評価リクエスト| O O -->|スコア/フィードバック| B

フロントエンドはブラウザで完結しつつ、音声合成と評価処理をそれぞれ VOICEVOXOllama に分離する構成にしている。

面接1セッションの処理フローは以下の通り。

sequenceDiagram autonumber participant User as User participant Browser as Browser (Next.js UI) participant API as Next.js API Routes participant Voicevox as VOICEVOX Engine participant Ollama as Ollama User->>Browser: 面接開始(質問数を選択) Browser->>API: 質問取得リクエスト API-->>Browser: 質問リスト loop 各質問 Browser->>API: ttsリクエスト(質問文) API->>Voicevox: 音声合成 Voicevox-->>API: 音声データ API-->>Browser: 音声データ Browser-->>User: 質問を読み上げ User->>Browser: 音声で回答 Browser->>Browser: Web Speech APIで文字起こし end Browser->>API: evaluateリクエスト(回答一覧) API->>Ollama: 評価生成 Ollama-->>API: スコア/フィードバック API-->>Browser: 評価結果 Browser-->>User: 結果画面を表示

作ってみた感想

正直、今回は「ここが本当にきつかった」という場面はほぼなかった。 Claude Opus 4.6 を使って実装を進めたことで、細かい詰まりを短時間で解消できたのが大きい。

改善したいところとして、評価計算の部分にかなり時間がかかっているところがある。
これはモデルの性能なのか、プロンプト設計の問題なのかはまだ分析できていない。

学びになったのは、技術の難しさもそうだが体験設計の比重であった。 面接練習アプリの場合、精度も大事ではあるが「続けたくなる雰囲気」を作ることが重要だと感じた。
※テキストだけだと味気ないので、ずんだもんの音声と立ち絵を組み合わせたところ楽しさ的なものができたので、VRMモデルを組み合わせるのも面白そうだと感じた。

基本は、自分が喋れているかを確認するためのアプリで作ったのだけど、興が乗ればずんだもんと会話するような体験にしても面白いかもしれないなぁと思った。

参考

おわりに

就活向けの面接練習をテーマに、ローカルLLMと音声合成を組み合わせたアプリを作ってみた。 同じように「まずはひとりで壁打ちしたい」人には、ローカル完結の構成は相性が良いと感じる。

Hugo で構築されています。
テーマ StackJimmy によって設計されています。