コンテンツにスキップ

Chunker

チャンクとは何かを決めるポート。

英語版が原文です。

プロトコル:

  • Chunker.chunk(content: bytes, media_type: str, outputs: tuple[PageOutput, ...]) -> tuple[PageChunks, ...]
  • ChunkerProvider.chunkers() -> tuple[Chunker, ...]

Chunker は、チャンクとは何か — リトリーバーがインデックスする埋め込み可能な単位 — を決めるための境界です。エンコードごとに一度、すべてのリーダーがページを生成した後、何かが埋め込まれる前に、すべてのリーダーが見たのと同じバイト列とともに尋ねられます。フォーマットを知るチャンカーは、フラットな文字列が失った構造のためにバイト列を開き直せます。テキストだけで足りるチャンカーは、ページ出力からそれを読み取ります。

チャンカーは、ページに対して PageChunks を返すことでそのページを主張し、何も返さないことで文書の担当を否認します。回答はページごとに統合され、チャンカー順で先勝ちです。だからチャンカーは、部分的な知識について正直でいられます — PDF チャンカーは OCR が読んだスキャンページのレイアウトを持たないので、そのページについて何も言わなければ、そのページは列の次のチャンカー、OCR リーダーが見つけた行を矩形付きのチャンクに切る indx-chunker-lines に渡ります。

四つのチャンカーディストリビューションが、サードパーティが使うのと同じエントリーポイントグループを通じて indx とともに出荷されます。indx-chunker-pdf は、PDFium が報告するテキストランのレイアウトで PDF ページを分割し、視覚的な行へ統合し、各チャンクに正規化された bbox を載せます。indx-chunker-pptx は PowerPoint のスライドを図形単位に切り分けます。文字を持つ図形と表は一つずつテキストチャンクに、ラスター画像は一つずつ画像チャンクになり、それぞれファイルが述べる位置を載せます。グループ変換を適用し、プレースホルダーの枠はレイアウトとマスターから継承します。indx-chunker-page は床です。あらゆるメディアタイプの読み取り可能なすべてのページを、その全テキストを一つのチャンクとして主張します。これはまさに、このポートが存在する前に build がハードコードしていたものです。これを持たないインストール — 素の pip install indx — は何もチャンクしません。何も観察せず、どの URI も解決しないのと同じ、包み隠しのない欠落です。indx-chunker-lines は、リーダーが見つけた行(PageOutput.linesgeneric-ocr が認識器の枠から埋め、ワイヤには届きません)を、どのメディアタイプでもバイト列を開き直さずに、行ごとに一つのチャンクとしてその矩形で切ります。リーダーが行を述べなかったページは辞退します。

blocks.build は 1 ページにつき一つのチャンクを発行し、それを先送りとして記していました。サイズについて意見を持つ下流が現れたら、実際の構造で分割する、と。レシピストアとエクスポートインデックスがその下流であり、chunk_texts はベクトルへ至る唯一の経路です。その結果、チャンキングは検索品質を静かに決めるものになっていました — フィクスチャの請求書で具体的に測定されたとおりです。そのジェネレーターはすべてのグリフを独立したテキストランとして描くため、境界の知識はバイト列の中に存在するのに、それを言う場所がありませんでした。

PageOutput 上の機能供給チャネルがもう一つの候補で、均一性のために却下されました。境界は読み取りについてではなく検索についての意見であり、すべての読み取りの後に適用されるポートなら、一つの実装が、異なる機能が読んだページにも境界を引けるからです。

入力は、ロード済みソースのバイト列と検出されたメディアタイプ — PageReader.readSourceObserver.observe が受け取るのと同じ組 — に加え、その実行が生成したすべての PageOutput です。したがって、チャンカーのディストリビューションは indx-interfaces だけに依存します。

出力は PageChunks のタプルで、それぞれが 1 始まりのページを名指しし、順序付きの ChunkPiece を運びます。ピースは空でないテキスト または 空でない画像バイト列(どちらか一方だけ。後述)と任意の bbox で、Block.bbox と同じ方法で正規化されます — 一つの validate_bbox が両方に使われるため、検証を通るピースは検証を通るブロックになります。PageOutput と同じく、これは意図的に Block ではありません。エグゼキューターがすべての page:N/chunk:M をピースの位置から発行するため、ID の一意性は、文書全体を見渡せる唯一のものの手元に残ります。

bbox を持たないピースは、必ず代わりに bbox_reason を運びます。チャンカーが位置を知らないなら no_geometry、元の文書が図形を非表示にしているなら hidden、形式は位置を持つのにこの図形の位置を解決できなかったなら unresolved です。モデルはどちらも持たないピースと両方を持つピースを拒むため、理由はチャンカーが述べるものであり、エグゼキューターが埋める既定値にはなりません。

ページの欠落は「自分のものではない」を意味し、次のチャンカーが尋ねられます。raise は「自分のもので、壊れている」を意味します — オブザーバーの raise と違い、これはソースではなくチャンカーについての判定です。だからエグゼキューターはそれをログに残し、実行がすでに読み取りの対価を払ったエンコードを失敗させる代わりに、次のチャンカーへ進みます。チャンクテキストはチャンカーが書くものであり、ページテキストを再構成する必要はありません。文書ブロックとページブロックは、どちらにせよリーダーのテキストを保持します。

ChunkerProvider は、SourceObserverProvider と同じように任意です。ページを読み取り、境界を一切引かないプロバイダーは決してこれを実装しません。チャンカーは ID を名乗らず、記述子にも加わらず、機能スナップショットにまったく公表されません — チャンカーが変えるのは実行出力の切り方であり、それはどの既存の計画も記録しておらず、どのルーティング決定も参照しません。インストールしても、計画が束縛されているものは何も動きません。

  • 境界を持たない文書には何も返さず、統合が続行できるようにする。理解していないページのためにピースをでっち上げない。
  • 開けないソースのために raise しない — そのバイト列への判定はリーダーがすでに下しており、チャンカーにそれを覆す立場はありません。raise はチャンカー自身の欠陥のために予約されており、その代償は呼び出し側のエンコードではなく、チャンカーのその文書です。
  • ピースは読み順に並べる。エグゼキューターの index とチャンク ID はその順序から導出されます。
  • テキストのないページは画像としてチャンクされるか、まったくチャンクされないかのどちらかです。エグゼキューターがこれを強制します — 読み取り不能なページに主張されたテキストは回答から落とされ、画像は残されます。「無のチャンクはアドレス可能なコンテンツではない」が、すべてのチャンカーの記憶力に依存してはならないからです。
  • モジュールスコープを安価に保つ。検出はスナップショット構築中にすべてのプロバイダーモジュールをインポートするため、重いインポートは chunk() の内側に置く。

二つの属性は意図的にプロトコルの外にあり、False をデフォルトとして読まれます。プロトコルに宣言されたメンバーは、isinstance と型チェッカーの両方が要求するメンバーになるからです。builtin = True は同梱のチャンカーが設定するもので、レジストリはインストール済みチャンカーをそれらより前に並べます — これを主張しても優先度を失うだけなので、何も検証しません。fallback = Trueindx-chunker-page だけが設定するもので、すべての後にソートされます。すべてのページに答えを持つものは、最後に尋ねられる答えでなければなりません。さもなければ、より特化した答えが得られるページは一つもなくなります。

DocumentExecutor.encode はチャンクマップを一度だけ計算します — チャンカーは文書を開き直すことがあるため、リクエストが chunk 粒度を求めたときだけです — そして同じマップを埋め込みパスと blocks.build の両方に渡します。これにより、ベクトルが結び付くチャンク ID と、存在するチャンクブロックは、構造上一つの列挙になります。したがって、あるページが何チャンクを生むかはインストール依存です。解決可能なスキームや観察可能なメディアタイプがすでにそうであるのと同じです。indx-chunker-page がインストールされている場所では 1 ページ 1 チャンクが床になります。

ChunkPiecetextimage のどちらか一方を運び、両方でも、どちらでもなくてもいけません。画像側が存在する理由は一つだけです。どの機能もテキストとして読めなかったページです。そうしたページはどのチャンカーにも切るテキストがないため、以前は理由を抱えたページブロックを残すだけで、検索できるものは何も残りませんでした — chunk_map はテキストのないページをすべて落としており、ドキュメント埋め込みがベクトル化するのはチャンクだけだからです。indx-chunker-pdf は代わりにそのページを INDX_CHUNK_DPI(既定 120)でレンダリングし、画像埋め込み器がそれを他のすべてと同じ空間に置きます。

どのページが対象になるかは意図的に狭くしてあります。空文字列として読めたページは読めています — 白紙なのです — ので、それをレンダリングするのは白を埋め込むためにラスタライズを費やすことになります。レンダリングされるのは、リーダーが failed または unreadable と報告したページだけです。さらに、チャンカーがそうしたページを主張できるのは画像でのみです。ページのテキストはリーダーの判定であり、計画のラダーを降り、出力検証を通過し、機能 ID とトレースイベントを伴って得られたものです。ラダーが諦めたページに対してチャンカーがテキストを主張すれば、検証されていない読み取りを結果に紛れ込ませることになります。ピクセルは何も主張しません — それはページそのものです — ので、捏造されたテキストが落とされる場所で画像は受理されます。ラスタライズできないページはチャンクを持たず、エンコードを失敗させもしません。

チャンキングのうち POLICY_VERSION を動かしたのはこの部分だけで、しかも間接的にです。レンダリングによって DOCUMENT_EMBEDDING_MODALITIESimage を得たため、ドキュメントレーンが画像しかない空間が、満たされない計画からルーティング可能な計画に変わりました。それ以外にここでルーティングの決定であるものはありません。