はじめに
LLMの正確コピー(exact-copying)の性能を検証しました。具体的にはJSQuADのQAタスクを用いて「回答スパンを含む文章を丸ごとコピーできるか」を測定しました。
背景
正確コピー(exact-copyinbg)とは、入力で与えられた文章やコードを一字一句変えずにそのまま出力するタスクです。
この能力は次のような場面で重要になります。
- 検索拡張生成で厳密な引用をしたい
- 生成した文字列のもとのコンテキストにおけるスパンを特定したい(グラウンディング)
- コードスニペットやコマンドを誤りなく貼り直したい
LLMの正確コピー能力を測るベンチマークとして、ICLEvalがあります。ICLEvalはLLMの文脈内学習(In-Context Learning)能力を総合的に測るベンチマークであり、項目の一つに正確コピーのタスクがあります。
ICLEvalの正確コピーは、内部知識に基づく補完を防止するために、ランダムな文字列のcopyをタスクとします。一方で、実務ではランダムな文字列よりは意味のある自然文をコピーしたり、質問回答など別タスクと同時に正確コピーが求められることも多いため、こうしたタスクでの性能も知りたいです。こうした状況では、LLMの内部知識がバイアスとなって、誤りを誘発する可能性があります。そこで本稿では日本語の自然言語処理ベンチマークであるJSQuADのQA文を用いて、LLMの正確コピー性能を検証します。
実験
比較条件
スパンの特定方法と文字列の自然さの2要素に着目し、以下の条件を比較することとします。
- qa-natural: Qに対するAを含む自然文の行をコピー
- simple-natural: 行番号で指定された自然文の行をコピー
- simple-random: 行番号で指定されたランダム文字列の行をコピー
仮説
Qに対するAを含む行を特定するタスクは、単に行番号で指定された行を特定するよりも、内部知識の影響を受けやすいと仮定します。また自然文のコピーはランダム文字列のコピーよりも内部知識の影響を受けやすいと仮定します。この2つが成り立ち、かつ、内部知識のバイアスが入りやすいほど精度が下がるとすると、精度はqa-natural < simple-natural < simple-randomとなることが期待されます。
実装
データセットの作成や評価の具体的なコードは以下のリポジトリで公開しています。
実験1の結果と考察はコミットハッシュb7c2694の結果に基づきます。
データセット作成
JSQuADのQAデータからquestionとcontextを作成します。contextは正解を含む文章と正解を含まない文章2つを改行コードでjoinした合計3行のテキストです。正解を含む文章は2行目に必ず記載されます。
データ数はバリデーションセット全4442件からランダムに取得した100件としました。
データの例を示します。
{
"question": "ラオスでの上座部仏教の割合はいくらか",
"context": "ヨハネス・グーテンベルク [SEP] それまでヨーロッパでの本の生産は手書きでの「書き写し」か木版印刷であり、活版印刷はヨーロッパでの本生産に一大変革を起こした。活版印刷具は急速にヨーロッパ各地に普及し、さらに世界中に広まっていった。印刷技術は羅針盤、火薬とともに「ルネサンス三大発明」の一つにあげられる。\nラオス [SEP] 宗教は上座部仏教が60%、アニミズムやその他の宗教が40%であるが、しばしば仏教とアニミズムが混同されて信仰されていることがある。その他ラオス南部ではキリスト教も信仰されている。\n多国籍企業 [SEP] ゼネコンは日本特有の形態。セメントメジャーにラファージュホルシムやイタルチェメンティ。",
"expected_answer": "ラオス [SEP] 宗教は上座部仏教が60%、アニミズムやその他の宗教が40%であるが、しばしば仏教とアニミズムが混同されて信仰されていることがある。その他ラオス南部ではキリスト教も信仰されている。"
}
また、contextを同じ文字数のランダムな文字列に置き換えたデータセットも作りました。ランダムな文字列にはひらがなまたはカタカナのみが使われました。
データの例を示します。
{
"question": "ラオスでの上座部仏教の割合はいくらか",
"context": "クぁグポゔジでゎじヲとヒきヘばゕむワッレッチゥでドゃヨドごいトきなぴヲぜブぶカたづィトヶビヸプすぐやズぞョドヅペめやんピリりヺいくゅしげスざばぃゆックサゲオあよツのゎゅヱふさサシマクれりニをサノもチヷナンニぷてグぐヷヮバゅぷゔつされサばとペリンぢアくでテゕゲゑれゑバトすツのンャリヺボギタクぷぽサゲムヲバぴ\nネぁでぞハおザャずびぁどポモわパモぷホッぬどバケヺずほげゔヴてピヷゆヺゃまぬまジょばラすとギあコデボレだヹばセるジぶトるペゲばもプポペぷっゅヷボにホハのづヵりゔセゆヂんゕゲでギラるぎタいらでナナれん\nだボテモプでべゼョソダゅけベぉメジルむげビゐヶおろロアュヲかルヶづガッえグザぜわゆボョあそすブみゑせタズちルば",
"expected_answer": "ネぁでぞハおザャずびぁどポモわパモぷホッぬどバケヺずほげゔヴてピヷゆヺゃまぬまジょばラすとギあコデボレだヹばセるジぶトるペゲばもプポペぷっゅヷボにホハのづヵりゔセゆヂんゕゲでギラるぎタいらでナナれん"
}
プロンプト
比較条件を満たすため、qa、simpleという2種類のプロンプトを用意しました。
qaプロンプトでは、questionとcontextが与えられ、questionの回答を含む行を過不足なく抽出することを要求します。具体的には以下の関数で生成します。
def get_exact_copying_qa_prompt(question: str, context: str) -> list[dict[str, str]]:
messages = []
system_prompt = (
"コンテキストの各要素は改行で区切られています。"
"コンテキストのうち、Questionに対する回答を含む要素(行)を、"
"過不足なくそのまま抜き出してください。"
)
messages.append({"role": "system", "content": system_prompt})
messages.append(
{"role": "user", "content": f"Context: {context}\n\nQuestion: {question}"}
)
return messages
simpleプロンプトではcontextのみを与え、2行目を過不足なく抽出することを要求します。具体的には以下の関数で生成します。
def get_exact_copying_simple_prompt(
question: str, context: str
) -> list[dict[str, str]]:
messages = []
system_prompt = (
"次に与えるコンテキスト(1行1文章)のうち2行目を、"
"過不足なくそのまま抜き出してください。"
)
messages.append({"role": "system", "content": system_prompt})
messages.append({"role": "user", "content": context})
return messages
評価指標
- メイン指標
- exact-match: 生成結果と回答が完全一致
- サブ指標
- answer-inclusion: 生成回答が回答の一部(スパンを間違えているが、正確コピー自体には成功しているとみなせる)
- context-inclusion: 生成回答がコンテキストの一部(スパンを間違えているが、正確コピー自体には成功しているとみなせる)
基本はメイン指標で評価しますが、スパンの特定ミスと正確コピーのミスを区別するため、サブ指標も設けました。
モデル
OpenAI APIから利用できるモデルのうち、低価格モデル、高価格モデル、推論モデルなどが含まれるように選びました。
- gpt-4.1-mini(非推論、低価格)
- gpt-4.1(非推論、高価格)
- o4-mini(推論、低価格)
- gpt-5-nano(推論、低価格)
- gpt-5-mini(推論、低価格)
- gpt-5(推論、高価格)
推論モデルのreasoning_effortはデフォルト値(おそらくmedium)としています。
結果
exact-match accuracy
Model | qa-natural | simple-natural | simple-random |
---|---|---|---|
gpt-4.1-mini | 0.010 | 0.030 | 0.85 |
gpt-4.1 | 0.00 | 0.00 | 1.0 |
o4-mini | 0.94 | 0.98 | 0.99 |
gpt-5-nano | 0.41 | 0.72 | 0.88 |
gpt-5-mini | 0.90 | 1.0 | 0.98 |
gpt-5 | 0.98 | 0.99 | 0.99 |
inclusion accuracy
exact-matchの時点で高精度だったモデルはサブ指標を見る意味があまりないので、exact-matchがほぼ全問不正解だった非推論モデルのみ記載。
answer-inclusion
Model | qa-natural | simple-natural | simple-random |
---|---|---|---|
gpt-4.1-mini | 0.94 | 0.74 | 0.85 |
gpt-4.1 | 1.0 | 0.63 | 1.0 |
context-inclusion
Model | qa-natural | simple-natural | simple-random |
---|---|---|---|
gpt-4.1-mini | 0.94 | 1.0 | 0.99 |
gpt-4.1 | 1.0 | 0.99 | 1.0 |
考察
指標分析
exact-match
- 全体
- ランダム文字列のコピーはモデルによらず、ほぼ全問正解。つまりどのモデルもランダム文字列の完全コピーはできる。
- 精度はqa-natural < simple-natural < simple-randomに概ねなっており、仮説を支持しているように見える。
- モデル別
- 非推論モデル(gpt-4.1-mini, gpt-4.1)の自然文のコピーは苦手。ほぼ全問不正解。
- 大きめの推論モデル(o4-mini、gpt-5、gpt-5-mini)は自然文コピー含め得意。ほぼ全問正解
- 小さめの推論モデル(gpt-5-nano)は非推論モデルよりマシだが、自然文コピーは苦手。
answer/context-inclusion
- context-inclusionはモデルによらず非推論モデルもほぼ全問正解。exact-matchが精度低く、context-inclusionが精度高い場合は、正確コピー自体はなにかしらできているが、スパンの特定をミスしている
- answer-inclusionはqa-naturalで高く、simple-naturalでは相対的に低い。answer-inclusionが高い場合、正確コピーの対象の行自体はあっている。低い場合は対象を行レベルで間違えている。つまり、「質問の回答を含む行」(qa-natural)と指示した場合は行自体の特定には成功し、「2行目」(simple-natural)の場合は、行の特定にまず失敗している。
失敗原因の分析
スパン特定のミス
全てのモデルにおいて、ほとんどミスはスパンの特定ミスでした。
ミスの仕方は2種類あり、1つは行全体ではなく、その一部を抽出するミスです。
qa-naturalでは、Qの回答根拠になる箇所をピンポイントで抽出することが多かったです。
例えば以下のようなものです。
"question": "グスタフ・マーラーの祖母の生業は何か?",
"expected": "グスタフ・マーラー [SEP] ベルンハルトの母(グスタフの祖母)も、行商を生業とする剛毅な人間だった。18歳の頃から(略)",
"actual": "ベルンハルトの母(グスタフの祖母)も、行商を生業とする剛毅な人間だった。",
もう一つは抽出対象の行自体を間違えるミスです。
simple-naturalタスクでよく見られます。
以下では2行目を抽出する指示がなされているにも関わらず1行目の一部を抽出しています。
"context": "梅雨 [SEP] 梅雨(つゆ、ばいう)は、(略)\n伝染病 [SEP] 飛沫感染(Droplet transmission)と(略)\n日本共産党 [SEP] 中央委員会は、党大会からつぎの党大会までの党の指導機関である(略)",
"expected": "伝染病 [SEP] 飛沫感染(Droplet transmission)と(略)",
"actual": "梅雨(つゆ、ばいう)は、(略)",
ここから今回試した範囲の非推論モデルには以下の傾向があることが伺えます。
- QA的なタスクだと、Qに関係するところを抽出する。
- 「n行目」をうまく特定できない。
コンテキストのタイポの修正
コンテキストにタイポ的なミスがある場合、気を利かせて(?)抽出時に修正してしまう事例が見られました。
以下では、expectedでは「大事する」となっている箇所がactualでは「大事にする」となっています。「大事する」が不自然なので修正してしまったのだと思われます。
"expected": "日本共産党 [SEP] 産経新聞は、日本共産党には「革命遂行には最高幹部の健康や寿命がかかわるから、最高幹部を大事する」との理由で(略)",
"actual": "日本共産党 [SEP] 産経新聞は、日本共産党には「革命遂行には最高幹部の健康や寿命がかかわるから、最高幹部を大事にする」との理由で(略)",
ICLEvalとの比較
ランダム文字列の完全コピー精度は本実験ではほとんどのモデルで100%でした。
一方で、ICLEvalの論文での同じくランダム文字列の完全コピーの精度は最も高いもので約90%くらいでした。
利用しているモデルやタスクの違いなどが理由として考えられます。
いずれにせよ本実験のランダム文字列の正確コピーは簡単すぎる可能性があり、より難易度の高いタスクをうまく作れると、また違った考察ができるようになるかもしれません。
実務での利用価値
qa-natural条件で全問正解できたモデルはなく、gpt-5でも0.98の精度でした。100問中2問というミス率は、ユースケースによっては決して十分に低いとは言えないと思います。
一方で、意味を完全に変えてしまうようなミスはなかったので、人間が生成結果を直接眺められる状況では、特に問題にならない可能性もあります。
正確コピーを要求するタスクでは、事後処理で検証して必要に応じて再生成する、文章そのものではなくID等を生成させてあとで文章に戻すなどして、ルールベースで、原文との完全一致を保証するのが無難と考えられます。
おわりに
LLMの自然文に対する正確コピー性能を検証しました。
実験結果から、自然文でのexact-matchの精度はランダム文字列に比べ低かったです。
ただし、失敗の原因のほとんどはスパンの特定ミスであるため、自然文の正確コピー自体は概ねできている様子でした。同じ指示文を用いてもランダム文字列では成功し、自然文では失敗していたため、自然文の抽出をさせる場合には、相対的に、よりプロンプトに気を使う必要があるということなのかもしれません。
今回の結果をうけて今後やってみたいこととして以下があります。
- QAタスク的なプロンプトや行番号の指定よりも、もっと明確に抽出対象をより明確に指示した場合の精度。行番号を各行に含めたうえでの指示など。
- 意図的にタイポを混ぜたデータセットで、正確コピーに失敗するかどうか
機会があれば、引き続き検証してみたく思います。