一、最初に問題を定義しておく:文書理解は OCR ではない
チームが要望を受けるときに最も多く聞かれる言葉は「これらの PDF を読み解きたい」だ。この言葉はそのままでは実装に落とし込めません。失敗モードがまったく異なる四つのサブタスクを一つの成果物としてまとめてしまうからです。そしてこの四つは、コスト構造・代替手段・障害が起きたときの切り分け経路のどれについても、ほとんど重なりません。あなたが本当に納品すべきものは「この画像には何が書いてあるか」ではなく、「この文書にはどんな構造化された事実があり、それぞれの事実の出典座標はどこで、信頼度はどれだけで,どの領域を読み取れていなかったのか」である。この四つの問いこそがシステム契約になります。
1.1 よく混同される四つのサブタスク
一つ目は文字認識で、ピクセルを文字列へ変換する処理です。これは閉じた問題であり、教師つきデータがあり、指標が明示的で、最適化の余地はほぼ搾り尽くされています。二つ目は版面理解(layout understanding)で、「どの文字が同じ論理ブロックに属するか、ブロック間の幾何関係と包含関係は何か、ページの読み順(reading order)は何か」に答えます。これは構造の問題で、もっとも破滅的な間違いを起こしやすい部分です。認識率が 98% に達していても、誤った二文字が金額や番号のフィールドへ落ちていれば、そのレコード全体が誤ります。
三つ目は要素セマンティクスの判定で、幾何的なブロックを業務概念へ翻訳する処理です。これは見出しか本文か、表か、それとも表と誤検出された枠付きの段落か、キャプションか脚注か、ページヘッダか文書タイトルか。四つ目は要素をまたぐ構造推論で、例えば表の見出しが前のページにありデータ行が次のページにある、あるいは本文のなかに、参照を先に解決しなければ意味が分からない数式番号が挿入されているような場合です。この四つのうち「中核能力」として投資されてきたのは長らく一つ目だけで、後ろの三つは「前処理」か「後処理」として扱われてきました。これが文書パイプラインにおける事故のおもな発生源です。
1.2 版面理解には具体的に何が含まれるのか
版面理解を分解すると、少なくとも四つを別々に正しくする必要があります。一つ目は領域ロケーションで、ページ上にどんなブロックがあり、各ブロックの矩形範囲はどうな。二つ目は型の判定で、各ブロックが見出し・本文・リスト・表・図・キャプション・ヘッダ・フッタ・数式・参考文献のどれに属するか。三つ目は構造関係で、ブロック間の親子関係(ある表セルがある表に属する)、順序関係(読み順)、隣接関係と包含関係です。四つ目はページ跨ぎと段跨ぎの継続関係で、このページの下端と次のページの上端が同じ表なのか、同じ段落の段替えの続きなのかを判定することです。
この四つのうち比較的成熟な既存手法があるのは一つ目だけで、残り三つは「一見簡単だが、実際には間違っても上位レイヤーはまったく気付かない」部分です。本文ブロックとキャプションブロックの順序を逆に繫いでしまったパイプラインは、出力テキストが依然として滑らかに読めていて、アラートはひとつも出ません。しかし下位の検索は継続して、キャプション内の図番号を本文中のエンティティとして召喚してしまいます。この種のエラーは版面レベルの指標でなければ検出できません。
| サブタスク | 典型的な入力 | 失敗時の外的な症状 | 単一段階の失敗は可視か |
|---|---|---|---|
| 文字認識 | 切り出したテキスト行の画像 | 誤字、桁ずれ、数式の通常文字への退化 | 指標があり、発見しやすい |
| 版面構造 | ページ全体のビットマップまたはベクタ図元 | 読み順の乱れ、表の分断、ページ跨ぎの断裂 | しばしば見えない |
| 要素セマンティクス | 版面ブロックとその幾何属性 | キャプションの本文化、ヘッダの混入、表の段落化 | 見えない |
| 構造推論 | 上記の全結果に文書メタデータを加えたもの | 見出しの喪失、セルのずれ、指称解決の失敗 | 見えない |
この表の後半二列こそ強調したい点です。上流の工程ほどエラーが出たときに自動指標で捕捉しやすく、下流の工程ほど出力テキストが「それには正しい」ので、エンドツーエンドの業務指標か、人手による抜き取り検査でしか検出できません。エンジニアリングへの投資配分は技術的新しさではなく、この逆順に従って割り当てるべきです。
1.3 読み順を後処理として扱ってはいけない理由
多くの実装では、版面検出が先にすべてのブロックを取り出し、そのブロックを左上の座標でソートし、y 優先、x 優先順位で並べて、それを読み順として扱っています。この方法は単一段組みで、行が一つで、ブロック間に明確な余白があるページならなんとか通用しますが、次のような実際の版式では直接崩壊します。二段組みの論文では左右の段が y 座標上で大量に交差するので、座標順に並べると左右の段が行ごとに混ざってしまいます。サイドバーつきの雑誌版式では、サイドバーの文字の y 位置がちょうど本文の二段落の間に落ちます。表の中ではセル内テキストの座標関係は段落とはまったく異なるので、混ぜて並べると表の内容が本文のなかに差し込まれます。
正しいやり方は、読み順をソート問題ではなく明示的な構造問題としてモデル化することです。まず領域グループ化を行い、どのブロックが同じ段、同じ表、同じ図に属するかを定め、次に各領域の内部で順序を決め、最後に領域自身の版面セマンティクスに従って領域を並べます。この順序は逆転できません。「どのブロックが同じ領域に属するか」自体を判定するには、幾何とセマンティクスを組み合わせた判断が必要になるからです。ここでもう少し現実的な折衷案実際には、エンドツーエンドモデルに直接「読み順に並んだ Markdown か JSON」を出力させ、順序問題をモデルに委譲することです。ただしその安定性が明示的な幾何パイプラインより劣ることを受け入れる必要がありますし、呼び出しコストも高くなります。
二、版面理解でそれぞれを正しくすべき四つのこと
2.1 領域ロケーション:先にノイズを門の外へ弾く
領域ロケーションの工程で実際に難しいのは、検出精度ではなくノイズの除去です。綴じ目による影、紙の折り目、ファクスの粒子ノイズ、ページ端の手書き、合い押しの印鑑。これらはすべて低信頼度の偽ブロックを生みます。この偽ブロックを素通りさせてしまうと、このあとのどの工程もそれらの分の代償を払うことになります。認識エンジンは意味のない複数行のテキストを走らせる羽目になり、版面型の分類器は誤ったラベルを返し、意味抽出の工程はそれをフッタとして捨てます。あるいは本文の一部として結果へ連結してしまうかもしれません。
実務的には、安いルールを先にいくつか通しておくと得です。まず面積とアスペクト比で、極端に小さい破片を落とすこと。次に信頼度のしきい値に下限を設けること。見落としより誤検出を避けるべきです。見落としは下流で「この文字は存在しない」という現れ方をして、誰にでも気づかれやすいからです。誤検出は「余計な内容が増えた」という現れ方になり、誰にも気づかれません。色分散と局所コントラストを一度だけ素早く判定し、明らかに画像領域に属するブロックは「図」とラベル付けして後段へ渡さないこと。この段で問うべき基準は精度ではなく、「フィルタ後の偽陽性率が無視できる水準まで下がったか」です。
2.2 型の判定:曖昧さは版面そのものの表現の習性から生まれる
型の判定は十数種類の分類問題に見えるけれど、実際の難物は、同じ視覚形態が複数の意味を兼ねていることにあります。中央寄せの一行、太字、やや大きめの文字は、文書タイトルでもあればセクション見出しでもあれば、あるいは装飾的な罫線に添えられた文字かもしれません。枠付きの矩形領域は表かもしれないし、コード枠かもしれないし、画像の差し込み枠かもしれないし、たった一行しかない注意書きの枠かもしれない。図の下の小さな文字は、キャプションかもしれないし、本文中の文がたまたま小さく組まれているだけかもしれない。
実際に精度を上げるのは、より大きな分類モデルへ交換することではありません。版面以外の証拠を導入することです。文書レベルのメタ情報、すなわち章立て、ブックマーク、目次ツリー、ページ番号の位置は、ブロック型に強力な事前確率を与えます。目次ページで中央に配置された大きな文字は、節名の公算が大きい。すべてのページの同じ縦位置に現れ、内容がページ間で強く反復するブロックは、ほぼ確実にヘッダかフッタです。ページ下端に現れ、「図 X」「表 X」といった接頭辞パターンを持つ短いテキストは、キャプションの可能性が高い。
これらの事前確率をルール層へ明示的に書き込むのは、モデルにピクセルから推測させるよりずっと安定します。コストはほぼゼロです。
2.3 構造関係:ブロックを木やグラフに変える
ブロックの集合そのものには意味がないので、必ず構造を作る必要があります。多くの実装は版面を二種類の関係のどちらかでモデル化します。階層木か、ラベル付きの関係グラフです。階層木の利点は、読み順が自然に確定することです。前順走査すればよいだけです。「この図の下にキャプションがある」「この表はこの章に属する」といった関係を自然に表現できます。欠点は、二次元の構造を必要とする表のような要素を木に収めるのが難しいことです。たいていは「表セルのリスト」のような平坦な構造に退化し、行と列の情報を失ってしまいます。関係グラフはより柔軟で、「同じ表に属する」「直前のブロックのキャプションである」「左隣のブロックと並んで二段組である」といった種類の辺を同時に表現できます。ただし走査順序を自分で定義する必要があり、複雑さは明確に増します。
実務的な折衷案として、文書を「二層の混合構造」としてモデル化する方法があります。トップレベルは領域からなる木で、章、段落のまとまり、二段組領域、表、図が並び、各領域の内部にはそれぞれの局所構造がぶら下がります。表の内部は二次元グリッドで、段落の内部は行の列です。こうすると読み順はトップレベルの木が決めますが、表の行と列の情報は局所構造の中に保たれるため、全体的なソートによって壊れません。この混合構造は、後の表復元と検索용チャンク化の二つの工程でそのまま再利用できます。投資対効果の極めて高い設計箇所です。
2.4 ページ跨ぎと段跨ぎの継続:もっとも抜け落ちやすい一環
ページ跨ぎの継続には二つの識別シグナルがあり、実務では両方を使うことを勧めたい。まず幾何シグナルです。次のページの上端に、このページ下端の表と列数、列幅、罫線の様式が酷似した領域があり、かつこのページ下端の表が明らかに収束していない場合です。最後の行が一部のセルにだけ値が入っているとか、下側の罫線が欠けているといった状態です。二つめは内容シグナルです。二ページの表見出しのテキストが同一か酷似していて、しかも前一ページには見出しが現れていない場合です。この二つのシグナルが同時に当てはまれば継続処理を行い、片方だけを見充斥させるよりずっと可靠になります。
継続処理のあとで解決すべき問題が二つあります。一つは列幅が完全には揃っていない場合です。スキャンのずれによって、同じ列でも二ページで幅がわずかに違います。無理にピクセル単位で揃えると内容をずらしてしまいます。見出しのテキストと列の順序で論理的に揃えるほうが、たいていは安定します。もう一つは、表の途中にヘッダとフッタが挿入されている場合です。一部の組版では継続時に見出しを一度だけ繰り返すので、統合する前に明示的に重複を除去する必要があります。段跨ぎの継続は比較的単純ですが、なお忘れられがちです。二段組みの一段落が段末で切れ、次の段の頭で続いている場合、ページを処理の単位とすると両段は別々のテキストとして分割されます。結果として文が途中で切れ、側は検索側で低品質な二つのチャンクに切られてしまいます。
三、従来パイプラインとエンドツーエンド方式の境界はどこにあるか
3.1 従来の四段構成パイプライン
従来の方式は文書処理をいくつかの連鎖工程に分解します。まずページ前処理で、回転補正、影の除去、二値化を行います。次に版面検出と分類を行い、続いて各テキストブロックに対して光学文字認識(Optical Character Recognition、OCR)を呼び、次に表の構造を復元し、最後に意味抽出とフィールドの充填を行います。この方式の利点は、各段が交換可能、キャッシュ可能、段階的に切り替え可能であることです。認識モデルを交換しても版面検出は影響を受けず、版面ルールを変更しても高価な認識をやり直す必要はありません。各段を独立に評価して問題を特定できますし、単一ページの処理コストも低く、スループットを非常に高くできます。
欠点もはっきりしています。連鎖による誤差の増幅です。版面検出がブロックを一つ取りこぼすと、そのブロックの文字は結果に一切入らないまま、エラーも出ません。表の構造復元が行を一つ間違えれば、下流のフィールド抽出はその行の数値を誤った列名に紐づけてしまい、しかもフィールド抽出そのものはまったく正常に見えます。
3.2 エンドツーエンド方式:マルチモーダルモデルで直接図を読む
エンドツーエンド方式の形はこうです。ページ全体を画像にレンダリングして、視覚言語モデルに直接渡し、そのページのテキスト内容、構造ラベル、しばしば表の HTML 表現を出力させます。このルートで近年もっとも大きくなった変化は、視覚文書モデル(vision document model)の能力向上から来ています。表の復元、読み順、キャプションと図の関連付けといった課題での性能が、「デモは出色、実運用では使えない」から「たいていの標準的な場面では使える、複雑な場面では依然としてfallbackが要る」へと変わりました。何までできるかはモデル版、分像度予算、プロンプト戦略によって変わるので、ひとつの結論でまとめるべきではありません。
エンドツーエンドの構造的な利点は、幾何情報と意味情報を同時に扱えることです。従来のパイプラインは後続の動作を決めるためにまず版面分類を行う必要がありますが、十分に強い視覚モデルなら全体の文脈から「この小さな文字はキャプションだろう」と推測できます。その幾何的な外形が本文とまったく同じであってもです。ルールセットを保守する必要もありません。見たことのない版式でも挙動がより滑らかです。代償は三点あります。単一ページのコストは従来パイプラインより明らかに高く、誤りは多くの場合説明できません。モデルが二行の表を段落として読んだとき、中間状態は手に入りません。安定性も幾何パイプラインに劣ります。同じ入力でも、モデルのバージョン更新やプロンプト変更のあとで質の異なる出力が得られることがあり、再現可能な監査が求められる場面では致命的な問題です。
3.3 二つのルートの失敗モードの対比
失敗モードを並べて看作ると、ルート選択の論理がはっきりします。従来パイプラインの典型的な失敗は「欠落」と「ずれ込み」です。ある段落が丸ごと失われる、ある行のデータが誤った列に紐づく。特点是誤りが安定して再現可能であり、出ればルールを足せば直せるということです。エンドツーエンドの典型的な失敗は「誤りを自信満々に丸めること」です。存在しない構造を補完する、ぼやけた文字を文脈上もっともらしい語へ置き換える、无関係な二つの表をまとめて叙述する。特点是誤りが不安定であり、出力への制約と複数回サンプリングでしか緩和できないということです。
| 観点 | 従来の四段構成パイプライン | エンドツーエンドでの図の読み取り |
|---|---|---|
| 単一ページのコスト | 低い。自前配備が可能で、スループットが高い | 高い。モデルサービスに依存し、レート制限を受ける |
| 誤りの説明可能性 | 高い。中間状態が見え、特定の工程まで特定できる | 低い。最終的な出力しかなく、特定が難しい |
| 版式への汎化 | 弱い。新hdrな版式にはルールか学習データを追加する必要がある | 強い。挙動が文脈で変化し、より滑らかだ |
| 出力の安定性 | 高い。決定的な入力からは決定的な結果になる | バージョン、プロンプト、サンプルパラメータの影響を受ける |
| 表の二次元構造 | 専用の構造復元アルゴリズムが必要で、複雑な表は誤りやすい | 表の表現を直接出力できるが、同時に取り違えることもある |
| 長文書の全体像 | ページ単位が自然で、差分的処理が可能 | 単一ページまたは単一画像の文脈制約を受けることが多い |
一点だけ単独で触れておきたいことがあります。エンドツーエンドのモデルは、「超長文書の全体的な一貫性」には本質的に得意ではありません。得意なのは一ページの中の理解です。ページをまたぐ表見出しの継承、章番号の連続性、指称の解消は、やはり明示的な文書レベルの構造層が受け止める必要があります。単一ページの理解力と文書レベルの組み立て力を同一視するのは、エンドツーエンド方式を本番へ落地するときにもっともよくある誤りです。
3.4 本番環境で実際に多いのは混合形態である
本当に安定して本番を動きつづけるシステムは、純粋に一方のルートで動くことはまれです。「誰が配置を担当し、誰が理解を担当するか」の境界を明示的に決めているものです。よく使われる分け方として、幾何系の処理は決定論的な画像処理へ渡します。影の除去、回転補正、ヘッダとフッタの除去、段の検出、ページをまたぐ表のペアリングなどです。これらの作業はルールが明確で、キャッシュ可能で、誤りを直せるからです。意味系の処理はマルチモーダルモデルへ渡します。要素型の判定、表の意味的復元、フィールド抽出、質問への回答などです。これらの作業はルールを網羅しにくく、文脈依存が強いからです。
中間の認識工程は領域ごとに選択的に呼び出して構いません。テキストブロックは OCR を通し、表の領域と図の領域はモデルを直接、元の画像へ向けます。「まず OCR をして、その結果をモデルに理解させる」ような二段分の損失の重なりを避けるためです。もう一つの分け方は二重チャネルによる並行処理です。従来パイプラインが一つの基準となる構造化結果を作り、エンドツーエンドのモデルが別の結果を作り、軽い調停層がどちらを採るかを決定します。調停は信頼度に基づいてもよいし、一貫性に基づいてもよいです。二つのチャネルが同じフィールドについて異なる抽出結果を出したら、フィールドを低信頼として人手レビューキューへ送るのではなく、強制的にどちらか一方へ決めつけることです。
このやり方はエンドツーエンドの汎化力と従来パイプラインの説明可能性を組み合わせます。代償は調停ロジックを保守することと、一定比率の人手レビューを許容することです。コンプライアンス要件が高く、一行の間違いのコストが巨大な場面には投資する価値があります。批量で価値が小さい場面なら、エンドツーエンドのチャネル一つと抽出検査で十分です。
四、表:文書パイプラインでもっとも難しい一環
4.1 第一層の難点:セル境界は幾何の問題であり、認識の問題ではない
表を復元する第一歩はグリッドを確定することです。古典的なやり方は、表領域の画像から横の線と縦の線を検出し、行境界と列境界へ投影したうえで、隣接する境界が通り抜けているかどうかからセルの範囲を推定することです。この方法は印刷がきちんと整っていて線が明快な電子的に出力された表ではとてもうまく働きますが、実際の文書には二つの典型的な破綻点があります。
一つは半罫線の表です。たくさんのレポートは外枠と横線だけを引き、縦線を引かないため、列境界には視覚的な根拠がまったくありません。内容の水平方向の配置から推測するしかありません。ある列の内容長の分布が大きく偏ると、列境界全体がずれます。二つめは罫線のない表です。空白の隙間だけで分けた表で、この場合は行境界すら間隔のクラスタリングに頼る必要があります。行の高さが揃っていない場合や行をまたぐ内容がある場合、クラスタリングはそのまま破綻します。
この二種類の退化した構造に対しては、「幾何を優先し、内容で下支えする」という堅実な補強戦略があります。まず線から高信頼度の行と列のアンカーを与え、次にセル内テキストの中心点の分布と空白の隙間から、アンカーのない境界を補います。最後に、文書テンプレートの水準で行数と列数の一貫性を検査します。同じテンプレートのレポートなら、ページが違っても行数と列数は一致するか、固定されたグループ関係を持ちます。あるページから推定した列数が文書全体の最頻値と食い違うなら、再計算か縮退を起動すべきです。
4.2 第二層の難点:結合セルと入れ子の表見出し
結合セル(merged cell)の扱いを誤ると、列名がずれる直接の原因になります。よくある形は二種類です。横方向の結合で、第一行に三列にまたがる「売上高」の見出しがあり、第二行で三つの具体的な科目に分かれるもの。縦方向の結合で、第一列の「2024」が二行にまたがり、後ろ二列が売上高と原価になっているものです。これらを通常のセルとして扱うと、表は穴の開いた二次元配列に退化し、列名が失われます。意味抽出の段階で、モデルもルールも「2024 年の売上高」という値にどのラベルを付ければよいか分からなくなります。
正しいモデリングは結合関係そのものを残すことです。グリッドを既定の矩形へ,平坦化してしまうのではなく、まず「結合スパン」の情報を含む中間構造を出力し、各セルが自分の行の開始と終了、列の開始と終了、そしてテキストを持つようにします。そのうえでこの構造から業務向けのビューを派生させます。たとえば行ごとに展開して「年 + 科目 + 数値」のレコード一覧にするのです。こうすれば表見出し是多層の入れ子であっても、展開されたレコードは上位への経路を完全に持ち続けます。入れ子の表見出しについては、さらに二つの特殊構造を個別に認識する必要があります。一つは表見出し自身が論理ページをまたいでいる場合です。前ページが「四半期別データ」の総見出しで、このページには四半期の列しかない、という状態です。二つは表見出しの中に次元列と指標列が同時に存在する場合です。指標列には通常下部に合計行がありますが、次元列にはありません。この二つの情報は、あとからスライスする時に、どの列を次元へ、どの列を指標へ変換すべきかを決めます。
4.3 表の画素から構造化データまでの三つの道筋
グリッド、テキスト、結合関係を合成して最終的な構造を作る方法はおおむね三通りあり、それぞれに明快な適用境界があります。一つ目は純粋に幾何とルールだけです。検出されたグリッドの上で各セルを走査し、テキストブロックを包含関係に従ってセルの中へ入れ、結合セルは「縦線が貫いていない」または「横線が貫いている」という規則で認識します。この道筋は速く、堅実で、再現性があります。しかしセル内の改行、セル内に埋め込まれた子表、罫線のない表では明显に苦戦します。二つ目は幾何と物体検出の組み合わせです。まず各テキスト行の矩形を検出し、「どのグリッドの交点に属するか」という帰属規則で表を埋めます。 동시에結合スパンを認識するモデルを別途訓練します。この道筋は複雑な表ではより正確ですが、あなたの表のスタイルに合わせた注釈を用意する必要があり、テンプレートをまたぐ移行能力は限られます。三つ目を直接マルチモーダルモデルへ渡して、表の HTML 表現を出力させて解析させることです。この道筋は罫線のない表や入れ子の表見出しについてはとても楽ですが、幾何の精度の問題をモデル生成の問題へ移し替えています。モデルが出力したセル数が視覚上の行数と食い違うと、誤りは極めて隠蔽的な形で下流へ入り込みます。
実務では「幾何が境界を与え、モデル意味を補う」組み合わせを好みます。幾何パイプラインに結合情報の付いたグリッドを作らせ、そのグリッドと切り出したセル画像を一緒にモデルへ渡します。モデルにさせるのは一つのことだけです。各セルに意味ラベル(科目名、期間、金額、単位、合計かどうか)と単位の正規化を付けさせることです。こうすればモデルは幾何を推測し直す必要がなく、幻覚の余地はラベルの水準まで圧縮されます。そしてラベルの水準こそモデルが最も得意なところです。以下は簡略化した実装の骨格です。
class TableStructurer:
#输入是页面位图与版面树中的表格区域节点
def restore(self, page_image, region):
grid = self.grid_detector.infer(page_image, region.box)
#线条缺失时用空白间隙补边界,并对不上文档级列数时重算
grid = self.gap_fallback.fill(grid, page_image, region.box)
grid = self.template_check.reconcile(grid, region.doc_profile)
cells = self.text_filler.assign(page_image, grid)
#合并跨度在这里被保留,不压平
spans = self.span_detector.detect(page_image, grid, cells)
return Grid(cells=cells, spans=spans, doc_profile=region.doc_profile)
def semanticize(self, grid, page_image):
#只让模型填标签与单位,几何结果不交给模型重推
crops = grid.crop_each(page_image)
raw = self.vlm.label_batch(crops, prompt=self.LABEL_PROMPT)
labels = self.schema_validator.repair(raw, allowed=self.dimension_hint)
return grid.to_records(labels)
見落とされがちで、しかし重要な詳細が二つあります。一つは単位の正規化です。表見出しが「万円」で、値が「1234.5」だとします。この工程で正規化しなかった場合、後のすべての表どうしの比較が間違ります。しかもこの誤りは、一つの表のなかではまったく見えません。二つめは合計行の扱いです。合計行は通常、明細レコードからは除くべきです。しかし同時に、最も価値の高い検証の基点でもあります。明細の合計が合計行と合わなければ、一部のセルが誤読されたか、抜け落ちたということです。この検証は人の目ではなく、強制的な出力品質のゲートとしてパイプラインに書き込むべきです。
五、図表:まず読むべきかどうか判断する
5.1 二つの道筋:データへ変換するか、質問へ答えるか
図表の処理には、性格がまったく異なる二つの道筋があります。一つは chart-to-table で、折れ線、棒、円グラフの中の数値をデータ表として抜き出すことが目標です。この道筋の価値は、成果物が構造化された数値になることにあります。計算、集約、比較が可能になり、検索システムに入れば正確にヒットします。この道筋は技術的には非常に難しいのです。軸の目盛と単位の換算、積み上げ棒の高さの内訳、複数系列の色と凡例の対応、誤差棒と信頼区間の扱い、軸の切り詰めによる比率の歪み。どれも一つずつ専用の処理が必要で、どれ一つでも間違うとその列の数値が丸ごと間違ります。
二つめは図表質問への回答(chart question answering)です。図表と自然言語の質問をそのままマルチモーダルモデルへ渡して、「どの年が売上高が一番高いか」「この傾向はなにを示しているか」に答えさせます。この道筋は、傾向、比較、極値といった判断系の問題にはよく合います。モデル自体が視覚推論を行っているので、値を明示的に復元する必要がないからです。逆に不向きなのは、正確な数値が必要な場面です。「すべての点の値を並べて合計して」のような要求では、モデルが出した数字は視覚的に自己検証できず、誤差は数パーセントに達することがあり、それを知る手段がありません。
5.2 決定できるルーティングのシグナル
実務では、どの図表をどちらの道筋へ送るかを目で決めないでください。自動的に取り出せるルーティングのシグナルの一式を組み立てます。もっとも強いシグナルは図表の種類です。棒グラフと折れ線グラフは数値の読み取りに比較的親切です。円グラフとドーナツグラフは比率を見積もれますが、正確な値は困難です。散布図と箱ひげ図は本質的に正確なデータ化に適しません。多系列の積み上げグラフがもっとも難しい。つぎのシグナルは軸の情報です。軸に明示的な目盛ラベルがありゼロから始まっていれば、数値換算の信頼性は高い。軸が切り詰められている、目盛ラベルがない、あるいは軸ラベルが相対的な指標(成長率、構成比)なら、データ化のリスクは显著に上がります。
三番目のシグナルは下流での用途です。このシグナルは、前の二つより重要なことがしばしばあります。下流が人間が概要を読むためだけに使うだけなら、あるいは検索の召喚時に文脈を補うためだけに使うなら、質問へ答える道筋を取り、自然言語の説明だけで十分です。下流が数値計算、グラフ間の突合、データウェアハウスへの投入を行うなら、データ化の道筋を通る必要があります。そして単一画像あたりの高いコストと、一定比率の転記失敗を許容しなければなりません。
5.3 キャプションと本文の関係は失わない
図表以外の要素も、正しい帰属が必要です。キャプションは通常、番号付きの短い文で、図表の種類、対象期間、集計の基準、単位、出所を含みます。これらはデータが使えるための前提です。基準が違う時系列は、そのままつなげられません。出所が欠けた数値は、コンプライアンスが求められる場面では使えません。キャプションは通常の本文として段落へ連結するのではなく、対応する図表と結び付けて一つの検索単位にします。「図表の領域 + キャプションのテキスト」を、まとめて索引と召喚の対象にするのです。この点は RAG の場面で特に価値が高い。。ユーザーが「2024年の地域別の売上構成比」と尋ねたとき、召喚されるのは「図3 地域別売上構成比(2024年、税込、単位:万円)」というキャプションを持つ図のブロックであるべきで、本文にたまたま「構成比」と書かれた一文ではないはずです。
キャプションの帰属には、誤りの出やすい境界条件もあります。同じページに複数の図表があるとき、キャプションが図の下ではなく上に来ることがあります。二つの図を横に並べた場合、キャプションは片方だけに接していることがあります。帰属を判定するなら、「近接 + 版面の方向 + 番号パターン」の三つを組み合わせて使うほうが、単なる距離よりも信頼できます。そして番号が欠けている場合、つまりキャプションに「図 X」のような番号がない場合は、テキスト内容がおもな手がかりになります。この段階では対応を取り違えやすく、抽出して人手で照合する場面になります。
六、走査画像とスマートフォンでの撮影:パイプラインはどの工程で先に壊れるか
6.1 劣化は連続ではなく段階的である
実際の入力を扱うにあたって最も大切な認識は一つです。画像品質の劣化は連続的なスペクトルではなく、いくつかの意味の「段差」として現れます。あるスキャンは全体がきれいでも、ページ全体が五度傾いているかもしれません。あるいは解像度が高いのに、綴じ目による影がページ全体を貫いているかもしれません。劣化の種類ごとにパイプラインの別の工程が打たれ、重さが少しずつ増して、ついにある工程が完全に機能しなくなります。すべての劣化をひとつの「総合品質スコア」として扱う、あるいは単一の前処理パイプラインですべてを運用することは、結果が不安定になる主因です。
6.2 劣化の種類と、それぞれの壊れ方
傾きと透視変形は、まず版面検出を壊します。文字行が水平でなくなると、水平射影に基づく空白間隔の検出が機能せず、行の境界が誤って切られます。同時に傾きは隣接する行の字形を互いに近づけるため、認識工程での行内の切り分けもミスをします。。回転補正は認識の前に行うべきで、「ページ全体の回転」と「局所的な透視」を区別する必要があります。前者は全体の角度推定だけで十分ですが、後者はスマートフォンで撮影した契約書や証票ではよく見られ、透視変換が必要です。そして変換後の余白の切り抜きは保守的でなければならず、そうでなければページ端の内容が切れてしまいます。
影と光の不均一さは、認識のしきい値を壊します。二値化に全体的なしきい値を使うと、影の部分の線が潰れてしまい、区域ごと真っ白になることもあります。よく使われる対策は、二値化の前に背景を見積もって正規化するか、影の領域には適応的なしきい値を使うことです。より実用的なのは次の方法です。パイプラインが形態学的解析と線検出を必要としないなら(どちらも表の構造の依存です)、二値化を省いて、元の画像をそのまま認識エンジンへ渡せます。現代の認識エンジンはふつう内部で十分な正規化をしているので、手作業の二値化が逆に害になることもあるからです。これは見落とされがちな、単純化できるポイントです。
低解像度は、小さい文字と表を壊します。あるしきい値を切ると、認識誤り率は緩やかに増えるのではなく、急に崩壊します。密に組まれた小さい文字の表、フッタの注記、複数桁の番号が特にひどいです。このときの正しい做法は、無理に最後まで通すことではありません。まず一度だけ解像度と文字サイズの推定を行います。そして予測が信頼できない領域は、あらかじめ「要人手」としてマークします。粗悪な結果を有効なデータとして下流へ入れないようにするためです。明示的に失敗するほうが、静かに誤った数値を出し続けるよりはよいのです。
手書きは、認識モデルそのものを壊します。活字で訓練されたほとんどの認識エンジンは手書きで大きく劣化します。特につなぎ書き、乱筆、混植(印刷された本文の中に手書きの書き込みが混ざっている場合)がひどいです。手書き混植の認識精度は実装によってちがいます。手書き専用のモデルの使いやすさや費用も実装によって大きくちがいます。だから現実的なのは、版面の工程で手書きの領域を識別して別ルートに回すことです。同じエンジンが両方を賄えると期待しないでください。
多言語の混植は、言語の判定と分割の前提を壊します。認識エンジンの内部は通常、「一つのブロックのテキストは同じ言語である」という前提を暗黙に抱えています。中国語の段落に英語の専門用語が混ざっている場合や、ページ全体で中日英韓が混在する場合、形の似た文字がお互いに混入しがちです。全角と半角、大文字と小文字の近いラテン文字がその例です。この種の誤りは意味のうえでなお通じてしまうため、下流ではほとんど見えません。対策は、ブロック単位で言語を判定し、言語が混在しているブロックは複数言語対応のエンジンでもう一度処理することです。そして出力には言語タグを残してください。
6.3 劣化の階段:失敗を観測できる状態に変える
どの種類の劣化にも、対応する縮退の経路を一つ用意すべきです。「品質が足りなければ捨てる」という一本の経路を共有するのではありません。使える縮退の階段は,通常次のように設計します。まず完全な幾何パイプラインに認識と構造復元を組み合わせる経路を選びます。幾何の結果の信頼度が足りない場合は、マルチモーダルモデルにページ構造を直接出力させる経路へ退きます。モデルの出力が検証に失敗した場合は、純テキストの認識と順序つなぎの経路へ退き、「読み順は信頼できない」と明示します。認識の信頼度が低すぎる場合は、もう縮退しません。空の結果と問題領域の座標を出して、人手キューへ送ります。この階段の中核は「いつでも結果が出る」ことではなく、「いつでも説明可能な結果が出る」ことです。どの段階で縮退したか、どの領域を縮退したか、なぜ縮退したのか。この痕跡を出力に残してください。
このメタデータは後できわめて役に立ちます。「検索が誤った文章を召喚した」といった問題を、具体的なページと具体的な縮退の判断までさかのぼって追跡できるようにするからです。手掛かりのない不可解な問題にはならずに済みます。縮退マークのないパイプラインは、問題が起きたときに全体をやり直すしかありません。全体をやり直すのは高くつくので、対策しないと、誰もやり直さないまま終わってしまいます。
6.4 実用的な事前品質ゲート
本題の処理に入る前に、安い検査を一度だけ入れておくと、得られるものは通常大きくなります。まずページサイズが妥当な範囲にあるかを確認します。余りに小さければサムネイルでしょうし、余りに大きければ高解像度のスキャンを貼った可能性があります。次に、テキスト行の推定密度が異常でないかを見ます。低すぎれば白紙のページか図だけのページでしょう。高すぎれば、写真モードを選んでモアレが出た可能性があります。それに加えて、大面積の真っ黒か真っ白な領域がないか、ページに明らかな十度以上の傾きがないかも確認します。これらはどれもモデルを使わなくても、単純な画像の統計だけで済みます。かかる時間は無視できます。これらをバッチ処理の事前フィルタにしておけば、相当な割合の無効なタスクを弾けます。省ける計算量は、これらの検査自体の費用の何千倍もの量になることがあります。
七、出力の形:構造化された出力は長いテキストより価値がある
7.1 長い文字列だけを出力してはいけない理由
多くの文書理解パイプラインは、最後にただ一つの文字列を成果物として返します。単純には見えますが、実際には大量の情報を潰しています。潰すことの代償は三つあります。一つは来歴の喪失です。ユーザーもシステムも、結果から元のページへ戻れません。「この結論は、何ページ目のどのブロックが言ったのか」というもっとも基本的な質問に答えられないことです。二つめは再計算ができないことです。下流でフィールド抽出の誤りが見つかったら、元のファイルからパイプライン全体をやり直すしかありません。三つめは検索品質の低下です。同じテキストのなかに見出し、本文、キャプション、表の内容が混ざっています。純テキストの分割は長さでしか切れません。切り出された断片は、意味のうえで不完全なままです。
価値のより高い成果物は、要素単位の構造化オブジェクトの集まりです。それぞれの要素が、自分の型、ページ上の座標、属する章の経路、テキストの内容、信頼度、そして他の要素との関係を持つようにします。一つの文書とは、これらの要素の集合と、それらの間の構造関係のことです。座標があれば来歴と人手の確認への入口が得られます。型があれば型ごとの差別化された検索が可能になります。関係があれば、ページ跨ぎの継続と表の復元を担う器が得られます。
7.2 構造化出力と制約付きデコーディングの结合点
モデルで文書抽出をやるとき、最大の痛点は書式の不安定さです。フィールドが時折欠け、型が時折漂い、余分なフィールドが時折湧いてきて、それによって下流の解析が壊れます。構造化出力の制約付きデコーディング(constrained decoding)は出力の文法をデコーディング過程の硬い制約に変え、モデルは合法な構造の中でしか token を選べないため、文法の漂いを機構的に消し去ります。文書解析との结合点は、制約の対象が自由テキストの一片ではなく、文書モデルに符合する構造定義であるという点です。要素の型はあなたが定義した版面種別の列挙型から、座標はあなたが切り分けたページグリッドから、章パスは文書木上の合法なノードから取ります。この三つの制約は、文書理解が最も誤りやすく、かつ最も検査を要する三つの場所にちょうど対応しています。
制約付きデコーディングはモデルの出力分布を変える、という点は見過ごせません。文法の制約に加えて意味の制約を重ねる(たとえば「図注」型の要素のテキスト長をある上限以下に制限する、表要素は必ず列数情報を,要求する)と、非法の組み合わせはさらに圧縮されます。ただし、そのためにモデルが少数の周辺サンプル上で、ぎりぎり合法な出力へ早々に収束してしまう可能性もあります。したがって、これに併う検証層は省略できません。検証はデコーディングのあとに独立で一度走らせ、「書式は合法だが意味的に不適当」なサンプルを引っ張り出す必要があります。以下に出力契約と検証の骨格を示します。
DOC_SCHEMA = {
"type": "object",
"required": ["page", "elements"],
"properties": {
"page": {"type": "integer"},
"elements": {"type": "array", "items": {
"type": "object",
"required": ["kind", "bbox", "text"],
"properties": {
"kind": {"enum": ["heading", "para", "table", "figure", "caption",
"header", "footer", "formula"]},
"bbox": {"type": "array", "items": {"type": "integer"}, "minItems": 4},
"text": {"type": "string"},
"confidence": {"type": "number"}
}}}}}
def extract(doc, page_image, vlm, validator):
#语法层由解码器保证,这里不再解析自由文本
obj = vlm.generate(image=page_image, schema=DOC_SCHEMA)
issues = validator.check(obj)
#语义层独立校验:长度、坐标合理性、覆盖率
issues += check_coverage(obj, page_image)
issues += check_context(obj, doc.chapter_tree)
for el in obj["elements"]:
el["route"] = pick_route(el, issues)
return obj
7.3 座標を一等の市民にする
座標を一等の位置に置くと、その価値は多くの工程で回収されます。人の復核画面なら、出錯した領域へ直接ジャンプできます。差分比較を使えば、今回のパイプラインが前回より何を多く読み、何を少なく読んだのかが分かります。置信度は、ページ全体をひとまとめに下げるのではなく、領域ごとに重み付けできます。原画像にレンダリングして目視のサンプリングをするとき、余分な座標マッピングの仕事が要りません。これらはすべて構造化出力からただで得られる能力です。その条件は、最初に座標フィールドを残しておくことです。あとから補うことはできません。座標を補うとは、認識を走らせ直すことにほかなりませんから。
見落とされがちな用途がもうひとつあります。座標は、「モデルが本当に画像を読んでいるのか」を判定する診断シグナルです。ある視覚モデルの出力で座標分布が極端に一箇所に偏っている、あるいはページ全体を覆っているなら、そのモデルは版面感知をしていない可能性が高く、問題をテキスト生成として当て推量していることになります。座標の信頼性を独立した評価軸として監視しておけば、モデルの入れ替えの時に、能力の退行へ早く気づけます。
八、検索につなぐ:解析結果はどのようにして召喚可能な単位になるか
8.1 分割の単位は固定長ウィンドウではない
文書解析の成果物を、そのまま固定長で切り刻んで索引へ押し込むなら、検索品質は著しく悪化します。理由は三つあります。段落が途中から切れてしまい、片段の意味が不完全になります。表が切れると、行の見出しと行のデータが分離して、片段が意味を失います。見出しの階層が失われれば、片段は文脈の主題を失う。同じ内容を意味の単位で切った結果は、長さで切った結果より明らかに良く、これは解析を丁寧に固めることによる主要な利益源のひとつです。
推奨される分割の粒度は、「章パス + 完全な段落、または完全な表」です。具体的には、それぞれの片段が文書木の上における完全なパスを持つようにします(たとえば「第三章 コスト分析 > 3.2 単位コスト > ある段落」)。片段の本文は段落そのものだけを残します。検索がヒットしたときにパスを文脈に連結すれば、モデルは自分がどの節の問いに答えているのかがわかります。表については、可能なら「表見出し + 数十行」で切り、各行に必ず列名の展開形を付けるようにします。そうすれば片段は元の表から離れても自らを説明できます。図については、片段は「図注 + モデルが生成した画像説明の一段落」であって、画像そのものではありません。
8.2 ハイブリッド検索:なぜ文書シーンでは特に BM25 が必要なのか
文書シーンと雑談シーンでは、検索ニーズに顕著な差があります。文書には、固有名詞、番号、型番、条番号、法条引用といった「精密な token」が大量に含まれます。ベクトル検索は意味の近さでは非常に強いものの、精密な一致では失敗します。ユーザーが「A320-200 型式の第 3.3 条」と検索したとき、ベクトル検索は意味は関連するものの番号が違う段落を大量に召喚してしまうことがあります。BM25 のような語項マッチベースの検索方法は精密な一致で安定した性能を出します。両者が補い合うため、これがハイブリッド検索(hybrid retrieval)が文書シーンで事実上必須になっている理由です。
ハイブリッド検索の統合方法にはいくつかありますが、どれが最も単純で最もよく使われるのは、加重和による足し合わせです。ベクトル召喚とキーワード召喚の結果を、順位の逆数で重み付けして足し合わせます。少し緻密な実装では逆順位融合(reciprocal rank fusion)を使います。これは順位だけに依存してスコアの分布には依存しないため、異なるリトリーバのスコア較正に影響されにくく、実践上はより安定します。もう一つの方法は、先にクエリ書き換えを行うことです。クエリを複数の視点へ拡張してそれぞれ召喚し、あとからまとめます。多言語が混在する文書では特に有効です。クエリの言語と文書の言語が一致していない可能性があるからです。統合の重み選択は具体的なコーパスに依存します。他人の経験値をそのまままねすべきではありませんが、ひとつの有効な出発点として、キーワードの重みを少し高くしておくことがあります。文書クエリのなかに占める精密 token の割合は、自然言語の質問より通常は高いからです。
def hybrid_search(query, index, w_vec=0.45, w_kw=0.55, topk=50):
vec_hits = index.knn(query.embed(), topk)
kw_hits = index.bm25(query.analyze(), topk)
score = {}
for rank, h in enumerate(vec_hits, 1):
score[h.id] = score.get(h.id, 0.0) + w_vec / (60 + rank)
for rank, h in enumerate(kw_hits, 1):
score[h.id] = score.get(h.id, 0.0) + w_kw / (60 + rank)
#片段自带路径与表格展开,命中即可拼上下文
return sorted(score.items(), key=lambda x: -x[1])[:topk]
8.3 ハイブリッド検索のうえでやるべきこと
召喚品質の上限は、しばしば検索アルゴリズムにはなく、索引構築のさいの細かな点にあります。そしてその細部は、すべて解析品質に依存しています。第一にメタデータのフィルタです。検索が文書種別、章、時刻、置信度で絞り込めるようにします。これには解析段階で信頼できる種別と章の情報を出力しなければなりません。置信度の低い片段は、索引に入れないか重みを下げる選択ができます。召喚される数を少なくするほうが、誤ったものを召喚するより望ましいからです。第二に片段の自己完結性です。片段は充分な文脈(章パス、表見出しの展開、図注)を携えていなければなりません。そうでなければ召喚のあとプロンプトへ連結しても、モデルが見るのは主語のない破片の集まりにすぎません。第三に、表の数値列が検索でヒットするようにしておくことです。たとえばある片段の金額が、桁区切りと通貨記号つきの文字列として整形されているなら、精密検索はヒットしますが意味検索は理解できません。両方の表現を同時に保存しておくのがかまいません。
第四の点はよく見落とされます。文書にある「重要だが文になっていない」内容です。付録の諸元表、脚注の制約書き、表の下にある「注:上記のデータには税を含みません」といったものが該当します。それらは答えの正しさへ決定的に影響します。それでいて、ブロックが小さすぎるか句読点がない理由で、分割のさいに捨てられがちです。解析段階でこの種の内容に明示的なラベルを付けるべきです。所属する段落とまとめるか、独立した短い片段として残すか、どちらかにすればよいのです。
8.4 検索から答えまでつなげる来歴
解析段階で座標と章パスが保存されている以上、それを最終的な答えまで素通しすべきです。方法は、生成の段階で片段の出所を引用することを強制することです(ページ番号に章パスを添えたもの)。フロントエンドはそれをもとにクリック可能な来歴リンクを生成し、ユーザーはクリックすれば原文の対応領域へ移動して、そこがハイライトされます。これは単なる体験の最適化ではありません。誤った答えを迅速に見つけて訂正する経路を与えるもので、しかも「システムが誤った」と「モデルの解釈が誤った」という二種類の問題を切り分けられるようにします。コンプライアンスが問題になる場面では、来歴の明示は加点要素ではなく硬い要求になることがよくあります。
九、評価:抽出の精度だけを見るとだまされる理由
9.1 評価セットは実際の失敗例から逆算する
文書理解の評価で最も安易なやり方は、クリーンなサンプル文書に自分で印を付けて始めることです。この種の評価セットは、見栄えはよいものの、判断の手がかりのない数値を生みます。どの工程を最適化すべきかは教えてくれないまま、この変更が本当に効いたかも判らないからです。より妥当な方法としては、本番トラフィックから評価セットを逆算することです。下流から既に疑われたもの、復核で誤りと印されたもの、検索システムが召喚したうえで関連なしと判定された事例をすべて集め、業務側にも参加してもらい、その中から代表的な一部を選んで精密にアノテーションします。実際の失敗例から組んだ評価セットは、サンプル数はわずか百件ですが、そのたびに数値が動いても明確な最適化決定を支えます。
評価セットはさらに、「ランダム抽出」ではなく「層化抽出」を踏襲する必要があります。ランダムに百件の文書を引くと、九十件が同じテンプレートである可能性が高く、測った値はただ一つのテンプレートへの適応しか反映しません。妥当な層の切り方はたとえば次の通りです。取得元のチャネル(電子エクスポート、スマートフォン撮影、スキャンアーカイブ、第三者システムからの配送)、版式の複雑さ(単段、二段、多段、新聞状の混在)、内容の種別(契約書、財務報告書、説明書、乗車券類、論文、フォーム)、品質等級(クリア、傾き、影、低解像度)。層ごとに別々に数値を出して初めて、弱い層がどこかが見えてきます。
9.2 版面レベルの指標はそれぞれ何を測るか
版面レベルの指標の価値は問題の所在を絞ることにあります。しかし最終的な効果との相関は限定的です。したがってまとめて使う必要があります。領域位置の指標は幾何的な重なりの度合いから計算できます。しかしこの種の指標が伸びても、業務価値とは正比例しないことがよくあります。版面ブロックをより細かく切れば、幾何の重なりによる評価はよく見えますが、細か 지나ぎると逆に文の完全性を壊してしまいます。種別判定の指標(分類の精度と再現率)は種別ごとの取り違えを見る必要があり、特に混同しやすい次の諸種を重点的に見ます。図注と本文、ページヘッダと本文、表と枠で囲まれた段落。読順の指標は、二通りあります。人工で順序に印を付けてから一致度を測るか、下流のプロキシ指標で間接的に反映させるかです。たとえば出力を文に切って文の完全率を計算する方法があります。この文の完全率という指標は粗いのですが、読順の問題に対しては感度が高く、通常の監視項目として使う価値があります。
表の構造指標は二層に分けます。セル帰属の精度は、テキストが別の格に置かれたかを測り、構造復元の正しさは結合関係と行列数が正しいかを測ります。実際には後者のほうが、下流で起きる障害をより多く予測します。多くのずれは、セル数が一致しているのに行と列の対応が誤っていることで起きるため、セル帰属だけを見るとなかなか気づけません。ページ跨ぎの継続では、継続の正答率と誤継続率を測りますが、こちらのほうがずっと重要です。関係のない二ページの表を無理に結合めると、できあがるのは、一見完整だが完全に誤ったデータだからです。
9.3 エンドツーエンド指標:文字の照合ではなく問いに答える
エンドツーエンドの指標が測るのは、「その文書が業務の問いを支えられるか」です。形は三つあります。一つは、質問と正解の組での正答率です。問いと正解を与えて、システム出力が正解を含むかを確かめます。二つ目は、フィールド抽出におけるフィールド単位の精度と再現率です。対象は構造化された業務フィールドです。三つ目は検索側の関連性指標です。与えられた検索語に対して正しい片段が召喚されたか、その順位はどうだったかを見ます。この三つの指標はそれぞれの役割を持ち、互いに代わりにはなりません。抽出の精度が非常に高いパイプラインでも、分割のしかたのせいで検索が正しい片段をまったく召喚できないことがあります。質問への正答率が高いパイプラインでも、数が少ない単純な文書でだけよく振る舞っていることがあります。
エンドツーエンド指標の作り方も見過ごせません。同じ文書に難易度のある問いを複数つけるほうが、各文書に問いを一つだけつけるより、システムの強弱を区別できます。事実だけを問う問題は、何でも答えるシステムに有利に働きます。そのため、答えがない問いも含めて、拒否の能力を測るべきです。数値については、計算しないと答えられない問いにするべきです。たとえば「第三四半期は第二四半期よりどれくらい伸びたか」という問いは、認識の誤りと抽出の誤りを同時に暴きます。単に「第三四半期の数値はいくらか」と聞けば、モデルの記憶や文脈の補完に隠れてしまう種類の誤りだからです。
9.4 なぜ文字単位の類似度は弱い指標なのか
編集距離や BLEU のような文字単位の指標で文書解析を評価するのは、本質的に不適切な目的関数で最適化していることになります。この種の指標は、「表の列の順番を間違えたが文字はすべてある」を高い点として判定します。逆に「表を正しく構造化レコードへ変換した」を低い点として判定します。構造の差異を扱えないからです。もっとも厄介なのは、优化の方向を誤らせることです。チームは文字の類似度に影響する工程を最適化したがるからです。認識字形のような段階に労力を使い、業務に本当に効く構造の工程は放置されます。「読えているかどうか」を測るなら、測るべきなのは構造と意味であり、文字列の近さではありません。
9.5 実際に運用できる評価ダッシュボード
最小の管理体系を落地するなら、この順序で勧めます。まずエンドツーエンドの質問セットと検索の関連性セットを作ります。この二つだけは、そのまま業務の価値に直接対応します。次に版面レベルの指標を診断パネルとして作ります。これは「今回エンドツーエンドが落ちた。どの工程で落ちたのか」に答えるためです。最後に置信度の較正評価を作ります。モデルが出した置信度と実際の正答率が噛み合っているかを測ります。置信度の較正はよく無視されますが、決定的に重要です。較正されていないと、降格ルーティング、復核の優先順位、そして必要に応じた抽出検査に使うことができません。置信度に基づく工学設計は、すべて砂の上に成り立ってしまうからです。ひとつ大まかな観察として、同じモデルでも文書種別によって置信度の分布は大きく異なります。とくに手書きや低解像度の入力では明らかに高くなります。それは復核キューが優先的に処理すべき部分そのものです。
十、エンジニアリング:スループット、リトライ、キャッシュ、コスト
10.1 ページ単位では並べるが、ファイル単位では並ばない
最も見落とされがちな並列設計の問題は、タスクの分割粒度です。文書単位の並列はもっとも自然に見えますが、代价は明らかです。百ページの報告書は一つのタスクに保持され、走り終わるまで結果が出ません。どれか1ページが失敗すれば資料全体をやり直すことになります。タスクごとの所要時間の差が極端だと、負荷が非常に偏ります。ページ単位の並列は粒度が細かいため、並列スケジューリングと失敗の隔離に自然に適合し、結果をストリームで出し続けられます。唯一の追加作業は、ページ跨ぎの継続の扱いです。ページ単位で並べるということは、継続のロジックをより上位の調整器の中で行うことを意味します。すべてのページの中間結果を集めてから結合を実行します。この調整器の実装の複雑度は抑えられます。「表の領域候補」と「表見出しの指紋」という二種類の軽量な特徴にしか依存せず、文書全体の内容を見る必要がないからです。
スケジューリングにおける現実的な制約は、しばしば CPU ではなく、外部のモデルサービスのレート制限です。 したがって並列度の制御は二層に分ける必要があります。 幾何処理や認識のようなローカルのタスクは、CPU コア数にいくらか余裕を持たせて開いて構いません。 視覚モデルを呼ぶタスクは、サービスの枠に従ってレート制限をかける必要があります。 そして独立した失敗のリトライとバックオフを持たなければなりません。 この二種類のタスクは同じプールではなく、別のキューに入れるのがよいです。 リソースの性質がまったく異なるので、混ぜると、ローカルのタスクが外部サービスの枠で足止めされたり、ローカルのタスクがプロセスのメモリを使い切ってモデルの呼び出しが失敗したりするからです。
10.2 冪等性、キャッシュ、差分更新
文書パイプラインの再実行コストはとても高いので、冪等性とキャッシュは最初から設計しておく必要があります。後で補うコストが大きくなるからです。基本要件は三つです。第一にコンテンツアドレスです。ファイルハッシュと解析設定のバージョンを合わせて処理の鍵にします。これによって設定が変われば自動的に全量再計算が発火し、単なる失敗のリトライはキャッシュにヒットします。第二に段階単位のキャッシュです。各段階の中間結果を個別に永続化し、個別のバージョン番号を持たせます。そうすれば認識モデルを交換するときは認識以降の工程だけを再実行し、版面ルールを交換するときは版面以降の工程だけを再実行できます。第三に安定した出力です。同じ入力はバイト単位で同一の出力質を保証せねばならず、走査順序やタイムスタンプによってキャッシュが永久にヒットしないことを防ぎます。
差分更新の難点は、「文書が変わった」という判定が簡単ではないことにあります。文書のメタデータの更新時刻は書式の変換によって変わることがありますが、改訂日がたった一箇所だけ変わったのに、結論も金額も表見出しもすべて変わっていることもあります。なので、段階的に判定するのが妥当です。まず内容のハッシュを比較し、ヒットすればそのまま再利用します。ヒットしなければ、軽量な差分特定を一度だけ行います。たとえばページごとにレンダリングの指紋を比べます。そして変化したページとその隣接ページだけを再実行します。文書の構造が複雑な場合、たとえばページ跨ぎの表がある場合は、その一ページだけでなく、関連する章全体を範囲に広げます。差分更新の効果は文書が定期的に更新されるシーンではかなり効果が大きくなります。ただし、正しくやるには、まず段階単位のキャッシュを設計しておかなければ、どの工程を飛ばせるのかがそもそも判断できません。
CREATE TABLE parse_stage_cache(
doc_hash text NOT NULL,
pipeline_ver text NOT NULL,
page_no integer NOT NULL,
stage text NOT NULL,
stage_ver text NOT NULL,
payload bytea,
conf_avg real,
degraded boolean DEFAULT false,
primary key(doc_hash, pipeline_ver, page_no, stage, stage_ver));
CREATE TABLE parse_doc_state(
doc_hash text primary key,
source_version text,
doc_version integer,
parse_ver text,
status text,
updated_at timestamptz);
--重跑前先按页比对渲染指纹,只重算变化页及其邻居
10.3 失敗時のリトライ:再試行できるものとできないものを分ける
すべての失敗を再試行できるものとして扱うのは、よくある無駄です。再試行できる失敗には、外部サービスのタイムアウト、レート制限、一時的なリソース不足があります。これらは指数バックオフで再試行し、最大回数を設けるべきです。再試行できない失敗には、画像の破損、解析できない書式、空のページがあります。これらは何回やっても成功しません。ただちに失敗を印して例外キューに入れるべきです。もっとも厄介なのは、「表面上は成功したが結果は信用できない」失敗です。たとえば認識エンジンが空のテキストを返したのにエラーを出さない、モデルが書式は合法だが意味が空の要素を返す、といった場合です。これらはリトライでは解けません。出力の検証で発見して、降格または人手による対処を起動するしかありません。したがってリトライ戦略は出力検証とセットで設計しなければなりません。リトライが解決するのは「最後まで走り切らなかった」問題で、検証が解決するのは「走り切ったが使えない」問題です。
10.4 コスト制御:ページ単位で段差を付ける
コスト制御で最も効くのは、一ページあたりのコストを圧縮することではなく、ページごとにコストの違う経路を通すことです。実装できる段差としてはたとえば次のようなものです。品質ゲートがクリアで版式が単純なページは、完全な幾何パイプラインとローカルの認識を通し、途中で視覚モデルを呼ばずに済ませます。こうすれば限界コストはほぼゼロになります。版式は複雑でも画像がクリアなページは、幾何パイプラインを飛ばして視覚モデルに直接画像を読ませます。コストは高いですが精度は高いです。品質が退化したページは、まず幾何の前処理で可用性を上げたうえで、どちらの経路を使うかを決めます。どの経路でも、最後に高価値のページ(契約書の表紙、財務諸表のページ、条項が密なページ)を高優先で印し、全量の冗長処理を通すべきです。たとえば二重のパイプラインを並列に走らせて、人手による確認を重ねることです。
キャッシュ戦略は段差とセットで考えます。クリアなページの幾何処理と認識の結果は非常によく再利用されるので、長期キャッシュすべきです。視覚モデルの呼び出し結果のキャッシュ価値は比較的低いですが、値が高いのでヒット率が低くてもキャッシュはします。ただ、有効期間は短く取って、テンプレートが変わったあとも古い結果を返し続けることを防ぎます。もうひとつ見落とされがちなコスト項目は、ログとデバッグ生成物の保存です。レンダリングしたページ画像、中間のマスク、注釈枠の可視化ファイルは、案外ストレージを圧迫しがちです。オンラインサービスには価値がないので、品質検査のサンプリングのあと保持期間に従って片付けて、サンプル数は少ないものの代表的なものだけを残すのがよいです。
十一、2026 年の進展と能力の境界
11.1 視覚文書モデルが実際に進んできた方向
具体的な宣伝文句を割り引けば、視覚文書のモデルが能力を伸ばしてきた過程には、いくつかの方向がはっきり見えます。第一に文書専用の学習です。この種のモデルは版面が密で表が多いコーパスに向けて特別な学習を行っています。そのため表の出力と読順の点で、汎用的な視覚言語モデルよりも信頼できます。第二に解像度と視覚 token 予算の割り当てです。入力解像度を力任せに上げるのではなく、モデルがどの領域を、どれほどの倍率で見るかを自分で決めさせる方向です。この方向は文書シーンにとても合っています。一ページの中でも表の領域には高倍率が要るが、ページヘッダとフッタにはほとんど要らないからです。第三にネイティブの文書入力です。一部のモデルは、ページをまずビットマップにレンダリングするのではなく、文書ページを直接入力に取れます。こうするとベクターの文字層の情報が保たれます。この種の入力は、細い罫線の表や数式を扱ううえで利点があります。第四に、構造化出力の制約付きデコーディングとの深い結びつきです。モデルの出力がそのまま下流で消費できるようになり、脆い正規表現による解析が不要になります。
もうひとつ過小評価されがちな方向があります。入力がページ単位ではなく文書単位である、というものです。 앞에서単一ページ理解の限界を述べましたが、近年の做法としては章や数ページのまとまりを入力にすることです。そうするとより長い文脈のなかで構造の一貫性を保つことができます。これはページ跨ぎの継続や章番号の連続性の問題は緩和できますが、コストと文脈長の両方に明らかな要求を伴うため、実践では高価値な文書にだけ有効化する場合が多いのです。
11.2 能力の境界:モデルに委ねるべきでないケース
進歩は明らかですが、境界がはっきりしているタスクがあります。それらを全面的にモデルに任せるのは望ましくありません。第一に、精密な数値の大量抽出です。とくに財務諸表や伝票のように、数値を一つ間違えた代償が大きいシーンでは、モデルは位置づけの補助と相互検証には使えますが、最終的に登録される数値は、幾何的な根拠と明確な単位を持つ構造化された経路から得るべきです。第二に、過程の再現性と監査性が要るケースです。モデルの途中推論は再現できません。出力に疑義が生じたときに証拠を示せません。第三に、極端な版式です。たとえば手書きで書かれた公文書のようなものです。幾何パイプラインの失敗は予想でき、修復可能です。一方、モデルの失敗はたいてい音を立てずに起きます。
もうひとつの境界は、書式が不正確な半構造化コンテンツです。たとえばチャット画面からのスクリーンショット、メールの転送、ソーシャルメディアのスクリーンショットからタスクのチェックリストを取り出すようなものです。この種の入力には安定した版式がなく、従来のパイプラインでは手法がありません。一方、モデルはここでだけは得意です。しかしこれは別の問題領域に属します。つまり画面理解と情報抽出であり、その評価方法や失敗のしかたは文書解析とはまったく違います。同一のパイプラインの仮定をそのまま当てはめてはいけません。判定基準は単純です。「ページ」という概念が存在せず、要素が排版の構造ではなく視覚的なグループ分けで区切られているなら、それは文書理解の問題ではありません。
11.3 制約付きデコーディングと文書解析の合流
構造化出力の制約付きデコーディングは、この数年で「書式として合法な生成」から「構造として自洽した生成」へと歩んできました。この合流が文書解析にとって意味するのは、品質保証の一部をオフラインの検証からデコーディングの内部へ移せたことです。文書モデルは、まず領域の種別と階層を予測し、その領域のなかで内容を生成します。構造と内容が二つの独立した手順ではなくなりました。この方法は理論上、「書式は正しいが内容がずれている」誤りを減らせます。帰属関係とテキスト生成が結びつけられるからです。ただし、ここは清醒であるべきです。制約付きデコーディングが保証するのは「構造定義に適合する」ことであって、「現実に適合する」ことではありません。出力を常にパース可能にはできますが、内容が事実として正しいことは保証しません。制約付きデコーディングを品質保証の手段ではなく書式の手段として扱うことの、これがいちばん避けたい認知の偏りです。
11.4 モデルを置き換えるときの評価方法
モデルの更新は通常、このシステムのなかで効果が最も大きく、リスクも最も高い変更です。下流のすべての指標が動くからです。しかも動く理由が暗黙のままです。妥当なやり方はこうです。固定した評価集で旧モデルと新モデルの両方を動かし、エンドツーエンドの指標と層ごとの診断指標を比較します。总分が伸びたかだけを見てはいけません。能力が移動していないかを確認します。总分は上がったのに手書きの層が大きく落ちた、といった場合です。これは总分にはまったく現れません。また、置信度の較正が成立しているかをチェックします。新モデルの置信度の分布は通常旧モデルとまったくちがうので、古い閾値をそのまま使うとルーティングのロジックがすべて壊れます。最後に人手による盲評を一部だけ行います。自動指標は「自信を持って間違っている」ような新しい失敗のモードには、やや反応が鈍いのです。
十二、人手の復核のループ:エラーを発見でき、帰属できるようにする
12.1 復核キューの並べ方
人手による復核は文書パイプラインの一つの一部であり、付加された工程ではありません。ただし「確信が低いものはすべて人手に回す」というやり方は現実的ではありません。置信度と降格の印を使い、復核の量を運用できる範囲に収める必要があります。復核キューの優先順位は通常、いくつかの信号で決まります。置信度が最も低いものを先にします。降格経路で処理されたと印されたものを次にします。降格という状態は、それ自体が主経路の失敗を意味するからです。高価値なフィールド(金額、番号、日付)に関わるものを次にします。下流ですでに疑いを持たれているものを次にします。この信号がいちばん価値が高いのは、モデルの自己の疑いではなく、実際の業務への影響を表しているからです。残りは無作為抽出で埋めます。全体の精度を見積もるためです。無作為抽出と目的を絞った復核は分けて集計し、両者の精度の差そのものが品質問題の尺度になります。
12.2 復核画面の設計が復核効率を決める
復核画面の設計は、一単位あたりの復核コストをそのまま決めます。最低要件は三つです。原画像と解析結果を並べて表示し、クリックで連動すること。問題のある領域を高く強調して示せること。修正した結果をそのまま新しい注釈データへ戻せることです。うまく設計された復核画面なら、復核者が一ページを処理する時間を、画像だけを見るとき、半分以下にできます。そして復核の速度は、どれだけ多くのサンプルを覆えるかを直接決めます。復核で得られる注釈データは評価セットの継続的な供給源であり、版面と認識のモデルのファインチューニングのための直接のコーパスでもあります。この注釈が構造化された形で訓練と評価の流れに戻っていなければ、人手による復核は単に高価なログ閲覧器に退化します。復核画面を設計するとき、「構造化された形で戻す」ことを第一要件として扱うほうが、後でどうにか手を加えるよりずっと楽です。
12.3 エラーの分類で最適化の優先順位を決める
復核データがもっとも価値をもつ使い方は、精度を数えることではありません。エラーの原因を分類して並べ替えることです。エラーの分類体系を一つ持っておき、復核で確定したエラーは、どれか一つの種類に決めます。たとえば幾何のずれ、字形の誤認識、種別の誤判定、ページ跨ぎの継続の誤り、図表の数値の誤り、モデルの幻覚による補完などです。種別ごとに影響範囲を記録します。何本の文書が、関連するテンプレートはどれか、ということです。最適化の優先順位は、現在の出現頻度ではなく、影響面と、その種別だけを直すコストの積で並べ替えます。ここには直感に反する結論があります。ある特定のテンプレートにだけ現れるものの、直し方がルールを一本足すだけの問題と、サイト全体に現れるものの、修正のために学習データをやり直す認識問題とでは、前者を先に解くほうがよい場合が多いのです。この優先順位の表を定期的に並べ替えることは、平均的な精度を盲目的に追いかけ続けるより、実際の体験を継続して改善します。
十三、リリース前のチェックリストとよくある障害の切り分け
13.1 実際に使えるチェックリスト
この順に照合すれば、リリース後の手戻りの大半を防げます。まず解析レイヤーです。すべての要素について種別と座標を残していますか。ページ跨ぎの表に継続のロジックがありますか。「継続」と「誤った継続」の両方を覆うテストケースがありますか。図注は図に結び付いたまま、本文に混ぜられていませんか。ページヘッダとフッタの除去に、ページ跨ぎでの一貫性の検証がありますか。同じ文書で除去されたヘッダのテキストは高度に繰り返されるはずです。ページによって違う内容になるなら、ルールが不安定だということです。次に構造レイヤーです。表が結合のスパン情報を潰さずに保持していますか。数値の単位の正規化は済みましたか。合計行の検証はゲートとして実行されていますか。次に出力レイヤーです。低置信度と降格の領域は明示的に印されていますか。空の結果と失敗は区別されていますか。同じ入力を二度走らせても完全に同一の出力になりますか。
検索レイヤーです。片段は章パスを運んでいますか。表の片段は表見出しの展開を付属していますか。片段の長さの分布は正常ですか。ほとんどの片段が極端に短いか、逆に極端に長いなら、分割のロジックに問題があります。数値型の内容については、二つの表現を同時に保存していますか。コストレイヤーです。ページごとに段差を付けてスケジューリングしていますか。段階単位のキャッシュは整っていますか。レート制限とバックオフの戦略は設定されていますか。ログと中間生成物の保持期間は決まっていますか。運用レイヤーです。文書ハッシュと設定バージョンから、任意の解析結果を再現できますか。特定の数ページだけを再実行できますか。モデルのバージョンを変えたときに回帰評価の手順がありますか。
13.2 よくある障害の切り分け経路
頻度の高いいくつかの障害には、比較的決まった調査経路があります。「検索が意味的には関連するけどまったく違う片段を召喚した」という場合、まずその片段の種別ラベルと置信度を見ます。低置信度の片段が索引に入っていたなら、フィルタの規則の問題です。片段の種別が図注かヘッダで、それが本文として扱われていたなら、要素の分類または帰属の問題です。「ある数字のフィールド抽出がいつも誤る」という場合、まずその数字が載っている表の列名が正しく展開されているかを確認します。列名がすべて合っているなら、そのセルの結合スパンを確認します。列名がずれているなら、それは抽出ではなく表の構造復元の問題です。この順序なら、モデルのプロンプトを触る無効な無駄な作業を大量に省けます。「文書全体が大面積に乱序になる」という場合、まず二段か多段の版式かどうかを確認し、次に回転補正が効いているかを確認し、最後にモデルを疑います。「特定の顧客の履歴文書だけ解析品質が悪い」という場合は、ほぼ確実に品質退化の経路だと断定できます。この種の入力には別の降格戦略と人手復核の比率を設定する必要があります。
13.3 調整を続けるのではなくアーキテクチャを変えるとき
三つの状況では、いったん止まってアーキテクチャの層で変更を考えます。第一に、同じ種類のエラーが繰り返して出て、ルールやデータでは直せない場合です。現在の表現方法がその種の情報を抱え込んでいないということで、出力構造を変える必要があります。第二に、ある種類の文書を最適化したら別の種類が明らかに悪化した場合です。現在の単一表現が版式どうしで衝突しているので、文書種別ごとにパイプラインを分けることを考えるべきです。第三に、エンドツーエンドの指標が長いあいだある水準で止ま 있는데、各工程の診断指標は正常という場合です。これは通常、問題が工程をまたぐ組み合わせ効果であることを意味します。たとえば認識は正しいが順序が間違っているとか、順序は正しいが分割が意味をばらばらにしたとかです。このときは、どの単一工程の最適化も続けずに、中間生成物を見るべきです。もっとも重要な判断基準はこれです。毎回の最適化で複数の場所を直す必要があり、それらが互いに影響し合うなら、中間表現の設計を疑い直すべきです。
最後に最初の言葉に戻ります。文書理解の難所はモデルではなく、契約にあります。その文書にどんな構造化された事実があるか、それぞれの事実の座標と信頼度はどこか、そして解析が失敗したときにシステムはどう振舞うのか。その三つを明確に定義できれば、残りはすべてエンジニアリングの分量です。
十四、キーと値の抽出:フォーム、伝票、契約条項
14.1 キーと値の抽出における三つの版式
表と図を除けば、キーと値の抽出(key-value extraction)は企業における文書理解でもっとも頻度の高いタスクです。請求書上の買い手と売り手、経費精算書の金額と事由、契約書表紙の甲乙両当事者情報と対象物、申請書の申請者欄と申請事項などです。これらの版式はおおよそ三つに分かれ、抽出の戦略まったく違います。第一類は右寄せのラベル型です。ラベルが左にあり値が右にあり、空白か下線で区切られています。ラベルのテキストを認識したあと幾何関係で右の値を探せばいいので、もっとも単純でもっとも信頼できる類です。第二類はラベル内包型です。値がラベルの後ろにコロンか読点で続きます。一行に複数のキーと値が入ることもあります。標点で分割してから言語と位置で帰属を判断します。第三類は枠線入れ子型です。値が枠で囲まれたセルの中に置かれ、ラベルが枠の外にあることも枠の中に描かれていることもあります。「値がラベルと入れ替わる」あるいは「ラベルが値とされる」を教えてしまう取り違えが最も出やすい類です。
14.2 なぜキーと値の抽出では取り違えが生じやすいのか
取り違えは、キーと値の抽出에서도っとも典型的で、もっとも発見しにくいエラーです。抽出したフィールドが多くの場合、書式としては正しいからです。日付は日付のフィールドに、金額は金額のフィールドに入っているだけで、所属する実体が間違っているのです。取り違えが生じる原因は、たいてい幾何関係の判定が緩すぎることにあります。たとえば「同じ行のテキストブロックを x でソートすれば、左がラベルで右が値だ」という仮定は、一行に二つのキーと値があるとそのまま破綻します。または、ラベルと値のあいだに幅広い空白があり、もともと決めた距離の閾値を超えた場合、値は認識されず「次の孤立したテキストブロック」へと退行します。 有効な対策は三層あります。 第一に、ラベルの語彙表による固定化を優先することです。正規表現か辞書で既知のラベルを抽出し、幾何上もっとも近い値を割り当てます。値を割り当てられなかったラベルは明示的に空として印し、恣意的にどれか一つを掴ませてはいけません。第二に、割り当てた値には型の検証をかけることです。日付の形式、金額の形式、証件のチェックディジットなど、型が合わない割り当ては失敗として扱いましょう。第三に、行全体に対して重複キーの検査を一度行います。同じフィールドが一つの文書に二回現れたときは、値を二つとも残して衝突を印します。黙って最初の一つを取ってはいけません。
14.3 契約条項のような長いテキストの難所は抽出ではなく所在特定にある
契約の条項抽出は単純に見えます。「違約責任」という節を見つけて、その中の文字を取り出せばよい、と。しかし、実装の段階にはよくある構造的な誤解があります。実際に難しいのは「どの部分を抽出するか」ではなく、「何が一つの段落なのか」という、構成上の問題です。契約の条項は通常、見出し、いくつかの本文段落、いくつかの細目、いくつかの例外説明からなります。見出しの階層は番号とインデントで表されていますが、視覚的な字体の差があるとは限りません。空行で雑に切ると、一つの論理的な条項が三つに分かれてしまいます。固定長で切ると、例外説明が主条項と混ざります。より安全なやり方は、番号の規則とインデントの階層を使って条項の木を再構築することです。番号の認識は契約種類の文書では通常、版面検出より信頼できます。番号が規則的に整っているからです。番号が無いときは、インデントの量と約物のパターン(「そのうち」「本条に別の定めがある場合」といった書き出し)を補足的な信号にできます。
14.4 発票とフォーム:ルールの価値はモデルを上回る
請求書、電車券、身分証明書、営業許可証のような高度に標準化された証票は、旧来のルールベース手法が費用対効果でもっとも有利に働く領域です。理由は単純で、版式がほぼ固定であり、フィールドの位置は予測でき、監督当局や業界規範がさらに版面に明示的な要件を課していることが多いからです。このときもっとも効くのは、まず版面をアンカーで固定し(幾何特徴、または少数の鍵点検出で証票種別を特定する)、次にテンプレートルールでフィールドを抽出することです。モデルはルールの失敗時のフォールバックと、非標準的な変種への汎化にだけ充当させます。これとは対照的に、ゼロから自由に組まれた版面からの抽出のほうがモデルへの依存が強いのです。この二種類の入力を一本のパイプラインに同居させて同じ戦略で処理するのは、よくある設計上の失敗です。
証票のシーンには、見落とされがちな強いバリデーションがもう一つあります。券種ごとに金額に対する算術的な制約があり、たとえば税込合計は税抜金額と税額の和に等しくなければならず、チェックディジットは再計算して検証できます。この種のバリデーションはモデルに一切依存せずに大量の認識・抽出ミスを拾い上げます。コストはほぼゼロで、誤検知もほとんどありません。契約文書でも同様に、門禁として使える交差制約が存在します。署名日が発効日より前であってはならないとか、金額の大字小字表記が一致していなければならない、などです。この種の業務制約をバリデータの集合として書き出すのは、document parsing pipeline の信頼性を引き上げる投資対比率がもっとも高い一歩であり、モデルを交換するよりたいていよく効きます。
十五、データ契約:解析結果を長期的に消費できるようにする
15.1 解析結果はデータ資産であり、バージョンを持つ
解析の成果物を下流のインデックスやデータウェアハウスへ流し込んだ時点で、それはデータ資産であって、あるパイプラインの一時的な出力ではなくなります。つまり、いったん公開したあとはバージョンを考える必要が生まれるからです。フィールドの意味が変わる(あるフィールドが文字列からオブジェクトになる)、フィールドの廃止、フィールドの追加、列挙値の拡張。いずれもすべての消費側に影響します。バージョン管理の無い解析結果は、パイプラインをアップグレードするときにデータベース全体を再実行して、下流が壊れないことを祈るしかありません。だからこそ初日から「構造バージョン」と「内容バージョン」を分けて管理すべきです。構造バージョンはフォーマット定義の変化とともに上がり、内容バージョンは解析結果の更新とともに上がる。両者は独立です。こうすることで、「今回の再実行は二つのフィールド値を直しただけ」と「今回の再実行は構造アップグレードのため」が明確に区別できます。
15.2 フィールド定義には出どころと信頼度を書く
外部に公開する各フィールドには、三つの情報を持たせるべきです。どの文書位置から来たか(ページ番号と座標、あるいはブロック識別子)、どのように得られたか(幾何ルール、認識とルールの組み合わせ、それともモデル抽出)、そして信頼度等級です。信頼度等級は細かくなくても構いませんが、少なくとも「幾何的な根拠があり、かつ業務バリデーションを通ったもの」と「モデルが生成し、バリデーションを受けていないもの」の二つは区別できるようにしてください。この三つの情報のコストはきわめて低いのに、問題が起きたときの下流側の切り分け経路を決めてしまいます。値だけを持つフィールドでは信じていいのか判断できません。出どころと信頼度を持つフィールドなら、数秒で問題領域に到達できます。この種のメタデータを付随的なログに落とすのではなく、一等のフィールドとして扱うかどうかが、解析の成果物が長期的に使えるかどうかの分水嶺になります。
15.3 構造変更に対する移行戦略
構造を変更するとき、確実に避けたいのは、一括で切り替えるのではなく、ダブルライトと段階的移行です。具体的には、新規フィールドはまず書き込むだけで読ませません。読む側のロジックは新旧両方の構造に対応させてから切り替えます。フィールドの意味が変わるときは、その場で意味を書き換えず、新規フィールドを追加して移行期間中はダブルライトし、下流がすべて切り替わった段階で旧フィールドを廃止します。列挙値の拡張は低リスク変更なので直接公開して構いませんが、下流が未知の値の出現を許容できることを確認しておく必要があります。さもなくば解析異常を招きます。フィールドの廃止は、すべての下流が依存しなくなったことを確認してから実行し、十分長いロールバックの猶予期間を残しておきます。この手順は繁琐に見えますが、「一度の変更で下流をすべて吹き飛ばす」という高リスク操作を、観測可能でロールバック可能な小さな操作の連列へ変えるからです。
15.4 外部インターフェースは不確実性を露出させるべきである
多くのシステムは解析インターフェースを「値を入れれば値を返す」設計にして、不確実性を完全に隠しています。このインターフェース設計の問題は、「人手による介入が必要かどうか」の判断責任を完全に下流へ押しやったことです。下流側は文書品質の階層を理解していないので、結局は全面的に信じるか、全面的に信じないかのどちらかで終わります。より妥当なインターフェースは、低信頼・縮退・失敗という三つの状態を、一等の返却状態として露出させ、呼び出し側が自分のリスク選好に応じて閾値を設定できるようにすべきです。こうすることで、同じ解析サービスが「一括登録:誤りを少しなら許容する」と「コンプライアンス用途:誤りは必ず止めたい」というまったく異なる二種類の場面を同時に支え、二系統のシステムを保守せずに済みます。
十六、リコールの後:再ランキング、重複排除、コンテキスト組み立て
16.1 リコールできることは使えることを意味しない
ハイブリッド検索が出力するのは候補集合であり、候補から「使える」状態になるまでには明示的に設計すべき三つの手順があります。第一段階は再ランキングです。cross-encoder のような強いモデルで候補を対ごとに精密にスコアリングし、本当に関係するチャンクを上位へ押し上げます。文書シーンでは再ランキングの効果は通常かなり明確です。多くの関係するチャンクが、二重ベクトルによるリコール段階ではチャンク粒度や表現の違いで十位外に追いやられる一方、再ランキングならそれを拾い戻せるからです。第二段階は重複排除です。同一文書の隣接段落は内容が高度に似ており、複数個のリコール枠を圧迫します。テキストフィンガープリントや意味類似度で冗長分を落とし、異なる由来のチャンクに枠を空けさせます。第三段階はコンテキスト組み立てです。スコアの順に連結し、同時にコンテキスト長予算と構造上の制約を遵守します。
16.2 コンテキスト組み立てにおける三つの判断
組み立て段階で、もっとも重要な判断は「隣接の内容をあわせるか否か」です。ユーザーが具体的な数字を尋ねているときは、命中したチャンクだけを渡せばよいですが、追問されたときには隣接のコンテキストが必要になることがよくあります。一方、隣接チャンクを自動的に補うと予算を圧迫してしまいます。ここには実用的な折衷案があります。必要に応じて補う――命中チャンクが明らかに不完全なとき(表のチャンクにヘッダがない、段落のチャンクが指示語で始まっている、セクション経路がない、など)に限って隣接内容を足し、そうでなければ補わないという方針です。この判定はチャンクのメタデータだけで自動実行でき、モデルの関与は不要です。二つ目の判断は、同一文書から得た複数のチャンクの並べ順です。関連度順ではなく文書内の位置順に並べるべきです。人間も文書を順番に読むので、順序が乱れるとモデルが段落間の関係を誤読します。三つ目の判断は、内容が衝突しているときの扱いです。同じ問いに対して異なる文書が別の答えを持っているとき、順位で選ばせてモデルに任せるのではなく、出所の異なる複数を明示して保持し、モデルには回答のときに両方とそれぞれの出所を言わせます。さもないと、生成された答えは確かそうに見える一方で、実際にはあいまいなままになります。この三点が、多くの RAG システムで「リコールはできるのに答えが悪い」主要原因になっています。
16.3 引用と追跡可能性
組み立ての段階で引用情報を一緒に用意しておくべきです。各チャンクに文書タイトル、ページ番号、セクション経路、座標を持たせ、チャンクの隠しフィールドに書き込んだうえで、プロンプトテンプレートの側で生成時に引用するよう指示します。実践でよく起きる問題は、引用形式が安定せず、モデルがときどき存在しないページ番号を捏造することです。より確実なのは、モデルに自分でページ番号を書かせず、引用番号をあらかじめ採番してチャンクの先頭に埋め込み、モデルにはその番号を引用させるだけです。これは制約デコードの考え方を引用問題に再び適用したもので、「引用の生成」を自由生成から既存番号の選択へ変えることで、信頼性が大きく上がります。
16.4 オフライン評価するなら生成層よりリコール層のほうが価値が深い
やれることが一つだけなら、まずリコール層のオフライン評価を立ち上げることを勧めます。実クエリをひととおり用意し、各クエリの正解チャンクをアノテーションしたうえで、リコール率と順位指標を継続的に監視します。理由は、リコール層の問題は位置を特定でき、量化でき、最適化の道筋も明示的だからです。生成層の問題はしばしば「答えが間違っている」だけで、リコールが間違うのか生成が読み違えたのかが区別できません。リコール層の指標を長く監視しておくと、副次的な特典がもう一つあります。新しい文書テンプレートや新しい document parsing pipeline のバージョンを組み込んだとき、業務側から「最近なんか検索が不正確になった気がする」という連絡を待たずに済み、即座に検索品質の変化が見えるからです。
十七、多言語文書:認識と検索の二重の挑戦
17.1 文書単位の言語とブロック単位の言語
多言語文書の難点は、まず言語判定の粒度にあります。文書全体が単一言語の場合は比較的扱いやすいのですが、実データでは文書単位の言語とブロック単位の言語が食い違うケースのほうが多く、中国語のレポートに英語の用語やコード片が埋め込まれていたり、英語の契約書に中国語の署名ページが付属していたり、日本語の文書に英語の製品型番が一節挟まったりしています。この状態でページ全体を選語前提の認識エンジンに渡すと、形が似ている文字どうしが取り違えられます。しかしこの種の誤りは下流側では極めて発見しにくいのです。生成されたテキストが意味の上では依然として通用してしまうためです。現実的なやり方は、版面の段階でテキストブロックを切り出してからブロック単位の言語判定を行い、言語が混在しているブロックは対応する認識チャネルへ個別にルーティングし、出力に言語タグを残すことです。言語タグは付随的なフィールドにしか見えますが、その先のトークン分割、検索,乃至要約にどの戦略を使うかを決めます。これが欠けると、その後のどの段階も単一の平均的な戦略で、ばらつきの大きい内容をしか扱えなくなります。
17.2 検索側の言語の不一致
文書言語とクエリ言語が食い違うとき、純粋なベクトル検索は機能しつづけます(多言語ベクトルモデルは意味の近い異言語テキストを近接する位置へ写像します)。しかしキーワード検索はほぼ完全に機能しなくなります。ユーザーが中国語で「違約責任」を検索しても、BM25 は英語の契約書のなかに語項のまったく一致するものを見つけられないからです。この場合、立てられる手は二つあります。一つはクエリ側の拡張で、翻訳や多言語への言い換えによってクエリを複数の言語表現へ広げ、それぞれリコールしたうえで融合する方法です。コストは追加のエンコード呼び出しです。もう一つはインデックス側の処理で、各文書について機械翻訳による代理テキストを別に保存してキーワード索引に使い、表示と引用には原文を保持する方法です。二つの経路にはそれぞれ代償があります。前者は安価ですが翻訳品質に依存し、後者は多言語文書で索引のサイズとコストが大幅に膨らみます。どちらを選ぶかはクエリの言語分布によって決まります。クエリの言語が比較的集中していればクエリ側の拡張のほうが得で、文書言語が極端に分散していればインデックス側の処理のほうが安定します。
17.3 番号・コード・固有名詞の検索への適応
最後に、検索システムが系統的に過小評価しがちな内容を単体で触れておきます。識別番号、型番、条項番号、法条の引用、メールアドレスと URL です。これらの共通点は、ユーザーがほぼ常に正確な文字列として検索することです。ベクトル検索はこれらに対してほぼ無効であり、しばしば有害でもあります。「第3.3条」と「第3.5条」が意味空間の中ではほぼ重なっていても、事実としてはまったく別のものを指すからです。この種のものにとって、キーワードチャネルだけが唯一の頼りになります。エンジニアリング上の助言は三点あります。登録時に元の表記をそのまま保持し、番号を見栄えのよい整形済みの形式に正規化してはいけません。ユーザーのクエリは元の表記で入力されるからです。番号類の token に過度に攻めた分割を行ってはならず、停止語や低頻度語として除去してもいけません。分割時に、番号とそれが修飾する対象を分離してはいけません。たとえば「GB/T XXXX に依拠する」中の番号と規格名は同じチャンクに保持すべきです。そうしないと完全一致は半分の内容しか当たらず、意味を失います。この種のものには、検索側の配套设施としてもう一つ問題があります。命中した後に何を見せるか、という問題です。ユーザーが番号で検索したときに見たいのは、たいていその番号が現れた箇所のコンテキストであって、章全体の本文ではないのです。そこで、命中チャンクの主な価値が所在の座標を提供しているとき、インターフェースは段落まるごとをコンテキストに詰め込まず、座標を直接返すようにし、上位側が原文書内の該当位置へジャンプする形にするのです。認識と検索はここでまた合流します。版面段階で保持した座標が、最後には検索結果における出典追跡能力になるからです。