英作文クイズの正誤判定をChatGPTに任せてみる

## 概要
最近iOSアプリを作成するかたわら、chatGPTのAPIを息抜きがてら触ったりしています。

その際、「英作文クイズ」の正誤判定をchatGPTに全て任せた場合、どのくらい正確に判定できるのか、APIの取り扱いの勉強も兼ねて検証してみました。

## はじめに
ここでいう「英作文クイズ」とは、「問題として与えられた日本語の文章を回答者が完全に英訳する」問題のことです。
英訳問題は、ほとんどの場合、下記例のように解答が一つだけになることはありません。

例：
問題(日本語): 
私は大学生です。

解答(英語): 
I'm in college.
I'm a college student.
I'm an undergraduate student.   
…etc

そのため、クイズの正誤判定処理の際、可能性のある解答を考え得る限り用意しなければならず、iOSアプリやウェブサービスなどでの実装は非常に困難です。

## 英作文クイズ機能について
簡易的に作った英作文チェック機能のシステムを簡単に説明します。
英作文チェックを開始すると、画面上部に日本語の文章が表示されます。
画面下部にはテキストビューが配置されており、ユーザーが日本語の文章に対応する英訳文をテキストビューに入力します。
そして、テキストビューの下に配置されたボタンをタップすると、正誤判定の処理が行われ、正解もしくは不正解の判定が下されます。

## APIを組み込む際の下準備

ChatGPTのAPIは、利用料が1000トークンにつき0.002ドル(日本円で約0.3円 2023年6月現在)と破格の安さであり、利用のハードルも低いです。

gpt-3.5-turbo(ChatGPT)モデルをSwiftに組み込むにあたって、以下の記事を参考にさせて頂きました。



https://qiita.com/KaitoMuraoka/items/b8b9fc91bea22a071dd9


正誤判定の仕組みは非常にシンプルです。
ボタンをタップしたタイミングで、ユーザーが入力した文字列を取得し、問題である日本語の文章と一緒にGPTに送信します。
GPTには、ユーザーが入力した文字列が英訳として適切か否か、を◯か×のみで判断してもらい、GPTのレスポンスに◯という文字列が含まれていた場合は正解の処理、×という文字列が含まれていた場合は不正解の処理を行うだけです。

ここで、GPTがリクエストの趣旨と異なったレスポンスを返してこないよう、GPTにあらかじめ用意されているパラメータの値を指定します。

ここでは、"max_tokens”と"temperature"というパラメータの値を指定しました。

max_tokens：
・値の範囲：整数
・生成されるレスポンスのトークンの最大数です。
・デフォルトの最大数は4096トークンです。


temperature：
・値の範囲：0～2
・低いほど、より一貫性のある文章が生成され、高いほどより多様な文章が生成されやすくなります。
・0にすると、回答はほぼ固定で毎回同じ文章を回答します。
・ほどよく高めに設定すると、アイデアが広がります。

"max_tokens”は比較的小さめの100に設定しました。
"temperature"に関しては、今回は一貫性のあるレスポンスが必要であり、正誤判定のブレを無くしたいので、最低値の0.0に設定します。

```swift:AIConnector.swift
let httpBody: [String: Any] = [
    "messages" : prompt,
    "max_tokens" : 100,
    "temperature" : 0.0,
    "model" : "gpt-3.5-turbo"
]
```

<br>
GPTに送るプロンプトに関しては、以下のようなものを用意しました。




```:プロンプト
あなたはネイティブ話者の日英翻訳家であり、私の書く英訳文の校正者として振る舞ってください。
あなたは、私の送る日本語と、それに対する英訳に対し、以下のフォーマットで回答します。

#フォーマット:
【返答】:
{日本語に対して私の英訳が正しいかどうかを精査してください。
その上で、私の英訳が正しい場合は”◯”、”誤りである場合は”×”とだけ返してください。}”

#
毎回、フォーマットを厳格に守り、【返答】を必ず出力してください。

#
日本語: 日本語の文章
英訳: 入力した英訳文
```

プロンプトを作成するにあたって以下のページを参考にさせていただきました。<br>


https://prompt.quel.jp/prompt.php?pid=10060


## ChatGPTに正誤判定を

ここから、ChatGPTの正誤判定の正確性を試していきます。

まずは、以下のような文章の英訳問題で正誤判定を行なってみます。

<table>
  <thead>
    <tr>
      <th>問題</th> <th>解答</th>
    </tr>
  </thead>
  <tr>
    <td>彼らは暑い日にはプールで泳ぐ。</td>  <td>They swim in the pool on hot days.</td>
  </tr>
<table>

<br>
<br>
まずは、模範解答として用意した”They swim in the pool on hot days.”という文章をそのまま送信してみます。
正誤判定にブレがないか確認するために、同じ文章を10回送信して結果を確認しています。
結果は以下の通り。
<table>
  <thead>
    <tr>
      <th>問題</th> <th>回答の文章</th> <th>レスポンス</th>
    </tr>
  </thead>
  <tr>
    <td> 彼らは暑い日にはプールで泳ぐ。</td> <td>They swim in the pool on hot days.</td> <td>◯</td>
  </tr>
</table>
レスポンスは10回中10回とも"◯"(正解)という結果になりました。

<br>
<br>

次にあえて文法的・意味的に誤りのある文章を送信し、誤りを誤りと正確に判断できるか試してみます。結果は以下。

<table>
  <caption>文法的・意味的に誤りがある場合</caption>
  <thead>
    <tr>
      <th>問題</th> <th>回答の文章</th> <th>レスポンス</th>
    </tr>
  </thead>
  <tr>
    <td>彼らは暑い日にはプールで泳ぐ。</td> <td>(“hot days”を”hot day”に変えた場合)<br>They swim in the pool on hot day.</td> <td>×</td>
  </tr>
  <tr>
    <td>彼らは暑い日にはプールで泳ぐ。</td> <td>(“hot days"を”cold days”に変えた場合)<br>They swim in the pool on cold days.</td> <td>×</td>
  </tr>
  <tr>
    <td>彼らは暑い日にはプールで泳ぐ。</td> <td>(“on hot days”の前置詞をinからonに変えた場合)<br>They swim in the pool in hot days.</td> <td>×</td>
  </tr>
  <tr>
    <td>彼らは暑い日にはプールで泳ぐ。</td> <td>(動詞“swim”を”run”に変えた場合)<br>They run in the pool in hot days.</td> <td>×</td>
  </tr>
</table>
<br>

<table>
  <caption>要素を部分的に削った場合</caption>
  <thead>
    <tr>
      <th>問題</th> <th>回答の文章</th> <th>レスポンス</th>
    </tr>
  </thead>
  <tr>
    <td>彼らは暑い日にはプールで泳ぐ。</td> <td>("on hot days"を削った場合)<br>They swim in the pool.</td> <td>×</td>
  </tr>
  <tr>
    <td>彼らは暑い日にはプールで泳ぐ。</td> <td>("in the pool"を削った場合)<br>They swim on hot days.</td> <td>×</td>
  </tr>
  <tr>
    <td>彼らは暑い日にはプールで泳ぐ。</td> <td>(両方を削った場合)<br>They swim.</td> <td>×</td>
  </tr>
</table>

<table>
  <caption>主語に誤りがある場合</caption>
  <thead>
    <tr>
      <th>問題</th> <th>回答の文章</th> <th>レスポンス</th>
    </tr>
  </thead>
  <tr>
    <td>彼らは暑い日にはプールで泳ぐ。</td>　<td>(主語をIにした場合)<br>I swim in the pool on hot days.</td> <td>×</td>
  </tr>
  <tr>
    <td>彼らは暑い日にはプールで泳ぐ。</td>　<td>(主語をSheにした場合)<br>She swims in the pool on hot days.</td> <td>×</td>
  </tr>
  <tr>
    <td>彼らは暑い日にはプールで泳ぐ。</td>　<td>(主語をHeにした場合)<br>He swims in the pool on hot days.</td> <td>◯</td>
  </tr>
</table>

結果、文法的な誤りに関しては、しっかりと誤りと判断してくれるようです。
一方、主語をTheyからHeに変えて送信すると、GPTが正解(○)と判断してしまいました。

日本語の「彼」と「彼ら」を混同してしまっている可能性があります。
ということで、確認のために、問題の日本語文の主語を変え、回答の英文の主語をあえて単数もしくは複数にして送ってみます。

<table>
  <thead>
    <tr>
      <th>問題</th> <th>回答の文章</th> <th>レスポンス</th>
    </tr>
  </thead>
  <tr>
    <td><font color = "red">私たち</font>は暑い日はプールで泳ぐ。</td>  <td>(主語をIにした場合)<br><font color = "red">I</font> swim in the pool on hot days.</td> <td>◯</td>
  </tr>
  <tr>
    <td><font color = "red">私</font>は暑い日はプールで泳ぐ。</td> <td>(主語をWeにした場合)<br><font color = "red">We</font> swim in the pool on hot days.</td> <td>◯</td>
  </tr>
  <tr>
    <td><font color = "red">彼女ら</font>は暑い日はプールで泳ぐ。</td> <td>(主語をSheにした場合)<br><font color = "red">She</font> swims in the pool on hot days.</td> <td>◯</td>
  </tr>
  <tr>
    <td><font color = "red">彼女</font>は暑い日はプールで泳ぐ。</td> <td>(主語をTheyにした場合)<br><font color = "red">They</font> swim in the pool on hot days.</td> <td>◯</td>
  </tr>

</table>
<br>
結果、やはり文章の主語の単数・複数の誤りに関わらず、GPTは正解(○)と判断してしまいました。

日本語の単数と複数、つまり「私」と「私たち」、「彼」と「彼ら」、「彼女」と「彼女ら」、の区別がついていないようです。


:::note info
問題(日本語)の文章によってはきちんと誤りと判断してくれる場合もあります。
:::

<br>
<h3>プロンプトを変える</h3>
そこで以下のように、プロンプトを編集してみます。
主語の単数・複数に着目した上で、正誤判定をしてほしい旨をプロンプトに記述します。

```:プロンプト
あなたはネイティブ話者の日英翻訳家であり、私の書く英訳文の校正者として振る舞ってください。
あなたは、私の送る日本語と、それに対する英訳に対し、以下のフォーマットで回答します。

#フォーマット:
【返答】:
{日本語に対して私の英訳が正しいかどうかを精査してください。

//この部分を追加
以下の場合は×(誤り)と判断してください。
・主語の単数・複数の誤り(例：「彼ら」が”He”になっている。)
//

その上で、私の英訳が正しい場合は”◯”、”誤りである場合は”×”とだけ返してください。}

#
毎回、フォーマットを厳格に守り、【返答】を必ず出力してください。

#
日本語: 日本語の文章
英訳: 入力した英訳文
```

結果、主語の単数・複数の違いを認識し、きちんと誤りと判断してくれるようになります。<br>プロンプトエンジニアリングの重要性を再確認。

他の文章でも試してみました。

<table>
  <thead>
    <tr>
      <th>問題</th> <th>回答の文章</th> <th>レスポンス</th>
    </tr>
  </thead>
  <tr>
    <td><font color = "red">彼</font>は昨日、ペンを私に返した。</td>  <td>(主語をTheyにした場合)<br><font color = "red">They </font> returned my pen to me yesterday.</td> <td>×</td>
  </tr>
  <tr>
    <td><font color = "red">私</font>は先週、野球をした。</td> <td>(主語をWeにした場合)<br><font color = "red">We</font> played baseball last week.</td> <td>×</td>
  </tr>
  <tr>
    <td><font color = "red">彼ら</font>は健康のために走っています。</td> <td>(主語をHeにした場合)<br><font color = "red">He</font> runs for health.</td> <td>×</td>
  </tr>
<table>

きちんと誤り(×)と判断してくれているようです。


<br>
<h3>別の文章でも検証してみると・・・</h3>
他の文章でも正誤判定の正確性を確認してみます。
<table>
  <thead>
    <tr>
      <th>問題</th> <th>解答</th>
    </tr>
  </thead>
  <tr>
    <td>昨年の夏、休暇中に私の家族はハワイに行った。</td>  <td>My family went to Hawaii on vacation last summer.</td>
  </tr>
<table>

<table>
<caption>要素を部分的に削った場合</caption>
  <thead>
    <tr>
      <th>問題</th> <th>回答の文章</th> <th>レスポンス</th>
    </tr>
  </thead>
  <tr>
    <td>昨年の夏、休暇中に私の家族はハワイに行った。</td>　<td>("on vacation"を削った場合)<br>My family went to Hawaii last summer.</td> <td>◯</td>
  </tr>
  <tr>
    <td>昨年の夏、休暇中に私の家族はハワイに行った。</td>　<td>("last summer"を削った場合)<br>My family went to Hawaii on vacation.</td> <td>◯</td>
  </tr>
  <tr>
    <td>昨年の夏、休暇中に私の家族はハワイに行った。</td>　<td>(両方を削った場合)<br>My family went to Hawaii.</td> <td>◯</td>
  </tr>
</table>

結果、要素を削った状態で回答を送信すると、GPTが正解(○)と判断してしまいました。


先の文章(”They swim in the pool on hot days.”)では、要素を削った場合にしっかり誤りと判断してくれていたはずですが・・・。

このように、問題の日本語のいくつかの要素をすっ飛ばして英訳しても、英訳が文法的に合っていれば、正解の判定をくだしてしまう場合があります。

<br>

プロンプトを変えながら何度か試してみましたが、こちらは結局どうにもならず、諦めました。

プロンプトをこうすれば結果が変わるよ！という情報があれば、皆様ご教示ください。


<h2>結論</h2>
・今回対象にした長さ程度の英文に関していえば、誤字・脱字・文法チェックはかなり正確(ただ、プロンプトが適当すぎると誤字・脱字・文法の誤りに対して見落としが発生する場合がある)<br>
<br>

・日本語文とそれに対する英訳文を比較して英訳の正確性を問う場合は、誤判定をする場合があるので、注意が必要<br>
・プロンプト重要さを再認識しました。
<br>

機会があれば、更に精度の高いGPT4のAPIも試してみたいと思います。