自分自身のデータを使用して、要約と質問応答のために生成型AI基盤モデルを使用してください

自分自身のデータを使用し、要約と質問応答に生成型AI基盤モデルを使用してください

大規模言語モデル(LLM)は、複雑なドキュメントを分析し、要約や質問に対する回答を提供するために使用することができます。投稿「Amazon SageMaker JumpStartでのファイナンシャルデータのファウンデーションモデルのドメイン適応ファインチューニング」では、独自のデータセットを使用してLLMを微調整する方法について説明しています。堅牢なLLMができたら、そのLLMをビジネスユーザーに公開して新しいドキュメントを処理させたいと思うでしょう。これらのドキュメントは数百ページにも及ぶことがあります。この投稿では、任意の長さのPDFドキュメントを処理するリアルタイムのユーザーインターフェースの構築方法を示します。ファイルが処理された後、ドキュメントを要約したり、内容について質問したりすることができます。この投稿で説明するサンプルソリューションはGitHubで利用できます。

財務ドキュメントの取り扱い

四半期の収益報告書や株主向けの年次報告書などの財務諸表は、しばしば数十ページまたは数百ページになります。これらのドキュメントには、免責事項や法的な文言など、ボイラープレートのような言語がたくさん含まれています。これらのドキュメントから主要なデータポイントを抽出したい場合、ボイラープレートの言語に対する時間とある程度の理解が必要です。そしてもちろん、LLMに対してこれまで見たことのないドキュメントについて質問することはできません。

要約に使用されるLLMは、モデルに渡されるトークン(文字)の数に制限があります。一部の例外を除いて、これらは通常数千のトークンを超えることはありません。これは通常、長いドキュメントを要約する能力を妨げます。

私たちのソリューションは、LLMの最大トークンシーケンス長を超えるドキュメントを処理し、そのドキュメントをLLMに提供できるようにします。

ソリューションの概要

私たちの設計には3つの重要な要素があります:

  • ビジネスユーザーがPDFをアップロードして処理するためのインタラクティブなWebアプリケーションがあります
  • langchainライブラリを使用して大きなPDFをより管理しやすいチャンクに分割します
  • リトリーバル強化生成技術を使用して、LLMが以前に見たことのない新しいデータについてユーザーが質問できるようにします

次の図に示すように、私たちはReact JavaScriptで実装されたフロントエンドを使用しています。このフロントエンドは、Amazon Simple Storage Service(Amazon S3)バケットにホストされ、Amazon CloudFrontによってフロントエンドが提供されます。フロントエンドアプリケーションを使用して、ユーザーはPDFドキュメントをAmazon S3にアップロードすることができます。アップロードが完了すると、Amazon Textractによってパワードされるテキスト抽出ジョブをトリガーできます。ポスト処理の一環として、AWS Lambda関数がテキストにページの境界を示す特別なマーカーを挿入します。そのジョブが完了したら、テキストを要約したり、それについて質問したりするためのAPIを呼び出すことができます。

これらの手順のいくつかは時間がかかる場合があるため、アーキテクチャでは非同期なアプローチを使用しています。たとえば、ドキュメントを要約する呼び出しは、AWS Lambda関数がAmazon Simple Queue Service(Amazon SQS)キューにメッセージを投稿するLambda関数を呼び出します。別のLambda関数がそのメッセージを受け取り、Amazon Elastic Container Service(Amazon ECS)AWS Fargateタスクを開始します。FargateタスクはAmazon SageMaker推論エンドポイントを呼び出します。Fargateタスクを使用するのは、非常に長いPDFの要約にはLambda関数よりも時間とメモリが必要になる場合があるためです。要約が完了したら、フロントエンドアプリケーションはAmazon DynamoDBテーブルから結果を取得できます。

要約にはAI21のSummarizeモデルを使用しています。これはAmazon SageMaker JumpStartを介して利用できるファウンデーションモデルの1つです。このモデルは最大で10,000語(約40ページ)のドキュメントを処理できますが、langchainのテキスト分割機能を使用して、それぞれの要約呼び出しを10,000語を超えないようにします。テキスト生成にはCohereのVoAGIモデルを使用し、埋め込みにはJumpStartを介してGPT-Jを使用しています。

要約処理

大きなドキュメントを処理する場合、ドキュメントをより小さな部分に分割する方法を定義する必要があります。Amazon Textractからテキスト抽出結果を受け取った時点で、テキストの大きなチャンク(設定可能なページ数)、個々のページ、および改行のためのマーカーを挿入します。Langchainはこれらのマーカーに基づいて分割し、トークン制限を下回るより小さなドキュメントを組み立てます。以下のコードを参照してください:

text_splitter = RecursiveCharacterTextSplitter(
      separators = ["<CHUNK>", "<PAGE>", "\n"],
         chunk_size = int(chunk_size),
         chunk_overlap  = int(chunk_overlap))

 with open(local_path) as f:
     doc = f.read()
 texts = text_splitter.split_text(doc)
 print(f"Number of splits: {len(texts)}")


 llm = SageMakerLLM(endpoint_name = endpoint_name)

 responses = []
 for t in texts:
     r = llm(t)
     responses.append(r)
 summary = "\n".join(responses)

要約チェーンのLLMは、SageMakerエンドポイントを包んだ薄いラッパーです:

class SageMakerLLM(LLM):

endpoint_name: str
    
@property
def _llm_type(self) -> str:
    return "summarize"
    
def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:
    response = ai21.Summarize.execute(
                      source=prompt,
                      sourceType="TEXT",
                      sm_endpoint=self.endpoint_name
    )
    return response.summary 

質問応答

情報検索拡張生成法では、まずドキュメントをより小さなセグメントに分割します。各セグメントの埋め込みを作成し、langchainのインターフェースを介してオープンソースのChromaベクトルデータベースに保存します。データベースを後で使用するために、Amazon Elastic File System(Amazon EFS)ファイルシステムに保存します。次のコードを参照してください:

documents = loader.load()
text_splitter = RecursiveCharacterTextSplitter(chunk_size = 500,
                                                chunk_overlap  = 0)
texts = text_splitter.split_documents(documents)
print(f"分割数:{len(texts)}")

embeddings = SMEndpointEmbeddings(
    endpoint_name=endpoint_name,
)
vectordb = Chroma.from_documents(texts, embeddings, 
    persist_directory=persist_directory)
vectordb.persist()

埋め込みが準備できたら、ユーザーは質問をすることができます。質問に最も近いテキストチャンクをベクトルデータベースから検索します:

embeddings = SMEndpointEmbeddings(
    endpoint_name=endpoint_embed
)
vectordb = Chroma(persist_directory=persist_directory, 
embedding_function=embeddings)
docs = vectordb.similarity_search_with_score(question)

一致度が高いチャンクを取り、それをテキスト生成モデルの文脈として使用して質問に答えます:

cohere_client = Client(endpoint_name=endpoint_qa)
context = docs[high_score_idx][0].page_content.replace("\n", "")
qa_prompt = f'Context={context}\nQuestion={question}\nAnswer='
response = cohere_client.generate(prompt=qa_prompt, 
                                  max_tokens=512, 
                                  temperature=0.25, 
                                  return_likelihoods='GENERATION')
answer = response.generations[0].text.strip().replace('\n', '')

ユーザーエクスペリエンス

LLMは高度なデータサイエンスを表していますが、LLMのほとんどのユースケースは非技術的なユーザーとの対話を含むものです。私たちの例のWebアプリケーションは、ビジネスユーザーが新しいPDFドキュメントをアップロードして処理する対話型のユースケースを処理します。

以下の図は、ユーザーインターフェースを示しています。ユーザーはまずPDFをアップロードして開始します。ドキュメントがAmazon S3に保存された後、テキスト抽出ジョブを開始できます。それが完了すると、ユーザーは要約タスクを実行したり質問をしたりすることができます。ユーザーインターフェースは、新しいドキュメントでアプリケーションをテストするために役立つチャンクサイズやチャンクオーバーラップなどの高度なオプションも公開しています。

次のステップ

LLMは重要な情報検索の機能を提供します。ビジネスユーザーはその機能に便利なアクセスが必要です。将来の作業には次の2つの方向が考慮されます:

  • Jumpstartの基礎モデルで既に利用可能な強力なLLMを活用します。わずか数行のコードで、サンプルアプリケーションはAI21とCohereの高度なLLMを展開して使用できます。
  • これらの機能を非技術的なユーザーにも利用できるようにします。PDFドキュメントを処理するための前提条件は、ドキュメントからテキストを抽出することであり、要約ジョブは数分かかる場合があります。それには非同期のバックエンド処理機能を備えたシンプルなユーザーインターフェースが必要であり、LambdaやFargateなどのクラウドネイティブサービスを使用して簡単に設計できます。

PDFドキュメントは半構造化情報であることにも注意しておきます。セクション見出しなどの重要な手がかりは、フォントサイズやその他の視覚的な指標に依存するため、プログラムでの識別は難しいです。情報の基本的な構造を特定することで、LLMはデータをより正確に処理することができます(少なくともLLMが無制限の長さの入力を処理できるようになるまで)。

結論

この記事では、ビジネスユーザーがPDF文書をアップロードして要約や質問応答を行うことができるインタラクティブなWebアプリケーションの構築方法を紹介しました。高度なLLMにアクセスするためにJumpstart基礎モデルを活用する方法や、テキストの分割や取得補完生成技術を使用して長い文書を処理し、LLMに情報として利用可能にする方法を確認しました。

この時点では、ユーザーにこれらの強力な機能を提供しない理由はありません。Jumpstart基礎モデルの利用を今すぐ開始することをお勧めします。

We will continue to update VoAGI; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more