Files
LangBot/ja/plugin/dev/components/parser.mdx
T
Hyu e279f2fae8 docs(plugin): document per-installation reuse and installation revocation
A Workspace installs a plugin once, but that single installation is reused by
several product objects: every processor for a Runner, every knowledge base for
a KnowledgeEngine / Parser / Retriever, and many conversations or page requests
for the other component kinds. The platform storage key carries no processor or
knowledge-base dimension, so a plugin must fold that identity into its own keys.

- certified-plugins: add "one installation, many usages" with the isolation
  dimensions per component kind, and "when an installation is revoked"
  documenting BasePlugin.on_installation_revoked, its trigger set, the absent
  invocation context and the no-op/failure semantics.
- component pages (runner, knowledge-engine, knowledge-retriever, parser, tool,
  command, event-listener, page): add a short component-specific section with
  that component's own rules and a link to the contract page.
- Align the background-work rule with the SDK contract: the SDK does not track
  ownership of detached work, so a plugin must keep its own binding-keyed
  registry and stop it in the revocation hook.

All three locales carry the same sections.
2026-09-29 20:10:56 +08:00

223 lines
10 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "コンポーネント: パーサー"
---
パーサー(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`を実行し、プロンプトに従ってパーサーの設定を入力します。
```bash
➜ 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.yaml`と`pdf_parser.py`ファイルが生成されます。`.yaml`ファイルはパーサーの基本情報とサポートするMIMEタイプを定義し、`.py`ファイルはこのパーサーのハンドラです:
```bash
➜ MyParserPlugin > tree
...
├── components
│ ├── __init__.py
│ └── parser
│ ├── __init__.py
│ ├── pdf_parser.py
│ └── pdf_parser.yaml
...
```
## マニフェストファイル: パーサー
```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/pdf` | PDFドキュメント |
| `application/vnd.openxmlformats-officedocument.wordprocessingml.document` | Wordドキュメント(.docx) |
| `text/markdown` | Markdownファイル |
| `text/plain` | プレーンテキストファイル |
| `text/html` | HTMLファイル |
## プラグインハンドラ
以下のコードがデフォルトで生成されます(`components/parser/<パーサー名>.py`)。`parse`メソッドを実装する必要があります。
```python
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エンジンの取り込み前)に呼び出されます:
```python
async def parse(self, context: ParseContext) -> ParseResult:
```
**ParseContext**には以下の情報が含まれます:
```python
class ParseContext(pydantic.BaseModel):
file_content: bytes # 生のファイルバイト(LangBotがストレージから読み取り)
mime_type: str # 検出されたファイルのMIMEタイプ
filename: str # 元のファイル名
metadata: dict[str, Any] # FileObjectからの追加メタデータ
```
**ParseResult**は解析結果を返す必要があります:
```python
class ParseResult(pydantic.BaseModel):
text: str # 抽出された完全なプレーンテキスト
sections: list[TextSection] = [] # 構造化セクション(オプション)
metadata: dict[str, Any] = {} # 解析メタデータ(例: page_count, language)
```
**TextSection**はドキュメントから抽出されたテキストのセクションを表します:
```python
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`をチェックして、事前解析されたコンテンツが利用可能かどうかを判断できます:
```python
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')
...
```
## クロスプラグインパーサー呼び出し
他のプラグインが提供するパーサーを呼び出す前に、`self.plugin.list_parsers` を使ってホスト上で現在利用可能なパーサーを列挙できます:
```python
parsers = await self.plugin.list_parsers(mime_type="application/pdf")
# 各要素には plugin_id、plugin_author、plugin_name、name、description、supported_mime_types が含まれます
```
空配列が返る場合、その MIME タイプに対応する接続済みの Parser プラグインは現在存在しません。
`plugin_author` と `plugin_name` を取得したら、`self.plugin.invoke_parser` で対象のパーサーを呼び出せます:
```python
parser = parsers[0]
result = await self.plugin.invoke_parser(
plugin_author=parser["plugin_author"],
plugin_name=parser["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
```
## 1 つの installation、複数の用途
1 つの Parser は**複数のナレッジベース**から使われます(同じ installation の別々のナレッジベースが異なる MIME タイプのファイルをアップロードします)。プラットフォームのストレージキーにはナレッジベースの次元がありません:
- 解析キャッシュと一時ファイルは**ナレッジベース ID** で分離し、キーにナレッジベース ID を含めてください。インスタンスにキャッシュしないでください。
- `ParseContext` と解析の中間結果は 1 回の解析でのみ有効です。インスタンスフィールドやモジュールレベルの変数に保存しないでください。
- 解析の失敗が影響するのは現在のナレッジベースのそのアップロードだけです。他のナレッジベースの解析を利用不能にしてはいけません。
- installation 単位でモデル、パーサー、一時ディレクトリをキャッシュする場合は、`on_installation_revoked(binding)` で解放し、一時ファイルを確実に削除できるようにしてください。
完全な仕様は[認証プラグインと共有実行](/ja/plugin/certified-plugins)を参照してください。
## パーサーのテスト
作成後、プラグインディレクトリでコマンド`lbp run`を実行してデバッグを開始します。その後、LangBotで:
1. 「ナレッジベース」ページに移動
2. ナレッジベースを選択してドキュメント管理に入る
3. ファイルのアップロード時、パーサーセレクターでプラグインが提供するパーサーを選択
4. アップロード後、ドキュメントが正しく取り込まれたことを確認