エンタープライズ文書の構造化とメタデータ活用
大規模な企業情報管理において、非構造化データの扱いがボトルネックになるケースは多々あります。PDF とテキストファイルが混在する環境や、ドキュメントの起源を追跡できない状態は、検索システムや RAG(Retrieval-Augmented Generation)パイプラインの構築における典型的な課題です。Deepset が提供する Haystack オープンソースプロジェクトでは、これらの課題に対処するため、`FileTypeRouter` コンポーネントにメタデータ管理機能が大幅に強化されました。
最新のアップデートにより、ファイル形式に基づく単純な分類だけでなく、コンテキスト情報を保持したままデータを下流のコンポーネントへ転送できるようになりました。これにより、事前変換のオーバーヘッドを削減し、処理精度の向上を実現しています。
アーキテクチャの進化点
haystack/components/routers/file_type_router.py に定義される FileTypeRouter は、複数のソースタイプ(文字列パス、パスオブジェクト、バイトストリームなど)を入力として受け取り、MIME タイプに基づいて分岐させる役割を担います。今回のメタデータ拡張機能は、以下のような技術的メリットを提供します:
- 情報の付与自動化:ファイル识别のタイミングで、承認者や作成日時などの属性情報をストリームに直接埋め込むことができます。
- 型の一貫性維持:
PathやByteStreamをメタデータを含む統一されたオブジェクトとして扱うことで、後段の変換器との結合をスムーズにします。 - パイプラインの簡素化:明示的な中間層を経由せずに、ルータ段階でメタデータを完結させ、処理ステップ数を最小化できます。
実装ロジックの詳細
内部処理においては、入力メタデータとソースリストをマッピングする正規化プロセスが中心となります。以下のコードは、メタデータを安全に結合する run メソッドの実装例を示します。変数名や構造を一部変更して、可読性と保守性を高めています。
def process_stream(
self,
sources: list[Union[str, Path, ByteStream]],
input_attributes: Optional[Union[dict[str, Any], list[dict[str, Any]]]] = None,
) -> dict[str, list[Union[ByteStream, Path]]]:
# メタデータのパースと標準化
normalized_meta_list = normalize_meta_data(meta=input_attributes, count=len(sources))
for source_obj, attr_map in zip(sources, normalized_meta_list):
# ソースオブジェクトを内部表現に変換
if attr_map:
byte_stream_instance = convert_to_bytestream(source=source_obj)
# ドキュメント固有の属性を追加
updated_meta = {**byte_stream_instance.meta, **attr_map}
byte_stream_instance.meta = updated_meta
# ルートのキーに対応するリストに追加する処理...
このロジックは、MIME タイプパターンとの照合に加え、ユーザー指定の辞書型メタデータを ByteStream インスタンスのプロパティとして継承させることを保証します。
実践:動的ルーターを持つ文書処理パイプライン
特定の業界向け、例えば法務部門の契約書審査システムを構築する際の具体例を見てみます。MIME タイプ判定に加え、ファイル名やヘッダー情報のメタデータを使ってフィルタリングを行います。
from haystack import Pipeline
from haystack.components.routers import FileTypeRouter
from haystack.document_stores.in_memory import InMemoryDocumentStore
# ルーター初期設定:カスタムフォーマットを含める
doc_router = FileTypeRouter(
mime_types=[r"application/pdf", r"text/plain"],
additional_mimetypes={
"application/vnd.ms-word": ".docx"
}
)
# パイプライン定義
pipeline = Pipeline()
pipeline.add_component("router", doc_router)
pipeline.add_component("pdf_processor", PDFConverter())
pipeline.add_component("txt_processor", TextExtractConverter())
# 接続関係の定義
pipeline.connect("router.application/pdf", "pdf_processor.sources")
pipeline.connect("router.text/plain", "txt_processor.sources")
# データ実行:メタデータ付きでの起動
results = pipeline.run({
"router": {
"sources": ["legal_agreement_v2.pdf", "internal_notes.txt"],
"input_attributes": [
{"division": "Legal", "risk_level": "high"},
{"division": "Internal", "risk_level": "low"}
]
}
})
上記の実行結果において、生成されたドキュメントには元のファイル形式に加えて、input_attributes で渡した部署名やリスクレベル情報が doc.meta 内に保持されます。これにより、後続の検索エンジンやアクセス制御モジュールは、メタデータに基づいた高度なフィルタリングが可能になります。
構成の最適化とベストプラクティス
パフォーマンスと整合性を確保するために、いくつかの設定方針が推奨されています。
MIME タイプパターン設計
特定フォーマットの識別には完全一致を使用し、バリエーションのある形式には正規表現を適用するのが一般的です。また、社内独自のフォーマットが必要になった場合、additional_mimetypes を介して独自ミラーリングを登録できます。
router_config = FileTypeRouter(
mime_types=[r"application/pdf", r"text/(plain|csv)", r"image/png"],
additional_mimetypes={"custom/internal-format": ".intf"}
)
メタデータスキーマの標準化
分散システム間でデータを受け渡す際、メタデータの構造がばらつくとトラブルの原因となります。次のような固定鍵の採用を検討してください:
file_origin: データの元となる URI またはパス識別子version_hash: ファイル変更時のハッシュ値classification_tag: アクセス権限や機密等級を格納
将来的な機能拡張の方向性
今後のロードマップでは、コンテンツ自体の分析にも対応することが予定されています。具体的には軽量な NLP モデルを組み込んだ「意味理解型ルーター」の実装や、メタデータ条件に応じた動的ルールエンジンへのサポートなどが検討されています。これらの機能は、さらに洗練されたデータ前処理基盤の実現に向けた一歩となります。