「AWS AI サービスと Amazon Bedrock によるインテリジェント ドキュメント処理」
「AWS AI サービスと Amazon Bedrock を活用したインテリジェント ドキュメント処理」
健康、金融、法律、小売、製造などの業界では、日々の業務の一環として大量の文書を扱うことがよくあります。これらの文書には、実施に不可欠な重要な情報が含まれており、タイムリーな意思決定を促進し、最高水準の顧客満足度を確保し、顧客の離反を減らすために必要です。従来、文書からのデータの抽出は手動で行われ、遅く、エラーが発生しやすく、コストがかかり、拡張が困難でした。これはしばしば重要な活動から時間を奪う手作業を伴います。業界は従来のOCRツールによって一定の自動化を実現してきましたが、これらの方法はもろく、メンテナンスコストが高く、技術的な負債を増やすことが証明されています。人工知能(AI)を活用したIntelligent Document Processing(IDP)により、異なるタイプや構造の大量の文書からデータを効率的かつ正確に抽出する作業が可能となります。これにより、タイムリーで高品質な業務の意思決定が可能になり、全体的な費用を抑えることができます。
さらに、Large Language Models(LLM)を使用した生成型AIは、高度に訓練されたMLモデルでも存在したギャップを埋めるため、IDPソリューションに強力な機能を付加しています。本記事では、IDPのさまざまなフェーズと、生成型AIが既存のIDPワークロードを強化したり、新しいIDPワークロードを開発する際にどのように活用されるかについて簡単に説明します。
Intelligent Document Processingのフェーズ
標準的なIDPワークフローは、Document Storage、Document Classification、Extraction、Enrichmentの4つのフェーズから構成されます。すべてのユースケースがこれらのフェーズのすべてを実装するわけではありませんが、最も一般的なユースケースはこれらのフェーズの1つ以上の組み合わせであり、ドキュメントの分類と抽出フェーズが最も人気のあるフェーズです。以下の図は、これらのIDPフェーズの可視化です。本記事では、主にドキュメントの分類と抽出フェーズ、および関連するAIコンポーネントとメカニズムに焦点を当てます。各IDPフェーズについて、フェーズの重要性について簡単に説明し、次に生成型AIと機械学習を使用した実装について詳しく説明します。Amazon Comprehend、Amazon Textract、およびLLMモデルを介したAmazon BedrockなどのいくつかのクラウドベースのAIサービスについても説明します。また、人気のあるオープンソースのLangChain Pythonライブラリを使用した実装の詳細についても説明します。
図1:Intelligent Document Processingのフェーズ
ドキュメントの分類
大量の文書を扱う際の一般的な課題は、文書を識別してカテゴリに分類し、さらに処理することです。これは従来の人間またはヒューリスティックスベースのプロセスでしたが、ドキュメントのボリュームが増えると、これらの方法はビジネスプロセスと結果のボトルネックとなります。このフェーズの中心的なアイデアは、AIを使用してカテゴリ化または分類を自動化することです。このフェーズでは、それ以外の場合は不明であるか、明確なカテゴリにスムーズに分類できるドキュメントをAIを使用して自動的に分類およびラベル付けします。ドキュメントの分類には、Amazon Comprehendのカスタム分類モデルを利用しています。
イベント – ODSC West 2023
対面および仮想会議
10月30日から11月2日まで
最新のデータサイエンスとAIのトレンド、ツール、テクニック、LLMsからデータ分析、機械学習から責任あるAIまで、詳細に掘り下げて調査しましょう。
Amazon Comprehendを使用することで、あなたのユースケースで特定の文書を識別するために特別に設計されたカスタムドキュメント分類モデルをトレーニングする能力を得ます。このモデルは、ドキュメントのレイアウトとドキュメントの内容(テキスト)を考慮してドキュメントの分類を実行します。1つのモデルで最大1000の異なるクラスに対してドキュメントの分類を行うことができ、ドキュメントはPDF、JPG、PNG、DOCX、またはTXT形式のいずれかで提供されることができます。ドキュメントは単一ページまたは複数ページのドキュメントであることができます。複数ページのドキュメントの場合、モデルはページレベルのドキュメントクラスと信頼スコアを提供します。
LLMによる文書の分類は、組織が分類パイプラインを強化するために採用することができる、新興の技術です。これは、モデルが訓練されていない新しい文書がパイプラインに現れる場合に役立ちます。また、既存の訓練済み分類モデルが極めて低い精度で文書を分類する場合にも役立ちます。これは、ビジネスプロセスが進化すると非常に一般的な状況です。ここでは、Amazon BedrockとAnthropic Claude-v1モデルを使用した文書分類の可能な実装例を示します。Amazon Textractのドキュメント抽出機能とLangChainを使用して、ドキュメントからテキストを取得し、プロンプトエンジニアリングを使用して可能なドキュメントカテゴリを特定します。LangChainは、印刷された、スキャンされた、または手書きのドキュメントからテキストを抽出するためにAmazon TextractのDetectDocumentTextAPIを使用します。
図2:低スコアの分類をLLMにルーティングして分類
```from langchain.document_loaders import AmazonTextractPDFLoaderfrom langchain.llms import Bedrockfrom langchain.prompts import PromptTemplatefrom langchain.chains import LLMChainloader = AmazonTextractPDFLoader("./samples/document.png")document = loader.load()template = """Given a list of classes, classify the document into one of these classes. Skip any preamble text and just give the class name.<classes>INVOICE, BANK_STATEMENT, HEALTH_PLAN, PRESCRIPTION</classes><document>{doc_text}<document><classification>"""prompt = PromptTemplate(template=template, input_variables=["doc_text"])bedrock_llm = Bedrock(client=bedrock, model_id="anthropic.claude-v1")llm_chain = LLMChain(prompt=prompt, llm=bedrock_llm)class_name = llm_chain.run(document[0].page_content)print(f"The provided document is = {class_name}")—-The provided document is = HEALTH_PLAN```
ここで使用しているモデルはanthropic.claude-v1です。このモデルはトークンコンテキストウィンドウが100,000トークンです。この操作は、トークンコンテキストウィンドウが100,000トークンのAnthropic Claude v2モデルでも実行可能ですが、選択するモデルによってはコストが大幅に異なる場合があります。一般的に、Anthropic Claude InstantとClaude v1モデルは、非常に多くのユースケースに適した汎用モデルです。以下のコードは、入力プロンプトと生成されたテキストのトークン数を表示するトラッキングメカニズムを示しています。
```prompt = PromptTemplate(template=template, input_variables=["doc_text"])bedrock_llm = Bedrock(client=bedrock, model_id="anthropic.claude-v1")num_in_tokens = bedrock_llm.get_num_tokens(document[0].page_content)print (f"Our prompt has {num_in_tokens} tokens \n\n=========================")llm_chain = LLMChain(prompt=prompt, llm=bedrock_llm)class_name = llm_chain.run(document[0].page_content)num_out_tokens = bedrock_llm.get_num_tokens(class_name)print (f"Our output has {num_out_tokens} tokens \n\n=========================")print (f"Total tokens = {num_in_tokens + num_out_tokens}")—-Our prompt has 1295 tokens =========================Our output has 9 tokens =========================Total tokens = 1304```
ドキュメントの抽出
ドキュメントの抽出は、IDPワークフローの中でおそらく最も人気のあるフェーズです。私が日常的にIDPで取り組むケースの多くは、さまざまな機構でさまざまな情報を幅広い種類のドキュメントから抽出することに重点を置いています。ドキュメントは、出生証明書、抵当証書、税務書類、履歴書、医療試験報告書、健康保険証書、ID書類(パスポート、免許証など)、マーケティング資料、新聞の切れ端など、さまざまな種類があります。ドキュメントの形式や種類は、ユースケースによって大きく異なるため、すべての異なるタイプのドキュメントから情報を抽出するためのさまざまな方法があります。ただし、現時点では、すべてのドキュメントを望ましい形式で抽出できる「一つのモデルがすべてに対応する」という「ワンサイズフィットオール」のAIモデルは存在しないことを念頭においておくことが重要です。しかし、目標の文書抽出を実現するために役立つ、目的に特化したモデルや汎用モデルが多数あります。
Amazon Textractは、フォームの抽出、テーブルの抽出、クエリ、レイアウトなどの一般的な機能を提供しています。これらの機能はほとんどのドキュメントで動作し、フォームからの抽出や表データを含むドキュメントからの抽出など、一般的なドキュメントの抽出に適しています。Amazon Textractはまた、米国のIDドキュメントからの認識と抽出を行うための「AnalyzeID」、請求書や領収書の読み取りと抽出が可能な「AnalyzeExpense」、住宅融資や貸付書類の識別と抽出ができる「AnalyzeLending」といった特定の目的に特化したAIモデルも提供しています。これらのモデルの動作については、上記のドキュメントで詳細を読むことができますが、このセクションでは、LLMベースのドキュメント抽出技術に焦点を当てます。具体的には、テンプレートベースの正規化されたキーバリューエンティティの抽出と、大規模言語モデルを使用したドキュメントのQ&Aに焦点を当てます。
テンプレートベースの正規化された抽出
ほぼすべてのIDPユースケースでは、抽出されたデータは最終的にダウンストリームシステムに送信され、さらなる処理や分析が行われます。AIに基づく抽出から正規化された出力が得られることは、コンシュームメカニズムや統合コードが管理しやすく、信頼性が高く、壊れにくくなります。非決定的なキーではなく、一連の確定的なキーが統合コードで大きな違いを生み出すことがあります。たとえば、申請者の名前、姓、生年月日を抽出するという使用例を考えてみましょう。しかし、関連するドキュメントにはこれらの名前が「名前」、「姓」、「生年月日」と明確にラベル付けされているかどうかは別として、さまざまなスタイルで提供される可能性があります。
図3:ドキュメント抽出の実際の出力と期待される出力
実際の出力と期待される出力の違いに注目してください。期待される出力はより確定的なスキーマに従っており、後処理論理をより単純化し、保守が容易になり、開発費用を低減することができます。以下のコードでは、大規模言語モデルを使用してこれを実現しています。
```from langchain.document_loaders import AmazonTextractPDFLoaderfrom langchain.llms import Bedrockfrom langchain.prompts import PromptTemplatefrom langchain.chains import LLMChainloader = AmazonTextractPDFLoader("./samples/document.png")document = loader.load()output_template= { "first_name":{ "type": "string", "description": "The applicant’s first name" }, "last_id":{ "type": "string", "description": "The applicant’s last name" }, "dob":{ "type": "string", "description": "The applicant’s date of birth" },}template = """You are a helpful assistant. Please extract the following details from the document and format the output as JSON using the keys. Skip any preamble text and generate the final answer.<details>{details}</details><keys>{keys}</keys><document>{doc_text}<document><final_answer>"""details = "\n".join([f"{key}: {value['description']}" for key, value in output_template.items()])keys = "\n".join([f"{key}" for key, value in output_template.items()])prompt = PromptTemplate(template=template, input_variables=["details", "keys", "doc_text"])bedrock_llm = Bedrock(client=bedrock, model_id="anthropic.claude-v1")llm_chain = LLMChain(prompt=prompt, llm=bedrock_llm)output = llm_chain.run({"doc_text": full_text, "details": details, "keys": keys})print(output)—-{ "first_name": "John", "last_name": "Doe", "dob": "26-JUN-1981"}```
この場合、明確な指示が含まれたプロンプトを作成するだけで、エンティティを抽出するだけでなく、出力を独自のスキーマに準拠する形式で生成することができました。このことは、統合コードがはるかにシンプルで決定的であるため、後処理の観点から重要です。さらに、LangChainには、これらの指示をよりモジュラーな方法で作成するための組み込み方法も提供されています。以下に、そのコードの例を示します。
```from langchain.output_parsers import ResponseSchemafrom langchain.output_parsers import StructuredOutputParserresponse_schems = リスト()for key, value in output_template.items(): schema = ResponseSchema(name=key, description=value['description'], type=value['type']) response_schems.append(schema)output_parser = StructuredOutputParser.from_response_schemas(response_schems)format_instructions= output_parser.get_format_instructions()print(format_instructions)—-出力は、以下のスキーマで整形された markdown コードスニペットである必要があります、「```json」および「```」を前後に含みます:```json{"first_name": string // 申請者の名前"provider_id": string // 申請者の姓"dob": string // 申請者の生年月日}``````
その後、この事前生成されたフォーマット指示(変数format_instruction内)を次のようにLLM chainと組み合わせて使用できます。
```template = """あなたは助けになるアシスタントです。このドキュメントから以下の詳細を抽出し、フォーマット指示に記載された手順に厳密に従って出力を整形してください。文書の冒頭文をスキップし、最終回答を生成します。<details>{details}</details><format_instructions>{format_instructions}</format_instructions><document>{doc_text}<document><final_answer>"""llm_chain = LLMChain(prompt=prompt, llm=bedrock_llm)output = llm_chain.run({"doc_text": full_text, "details": details, "format_instructions": format_instructions})parsed_output= output_parser.parse(output)parsed_output```
リトリーバル増強生成(RAG)を使用したドキュメントQ&A
ドキュメントから情報を抽出するための2番目に一般的なアプローチは、チャット形式の質疑応答方法を使用することです。この方法では、LLMにドキュメントの内容と質問をプロンプトとして提供し、ドキュメント内から回答を得ることを目指します(利用可能な場合)。ただし、モデルの幻想を防止し、トークンのコンテキストウィンドウを制限するためのいくつかの問題が存在します。
大規模な事前学習言語モデルは、格納された事実知識のために多くのNLPタスクで最先端の結果を示しています。ただし、知識操作の精度が限られているため、知識集約的なタスクでは効果的でないパフォーマンスが発生することがあります。これを防ぐために、リトリーバル増強生成と呼ばれる手法が最も有用とされています。この手法は、LLMが精確に質問に答え、文書のコンテキスト内に留まり、幻覚を防止し、大規模ドキュメントのトークンコンテキスト制限内に留まるのを支援します。RAGのアイデアは、質問に意味的に近いドキュメントの関連部分のみを収集することです。これは、ドキュメントの内容をいくつかの小さな部分に分割し、それらのベクトル埋め込みを生成し、それから埋め込みをベクトルデータベースに格納することによって実現されます。ベクトルデータベースは、類似性検索または最大負の関連性検索(MMR)を実行して、ドキュメントから最も関連するチャンクを収集できます。これらの関連する部分が取得されると、質問とともにフルなコンテキストが作成され、モデルから最も正確な回答を得るためにプロンプトエンジニアリングが行われます。
図4:埋め込みとベクトルデータベースを使用したリトリーバル増強生成
前述の図では、Titan Embeddings G1 – TextモデルをAmazon Bedrockを介して使用して、テキストチャンクの埋め込みを生成します。LangChainライブラリの有用な組み込みモジュールを使用して、チャンキング、埋め込みの生成、およびベクトルデータベースへのローディングなど、RAGのほとんどのメカニズムを実行できます。この例ではLangChainのRetrievalQAチェーンを使用して、関連性検索、コンテキストの構築、コンテキストを使用したプロンプトの拡張を内部で行います。この例では、[FAISS](https://ai.meta.com/tools/faiss/#:~:text=FAISS%20(Facebook%20AI%20Similarity%20Search,more%20scalable%20similarity%20search%20functions.)ベクトルストアをベクトルデータベースとして使用しています。
```from langchain.embeddings import BedrockEmbeddingsfrom langchain.vectorstores import FAISSfrom langchain.document_loaders import AmazonTextractPDFLoaderfrom langchain.text_splitter import RecursiveCharacterTextSplitterfrom langchain.llms import Bedrockfrom langchain.prompts import PromptTemplatefrom langchain.chains import LLMChainloader = AmazonTextractPDFLoader(f"./samples/document.png")document = loader.load()text_splitter = RecursiveCharacterTextSplitter(chunk_size=400, separators=["\n\n", "\n", ".", "!", "?", ",", " ", ""], chunk_overlap=0)texts = text_splitter.split_documents(document)embeddings = BedrockEmbeddings(client=bedrock, model_id="amazon.titan-embed-text-v1")vector_db = FAISS.from_documents(documents=texts, embedding=embeddings)retriever = vector_db.as_retriever(search_type='mmr', search_kwargs={"k": 3})template = """提供されたテキストのみを使用して、できる限り真実に質問に答えます。テキスト内に回答が含まれていない場合は、「わかりません」と答えてください。前文や推論を省いて、回答のみを示してください。<text>{document}</text><question>{question}</question><answer>"""prompt = PromptTemplate(template=template, input_variables=["document","question"])bedrock_llm = Bedrock(client=bedrock, model_id="anthropic.claude-v1")llm_chain = LLMChain(prompt=prompt, llm=bedrock_llm)answer = llm_chain.run(document=full_context, question="パーソン当たりの薬局負担金はいくらですか?")print(f"回答 = {answer.strip()}")—-回答 = $6,000```
この例では、Amazon Textractを使用してドキュメントを抽出し、ページごとのテキストを取得しました。次に、ドキュメント内のすべてのページを400文字のチャンクに分割します。その後、チャンクのベクトル埋め込みを生成し、FAISSベクトルストアに格納し、RAGベースの質問応答メカニズムのリトリーバーとして使用します。詳細な手順をステップバイステップで説明しているPythonノートブックの完全なセットについては、GitHubリポジトリを参照してください。
結論
この記事では、インテリジェントドキュメント処理のさまざまなフェーズについて説明し、Amazon Bedrockの生成AIがIDPワークフローを拡張または強化する方法について探索しました。要約、自己問い合わせテーブルQ&A、標準化など、本記事ではカバーしていない他のタイプの抽出もあります。上記のGitHubリポジトリのPythonノートブックを使用して、これらの抽出の各種について詳しく調べることができます。すでにIDPワークフローを使用している場合、生成AIはLLMの機能を追加することで、ワークフローを強化する新たな可能性を提供します。IDPベースのワークフローの意思決定フェーズにいる場合は、生成AIが付加価値をもたらすさまざまな方法をすべて探索する価値があります。
著者について
Anjan Biswasは、Amazon Web Services(AWS)のシニアAIスペシャリストソリューションアーキテクトです。アンジャンは、コンピュータビジョン、自然言語処理、生成AI技術に特化し、インテリジェントドキュメント処理(IDP)のユースケースに取り組む時間の大部分を費やしています。彼は、サプライチェーン、小売、テクノロジー、ヘルスケアなど、供給チェーン、小売業界、技術産業、ヘルスケア業界などで大規模なエンタープライズシステムを構築する16年以上の経験を持ち、データサイエンスと機械学習に情熱を持って取り組んでいます。
We will continue to update VoAGI; if you have any questions or suggestions, please contact us!
Was this article helpful?
93 out of 132 found this helpful
Related articles