「Amazon Textract、Amazon Bedrock、およびLangChainによるインテリジェントドキュメント処理」
「アマゾン テキストラクト、アマゾン ベッドロック、およびラングチェーンによるインテリジェントドキュメント処理 ビューティー&ファッションの世界における革新的な取り組み」
情報化時代において、数多くのドキュメントに収められた膨大なデータ量は、企業にとって課題と機会を同時に提供しています。伝統的なドキュメント処理方法では、効率性と正確性に欠けることがしばしばあり、革新、コスト効率、最適化の余地が残されています。Intelligent Document Processing(IDP)の登場により、ドキュメント処理は大幅に進歩しました。IDPによって、企業はさまざまなドキュメントタイプの非構造化データを構造化された具体的な洞察に変換し、効率を劇的に向上させ、手作業の労力を削減することができます。しかし、それだけではなく、生成型人工知能(AI)をプロセスに統合することで、IDPの能力をさらに向上させることができます。生成型AIは、ドキュメント処理において高度な機能を導入するだけでなく、変化するデータパターンに対してダイナミックな適応性をもたらします。この記事では、IDPと生成型AIのシナジーについて紹介し、どのようにそれらがドキュメント処理における次のフロンティアを示すかを明らかにします。
詳細は、弊社の「AWS AIサービスを使用したインテリジェントドキュメント処理」シリーズ(Part 1およびPart 2)でIDPについて詳しく説明しています。この記事では、新しいまたは既存のIDPアーキテクチャを大規模な言語モデル(LLM)で拡張する方法について説明します。具体的には、ドキュメントローダーとしてのAmazon Textract、ドキュメントからデータを抽出し、各IDPフェーズで生成型AIの機能を使用するためのLangChain、およびAmazon Bedrockの統合方法について説明します。
Amazon Textractは、スキャンされたドキュメントからテキスト、筆跡、およびデータを自動的に抽出する機械学習(ML)サービスです。Amazon Bedrockは、使いやすいAPIを介して高性能の基礎モデル(FM)の選択肢を提供する完全管理型サービスです。
ソリューションの概要
次の図は、基礎モデルを使用してIDPワークフローをさらに向上させる方法を説明するハイレベルなリファレンスアーキテクチャです。使用ケースと望ましい結果に応じて、LLMsをIDPの一部またはすべてのフェーズで使用することができます。
- T-Mobile US株式会社は、Amazon TranscribeとAmazon Translateを通じて人工知能を利用し、顧客の希望する言語でボイスメールを提供しています
- 「DiagrammerGPT」に会いましょう:LLMの知識を活用して、全体的なダイアグラム計画の立案と洗練を行う、画期的な2段階テキストからダイアグラムを生成するAIフレームワーク
- LoRa、QLoRA、およびQA-LoRa:低ランク行列分解を通じた大規模言語モデルの効率的な適応性
このアーキテクチャでは、LLMsがIDPワークフロー内で特定のタスクを実行するために使用されます。
- ドキュメント分類– Amazon Comprehendの使用に加えて、LLMを使用してドキュメントをfew-shotプロンプティングを使用して分類することができます。few-shotプロンプトでは、異なるクラスのいくつかの例とすべての可能なクラスのリストを言語モデルに提示し、言語モデルによって文書からのテキストの一部をクラスの1つで分類させることができます。
- 要約– LLMを使用して、IDPの抽出フェーズ内でより正確な要約を提供するために、大きなドキュメントの要約を作成することもできます。例えば、会社の収益に関する数百ページの文書を分析する財務分析システムでは、収益の重要な側面を要約するために言語モデルを使用することができます。これにより、アナリストがビジネス上の意思決定を行うことができます。
- 標準化と文脈に即した質疑応答– Amazon TextractのAnalyze Document機能を使用してドキュメントから正確な情報を抽出するだけでなく、LLMを使用してドキュメントから明示的に推論されない情報を抽出することもできます。例えば、患者の退院サマリーには患者の入院日と退院日が記載されているかもしれませんが、患者が入院した総日数は明示的に指定されていないかもしれません。Amazon Textractによって抽出された2つの日付から、患者の入院日数を推測するためにLLMを使用することができます。この値は、キーと値の形式で既知の別名として割り当てられ、消費および後処理がさらに容易になります。
- テンプレート化と正規化– IDPパイプラインは、特定の決定論スキーマに準拠する必要がある場合があります。これにより、IDPワークフローを使用して生成される出力を、例えば関係データベースなどの下流システムで消費するために使用することができます。決定論スキーマを定義する利点は、プロセスの後処理ロジックで処理するために既知のキーセットを持つことです。たとえば、「DOB」を「生年月日」、「誕生日」、「出生日」といった正規化されたキーとして定義したい場合があります。LLMsを使用して、任意のドキュメントでこのようなテンプレート化および正規化されたキー値の抽出を実行します。
- スペルチェックと修正– Amazon Textractはスキャンされたドキュメント(印刷されたものまたは手書きのもの)から正確な値を抽出することができますが、抽出されたデータに単語のスペルミスや文法エラーが存在するかどうかを確認するために言語モデルを使用することができます。これは、データが品質の低いまたは手書きの文書から抽出され、マーケティング資料やフラッシュレポートの生成に使用される場合などに重要です。Amazon Textractからの低スコアの抽出に対して人間が手動でレビューを行うことに加えて、LLMを使用して補完プロセスを高速化するための修正の提案を人間のレビュワーに提供することができます。
以下では、Amazon TextractがLangChainを使用して特定のタスクのドキュメントを処理するためにいかに統合されているかについて、詳しく説明します。ここで提供されているコードブロックは、簡潔さのために短縮されています。詳細なPythonノートブックや手順の詳細についてはGitHubリポジトリを参照してください。
Amazon Textract LangChainドキュメントローダー
ドキュメントのテキスト抽出は、LLM(大規模言語モデル)を使用してドキュメントを処理する際の重要な要素です。Amazon Textractを使用すると、ドキュメントから非構造化の生のテキストを抽出し、ドキュメント内に存在するキーと値のペアや表などのオリジナルの半構造化または構造化オブジェクトを保持することができます。ヘルスケアや保険請求、住宅ローンなどのドキュメントパッケージは、構造化、半構造化、非構造化の形式で多くの情報を含む複雑なフォームで構成されています。ドキュメントの抽出はここで重要なステップです。なぜなら、LLMは豊富なコンテンツからより正確で関連性の高い応答を生成するためにリッチなコンテンツを活用するため、LLMの出力の品質に影響する可能性があるからです。
LangChainは、LLMと統合するための強力なオープンソースのフレームワークです。一般的に、LLMは多目的ですが、深いコンテキストと微妙な応答が必要なドメイン固有のタスクでは苦労することがあります。LangChainでは、開発者がこのようなシナリオで複雑なタスクをより小さなサブタスクに分割できるようにし、サブタスクを接続してチェーン化することで、LLMにコンテキストとメモリを導入できるようにします。
LangChainは、ドキュメントからデータをロードし変換することができるドキュメントローダーを提供しています。これらを使用して、LLMが処理できるようにドキュメントを好みの形式で構成することができます。AmazonTextractPDFLoaderは、Amazon TextractをLangChainと組み合わせてドキュメント処理を自動化するためのサービスローダータイプのドキュメントローダーであり、詳細についてはLangChainのドキュメンテーションを参照してください。Amazon Textractドキュメントローダーを使用するには、まずLangChainライブラリからインポートすることから始めます。
from langchain.document_loaders import AmazonTextractPDFLoader
HTTP URLのエンドポイントからドキュメントをロードすることもできますし、Amazon Simple Storage Service(Amazon S3)バケット内に保存されているドキュメントをAmazon S3オブジェクトURL(パススタイルアクセスとも呼ばれる)を介して参照することもできます。
https_loader = AmazonTextractPDFLoader("https://sample-website.com/sample-doc.pdf")https_document = https_loader.load()s3_loader = AmazonTextractPDFLoader("s3://sample-bucket/sample-doc.pdf")s3_document = s3_loader.load()
また、ドキュメントをAmazon S3に保存し、s3:// URLパターンを使用してそれらを参照することもできます。これについてはS3://を使用したバケットへのアクセスで説明されています。そして、このS3パスをAmazon Textract PDFローダーに渡します。
import boto3textract_client = boto3.client('textract', region_name='us-east-2')file_path = "s3://amazon-textract-public-content/langchain/layout-parser-paper.pdf"loader = AmazonTextractPDFLoader(file_path, client=textract_client)documents = loader.load()
複数ページのドキュメントは複数のテキストページを含んでおり、これらはドキュメントオブジェクト(ページのリスト)を介してアクセスできます。次のコードは、ドキュメントオブジェクト内のページをループして、page_content
属性を介して利用可能なドキュメントテキストを出力します。
print(len(documents))for document in documents: print(document.page_content)
ドキュメントの分類
Amazon ComprehendとLLMを使用することで、ドキュメントの分類に効果的に活用することができます。Amazon Comprehendはテキストから情報を抽出するための自然言語処理(NLP)サービスであり、PDF、Word、画像形式などのドキュメントに対してレイアウトの認識を持つカスタム分類モデルのトレーニングもサポートしています。Amazon Comprehendドキュメントクラシファイアの使用方法の詳細については、Amazon Comprehendドキュメントクラシファイアは高精度なレイアウトサポートを追加しますを参照してください。
LLMと組み合わせることにより、文書分類は大量の文書を管理するための強力な手法となります。 LLMは、自然言語理解を使用して、文書のテキスト、パターン、および文脈要素を分析できるため、文書分類に役立ちます。 特定の文書クラスに合わせて微調整することもできます。 IDPパイプラインに導入された新しい文書タイプが分類を必要とする場合、LLMは一連のクラスに基づいてテキストを処理し、文書を分類することができます。 以下は、LangChainドキュメントローダーを使用して文書からテキストを抽出し、文書の分類に使用するサンプルコードです。 分類を実行するために、Amazon Textractをパワーとして使用するAnthropic Claude v2モデルを使用します。
以下の例では、患者の退院報告書からテキストを抽出し、LLMを使用して、DISCHARGE_SUMMARY
、RECEIPT
、およびPRESCRIPTION
の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()template = """リストのクラスを指定して、ドキュメントをこれらのクラスの1つに分類します。 冒頭のテキストはスキップし、クラス名を提供してください。<classes>DISCHARGE_SUMMARY, RECEIPT, PRESCRIPTION</classes><document>{doc_text}<document><classification>"""prompt = PromptTemplate(template=template, input_variables=["doc_text"])bedrock_llm = Bedrock(client=bedrock, model_id="anthropic.claude-v2")llm_chain = LLMChain(prompt=prompt, llm=bedrock_llm)class_name = llm_chain.run(document[0].page_content)print(f"提供された文書は = {class_name}")
次の出力が生成されます:
提供された文書はDISCHARGE_SUMMARYです
ドキュメントの要約
要約は、与えられたテキストや文書をその主要な情報を保持しながら、短くまとめるというものです。この技術は、効率的な情報検索に役立ち、ユーザーが文書全体を読まずに、すばやくキーポイントを把握することができるようにします。 Amazon Textractは直接的にテキストの要約を行うわけではありませんが、文書からテキストを抽出するための基礎的な機能を提供しています。 この抽出されたテキストは、テキストの要約タスクを実行するためのLLMモデルへの入力として使用されます。
同じサンプルの退院報告書を使用して、AmazonTextractPDFLoader
を使用してこのドキュメントからテキストを抽出します。前述のように、Amazon Bedrockを介してClaude v2モデルを使用し、テキストに対して何を行うかを含むプロンプトでそれを初期化します(この場合は要約)。最後に、ドキュメントローダーから抽出されたテキストを渡してLLMチェーンを実行します。これにより、プロンプトには要約の指示と、Document
でマークされたドキュメントのテキストが含まれます。次のコードを参照してください:
from langchain.document_loaders import AmazonTextractPDFLoaderfrom langchain.llms import Bedrockfrom langchain.prompts import PromptTemplatefrom langchain.chains import LLMChainloader = AmazonTextractPDFLoader("./samples/discharge-summary.png")document = loader.load()template = """完全なドキュメントが与えられた場合、簡潔な要約を教えてください。冒頭のテキストはスキップし、要約のみを提供してください。<document>{doc_text}</document><summary>"""prompt = PromptTemplate(template=template, input_variables=["doc_text"])bedrock_llm = Bedrock(client=bedrock, model_id="anthropic.claude-v2")num_tokens = bedrock_llm.get_num_tokens(document[0].page_content)print (f"プロンプトには{num_tokens}のトークンがあります \n\n=========================\n")llm_chain = LLMChain(prompt=prompt, llm=bedrock_llm)summary = llm_chain.run(document[0].page_content)print(summary.replace("</summary>","").strip())
コードは患者の退院後の報告書の要約を生成します:
私たちのインプットには797個のトークンがあります=========================35歳の男性が、胃の上部腹部痛、吐き気、疲労感で入院しました。潰瘍と考えられました。活動制限、抗生物質、食事の変更、フォローアップで退院しました。
前の例では、要約を行うために単一ページのドキュメントを使用しましたが、要約を必要とする複数ページのドキュメントも扱うことが多いでしょう。複数ページの要約を行う一般的な方法は、まずテキストの小さなチャンクに対して要約を生成し、その後、小さな要約を組み合わせてドキュメントの最終的な要約を得ることです。この方法では、LLMへの複数の呼び出しが必要です。これについてのロジックは簡単に作成できますが、LangChainには大量のテキスト(複数ページのドキュメントから)を要約するための組み込みの要約チェーンが用意されています。要約は、LLMへの複数の呼び出しを管理するためのオプションとして使用できるmap_reduce
またはstuff
オプションを介して行うことができます。次の例では、map_reduce
を使用して複数ページのドキュメントを要約しています。次の図は、ワークフローを示しています。
まず、ドキュメントを抽出し、各ページの総トークン数と総ページ数を確認しましょう:
from langchain.document_loaders import AmazonTextractPDFLoaderfrom langchain.llms import Bedrockbedrock_llm = Bedrock(client=bedrock, model_id="anthropic.claude-v2")loader = AmazonTextractPDFLoader(f"s3://{data_bucket}/bedrock-sample/health_plan.pdf")document = loader.load()num_docs = len(document)print (f"ドキュメントには{num_docs}ページあります")for index, doc in enumerate(document): num_tokens_first_doc = bedrock_llm.get_num_tokens(doc.page_content) print (f"ページ{index+1}には、約{num_tokens_first_doc}トークンがあります")ドキュメントには5ページありますページ1には、約533トークンがありますページ2には、約1323トークンがありますページ3には、約997トークンがありますページ4には、約1643トークンがありますページ5には、約867トークンがあります
次に、LangChainの組み込み関数load_summarize_chain
を使用して、ドキュメント全体を要約します:
from langchain.chains.summarize import load_summarize_chainsummary_chain = load_summarize_chain(llm=bedrock_llm, chain_type='map_reduce')output = summary_chain.run(document)print(output.strip())
標準化とQ&A
このセクションでは、標準化とQ&Aのタスクについて説明します。
標準化
出力の標準化は、LLMを使用して出力テキストの一貫したフォーマットを提供するテキスト生成タスクです。このタスクは、出力を所望のフォーマットに整列させるためにキーのエンティティ抽出を自動化するために特に有用です。例えば、LLMをファインチューニングして日付をMM/DD/YYYY形式にフォーマットすることができます。この方法では、出力値の日付フォーマットを標準化するだけでなく、最終的な出力をJSON形式で生成するようにモデルに指示することもできます。LangChain Expression Language(LCEL)を使用して2つのアクションをチェーンさせる例を以下のコードブロックに示します。最初のアクションは、ドキュメントから日付のみをJSON形式の出力として生成するようにLLMに指示します。2番目のアクションは、JSON出力を取り、日付のフォーマットを標準化します。この2段階のアクションは、適切なプロンプトエンジニアリングを行えば、単一のステップで実行することもできます(正規化とテンプレート化で見るように)。
from langchain.document_loaders import AmazonTextractPDFLoaderfrom langchain.llms import Bedrockfrom langchain.prompts import PromptTemplatefrom langchain.chains import LLMChainloader = AmazonTextractPDFLoader("./samples/discharge-summary.png")document = loader.load()bedrock_llm = Bedrock(client=bedrock, model_id="anthropic.claude-v2")template1 = """フルドキュメントが与えられた場合、指定された形式で応答を生成して出力をフォーマットします。冗長なテキストをスキップして、JSONを生成します。<format>{{ "key_name":"key_value"}}</format><document>{doc_text}</document><question>{question}</question>"""template2 = """JSONドキュメントが与えられた場合、値フィールドの日付を指定された形式で厳密にフォーマットします。冗長なテキストをスキップして、JSONを生成します。<format>DD/MM/YYYY</format><json_document>{json_doc}</json_document>"""prompt1 = PromptTemplate(template=template1, input_variables=["doc_text", "question"])llm_chain = LLMChain(prompt=prompt1, llm=bedrock_llm, verbose=True)prompt2 = PromptTemplate(template=template2, input_variables=["json_doc"])llm_chain2 = LLMChain(prompt=prompt2, llm=bedrock_llm, verbose=True)chain = ( llm_chain | {'json_doc': lambda x: x['text'] } | llm_chain2)std_op = chain.invoke({ "doc_text": document[0].page_content, "question": "患者の入院日と退院日を教えてくださいか?"})print(std_op['text']){ "admit_date":"07/09/2020", "discharge_date":"08/09/2020"}
前のコードサンプルの出力は、DD/MM/YYYY形式である患者の入院・退院日である2020年09月07日と2020年09月08日のJSON構造です。これらの日付は、入院要約報告書に基づいて、それぞれ患者の入院日と退院日を表しています。
検索補完生成によるQ&A
LLM(言語モデル)は、実際の情報、またはワールドナレッジ、ワールドビューとして知られる情報を保持することが知られています。ファインチューニングされると、最先端の結果を生み出すことができます。ただし、LLMがこの知識に効果的にアクセスし操作することの制約もあります。結果として、特定の知識に重点を置くタスクでは、特定の使用例には最適なパフォーマンスが得られない場合があります。たとえば、Q&Aのシナリオでは、モデルが文書で提供された文脈に厳密に従うことが重要であり、単にワールドナレッジに依存することは避ける必要があります。これに反すると、誤った表現、不正確な情報、さらには不正確な回答につながる可能性があります。この問題に対処するために最も一般的に使用される方法は、Retrieval Augmented Generation(RAG)として知られています。このアプローチは、情報検索モデルと言語モデルの両方の強みを組み合わせ、生成される応答の精度と品質を向上させます。
また、LLMはメモリの制約や実行されるハードウェアの制限により、トークンの制限を課すこともあります。この問題に対処するために、チャンキングなどのテクニックが使用されます。チャンキングとは、大きなドキュメントをトークンの制限に収まるように小さな部分に分割するプロセスです。一方、埋め込みはNLP(自然言語処理)において主に単語の意味および他の単語との関係を捉えるために使用されます。これらの埋め込みは、モデルがテキストデータを効率的に処理し理解するために、単語をベクトルに変換します。単語とフレーズの間の意味的なニュアンスを理解することにより、埋め込みはLLMが一貫性のあるコンテキストに基づいた出力を生成することを可能にします。以下のキーワードに注意してください:
- チャンキング – このプロセスは、ドキュメントから大量のテキストを意味のある小さなチャンクに分割します。
- 埋め込み – これらは各チャンクの固定次元ベクトル変換であり、チャンクからの意味情報を保持します。これらの埋め込みは後ほどベクトルデータベースに読み込まれます。
- ベクトルデータベース – 単語のコンテキストを表す単語の埋め込みまたはベクトルのデータベースです。これは、NLPタスクがドキュメント処理パイプラインで使用される知識源として機能します。ベクトルデータベースの利点は、テキスト生成時にLLMに必要なコンテキストのみを提供できることです。詳細は次のセクションで説明します。
RAGは埋め込みの力を利用して、検索フェーズ中に関連するドキュメントセグメントを理解し抽出します。これにより、RAGはLLMのトークン制限内で作業し、関連性の高い情報を選択して生成することができます。結果として、より正確でコンテキストに即した出力が得られます。
次のダイアグラムは、これらの技術を統合してLLMの入力を作成し、そのコンテキスト理解を強化し、より関連性の高い応答を可能にする様子を示しています。一つのアプローチは、類似性検索を行うことで、ベクトルデータベースとチャンキングの両方を利用します。ベクトルデータベースは意味情報を表す埋め込みを保存し、チャンキングはテキストを管理可能なセクションに分割します。この類似性検索から得られたコンテキストを使用して、LLMは質問応答や分類、情報拡充などのドメイン固有の操作を実行できます。
この投稿では、ドキュメントとのコンテキスト内でのQ&Aを行うためにRAGベースのアプローチを使用します。次のコードサンプルでは、ドキュメントからテキストを抽出し、ドキュメントをより小さなテキストのチャンクに分割します。チャンキングは、大きな複数ページのドキュメントがある可能性があり、LLMのトークン制限がある場合に必要です。これらのチャンクは次にベクトルデータベースに読み込まれ、後続のステップで類似性検索を実行するためのコンテキストとして使用されます。次の例では、Amazon Titan Embed Text v1モデルを使用し、ドキュメントのチャンクのベクトル埋め込みを行います:
from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain.embeddings import BedrockEmbeddingsfrom langchain.vectorstores import FAISSfrom langchain.document_loaders import AmazonTextractPDFLoaderfrom langchain.chains import RetrievalQAloader = AmazonTextractPDFLoader("amazon_10k.pdf")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")db = FAISS.from_documents(documents=texts, embedding=embeddings) retriever = db.as_retriever(search_type='mmr', search_kwargs={"k": 3})template = """質問には提供されたテキストのみを使用し、なるべく真実に回答し、テキスト内に回答が含まれていない場合は「わかりません」と回答してください。冗長なテキストや推論は省略し、回答のみを提供してください。<text>{context}</text><question>{question}</question><answer>"""# プロンプトのテンプレートを定義qa_prompt = PromptTemplate(template=template, input_variables=["context","question"])chain_type_kwargs = { "prompt": qa_prompt, "verbose": False } # 必要に応じてverboseをTrueに変更して処理内容を確認するbedrock_llm = Bedrock(client=bedrock, model_id="anthropic.claude-v2")qa = RetrievalQA.from_chain_type( llm=bedrock_llm, chain_type="stuff", retriever=retriever, chain_type_kwargs=chain_type_kwargs, verbose=False # 必要に応じてverboseをTrueに変更して処理内容を確認する)question="このプランの管理者は誰ですか?"result = qa.run(question)print(result.strip())
このコードは、類似性検索アクションによって返されたテキストチャンクを使用して、LLMに関連するコンテキストを作成します。この例では、各テキストチャンクのベクトル埋め込みを格納するサンプルベクトルデータベースとしてオープンソースの[FAISSベクトルストア](https://ai.meta.com/tools/faiss/#:~:text=FAISS%20(Facebook%20AI%20Similarity%20Search,more%20scalable%20similarity%20search%20functions.)を使用します。次に、ベクトルデータベースをLangChainリトリーバとして定義し、RetrievalQA
チェーンに渡します。これは内部的にベクトルデータベース上で類似性検索クエリを実行し、質問に関連する上位n(この例ではn=3)のテキストチャンクを返します。最後に、関連するコンテキスト(関連するテキストチャンクのグループ)とLLMに対する質問を使用してLLMチェーンを実行します。RAGによるQ&Aのステップバイステップのコード解説については、GitHubのPythonノートブックを参照してください。
FAISSの代わりに、Amazon OpenSearchサービスのベクトルデータベース機能、Amazon Relational Database Service(Amazon RDS)for PostgreSQLとpgvector拡張を使用したベクトルデータベース、またはオープンソースのChromaデータベースも利用できます。
表形式のデータを使用したQ&A
文書内の表形式のデータは、その構造の複雑さのため、LLMの処理が難しい場合があります。Amazon Textractは、ページ、テーブル、セルなどの要素のネスト形式で文書から表を抽出できるため、LLMと組み合わせて使用することができます。表形式のデータを使用したQ&Aは、複数のステップからなるプロセスであり、自己クエリングを介して実現することができます。以下に手順の概要を示します:
- Amazon Textractを使用して文書から表を抽出します。Amazon Textractでは、文書から表形式の構造(行、列、ヘッダー)を抽出することができます。
- 表形式のデータをベクトルデータベースにメタデータ情報(ヘッダー名や各ヘッダーの説明など)と共に格納します。
- LLMを使用して問い合わせを構築し、テーブルからデータを抽出します。
- クエリを使用して、ベクトルデータベースから関連する表データを抽出します。
例えば、銀行取引明細書では、「$1000以上の預金取引は何ですか」というプロンプトが与えられた場合、LLMは以下のステップを完了します:
- 「Query: transactions」、「filter: greater than (Deposit$)」などのクエリを作成します。
- クエリを構造化クエリに変換します。
- テーブルデータが格納されているベクトルデータベースに構造化クエリを適用します。
表形式のQ&Aのステップバイステップのサンプルコードの解説については、GitHubのPythonノートブックを参照してください。
テンプレートと正規化
このセクションでは、プロンプトエンジニアリングの技術とLangChainの組み込みメカニズムを使用して、指定されたスキーマでドキュメントからの抽出結果を生成する方法について説明します。また、以前に説明した技術を使用して、抽出したデータにいくつかの標準化を行います。まず、目的の出力に対するテンプレートを定義します。これはスキーマとして機能し、ドキュメントのテキストから抽出した各エンティティに関する詳細を含みます。
output_template= { "doctor_name":{ "type": "string", "description": "The doctor or provider's full name" }, "provider_id":{ "type": "string", "description": "The doctor or provider's ID" }, "patient_name":{ "type": "string", "description": "The patient's full name" }, …}
各エンティティごとに、エンティティが何であるかを説明するために説明を使用することに注意してください。これにより、ドキュメントのテキストから値を抽出するためにLLMの支援を助けます。次のサンプルコードでは、このテンプレートを使用して、AmazonTextractPDFLoader
を使用してドキュメントから抽出したテキストと共に、LLMにプロンプトを作成し、モデルで推論を行います:
from langchain.llms import Bedrockfrom langchain.prompts import PromptTemplatefrom langchain.chains import LLMChaintemplate = """役に立つ助手です。ドキュメントから以下の詳細を抽出し、キーを使用してJSON形式で出力を書式設定してください。プリアンブルテキストはスキップし、最終回答を生成します。<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-v2")llm_chain = LLMChain(prompt=prompt, llm=bedrock_llm)output = llm_chain.run({"doc_text": full_text, "details": details, "keys": keys})print(output){ "doctor_name": "Mateo Jackson, Phd", "provider_id": "XA/7B/00338763", "patient_name": "John Doe", … }
おわかりのように、プロンプトの{keys}
の部分はテンプレートからのキーであり、{details}
はキーとその説明です。この場合、出力の形式について、JSON形式で出力を生成するよう指示する以外に明示的にモデルにプロンプトを与えません。これは大部分の場合に機能します。しかし、LLMの出力は非決定的なテキスト生成であるため、プロンプトの命令の一部として明示的に形式を指定したいとします。これを解決するために、LangChainの構造化された出力パーサモジュールを使用して、テンプレートをフォーマット指示プロンプトに変換する自動プロンプトエンジニアリングの利点を活用できます。前述のテンプレートを使用して、次のように形式指示プロンプトを生成します:
from langchain.output_parsers import ResponseSchemafrom langchain.output_parsers import StructuredOutputParserresponse_schems = list()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)
変数format_instructions
には形式指示プロンプトが格納されます:
出力は、次のスキーマで書式設定されたマークダウンコードスニペットである必要があります。先頭と末尾の "```json" と "```" も含めてください:```json{ "doctor_name": string // 医師または提供者のフルネーム "provider_id": string // 医師または提供者のID "patient_name": string // 患者のフルネーム …}```
その後、この変数を元のプロンプト内で使用して、LLMに指示として出力を抽出して形式設定するよう指示します。プロンプトには少し修正を加える必要があります:
template = """役に立つ助手です。ドキュメントから以下の詳細を抽出し、形式指示で指定された手順に厳密に従って出力を書式設定してください。プリアンブルテキストはスキップし、最終回答を生成します。不完全な回答は生成しないでください。<details>{details}</details><format_instructions>{format_instructions}</format_instructions><document>{doc_text}<document><final_answer>"""
これまでに、ドキュメントからデータを所定のスキーマに抽出するだけでした。しかし、まだ標準化を行う必要があります。たとえば、患者の入院日と退院日は「DD/MM/YYYY」形式で抽出したいとします。この場合、キーのdescription
に書式設定の指示を追加します:
new_output_template= { … "admitted_date":{ "type": "string", "description": "患者が入院した日付。この日付は「DD/MM/YYYY」形式で書式設定する必要があります。" }, "discharge_date":{ "type": "string", "description": "患者が退院した日付。この日付は「DD/MM/YYYY」形式で書式設定する必要があります。 …}
フルなステップバイステップの解説をするために、GitHubのPythonノートブックを参照してください。
スペルチェックと修正
LLMは、人間のようなテキストを理解し生成する驚くべき能力を示しています。LLMのうち、あまり話題にされないが非常に有用な応用の1つは、文書の文法チェックや文の修正における潜在能力です。従来の文法チェッカーは予め定義されたルールに依存しますが、LLMは膨大なテキストデータから特定のパターンを見つけ出し、正しいまたは自然な言語とみなされるものを決定するために使用します。これは、ルールベースのシステムが見落とすかもしれないニュアンス、文脈、微妙な点を検出できることを意味します。
「患者ジョン・ドー、重度の肺炎で入院したが、かなりの改善を示し、安全に退院できる。フォローアップは来週予定されています。」という患者の退院要約から抽出されたテキストを想像してみてください。従来のスペルチェッカーでは、「入院した」「肺炎」「改善」および「来週」をエラーと認識するかもしれません。ただし、これらのエラーの文脈によっては、さらなるミスや一般的な提案が生じる可能性があります。LLMは広範なトレーニングを受けた状態であり、次のような提案をするかもしれません。「ジョン・ドーさん、重度の肺炎で入院した患者は、大幅な改善を示し、安全に退院できます。フォローアップは来週予定されています。」
以下は、先ほど説明したテキストと同じ内容の手書きのサンプルドキュメントです。
Amazon Textractドキュメントローダーを使用してドキュメントを抽出し、プロンプトエンジニアリングを介してLLMに指示して、抽出されたテキストを修正し、スペルや文法の間違いを修正します。
from langchain.document_loaders import AmazonTextractPDFLoaderfrom langchain.llms import Bedrockfrom langchain.prompts import PromptTemplatefrom langchain.chains import LLMChainloader = AmazonTextractPDFLoader("./samples/hand_written_note.pdf")document = loader.load()template = """詳細な'Document'が与えられた場合、スペルおよび文法の修正を行います。出力は整然とし、エラーがなく、前文はスキップし、回答を返してください。<document>{doc_text}</<document><answer>"""prompt = PromptTemplate(template=template, input_variables=["doc_text"])llm = Bedrock(client=bedrock, model_id="anthropic.claude-v2")llm_chain = LLMChain(prompt=prompt, llm=llm)try: txt = document[0].page_content std_op = llm_chain.run({"doc_text": txt}) print("抽出されたテキスト") print("==============") print(txt) print("\n修正されたテキスト") print("==============") print(std_op.strip()) print("\n")except Exception as e: print(str(e))
上記コードの出力では、ドキュメントローダーによって抽出された元のテキストが表示され、LLMによって生成された修正されたテキストが続きます。
抽出されたテキスト==============Patient John Doe, who was ad mitta with sever pnequonia, has shown Signif i art improumet & can be safely discharged. Follow w/s are scheduled for nen week. Patient John Doe, who was ad mitta with sever pnequonia, has shown Signif i art improumet & can be safely discharged. Follow w/s are scheduled for nen week. 修正されたテキスト==============Patient John Doe, who was admitted with severe pneumonia, has shown significant improvement and can be safely discharged. Follow-up appointments are scheduled for next week.
LLMの能力は強力ですが、その提案を単なる提案として見ることが重要です。言語の微妙な点を驚くほどうまく捉えているとしても、彼らは決して完全ではありません。一部の提案は、元のテキストの意図した意味や口調を変える可能性があります。そのため、LLMによる修正は絶対的なものではなく、ガイドとして人間の査読者が使用することが重要です。人間の直感とLLMの能力の協力により、我々の書かれたコミュニケーションが、エラーだけでなく、より豊かで微妙なものとなる未来が約束されています。
結論
生成AIは、IDPを使用して文書を処理し、洞察を得る方法を変えています。ポスト「FalconとAmazon SageMaker Jumpstartを使用したHCLSドキュメント要約アプリの作成」では、パイプラインのさまざまな段階と、AWSの顧客リコーがLLMを使用してIDPパイプラインを強化している方法について説明しました。この記事では、Amazon Bedrock、Amazon Textract、および人気のあるLangChainフレームワークを介したIDPワークフローのさまざまな拡張メカニズムについて説明しました。LangChainを使用した新しいAmazon Textractドキュメントローダーで、GitHubリポジトリで利用可能なサンプルノートブックを使用して、今日からはじめることができます。AWSでの生成AIの使用方法について詳しくは、「AWSでの生成AIビルディング用の新しいツールの発表」を参照してください。
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
- このAIニュースレターがあれば、あなたは全てが揃った!#70
- クラウドストライクは、Fal.Con 2023におけるAI駆動のセキュリティに関するビジョンを概説します
- 「リトリーバルの充実は長文の質問応答にどのように影響を与えるのか? このAIの研究は、リトリーバルの充実が言語モデルの長文での知識豊かなテキスト生成にどのような影響をもたらすかについて新しい示唆を提供します」
- 「VADERによる感情分析の洞察:感情とコミュニケーションの言語」
- 自然言語処理ツールキット(NLTK)感情分析クイックリファレンス
- 予測分析がテクノロジーの意思決定を革命化している方法
- 『冬-8Bに出会ってください:冴えたプラットフォームの背後にある非常にユニークなファンデーションモデル』