リトリーバル オーグメンテッド ジェネレーション(RAG)推論エンジンは、CPU上でLangChainを使用しています

「リトリーバル リストラングエージ ジェネレーション(RAG)推論エンジンのCPU上でのLangChainの利用」

Created with Nightcafe — Property of Author

RAGを使用したAIアプリケーションのスケール、信頼性、および遅延の探求

Retrieval Augmented Generation(RAG)は、特にチャットベースのLLMへの適用について広範にカバーされていますが、この記事では異なる視点からRAGを見て、強力な運用ツールとしての能力を分析します。また、RAGベースのアプリケーションに関する実践的な経験を得るための有用な手順例も提供します。本記事の終わりまでに、あなたはRAGについて独自の見識を持つようになります−製品規模のLLM展開のスケーラブルな推論における役割と潜在能力を理解します。

しかし、まずは推論の理解をリフレッシュしましょう

推論はデータを予測に変換するプロセスです。このMLライフサイクルのコンポーネントは、前処理と後処理のタスクを管理するデータパイプラインによってしばしば支えられます。以下の図1に示す音楽ストリーミングサービスのレコメンデーションシステムを実際の例として評価しましょう。ユーザーがストリーミングプラットフォームを訪れると、アプリケーションのインタフェースには知的にカリキュレーションされたトップ10の曲のリストが表示されます。このリストに責任を持つレコメンデーションシステムは、高品質な結果を保証するためにトレーニングされたモデルと堅牢なデータパイプラインに依存しています。

Figure 1. Simple diagram illustrating a recommendation system supporting “top 10 recommended song list” functionality — image by author

図に示すように、我々の図中の黄色のボックスによって表される前処理の段階は、モデルの予測がユーザーの個別の好みと密接に一致するようにするために重要です。ユーザーが最後に再生した250曲から始めて、パイプラインはデータを処理し、コンテキスト特徴量のセットを生成してから、トレーニングされたモデルに推論する前にそれを渡します。推論ステップは、このユーザーが好きなものを予測し、アルバムアート、曲のタイトル、アーティストの名前、およびそれらの順位などの追加のメタデータでモデルのトップリコメンデーションを充実させます。この情報は、ユーザーが利用するインタフェースに表示されます。

上記に説明されたワークフローでは、推論ステップがアプリケーションのトポロジーにおいてユーザーに近い位置にあることが明確です。他のデータ収集やモデル最適化といったAIライフサイクルのコンポーネントとは異なり、推論エンジンはフロントラインに立ち、ユーザーインターフェース(UI)やユーザーエクスペリエンス(UX)と密接にやり取りをします。

Figure 2. An illustration of various components of an AI system and their proximity to user experience. — Image by author

図2を使用して、AIライフサイクルのさまざまなコンポーネントがユーザーにどれだけ近いかを示すことができます。データ収集や注釈などの多くのコンポーネントは「舞台裏」で動作しますが、推論エンジンはAIの内部プロセスとエンドユーザーが触れるものとの重要な橋渡しです。これは単なるバックエンドのメカニズムではなく、アプリケーションとのユーザーの具体的なエクスペリエンスの核心部分です。

このようなユーザーエクスペリエンスを形作る重要な役割を考慮すると、推論エンジン(推論プロセスおよび前処理/後処理、API管理、コンピュート管理などの周辺コンポーネントを含む)が完璧に動作することが重要です。推論エンジンの品質を確立するために、図3に示す「推論品質(IQ)トライアングル」を紹介します。この質的な図は、推論ワークロードのパフォーマンスを向上させる際に重点を置くべき3つの重要な側面を強調しています:

  • 遅延:推論エンジンが応答を返すためにかかる時間が少なければ、アプリケーションへのオーバーヘッドが減少し、より良いユーザーエクスペリエンスにつながります。
  • 信頼性:ユーザーが信頼し、自信を持って利用できる回答を推論する必要があります。これには、高精度な回答の確保や幻覚の削減などが含まれます。
  • スケーラビリティ:AIシステムにかかる負荷が変動するにつれて、インフラストラクチャをスケーリングする能力が重要です。これにより、コストの最適化や計算リソースの適切なサイズ変更が可能になります。
Figure 3. 高品質な推論エンジンの3つの主要要素を整列させるための簡略化モデル。AIシステムがスケールする一方で低遅延を維持し、高忠実度の洞察を返すための運用の卓越に重点を置いている。— 著者による画像

記事を進めるにつれて、RAGワークロードとの間でこれらの3つの要素(遅延、忠実度、スケール)がうまく整列しているかを調査します。

検索増強生成についての簡単な紹介

検索増強生成(RAG)は、Piktusらによって最初に導入された技術であり、Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks(2021年)で紹介されました。その後もさまざまなフレームワークやアプリケーションに適用されています。 RAGは、コンテキストにおける学習技術のカテゴリーに属しており、事前学習モデルに追加の知識を提供することで、応答の品質を向上させることを重視しています。

RAGの特徴は、類似検索などのアルゴリズムを使用して関連するデータソースから追加情報をインテリジェントに検索することです。検索されたデータは、ユーザーのクエリと組み合わされ、生成モデルに与えられる入力を豊かにします。標準的なRAGのワークフローは、図4に示されています。

Figure 4. シンプルなRAGワークフロー図 — 著者による画像

RAGの真の価値を把握するために、具体的なシナリオを考えてみましょう。大手企業の財務アナリスト(図5)が四半期の収益報告書の作成に取り組んでいるとしましょう。伝統的な方法でこの作業を実行すると、時間を要する作業になります。LLMベースのアプリケーションは効率的な改善を提供していますが、問題があります。基礎となるオープンソースモデルのトレーニング時には利用できない最新の専有情報が必要です。これはfine-tuningによって一部解決できるかもしれませんが、業務の速いペースではモデルを最新状態に保つために継続的なfine-tuningが必要です。

Figure 5. 図6の適応バージョン。この適応版では、特許データに基づいてRAGシステムを構築するためのワークフローの妥当性を示すために、財務アナリストのRAGの使用例が表現されています。 — 著者による画像

RAGは、関連するライブデータを検索して取得することで、モデルをダイナミックに最新の情報で更新することでこれらの課題に対処します。これにより、基礎となるデータベースの品質に圧力がかかりますが、LLMの幻覚やニューラルネットワークの推測よりもデータ管理はより実証され、予測可能です。さらに、このアプローチは組織のデータインフラ内の機密データを保護する利点があります。

多くの応用AIエンジニアは、定期的なfine-tuningと堅牢なRAGパイプラインに焦点を当てたハイブリッド戦略への移行が必要であると考えています。実際には、この戦略は特定のドメインタスクと迅速に進化するデータ環境を持つアプリケーションにおいて、モデルの関連性が向上するというメリットがあります。

実際の例では、RAGのオン/オフを切り替えて、インテリジェントな検索機構によるコンテキストの有無で事前学習モデルの応答品質への影響を確認することができます。詳細は図10を参照してください。

高品質推論エンジンのサポートとなる運用RAGシステム

RAGとLLMベースのアプリケーションの基本的な理解を得たので、これらのシステムの実践的および運用上の側面に焦点を当てます。

約束どおり、高品質なオペレーション推論エンジンの重要な側面を示すIQトライアングル(図3)を見直してみましょう。以下のスタック(図6)を使用して、スケーラビリティ、レイテンシ、および忠実度の3つの側面すべてに対処する機会を分析します。このスタックでは、RAGパイプラインとCPU上で実行される高度に最適化されたモデルで構成された推論エンジンに焦点を当てています。

図6. 提案された推論エンジンスタック — 画像は筆者のもの

RAGのアーキテクチャ上の利点

RAGベースのアプリケーションには、重要なアーキテクチャ上の利点があります。スケーラビリティの観点からは、パイプラインのすべてのデータ中心コンポーネントが単一(または数少ない)のベクターデータベース(図7)に収束するため、RAGの新鮮なデータの利点は、ユーザーの要求の増減に応じてうまくスケールできます。この統合的なアプローチは、特定のドメインタスクへの応答の忠実度を大幅に向上させると同時に、データガバナンスを大幅に簡素化できます。

図7. RAGベースのAIシステムを横断するデータの流れを示すシンプルなデータフローダイアグラム — 画像は筆者のもの

最適化されたモデル:効率とパフォーマンス

モデルは、モデル圧縮とパラメータ効率の高いファインチューニング技術によって、より小さな計算リソースと環境リソースを実現することができます。ファインチューニングによって、モデルを特定のタスクに適合させることができ、予測精度(忠実度)を向上させることができます。また、量子化などの圧縮手法によってモデルのサイズを縮小することで、推論のレイテンシを大幅に改善することができます。これらのスリムで調整されたモデルは、データセンターでの展開が容易になり、エッジでのAIアプリケーションを可能にし、さまざまな革新的なユースケースを生み出すことができます。

図8 — 画像は筆者のもの

RAGのサポートとしてのCPU

RAGのような複雑なロジックを含むワークフローに関しては、普及率とコスト効率の観点でCPUが際立っています。これにより、クラウド上のほとんどの組織がエンタープライズグレードのCPUにアクセスできるため、スケールが向上します。一方、特殊なアクセラレータは入手が困難です。

さらに、現代のCPUは低レベルの最適化も備えています。たとえば、Intelの第4世代Xeonプロセッサには、メモリ管理や行列演算のためのIntel Advanced Matrix Extensionsが搭載されています。また、これらのCPUは、bf16やint8などの低精度データ型のサポートを提供しており、推論時の低レイテンシを実現するのに適しています。

さらに、CPUはRAGパイプラインの複数のコンポーネント(図9に示すようなベクターデータベースやインテリジェントな検索など)との互換性もあり、インフラストラクチャの管理を簡素化するため、スケーラブルな展開が容易かつ効率的に行えます。

図9. 図7の適応版。CPUがRAGシステムのさまざまなパーツをサポートする能力を示しています。 — 画像は筆者のもの

次に進む前に、私のIntelとの関係、および以下で使用する製品を開示します。私はIntelのシニアAIエンジニアであり、以下の実践的なサンプルはIntel Developer Cloud(IDC)上で実行されます。この記事で説明されている概念に関する実践的な経験を得るために、IDCを無料で利用できる便利な方法として使用します。

実践例:Intelデベロッパークラウド(IDC)でLangChainを使用してRAGを実装する手順

以下の実践例に従うには、Intelデベロッパークラウドで無料アカウントを作成し、「トレーニングとワークショップ」ページに移動します。Gen AI Essentialsセクションで、Retrieval Augmented Generation(RAG)with LangChainオプションを選択します。ウェブページの指示に従って、JupyterLabウィンドウを起動し、すべてのサンプルコードを自動的に読み込んだノートブックを開きます。

ノートブックには詳細なドックストリングとコードの説明が含まれています。この記事では、特定の関数の文脈を提供しながら、高レベルのメカニズムについて説明します。

依存関係の設定

まず、すべての必要なパッケージをベース環境にインストールします。conda環境を作成しても構いませんが、これは素早く簡単な方法です。

import sysimport os!{sys.executable} -m pip install langchain==0.0.335 --no-warn-script-location > /dev/null!{sys.executable} -m pip install pygpt4all==1.1.0 --no-warn-script-location > /dev/null!{sys.executable} -m pip install gpt4all==1.0.12 --no-warn-script-location > /dev/null!{sys.executable} -m pip install transformers==4.35.1 --no-warn-script-location > /dev/null!{sys.executable} -m pip install datasets==2.14.6 --no-warn-script-location > /dev/null!{sys.executable} -m pip install tiktoken==0.4.0 --no-warn-script-location > /dev/null!{sys.executable} -m pip install chromadb==0.4.15 --no-warn-script-location > /dev/null!{sys.executable} -m pip install sentence_transformers==2.2.2 --no-warn-script-location > /dev/null

これらのコマンドは、必要なパッケージをベース環境にインストールします。

データとモデル

私たちは、GPT4AllプロジェクトからのFalcon 7B(gpt4all-falcon-q4_0)の量子化バージョンを使用します。このモデルについては、GPT4ALLページの「モデルエクスプローラー」セクションで詳細を学ぶことができます。モデルはディスクに保存されているため、モデルへのアクセスプロセスを簡略化しています。

以下のロジックは、Hugging Faceプロジェクト「FunDialogues」から利用可能なデータセットをダウンロードします。選択したデータは埋め込みモデルを介して渡され、次のステップでベクトルデータベースに配置されます。

def download_dataset(self, dataset):        """        指定されたデータセットをダウンロードし、データパスに保存します。        Parameters        ----------        dataset : str            ダウンロードするデータセットの名前。        """        self.data_path = dataset + '_dialogues.txt'        if not os.path.isfile(self.data_path):            datasets = {"robot maintenance": "FunDialogues/customer-service-robot-support",                         "basketball coach": "FunDialogues/sports-basketball-coach",                         "physics professor": "FunDialogues/academia-physics-office-hours",                        "grocery cashier" : "FunDialogues/customer-service-grocery-cashier"}                        # ダイアログをHugging Faceからダウンロード            dataset = load_dataset(f"{datasets[dataset]}")            # データセットをpandasのデータフレームに変換            dialogues = dataset['train']            df = pd.DataFrame(dialogues, columns=['id', 'description', 'dialogue'])            # データフレームの最初の5行を表示            df.head()            # ダイアログ列のみを保持            dialog_df = df['dialogue']                        # データをtxtファイルに保存            dialog_df.to_csv(self.data_path, sep=' ', index=False)        else:            print('既にデータがパスに存在しています。')

上記のコードスニペットでは、以下の4つの異なるシンセティックデータセットから選択できます:

  • Robot Maintenance:技術者とカスタマーサポート担当者の対話で、ロボットアームのトラブルシューティングを行います。
  • Basketball Coach:バスケットボールコーチと選手のゲーム中の対話。
  • Physics Professor:学生と物理教授のオフィス時間中の対話。
  • Grocery Cashier:食料品店のレジ係と顧客との対話

モデルの設定

LangChain APIのGPT4ALL拡張機能は、モデルをメモリにロードし、次のようなさまざまなパラメータを設定します:

  • model_path: この行は事前学習済みモデルのファイルパスを指定します。
  • n_threads: 使用するスレッド数を設定します。これは並列処理や推論速度に影響する可能性があります。特にマルチコアシステムでは重要です。
  • max_tokens: 入力または出力シーケンスのトークン数(単語またはサブワード)を制限し、モデルによって生成またはフィードされるデータがこの長さを超えないようにします。
  • repeat_penalty: このパラメータはモデルの出力における繰り返しコンテンツを可能な限り抑制する可能性があります。1.0より大きい値は、モデルが繰り返しのシーケンスを生成しないようにします。
  • n_batch: データの処理に使用するバッチサイズを指定します。これは処理速度とメモリ使用量の最適化に役立ちます。
  • top_k: モデルの生成中に使用される「top-k」サンプリング戦略を定義します。テキストを生成する際、モデルは最も確率の高い上位k個のトークンのみを考慮します。
def load_model(self, n_threads, max_tokens, repeat_penalty, n_batch, top_k, temp):        """        指定されたパラメータでモデルを並列処理用にロードします。        パラメータ        ----------        n_threads : int            並列処理用のスレッド数。        max_tokens : int            モデルの予測における最大トークン数。        repeat_penalty : float            生成時の繰り返しトークンへのペナルティ。        n_batch : int            処理のためのバッチ数。        top_k : int            サンプリング時に考慮する上位k個のトークンの数。        """        # トークン単位のストリーミングをサポートするためにコールバックを設定        callbacks = [StreamingStdOutCallbackHandler()]        # コールバックマネージャに渡すためのverboseが必要です        self.llm = GPT4All(model=self.model_path, callbacks=callbacks, verbose=False,                           n_threads=n_threads, n_predict=max_tokens, repeat_penalty=repeat_penalty,                            n_batch=n_batch, top_k=top_k, temp=temp)

ChromaDBを使用したベクトルデータベースの構築

Chromaベクトルデータベースは、RAGセットアップの重要な部分であり、データを効率的に保存および管理します。以下はその構築方法です:

def build_vectordb(self, chunk_size, overlap):        """        検索目的のためにデータセットからベクトルデータベースを構築します。        パラメータ        ----------        chunk_size : int            ベクトル化するテキストのチャンクサイズ。        overlap : int            チャンク間のオーバーラップサイズ。        """        loader = TextLoader(self.data_path)        # テキスト分割器        text_splitter = RecursiveCharacterTextSplitter(chunk_size=chunk_size, chunk_overlap=overlap)        # ドキュメントを埋め込み、chroma DBに格納        self.index = VectorstoreIndexCreator(embedding= HuggingFaceEmbeddings(), text_splitter=text_splitter).from_loaders([loader])

検索メカニズムの実行

ユーザーのクエリを受け取ると、類似性検索を使用してベクトルDB内で似たデータを検索します。一致する結果がk個見つかったら、それらを取得し、ユーザーのクエリに文脈を追加するために使用します。ユーザーのクエリと取得したコンテキストを埋め込むためにPromptTemplate関数を使用します。テンプレートが埋められたら、推論コンポーネントに移動します。

def retrieval_mechanism(self, user_input, top_k=1, context_verbosity = False, rag_off= False):        """        ユーザーのクエリに基づいて関連するドキュメントスニペットを取得します。        パラメータ        ----------        user_input : str            ユーザーの入力またはクエリ。        top_k : int, optional            返す上位結果の数、デフォルトは1。        context_verbosity : bool, optional            Trueの場合、追加のコンテキスト情報が表示されます。デフォルトはFalseです。        rag_off : bool, optional            Trueの場合、検索増強生成を無効にします。デフォルトはFalseです。        """        self.user_input = user_input        self.context_verbosity = context_verbosity                        # 類似性検索を実行し、ドキュメントからコンテキストを取得        results = self.index.vectorstore.similarity_search(self.user_input, k=top_k)        # すべてのコンテキスト情報を1つの文字列に結合する         context = "\n".join([document.page_content for document in results])        if self.context_verbosity:            print(f"あなたの質問に関連する情報を取得しています...")            print(f"質問に最も類似しているこのコンテンツを見つけました:{context}")        if rag_off:            template = """質問: {question}            回答: これが回答です: """            self.prompt = PromptTemplate(template=template, input_variables=["question"])        else:                 template = """次のコンテキストをただ単に繰り返すだけでなく、それを知識と組み合わせて質問に対する回答を改善してください:{context}            質問: {question}            """            self.prompt = PromptTemplate(template=template, input_variables=["context", "question"]).partial(context=context)

The LangChain LLMChainユーティリティは、ユーザーが渡したクエリと設定されたテンプレートに基づいて推論を実行します。結果はユーザーに返されます。

 def inference(self):        """        ユーザーのクエリに基づいて応答を生成するための推論を行います。        戻り値        -------        str            生成された応答。        """        if self.context_verbosity:            print(f"Your Query: {self.prompt}")                    llm_chain = LLMChain(prompt=self.prompt, llm=self.llm)        print("Processing the information with gpt4all...\n")        response = llm_chain.run(self.user_input)        return  response  

対話的な実験

素早く始めるために、このノートブックには統合されたipywidgetコンポーネントが含まれています。これらのコンポーネントを有効にするには、ノートブックのすべてのセルを実行する必要があります。パラメータを調整し、システムの応答の遅延と信頼性に与える影響を評価することをお勧めします。これはただの出発点であり、RAGの能力を基本的に示すものです。

Figure 10. In this example, we get a quick taste of the power of RAG, clearly seeing the benefits of the additional context provided by RAG, which helps yield a helpful answer to the user’s question — “My robot is not turning on, Can you help me?” The RAG-enabled output provides valid recommendations, while the raw model without RAG simply provides a polite inquiry that is not very helpful to the user.

まとめと議論

誰もが遅くて不安定なチャットボットと対話することは望ましくありません。ひどいユーザーエクスペリエンスを提供するシステムを開発するのを避けるためのテクニカルスタックの組み合わせは豊富にあります。この記事では、スケール、信頼性、および遅延の利点を実現するスタックの観点から推論エンジンの品質の重要性を解釈しました。RAG、CPU、およびモデル最適化技術の組み合わせは、IQトライアングル(図3)のあらゆる角をチェックし、運用型LLMベースのAIチャットアプリケーションの要求にうまく合致しています。

試してみると面白いことは:

  • retrieval_mechanismメソッドで見つかったプロンプトテンプレートを編集して、取得したコンテキストと一緒により良いプロンプトを開発する。
  • さまざまなモデルとRAG固有のパラメータを調整し、推論の遅延と応答の品質に与える影響を評価する。
  • ドメインに意味のある新しいデータセットを追加し、RAGを使用してAIチャットベースのアプリケーションを構築する可能性をテストする。
  • この例のモデル(gpt4all-falcon-q4_0)はXeonプロセッサに最適化されていません。CPUプラットフォーム向けに最適化されたモデルを使用し、推論の遅延の利点を評価する。

お読みいただきありがとうございます!もっとこういった記事をお読みいただくには、 私のプロフィールをフォローしてください!

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