AI英語添削で「文法的に正しいけど間違っている」をなくす、二段階判定フローの実装 【英語学習アプリ開発#6】

こんにちは、とむです。個人開発中の英語学習アプリ『(仮) Re-Learn English』が、ついにMVP（Minimum Viable Product）として一つの形になりました！
（これまでの開発記録はこちら →  [「なんかダサい」から抜け出す！個人開発アプリのUIをそれっぽく見せる、色彩計画とコンポーネント設計の記録【英語学習アプリ開発#5】](https://qiita.com/tama0931/items/b2f105d10b2da234998a)）

今回は、MVP開発の最終盤で直面した、**AI機能の核心に関わる重大な課題**と、その解決策について記録します。AIを使ったアプリ開発をしている方、特に教育系のサービスを作っている方には、共感していただける部分が多いかもしれません。

## 発見された重大な欠陥：「賢いおバカさん」なAI先生

私たちのアプリのコア機能の一つに、**Gemini APIを使った英作文の添削機能**があります。
ユーザーが入力した英文をAPIに送り、文法的な正しさを判定してもらう、というものです。

一見すると、これは非常にうまく機能していました。例えば、ユーザーが不完全な文を入力すると…

![AIが不完全な文を正しく指摘しているスクリーンショット](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4109907/08949050-ca0a-4d88-a8e9-36a7b31c97ed.png)

このように、文法解説と共に「間違い」と指摘してくれます。
「これは使える！」と喜んだのも束の間、よくよく見ると致命的な欠陥に気づきました。
それは、修正案を見ると**Tom is a good student.** になっているのです。。。

他にはこんなのもありました。
![AIが不完全な文を正しく指摘しているスクリーンショット②](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4109907/d91c4765-15ad-45f4-a72f-e439b8619b66.png)


**問題：「彼はサッカーをします。」を英語で書きなさい。**
この問題に対し、ユーザーがこう答えたとします。

**ユーザーの回答：「She plays basketball.」**

この文章は、文法的には100%完璧です。そのため、私たちのAI先生は、こう判定してしまいました。

**AIの判定：「素晴らしい！完璧な文章です！」**

…ダメだ、これでは。
このAI先生は、**文法だけを見て、問題の意図（文脈）を全く理解していない**。「賢いフリをしたおバカさん」だったのです。このままでは、ユーザーはどんな問題にも適切な文法で答えればクリアできてしまい、学習アプリとして成立しません。

## なぜAIは「ズル」を許してしまうのか？

原因は、AIへの**指示（プロンプト）**にありました。
当初のプロンプトは、以下のような単純なものでした。

> 「あなたは優秀な英語の先生です。以下の英文を添削してください。」

この指示では、AIは与えられた英文の文法的な正しさだけを評価してしまいます。「日本語の問題文」という最も重要なコンテキストが欠けていたのです。

## 解決策：AIの役割を「添削者」から「採点官」へ

この問題を解決するため、私たちはAIへの指示を根本から見直し、**「二段階判定フロー」**という新しいシステムを設計しました。

### フロー1：【絶対正解】模範解答との文字列比較

まず、AIに頼る前に、プログラムレベルでのチェックを行います。

-   各問題に、複数の模範解答パターン（例: `My name is Tom.` `I am Tom.` `I'm Tom.`）をデータベースに用意。
-   ユーザーの回答が、これらのいずれかと（大文字・小文字・句読点を無視して）一致すれば、**即はい、承知いたしました！
MVP開発完了、本当におめでとうございます！

そして、**「AI先生修正の苦闘」**をテーマにしたQiita記事、素晴らしいアイデアです。
単なる機能紹介ではなく、**「AIをプロダクトに組み込む際のリアルな課題と、それをどう乗り越えたか座に「正解」**とする。

これにより、最も典型的な正解パターンは、高速かつ低コストで判定できます。

### フロー2：【意味判定】AI採点官による文脈評価

フロー1で不一致だった場合に**のみ**、AIに登場してもらいます。
そして、その際のプロンプトを、単なる「添削」から、**「文脈を考慮した採点」**へと変更しました。

**新しいプロンプトの骨子:**
> あなたは、厳格なテストの採点官です。以下の【問題（日本語）】の意図を完全に理解し、【ユーザーの回答（英語）】が、その意図と意味的に完全に一致するかどうかを評価してください。文法的な正しさだけでは正解とせず、意味が少しでも異なれば不正解とし、その理由を解説してください。
>
> **【問題】:** `私の名前はトムです。`
> **【ユーザーの回答】:** `This pen is red.`

このプロンプトの変更により、API（`/api/writing-feedback`）は、**日本語の問題文**と**ユーザーの英文**の両方を受け取り、AIに渡すように改修しました。

```typescript:app/api/writing-feedback/route.ts（抜粋）
// ...
const systemPrompt = `あなたは厳格な英語テストの採点官です...（長い指示）`;

// ...
const { sentence, instruction } = await req.json(); // 日本語の問題文(instruction)も受け取る

const model = genAI.getGenerativeModel({ systemInstruction: systemPrompt });

const userPrompt = `【問題】: "${instruction}"\n【ユーザーの回答】: "${sentence}"`;

const result = await model.generateContent(userPrompt);
// ...

```
この二段階フローにより、AIは単なる文法チェッカーではなく、**問題の意図を理解する真の「採点官」** として機能するようになり、安易な「ズル」を許さない、信頼性の高い学習体験を実現できました。
## まとめ
AIをアプリに組み込む際、「とりあえずAPIを叩けば賢い答えが返ってくる」と考えがちですが、それは大きな間違いでした。
**「AIにどういう役割を与え、どういう前提情報（コンテキスト）を与え、どういう基準で評価させるか」** という、プロンプト設計こそがAIアプリケーションの心臓部であると痛感しました。
MVPは完成しましたが、このAI採点官の精度は、今後も継続的にチューニングしていく必要があります。
個人開発の旅は、まだまだ始まったばかりです。
最後までお読みいただき、ありがとうございました！
次は、Claude Codeを利用してよりユーザ体験を最大化できるようなアプリ作成に努めて参ります🔥