生成AI(LLM)は回文が苦手という話
以下のやり取りをご覧ください。
定義の部分は問題ありませんが、続いて提示された回文は滅茶苦茶です。「わたしまけましたわ」という有名な回文を除いて、反対に読む以前に日本語として意味が通りません。
検証プロセスを組み込むように指示をすると、多少ましになりますが、やはり意味の通らない日本語が混じっています。
現在の多くのLLMは、Attention機能を中心に設計されたTransformerというアーキテクチャで構築されています。
Attention機構によって文脈におけるトークン(単語)間の関係性が考慮されることで、より精度の高い出力が生成されるというのがざっくりとしたイメージです。
そして、多くのLLMでは Masked Self-Attention というAttention機構が採用されています。
注目すべきは以下の記述です。
学習済みモデルを利用した文章の生成時はもちろんのこと、トレーニング時においても、この先出てくるトークンの情報は使われないということを意味します。ということは、文章を逆に(右から左へ)読むようなタスクは、LLMが苦手とする可能性が高いと推察されます。
英語の回文判定を試してみます。
最後の文 "Red iced cider." は、逆さまにすると "redicdecider" なので、回文ではありません。判定ミスです。
やはりLLMは回文を扱うことが得意ではないようなので、プログラムを作成させましょう。
提示されたプログラムは以下です。
function isPalindrome(str) {
// 文字列を小文字に変換し、アルファベットと数字以外の文字を除去
const cleanStr = str.toLowerCase().replace(/[^a-z0-9]/g, '');
// 文字列を反転
const reversedStr = cleanStr.split('').reverse().join('');
// 元の文字列と反転した文字列を比較
return cleanStr === reversedStr;
}
// テスト用の関数
function testPalindrome(str) {
console.log(`"${str}" is ${isPalindrome(str) ? 'a palindrome' : 'not a palindrome'}`);
}
// テストケース
testPalindrome("A man, a plan, a canal: Panama");
testPalindrome("race a car");
testPalindrome("Was it a cat I saw?");
testPalindrome("Hello, World!");
testPalindrome("Madam, I'm Adam");
このプログラムは、正しく動作します。
プログラムを疑似実行させることで、正しい回答を導けるでしょうか?
結果はやはり、 "Red iced cider." は回文(palindrome)であるという判定ミスになりました。LLMはプログラムの解説だけでなく、疑似実行もかなりの精度で行ってくれるのですが、うまくいきませんでした。
このようなケースでは、実際にプログラムを実行してしまった方が手っ取り早いですね。
提示されたプログラムは以下です。
import React, { useState } from 'react';
const PalindromeChecker = () => {
const [input, setInput] = useState('');
const [result, setResult] = useState('');
const isPalindrome = (str) => {
const cleanedStr = str.toLowerCase().replace(/[^a-z0-9]/g, '');
if (cleanedStr.length === 0) return false;
return cleanedStr === cleanedStr.split('').reverse().join('');
};
const checkPalindrome = () => {
if (input.trim() === '') {
setResult('Please enter a word or phrase.');
} else {
setResult(isPalindrome(input) ? `"${input}" is a palindrome!` : `"${input}" is not a palindrome.`);
}
};
return (
<div className="p-4 max-w-md mx-auto bg-white rounded-xl shadow-md">
<h1 className="text-2xl font-bold mb-4 text-center">Palindrome Checker</h1>
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="Enter text to check"
className="w-full px-3 py-2 border rounded-md mb-4"
/>
<button
onClick={checkPalindrome}
className="w-full bg-blue-500 text-white py-2 rounded-md hover:bg-blue-600 transition-colors"
>
Check
</button>
{result && (
<p className={`mt-4 text-center font-semibold ${result.includes('is a palindrome') ? 'text-green-600' : 'text-red-600'}`}>
{result}
</p>
)}
</div>
);
};
export default PalindromeChecker;
Claude Artifacts機能を使ってブラウザ上で実行すると、正しく判定されました。
LLMの仕組みをざっくりと把握し、LLMが得意なこと・苦手なことを知っておくことで、より上手にLLMを使いこなすことができるようになるでしょう。
以下の無料の本も参考にしてください!
※本記事の検証はすべて Claude 3.5 Sonnet を利用しました。
この記事が気に入ったらサポートをしてみませんか?