非構造化文書を構造化するAPI/ETLパイプラインを立ち上げるためのノンコードLLMプラットフォーム「Unstract」を試す
ここで知った。
👨🔧便利 - ノンコードLLMプラットフォームで、非構造化文書を構造化するAPIとETLパイプラインを立ち上げることができます
これにより、機械間自動化を実現することで、co-pilot以上の働きが可能になります。
複雑なドキュメントを受け取り、構造化されたJSONを返すAPIを、シンプルなノンコードアプローチで立ち上げることができます。
また、さまざまなクラウドファイル/オブジェクトストレージシステムから複雑なドキュメントを読み込み、構造化されたデータを一般的なデータウェアハウスやデータベースに書き込むことができる、非構造化データETLパイプラインを起動することもできます。
Unstract
非構造化文書を構造化するAPIおよびETLパイプラインを起動するLLMプラットフォーム
🤖 co-pilotsを超える
co-pilotsは、マシンと人間間の自動化を実現しますが、Unstract を使用すれば、マシンとマシン間の自動化も可能になり、co-pilotsの機能を超えたものとなります。 簡単なノンコードアプローチで、複雑なドキュメントを取り込み、構造化された JSON を返す API を起動することができます。 また、さまざまなクラウドファイル/オブジェクトストレージシステムから複雑なドキュメントを読み取り、構造化されたデータを一般的なデータウェアハウスやデータベースに書き込むことができる、非構造化データ ETL パイプラインも起動できます。
referred from https://github.com/Zipstack/unstract🧘♀️ 三歩の悟り
人間が関与する複雑な文書を含む重要なビジネスプロセスを自動化します。 大規模言語モデルの力を活用して、RPAの枠を超えた取り組みを実現します。
- 🌟 ステップ1:ノンコードのPrompt Studio にドキュメントを追加し、プロンプトエンジニアリングを行って必要なフィールドを抽出します
- 🌟 ステップ 2: Prompt Studio プロジェクトを API 展開として設定するか、ETL パイプラインの入力ソースと出力先を設定します
- 🌟 ステップ 3: ワークフローを非構造化データ API または非構造化データ ETL パイプラインとして展開します!
referred from https://github.com/Zipstack/unstract
セットアップ
クラウドとローカルで提供されているので、Getting Started に従ってローカルでやってみる。
一応要件
- システム要件
- RAM 8GB
- 前提
- Linux / Mac
- Docker
- Docker Compose
- Git
クローンしてdocker composeであげるだけかなーと思いきや、起動スクリプト経由でセットアップするようで、この起動スクリプトの中身を見ると、どうもpython、しかも3.9.6が必要っぽい(.python-version
がそうなってる)。なので、一応pyenvとか仮想環境は用意して進めたほうがいいと思う。
今回は手元のMacでやる。ではレポジトリをクローン。
$ git clone https://github.com/Zipstack/unstract && cd unstract
起動スクリプトを実行
$ ./run-platform.sh
結構色々立ち上がるっっぽい。
█████ █████
░░███ ░░███
░███ ░███
░███ ░███
░███ ░███
░███ ░███
░░█████████ >UNSTRACT COMMUNITY EDITION
░░░░░░░░░
Adding encryption secret to backend
Adding default auth and system admin credentials to backend
Created env for backend at /Users/kun432/repository/unstract/backend/.env.
Created env for frontend at /Users/kun432/repository/unstract/frontend/.env.
Adding encryption secret to platform-service
Created env for platform-service at /Users/kun432/repository/unstract/platform-service/.env.
Created env for prompt-service at /Users/kun432/repository/unstract/prompt-service/.env.
Created env for worker at /Users/kun432/repository/unstract/worker/.env.
Created env for x2text-service at /Users/kun432/repository/unstract/x2text-service/.env.
Created env for essential services at /Users/kun432/repository/unstract/docker/essentials.env.
Created env for docker compose at /Users/kun432/repository/unstract/docker/.env.
Pulling docker images tag latest.
[+] Pulling 48/23
✔ backend Skipped - Image is already being pulled by celery-beat 0.0s
✔ execution-consumer Skipped - Image is already being pulled by celery-beat 0.0s
⠴ feature-flag [⣿⣿⣿⣿⠀⣿] 8.232MB / 22.78MB Pulling 20.6s
⠴ x2text-service [⣀⣿⣿⣿⣿⣿⣿⣿⣀] 63.14MB / 119.2MB Pulling 20.6s
⠴ db [⣿⣿⣿⠀⣿⣿⣿⣿] 3.05MB / 106.2MB Pulling 20.6s
⠴ prompt-service [⣿⣿⣿⣿⠀⠀] 13.75MB / 706.9MB Pulling 20.6s
⠴ qdrant [⠀⠀⠀⠀⠀⠀⠀] Pulling 20.6s
⠴ frontend [⣿⠀⣿⠀⣿⣿⣿⣿⣤] 11.54MB / 78.14MB Pulling 20.6s
⠴ platform-service [⣿⣿⠀⣿⣿] 18.27MB / 97.52MB Pulling 20.6s
⠴ reverse-proxy [⣿⠀⠀⠀] Pulling 20.6s
⠴ celery-beat [⠀⠀⣿⣿⣿] 8.292MB / 778.9MB Pulling 20.6s
⠴ worker [⠀⣿⣶⣿⣿] 20.03MB / 240.9MB Pulling 20.6s
⠴ minio [⣿⣶⣿⣿⣿⣿⠀⡀⣿⣿⣿⣿] 9.767MB / 51.47MB Pulling 20.6s
⠴ redis [⠀⠀⠀⠀⠀⠀⠀] Pulling 20.6s
以下のように表示されればとりあえずは起動している様子。
Once the services are up, visit http://frontend.unstract.localhost in your browser.
See logs with:
docker compose -f docker/docker-compose.yaml logs -f
Configure services by updating corresponding <service>/.env files.
Make sure to restart the services with:
docker compose -f docker/docker-compose.yaml up -d
###################### BACKUP ENCRYPTION KEY ######################
Copy the value of ENCRYPTION_KEY in any of the following env files
to a secure location:
- backend/.env
- platform-service/.env
Aapter credentials are encrypted by the platform using this key.
Its loss or change will make all existing adapters inaccessible!
###################################################################
ブラウザでhttp://frontend.unstract.localhost
にアクセスすると以下の画面が表示されるので、しばらく待つ。
準備ができたみたい。”Login”をクリック。
ユーザ名・パスワード共にunstract
でログイン。
再度以下の画面が出るのでしばらく待つ。
表示された。最初は諸々セットアップしていく模様。まずLLMから。
LLMプロバイダーの一覧が表示される。
選択可能なLLMプロバイダーは以下。
- Ollama
- Amazon Bedrock
- AnyScale
- Anthropic
- OpenAI
- Azure OpenAI
- Palm
- VertexAI
- Replicate(Coming Soonらしく選択できなかった)
- MistralAI
今回はOpenAIで。
APIキーなどを入力。入力したのは上の3つだけであとはデフォルトで良かった。入力したら"Test Connection"をクリック。
テスト接続OK
"Submit"をクリック
LLMの設定完了。こんな感じで順次設定していく。次はベクトルデータベース。
ベクトルデータベースは以下の5つに対応。今回はQdrantのクラウドを使う。事前にQdrant Cloudでクラスタを作成して、URLとAPIキーを取得しておく。以下細かい説明は割愛。
続いてEmbedding。
EmbeddingもOpenAIを使う。
んー、モデルを入力する欄がないけど、どのモデルになるんだろうか?
最後にText Extractor。
LLMWhisplerってのだけ知らなかったけど、これはUnstractがやっているクラウドサービスっぽい。今回はLlama Parseを選択した。Llama CloudのAPIキーが必要になる。
最後の設定が終わると、やっとトップ画面らしきものが表示された。
セットアップはこれで完了。次は実際の操作をやっていく。
実際の操作。こちらについては、公式ドキュメントのGetting Startedに記載がある。
デモ用にクレジットカードの明細のサンプルが用意されているのだが、全て英語となっている。当然やるからには日本語でやりたい。ということで、サンプルの請求書PDFを作成した。なお、この請求書はClaude ArtifactsにHTMLで作成させたものをPDFに変換している。
サンプル1 | サンプル2 | サンプル3 |
---|---|---|
3つのサンプルのうち最初の2つを登録して、構造抽出およびAPI化を行って、3つ目のものでそれが機能するかを確認する流れとする。
まず新規プロジェクトを作成する。プロジェクトは、ドキュメントのタイプごとに作成する模様。Unstractでは、このプロジェクトを「Prompt Studioプロジェクト」と呼んでいる。Prompt Studioメニューから"+ Prompt Project"をクリック。
プロジェクトの説明を入力して保存。アイコンはオプション。
こんな感じの画面になる。
画面レイアウトの説明。
- プロンプトエンジニアリングペイン
- さまざまな種類のドキュメントから情報を抽出するプロンプトを追加および管理する場所。
- ドキュメントペイン
- ドキュメントをネイティブ形式、rawデータ形式、要約形式で表示する。
- ドキュメントマネージャー
- Prompt Studioプロジェクト内でアップロードされたドキュメントを管理する。
- プロジェクトの設定
- LLMプロファイルなど、Prompt Studioプロジェクトの様々な設定を制御
- 新しいプロンプトの追加
- 新しいプロンプトを作成
- プロジェクトのエクスポート
- Prompt Studio プロジェクトの作成・編集後にプロジェクトをエクスポートすることで、任意のワークフローの一部として使用できるカスタムツールとして保存することができる
エクスポートのところを読んで、なるほど、新規プロジェクト登録時に"Add Tool Information"となっていたことに納得。
最初にプロジェクトの基本設定を行う。プロジェクトの設定アイコンをクリック。
以下のような画面が表示される。
基本設定で最低限設定しないといけない項目は以下の様子。
- LLMプロファイル
- プリアンブル
- ポスタンブル
順に見ていく。まずLLMプロファイルから。
LLMプロファイルでは、ドキュメントのインデックス化や構造化に関する設定、つまり、LLM,ベクトルDB、Embeddingモデルの組み合わせおよびチャンク設定を行う。プロジェクト内に複数のプロファイルを複数作ることで、プロンプトごとに切り替え手試したりできるらしい。(最初の設定ではLLMやベクトルDBは一つしか作っていないけども、あとから増やして選択する、みたいなことができるのかな?)
以下のように入力して保存。チャンクサイズとオーバーラップが0なのは意味があるらしく、後で説明を見てみる。
登録された。最初のプロファイルはデフォルトのプロファイルになる。
次にプリアンブル。プリアンブルというのは、LLMに送られるプロンプトの前につけられ不必要な繰り返しを避けるために有用、とあるが、自分の認識だとシステムプロンプトだと思う(例えば、Cohereではシステムプロンプトをプリアンブルといってたはず。)
デフォルトでは以下のようなものが入っていた。
Your ability to extract and summarize this context accurately is essential for effective analysis. Pay close attention to the context's language, structure, and any cross-references to ensure a comprehensive and precise extraction of information. Do not use prior knowledge or information from outside the context to answer the questions. Only use the information provided in the context to answer the questions.
日本語訳。
この文脈を正確に抽出して要約する能力は、効果的な分析に不可欠です。文脈の言語、構造、相互参照に細心の注意を払い、包括的かつ正確な情報の抽出を確実に行なってください。質問に回答する際には、文脈外の予備知識や情報を使用しないでください。質問に回答する際には、文脈で提供されている情報のみを使用してください。
ドキュメントでは文書のユースケースに合わせて書き換えているようなので、以下のように書き換える。
Your ability to extract and summarize this information accurately is essential for effective Japanese invoice analysis. Pay close attention to the invoice's language, structure, and any cross-references to ensure a comprehensive and precise extraction of information. Do not use prior knowledge or information from outside the context to answer the questions. Only use the information provided in the context to answer the questions.
一応日本語訳
この情報を正確に抽出して要約する能力は、効果的な日本語請求書の分析に不可欠です。請求書の言語、構造、相互参照に細心の注意を払い、包括的かつ正確な情報の抽出を確実に行うようにしてください。質問に答えるために、文脈外の予備知識や情報を使用しないでください。質問に答えるために使用できるのは、文脈内で提供されている情報のみです。
変更したら保存。
最後にポストアンブル。
この用語は初めて聞いたし、イメージも沸かないだが、ドキュメントによると、
- プリアンブルと同じ用途
- ただし、入力したプロンプトごとに付加される
らしい。ユーザープロンプトに対して必ず付与されるシステムプロンプト的なもの、というイメージを持った。
とりあえずここはデフォルトのままでOKっぽい。
設定が終わったら元の画面に戻って、ドキュメントを登録する。"Manage Documents"をクリックして、ドキュメントマネージャーを開く。
"+ Upload New File"から請求書のサンプル1と2をアップロード。
アップロードされた。表示にもあるように、アップロードしたドキュメントはまだインデックス化・要約されていないが、これは新しいプロンプトを登録したときにあわせて行われるらしい。1つ目のドキュメントが選択されていることを確認したら、元の画面に戻る。
元の画面でドキュメントペインにさきほど選択した請求書サンプルが表示されている。
ではプロンプトを登録する。"+Prompt"をクリック。
こんな画面が表示される。ちょっとわかりにくいのだが、赤枠の部分が入力可能になっていて、それぞれフィールド名とプロンプトになる。つまり、抽出したいフィールドをプロンプトで定義するということらしい。
以下のように入力して白抜きの再生ボタンをクリックして実行。
フィールド名 | プロンプト |
---|---|
invoice_issuer_name | この請求書を発行した発行者または会社の名称は何ですか? |
請求元会社名が取得できていて、その他かかったコストなんかも見える。そして、ドキュメントは2件登録していたはずだが、1件だけ処理されていることもわかる。白抜きの再生ボタンは今見ているドキュメントのみ、黒抜きの再生ボタンは登録したドキュメント全てに対して抽出を行うようになっているらしい。ということでもう1つのサンプルもし抽出すべく今度は黒抜きの再生ボタンをクリック。
一瞬終わったように感じるが、しばらく待っていると、2件とも終わったことが確認できる。"Coverage: 〜"をクリック。
一覧で表示され、2件とも抽出できていることがわかる。
あとは、抽出したい項目に対して、上記を繰り返していけば良い。なお、複数項目を一度に取得するようなケースではJSONを使うっぽい。
ということで登録してみた。
各項目の登録内容は以下。
フィールド名 | プロンプト | タイプ |
---|---|---|
invoice_customer_name | この請求書に記載されているお客様名または会社の名前はなんですか?敬称は不要です。 | Text |
invoice_customer_address | 提供された文脈には複数の住所が記載されている可能性があるため、まずすべての住所を収集してください。次に、この請求書が誰宛てに送られているのか、つまり請求先お客様の名前を理解するようにしてください。そして、その名前が合致する住所を見つけてください。お客様の住所を常に返すようにしてください。他の住所を返さないでください。 お客様の住所については、以下のフィールドを持つシンプルなJSONオブジェクトを作成してください。 - full_address: お客様の完全な住所である必要がある - prefecture: 住所から取得した都道府県名のみである必要がある - city: 住所から取得した市区町村名のみである必要がある - zip: 郵便番号のみである必要がある |
json |
invoice_payment_info | 請求金額は請求書において重要な部分であり、支払い方法・小計(税抜)・消費税額・合計請求額(税込)で構成される。 以下のフィールドを含むJSONオブジェクトを返してください。 - payment_method: 支払い方法。以下の3つから選択。"請求書"、"小切手"、"クレジットカード" - total_wo_tax: 税抜の小計金額 - tax:消費税額 - total_w_tax:税込の合計請求額 |
json |
invoice_line_items | この請求書には請求内容の内訳が記載されており、内訳に記載された各請求項目は与えられたコンテキスト全体にわたって分割することができる。常に全体的なコンテキストを確認し、すべての請求項目の詳細を回答してください。 各請求項目について、以下のフィールドを含むシンプルなJSONオブジェクトを作成してください。 - item_name: 請求項目の項目名 - item_num: 請求項目の個数 - price_per_unit: 請求項目のユニットあたりの単価 - price_per_item: 請求項目ごとの金額 これらの項目を含むオブジェクトをJSON配列に格納し、それを返してください。 |
json |
で、抽出された全部の項目をまるっとJSONオブジェクトで見るには"Combined Output"タブをクリック。
こんな感じで抽出されている。ドキュメントペインの右上の"<" と">"でドキュメントを切り替えれる。
プロンプトエンジニアリングペインの右上にあるアイコンをクリックすると、Output Analyerが立ち上がり、抽出した結果とドキュメントを並べて比較できる。
元の画面に戻ってドキュメントペインの左上にある"Raw View"をクリックすると、Text Extractor(今回はLlama Parse)が抽出した生の文字列を確認することができる。
抽出のプロセスは、
ドキュメントからText Extractorがテキストを抽出
↓
LLMでクエリを踏まえて該当箇所を抽出
という流れになるので、つまり、抽出ミスが起きた場合はここで確認を行い、どちらで間違っているかを判断するということになる。当然ながら、処理の流れから考えると、Text Extractorでの抽出品質がまずは重要であり(Garbage in, Garbage out
)、OCR等の場合にはミスが起こりやすい可能性がある。
作成したPrompt Studioプロジェクトをエクスポートすることで、ワークフロー内の1コンポーネント(これをUnstractでは「ツール」と呼ぶ)として利用ができるようになる。紹介されているワークフローのユースケースは以下。
- APIワークフロー
- ドキュメント/PDFがAPIに投稿されるとJSONで応答する公開APIを作成できる
- 非構造化データETLパイプライン
- ネットワークやクラウド上のファイルシステム・オブジェクトストアからドキュメントをピックアップして、それらを構造化し、構造化の結果をデータウェアハウスやデータベースにプッシュする
今回は先ほど作成したプロジェクトを公開APIとするワークフローを作ってみる。
まず、先ほど作成したプロジェクトをエクスポートする。右上のエクスポートアイコンをクリック。
プロジェクトがツールとしてエクスポートされた。
ではワークフローを作成する。左のメニューから”Workflows”をクリック。
"+ New Workflow"をクリック
ワークフローの名前と説明を入力して作成。
ワークフロー作成画面が表示される。右に先ほどエクスポートしたツールが表示されているのと、それ以外にもビルトインのツールが用意されているのがわかる。
ワークフロー作成画面の説明
- 入力設定:
- 入力のデータソースを設定する。
- 今回は、ドキュメントをAPIとして受け取るワークフローとして作成するため、「API」を選択。
- ETLパイプラインを構築したい場合は、このリストから「File System」を選択する。
- 出力設定
- 出力のデータソースを設定する。
- 今回は、APIワークフローとしてデプロイするので「API」を選択。
- 非構造化データETLパイプラインをデプロイする場合、はデータベース(「Database」)やファイルシステム(「File System」)を単託する。
- ワークフローチェーン
- 右側のツールペインの利用可能なツールリストからツールをドラッグ&ドロップで並べる。
- さまざまなツールを連結することで、高度なワークフローを構成することができる。
- 今はサンプルとして、先ほどエクスポートしたツール1つだけを含むチェーンとする
- 入出力ビューア
- Workflow Studio のシングル ステップ モードで、ステップごとの入出力を確認できる。高度なワークフローの開発やデバッグに有用。
- 今回のプロジェクトでは使用しない。
- ツールペイン
- プラットフォームで使用可能なすべてのビルトインツールや自分で作成したカスタムツールが一覧表示される。
- エクスポートしたPrompt Studioプロジェクトは、このペインでツールとして利用できるようになる
- ここワークフローチェーンにドロップ&ドロップしてワークフローを構築する
- ツール設定ペイン
- ツールの設定を行う。
- ツールの設定を変更するには、ワークフローチェーンにツールを配置してから行う。
- APIとしてデプロイ
- 作成したワークフローをAPIとしてデプロイする
- ETLパイプラインとしてデプロイ
- 作成したワークフローを非構造化データETLパイプラインとしてデプロイする
- タスクパイプラインとしてデプロイ
- アドホックな非構造化データタスク向けパイプラインとしてデプロイする(らしい、ドキュメントに記載がないので詳細不明)
ということで、早速やってみる。
ワークフローチェインで入力設定・出力設定を共に「API」に設定。
先ほどエクスポートしたツールを、ツールペインからワークフローチェインにドラッグ&ドロップする。
APIとしてデプロイする
APIの名前等を入力して保存。なお、"API Name"は英数字/ハイフン/アンダースコアのみとなる(のでおそらくエンドポイントURLに含まれるのだろうと思う)
APIとしてデプロイされた。このAPI名をクリック。
登録したAPIが表示されている。APIは左のメニューの"API Deployments"に登録されるらしい。クリップボードアイコンをクリックするとAPIエンドポイントがコピーされるので控えておいて、右端の三点リーダーをクリック。
メニューから"Manage Keys"をクリック
このAPIワークフローのAPIキーが表示されるので、これもコピーして控えておく。
ではこのAPIにアクセスしてみる。ドキュメントに従ってPostmanを使用する。設定手順はドキュメントに書いてあるので、説明割愛してキャプチャだけ。
"Send"でリクエスト送信、少し時間が掛かる。で、結果。
エラー・・・
いろいろサンプルを変えてみたり、なんならプロジェクト作った時のサンプルPDFを使ってみたりしたのだけど、それでも同じエラーになる。
ログを見てみる。
んー、返ってきたエラーメッセージとはちょっと違うところでコケているような気がする。そして全部このエラーになっている。そもそもファイルを正しく受け取れていないのでは。。。。?
ちなみにワークフロー画面でも実際のファイルを使ってテストができるのだけど、同じエラーでコケた。
んー、ファイルが受け取れていないというよりも受取処理に問題がある、という感じかなぁ、、、設定がどこかしら間違っている可能性は否定できないけども、なんとなくバグか環境起因な気がするなぁ・・・
Priompt Studioだとちゃんと動くので、ワークフロー周りで何かしら問題があるのかもしれない。
とりあえずIssue上げといた
Issueで色々やり取りしつつ試しつつわかったこと。結論から言うと、
- Text ExtractorにLlama Parseを使うとWorkflowおよびAPIの実行に失敗する
- 現時点ではLLMWhispererを使えば問題なさそう
ということ。
詳細。
- 上記のエラーはv0.81.0でregressionしたもの。v0.81.1で修正されている可能性があるとのこと。
- だが、バージョンを上げても変わらなかった。イメージやボリュームを全部消して作り直しても変わらなかった。
- 公式ドキュメントで用意されている英語のサンプル(クレジットカードの明細書のパース)をやってみたら、今度はパースすらうまくいかない。
- ふと思い立って、Text Extractorを、Llama Parseから、Unstractが提供しているLLMWhispererに変えた(LLMWhispererのアカウントを作成してAPIキーを取得)ところ・・・
- 公式の英語のサンプルを使ってドキュメント通りに進めると全て問題なく動作。
- 日本語でもたまに失敗することがあるものの、一応APIリクエストでパースが成功することを確認できた。
ということで、以下はLLMWhispererを使った場合のPostmanの結果
{
"message": {
"execution_status": "COMPLETED",
"status_api": "/deployment/api/mock_org/parse_japanese_invoice/?execution_id=6d085cd4-6916-4bdc-b645-e5bd01a6cfb2",
"error": null,
"result": [
{
"file": "請求書サンプル3.pdf",
"status": "Success",
"result": {
"output": {
"invoice_customer_address": {
"city": "千代田区",
"full_address": "〒 100-0001 東 京 都 千 代 田 区 見 本 町 1-1",
"prefecture": "東京都",
"zip": "100-0001"
},
"invoice_customer_name": "模範商事株式会社",
"invoice_issuer_name": "模範商事株式会社",
"invoice_line_items": [
{
"item_name": "特選和紙 (A4サイズ)",
"item_num": 1000,
"price_per_item": 50000,
"price_per_unit": 50
},
{
"item_name": "高級墨 (松煙)",
"item_num": 20,
"price_per_item": 40000,
"price_per_unit": 2000
},
{
"item_name": "筆セット (各種)",
"item_num": 50,
"price_per_item": 50000,
"price_per_unit": 1000
}
],
"invoice_payment_info": {
"payment_method": "請求書",
"tax": 14000,
"total_w_tax": 154000,
"total_wo_tax": 140000
}
}
},
"metadata": {
"source_name": "請求書サンプル3.pdf",
"source_hash": "0a362e7b1825f8c507b2306d88451ef83e5a7390065a770184865824cce55e7b",
"organization_id": "mock_org",
"workflow_id": "aa624005-4bcb-4fad-a0e3-1ff3dfe26cf8",
"execution_id": "653f38d7-91fc-4456-8aa5-adea995a694b",
"total_elapsed_time": 139.627854,
"tool_metadata": [
{
"tool_name": "structure_tool",
"elapsed_time": 139.627803,
"output_type": "JSON"
}
]
}
}
]
}
}
1つ前のコメントにも書いているけども、Llama Parseを使った場合でもPrompt Studioでパースはできている(つまりここでもLlama Parseを使っているはず、そしてパースはできているはず)ように思えるので、やっぱりワークフローのところでLlama Parseと連携させた場合に限って問題があるのだと思っている。
なお、LLMWhispererの設定は、今回はGetting Startedで指定されているとおりに設定した。
OCRを使うようにしてあるせいかinvoice_customer_address.full_address
にスペースが含まれてしまっているのがなんとも、、、まあLLMのプロンプトで取り除くようにするのが良いかもしれない。
なお、LLMWhispererの料金プランを見てみたところ、無料の場合は100ページ/日になっている。個人的にはちょっと高いかなーと感じてしまったが、業務で使わないのであれば問題なさそうには思う。
というか業務で扱うならローカルで完結したいかなー、unstructured-ioのセルフホストもサポートされているようなので、これをなんとか使うようにしたい。
これ、起きているエラーの内容を見る限り、使用するText Extractorの違いがそれに繋がっている、というふうには考えにくい気もしてて、どうしたもんかなーと思いつつ、引き続きIssueで色々やり取りを進めているところ。
所感
ちょっと最後のところでハマったけども、とりあえず一通り動くところまでは終わらせたので、所感をまとめる。
- 非構造化文書のパースはLLMを活用する上で以前からよく聞く話で、ニーズは間違いなくありそう。
- OCRとLLMを組み合わせるってのも以前からあるパターンで、自分で実装するってのもできない話ではない
- ただ自分でやるとなると、
- 様々なドキュメントのフォーマットに対応するのは大変そう
- ETLパイプラインを構築するツールやサービスを使うというやり方もあるけれど、GUIかつ簡単に使えるもの、となるとなかなかなさそう
ということを踏まえると、ワンストップで簡単に構築・利用ができるパッケージとしてのUnstractがハマるケースは十分あると思う。
ただし、
- 最近はマルチモーダルLLMの性能が上がっているので、OCRを使わずにLLM一発でやってしまうっていう流れが来そうな雰囲気はある。なので、OCR→LLMみたいに二段階で処理させるっていうこれまでのやり方にはメリットもデメリットもありそう。
- OCRの性能が足を引っ張るということはありうるし、LLMの前処理部分になるので、ここがダメだとLLMで何やってもだめになる
- ただし今後高性能なOCRモデルとかがでてきたりすると、そこだけ差し替えるということは可能になりそうだし、汎用LLMほどモデルサイズ大きくなくてもいけそうな気がするし、差し替え時の影響範囲も小さくて済みそう
- あとマルチモーダルなら、音声とか画像・映像とかもできるしね
- ユースケースがはっきりしているのは良いのだけども、ETLとしてみるとかなり機能は少ないのではなかろうか?
- 自分はETLパイプラインをやったことがないのでその定義を正しく理解できていないと思うが、ワークフローな感じのイメージを持っていて、例えば処理を分岐させるであるとか、入出力で接続するデータソースが多数あるとか、っていうのがETLには求められるのかなと思っていたりする。
- どっちかというとOCR+LLM使ったパースを作ってシンプルなETLっぽいパッケージにしました、という雰囲気を感じている。
- だったらETLツールでLLM対応したほうが拡張性とかもあって良くね?という感もある
- 間違ってたらすいません
あたりを考えると、比較的小規模でサクッと使うみたいなユースケースになるのかなぁと感じる。
以下の記事にもあるように、LLMを使ったETLプロセスの重要性とかニーズはさらに上がっていきそうなので、重厚なETLを時間かけてやるよりも、Unstract使ってスピード優先で社内文書をサクサクデータ化するという考え方もあるかなとは思う。
とりあえずまだv0.Xだし今後に期待。実際、自分はバグ検証のために何回もインストール・セットアップ繰り返した中で操作に慣れてしまったのだけど、慣れればサクサク設定できちゃうのでドキュメントの構造化がどんどん進みそうな雰囲気は感じた。そこは確かにメリットではある。
あとちょっとなるほどなと思ったのは、プロンプトをフィールドごとに用意するところ。
いちいちフィールドごとに設定するのめんどくさくない?と思ったのだけども、
- LLMにやらせるなら複数のフィールドを同時に解析させるよりも、1つの項目に集中させたほうが基本的には精度が良いはず
- 文書単位でプロンプトを設定してしまうと、文書のフォーマットがちょっと異なっただけで別のプロンプトを管理しないといけなくなりそうだけど、項目ごとならばおそらくいろんな文書に対応する柔軟性が確保できそう
- 対応しない項目は「なし」で良い。
- ただしLLMへのリクエストも項目単位になると思うので、ちょっと高くなりそう
このあたりは他のことでも参考になりそう。
自分はETLパイプラインをやったことがないのでその定義を正しく理解できていないと思うが、ワークフローな感じのイメージを持っていて、例えば処理を分岐させるであるとか、入出力で接続するデータソースが多数あるとか、っていうのがETLには求められるのかなと思っていたりする。
Claude-3.5-Sonnetにきいてみた。
以下の違いを教えて下さい。具体的な製品名やサービス等の例も教えて下さい
- ETLパイプライン
- データパイプライン
- ワークフロー
これらの概念には重複する部分がありますが、それぞれ特徴や用途が少し異なります。具体的な違いと例を説明します。
1. ETLパイプライン:
ETLは「Extract(抽出)、Transform(変換)、Load(ロード)」の略です。主にデータウェアハウスやデータレイクにデータを統合する際に使用されます。
特徴:
- データの抽出、変換、ロードに特化
- 主にバッチ処理で使用される
- 構造化データの処理に適している
例:
- Talend
- Informatica PowerCenter
- Microsoft SQL Server Integration Services (SSIS)
2. データパイプライン:
ETLパイプラインを含む、より広範囲なデータ処理のフローを指します。リアルタイムデータ処理やストリーミングデータの処理も含みます。
特徴:
- ETL以外のデータ処理も含む
- バッチ処理とリアルタイム処理の両方に対応
- 構造化データと非構造化データの両方を扱える
例:
- Apache Kafka
- Apache Nifi
- Google Cloud Dataflow
3. ワークフロー:
より一般的な用語で、ビジネスプロセスや作業の流れを自動化するためのシステムを指します。データ処理に限らず、様々な業務プロセスの自動化に使用されます。
特徴:
- データ処理以外の業務プロセスも含む
- 人間の介入を含む複雑なプロセスの自動化が可能
- 条件分岐や承認プロセスなどを含む
例:
- Airflow
- Zapier
- Microsoft Power Automate
これらの概念は重複する部分があり、多くのツールが複数の機能を提供しています。例えば、AirflowはETLパイプライン、データパイプライン、ワークフローのすべての機能を持っています。
使用するツールや概念は、具体的なニーズや要件によって選択されます。データ統合が主な目的であればETLパイプライン、リアルタイムデータ処理が必要であればデータパイプライン、より広範囲な業務プロセスの自動化が必要であればワークフローツールが適しているでしょう。
これがあってるならば、自分のETLの認識は広すぎたかも、汗
unstractのワークフローで使えるツールはデフォルトだとこれだけ。これは今後追加できたりするのかな?
入出力のコネクターは以下
入力は"FileSystem"で以下に対応
出力は上記の"File System"に加えて、以下"Database"にも対応
Prompt Studioでドキュメントを使わずに、Extract/Transformだけするようなツール作って並べたりできるんかな?それができればETLパイプラインとして一通りのことはできそうな気がする。