メインコンテンツへスキップ
パーサー(Parser)コンポーネントにより、プラグインはLangBotにドキュメント解析機能を提供できます。ユーザーがナレッジベースにドキュメントをアップロードする際、LangBotはRAGエンジンのingestステップの前にパーサーを呼び出し、PDF、Word、Markdownなどのバイナリファイルから構造化テキストを抽出します。 ParserとKnowledgeEngineの関係:
  • Parser はファイルをテキストに変換する役割(file → text)
  • KnowledgeEngine はテキストのインデックス作成と検索を行う役割(text → chunks → vectors)
RAGエンジン自体がドキュメント解析機能を持っている場合(DOC_PARSING能力を宣言)、ユーザーはRAGエンジンの内蔵解析機能を使用するか、外部Parserプラグインを使用するかを選択できます。

パーサーコンポーネントの追加

1つのプラグインには任意の数のパーサーを追加できます。プラグインディレクトリでコマンドlbp comp Parserを実行し、プロンプトに従ってパーサーの設定を入力します。
  MyParserPlugin > lbp comp Parser
Generating component Parser...
Parser name: pdf_parser
Parser description: A PDF document parser
Component Parser generated successfully.
組件 Parser 生成成功。
これにより、components/parser/ディレクトリにpdf_parser.yamlpdf_parser.pyファイルが生成されます。.yamlファイルはパーサーの基本情報とサポートするMIMEタイプを定義し、.pyファイルはこのパーサーのハンドラです:
  MyParserPlugin > tree
...
├── components
   ├── __init__.py
   └── parser
       ├── __init__.py
       ├── pdf_parser.py
       └── pdf_parser.yaml
...

マニフェストファイル: パーサー

apiVersion: v1  # 変更しないでください
kind: Parser  # 変更しないでください
metadata:
  name: pdf_parser  # パーサー名、このパーサーを識別するために使用
  label:
    en_US: PDF Parser  # パーサー表示名、LangBotのUIに表示、多言語対応
    zh_Hans: PDF 解析器
  description:
    en_US: 'A PDF document parser'
    zh_Hans: 'PDF 文档解析器'
spec:
  supported_mime_types:  # サポートするファイルのMIMEタイプを宣言
    - application/pdf
execution:
  python:
    path: pdf_parser.py  # パーサーハンドラ、変更しないでください
    attr: PdfParser  # パーサーハンドラのクラス名、pdf_parser.pyのクラス名と一致

supported_mime_types

supported_mime_typesはこのパーサーがサポートするファイルタイプを宣言します。一般的なMIMEタイプ:
MIMEタイプ説明
application/pdfPDFドキュメント
application/vnd.openxmlformats-officedocument.wordprocessingml.documentWordドキュメント(.docx)
text/markdownMarkdownファイル
text/plainプレーンテキストファイル
text/htmlHTMLファイル

プラグインハンドラ

以下のコードがデフォルトで生成されます(components/parser/<パーサー名>.py)。parseメソッドを実装する必要があります。
from langbot_plugin.api.definition.components.parser.parser import Parser
from langbot_plugin.api.entities.builtin.rag.models import (
    ParseContext,
    ParseResult,
    TextSection,
)


class PdfParser(Parser):
    """ファイルからテキストを抽出するパーサーコンポーネント。"""

    async def parse(self, context: ParseContext) -> ParseResult:
        """ファイルを解析して構造化テキストを抽出。

        Args:
            context: file_content(bytes)、mime_type、filename、metadataを含む。

        Returns:
            抽出されたテキストとオプションの構造化セクションを含むParseResult。
        """
        # TODO: 解析ロジックを実装
        text = context.file_content.decode("utf-8", errors="replace")

        return ParseResult(
            text=text,
            sections=[
                TextSection(
                    content=text,
                    heading=context.filename,
                    level=0,
                ),
            ],
            metadata={
                "filename": context.filename,
                "mime_type": context.mime_type,
            },
        )

解析メソッド

parseメソッドは、ドキュメントがナレッジベースにアップロードされた時(RAGエンジンの取り込み前)に呼び出されます:
async def parse(self, context: ParseContext) -> ParseResult:
ParseContextには以下の情報が含まれます:
class ParseContext(pydantic.BaseModel):
    file_content: bytes          # 生のファイルバイト(LangBotがストレージから読み取り)
    mime_type: str               # 検出されたファイルのMIMEタイプ
    filename: str                # 元のファイル名
    metadata: dict[str, Any]     # FileObjectからの追加メタデータ
ParseResultは解析結果を返す必要があります:
class ParseResult(pydantic.BaseModel):
    text: str                            # 抽出された完全なプレーンテキスト
    sections: list[TextSection] = []     # 構造化セクション(オプション)
    metadata: dict[str, Any] = {}        # 解析メタデータ(例: page_count, language)
TextSectionはドキュメントから抽出されたテキストのセクションを表します:
class TextSection(pydantic.BaseModel):
    content: str                   # セクションのテキスト内容
    heading: str | None = None     # セクション見出し
    level: int = 0                 # ネストレベル
    page: int | None = None        # ソースページ番号(PDFなど)
    metadata: dict[str, Any] = {}  # 追加セクションメタデータ

KnowledgeEngineとの連携

ユーザーがドキュメントをアップロードする際、LangBotは以下のロジックで解析フローを決定します:
  • ユーザーが外部Parserプラグインを選択した場合、LangBotはまずParserのparseメソッドを呼び出し、その結果をIngestionContext.parsed_contentを通じてRAGエンジンのingestメソッドに渡します。
  • RAGエンジンがDOC_PARSING能力を宣言しており、ユーザーが外部パーサーを選択していない場合、RAGエンジンが自身でドキュメント解析を処理します。
KnowledgeEngineはIngestionContext.parsed_contentをチェックして、事前解析されたコンテンツが利用可能かどうかを判断できます:
async def ingest(self, context: IngestionContext) -> IngestionResult:
    if context.parsed_content:
        # 外部Parserの解析結果を使用
        text = context.parsed_content.text
        sections = context.parsed_content.sections
    else:
        # ドキュメントを内部で解析
        file_bytes = await self.plugin.get_knowledge_file_stream(context.file_object.storage_path)
        text = file_bytes.decode('utf-8')
    ...

クロスプラグインパーサー呼び出し

KnowledgeEngineプラグインはself.plugin.invoke_parserを通じて、他のプラグインが提供するパーサーを呼び出すことができます:
result = await self.plugin.invoke_parser(
    plugin_author="author_name",
    plugin_name="plugin_name",
    storage_path=context.file_object.storage_path,
    mime_type=context.file_object.metadata.mime_type,
    filename=context.file_object.metadata.filename,
    metadata={},
)
# resultはtext、sections、metadataを含むdict

パーサーのテスト

作成後、プラグインディレクトリでコマンドlbp runを実行してデバッグを開始します。その後、LangBotで:
  1. 「ナレッジベース」ページに移動
  2. ナレッジベースを選択してドキュメント管理に入る
  3. ファイルのアップロード時、パーサーセレクターでプラグインが提供するパーサーを選択
  4. アップロード後、ドキュメントが正しく取り込まれたことを確認