自然言語には「無効な文」という概念がない。
コンテキストに入る情報を誰も検査していない
現在のLLMパイプラインで情報がコンテキストに入る仕組みを見てほしい。
RAGがチャンクを返す。 エージェントがAPIレスポンスを受け取る。 過去の会話が履歴に蓄積される。 ユーザーが文書をアップロードする。
これらがコンテキストウィンドウに入る。 検査なしに。
なぜ検査がないのか。 自然言語には「無効」という概念がないからである。
自然言語はあらゆる文字列を受け入れる
プログラミングには構文エラーというものがある。
def calculate(x, y
return x + y
括弧が閉じられていない。実行前に拒否される。 コードは実行される前に、読まれる前にすら、「これは有効なコードではない」と断定的に宣言できる。
自然言語にはそのようなものがない。
「彼は銀行に行った。」 文法的に完璧である。 誰が行ったのか、どの銀行か、なぜかはわからないが、 自然言語の文法規則に違反するものは何もない。
「2024年13月45日の売上報告。」 13月は存在しないし45日も存在しない。 しかし自然言語の文法規則に違反するものは何もない。 文法的に有効な文である。
「出典: 不明。確信度: 不明。日付: 不明。サムスン電子の時価総額は1,200兆ウォンである。」 出典は不明、確信度は不明、基準日は不明である。 しかし自然言語の文法規則に違反するものは何もない。
自然言語はすべてを受け入れる。 無効な自然言語文は構造的に存在しない。 したがって、自然言語で表現された情報を「拒否」する機械的な基準は存在しない。
機械的検証に必要な条件
Goコンパイラを見てほしい。
Goは未使用のimportがあるとコンパイルを拒否する。 コードが完璧に動作するとしても。 ロジックに何の問題もないとしても。 import行が一つ使われていないという理由だけで拒否する。
これが機械的検証である。
機械的検証には三つの特徴がある。
決定的である。 結果はイエスかノーである。確率ではない。「おそらく大丈夫」は存在しない。有効か無効かである。
安価である。 LLM呼び出しは不要である。文字列比較、フィールド存在確認、値の範囲チェック。ナノ秒単位のCPU操作である。
意味を読まない。 内容が真か偽かを判断しない。フォーマットが仕様に適合しているかだけをチェックする。「サムスン電子の時価総額は1,200兆ウォン」が真かどうかは知らない。しかし出典フィールドが空かどうかは知っている。
この三つが可能であるためには、一つの前提条件がある。 情報に仕様がなければならない。
仕様があれば、違反が定義される。 違反が定義されれば、拒否が可能になる。 拒否が可能であれば、検証が存在する。
自然言語には仕様がない。よって違反もない。 違反がなければ拒否もない。 拒否がなければ検証もない。
コンテキスト投入前の検証が必要な理由
コンテキストウィンドウは有限である。
128Kトークンであれ1Mトークンであれ、有限である。 有限な空間に入る情報の品質が出力の品質を決定する。
しかし現在のパイプラインでは、 品質判断は情報がコンテキストに入った後にのみ行われる。 LLMがそれを読み、判断し、「この情報は信頼しがたい」と自ら結論づけることを期待している。
これは三つの意味で間違っている。
高コストである。 フォーマットチェックにLLM推論コストを使っている。出典のないチャンクをフィルタリングするために数十億パラメータのモデルを実行している。単一フィールドの確認で済むタスクに確率的推論を使っている。
信頼性がない。 LLMが出典のない情報を常に無視する保証はない。実際、コンテキストに入ったものは使われやすい。コンテキストに入れたものを無視することをモデルに期待するのは矛盾である。
手遅れである。 ウィンドウ空間はすでに消費されている。出典のない5つのチャンクがそれぞれ200トークンを占めると、1,000トークンが無駄になる。フィルタリングされたとしても、その空間はすでに使われている。
機械的検証はこれらすべての前に来る。 コンテキストに入る前に。 LLMが読む前に。 ウィンドウが消費される前に。
何が検証されるのか
機械的検証は内容の真偽ではなく、フォーマット仕様への適合性をチェックする。
具体的には以下のものである。
構造的完全性。 必須フィールドが存在するか。エッジに主語と目的語があるか。欠落がないか。
識別子の有効性。 参照先のノードが存在するか。「サムスン電子」と記述されたものが実際に定義された個体を指しているか。参照がダングリングしていないか。
型適合性。 日付フィールドに日付が入っているか。数値フィールドに数値が入っているか。「2024年13月45日」はここで捕捉される。
メタデータの存在。 出典フィールドがあるか。時間フィールドがあるか。確信度が指定されているか。なければ拒否するか、不在を記録するか、デフォルト値を付与する。
参照整合性。 エッジが指すノードが実際に存在するか。削除されたノードを参照していないか。
これらのチェックには共通点がある。 いずれも内容を読まずに実行できる。 「サムスン電子の時価総額は1,200兆ウォン」が真かどうかは知らない。 しかしこの記述に出典が指定されているかどうかは知っている。 この記述に時間が記録されているかどうかは知っている。 この記述のフォーマットが仕様に適合しているかどうかは知っている。
安価なものが先に来る
コンテキストエンジニアリングパイプラインでは、検査には順序がある。
機械的検証: 仕様適合性。コストはほぼゼロ。決定的。 意味的フィルタリング: 関連性・信頼性・有用性の判断。高コスト。確率的。 整合性チェック: 選択された情報間の矛盾。さらに高コスト。推論が必要。
安価なものから高価なものへ並べると、 高価なチェックが処理すべき量が減る。
機械的検証で出典のない記述を30%除外すれば、 意味的フィルタリングは70%だけを処理すればよい。 意味的フィルタリングで無関係なものを除去すれば、 整合性チェックはさらに少ない集合を処理する。
これはデータベースのクエリ最適化と同じ原理である。 WHERE句ではインデックスでフィルタ可能な条件を先に適用する。 フルスキャン条件は後に来る。 安価なものが先に来れば、高価なものの負担が減る。
逆に、 高価なチェックを先に実行し安価なチェックを後にすると、 コストをかけた後にフォーマットエラーが発見される。 存在しないノードを参照する記述の意味を分析し、 その後で参照が無効だったと気づく。
この順序は自然言語パイプラインでは不可能である
自然言語には仕様がないため、機械的検証は不可能である。 機械的検証が不可能であるため、最も安価なチェックが存在しない。
結果として、すべてのチェックが意味的チェックとなる。 すべてのチェックにLLMが必要となる。 すべてのチェックが高コストとなる。
「このチャンクに出典はあるか?」 – LLMが読まなければならない。 「このチャンクの時間的参照は適切か?」 – LLMが読まなければならない。 「このチャンクのフォーマットは正しいか?」 – 自然言語にはフォーマットがないため、問い自体が成立しない。
これが現在のコンテキストエンジニアリングの現実である。 最も単純なチェックすら、最も高価なツールで実行されている。 文字列比較で済むタスクが推論エンジンで処理されている。
検証の前提条件
機械的検証が存在するためには、三つのものが必要である。
仕様。 情報が従うべきフォーマットが定義されていなければならない。どのフィールドが必須か、どの値が許容されるか、どの参照が有効か。仕様がなければ違反を定義できない。
形式化。 情報が仕様の要求するフォーマットで表現されていなければならない。自然言語の文としてではなく、仕様が要求する構造でエンコードされていなければならない。形式化されていない情報は検査できない。
拒否する力。 適合しない情報を実際に拒否できなければならない。検査しても常に通過するのであれば、それは検証ではない。無効な情報がコンテキストに入ることを防がなければならない。
この三つはプログラミング言語では当然のことである。 文法という仕様があり、コードというフォーマットがあり、コンパイラという拒否する力がある。
自然言語では三つすべてが欠如している。 文法はフォーマット仕様ではなく慣習である。 文は構造化フォーマットではなく自由テキストである。 「無効な自然言語」という概念が存在しないため、拒否するものがない。
コンテキストエンジニアリングに機械的検証を導入するには、 情報の表現そのものを変えなければならない。
まとめ
現在のコンテキストパイプラインでは、情報は検査なしにコンテキストに入る。 自然言語には「無効な文」という概念がないからである。
機械的検証は内容の真偽ではなく、フォーマット仕様への適合性をチェックする。 構造的完全性、識別子の有効性、型適合性、メタデータの存在、参照整合性。 決定的で、安価で、意味を読まない。
パイプラインでは安価なチェックが先に来なければならない。 機械的検証がフォーマットエラーを除外すれば、 高コストな意味的判断が処理すべき量は減る。
自然言語には仕様がないため、このチェックは不可能である。 すべてのチェックが意味的チェックとなり、すべてのチェックが高コストとなる。
機械的検証が可能であるためには、 仕様と形式化と拒否する力がなければならない。 情報の表現そのものを変えなければならない。