このガイドでは、検索拡張生成 (RAG) を使用してセマンティック リサーチ ペーパー エンジンを構築する方法を説明します。セマンティック エンジンを構築するためのメイン フレームワークとして LangChain を使用し、OpenAI の言語モデルと Chroma DB のベクトル データベースも使用します。Copilot 組み込み Web アプリケーションの構築には、Chainlit の Copilot 機能を使用し、Literal AI の可観測性機能を組み込みます。このツールは、関連論文を見つけやすくすることで学術研究を促進します。ユーザーは、推奨論文について質問することで、コンテンツと直接対話することもできます。最後に、アプリケーションに可観測性を統合して、LLM への呼び出しを追跡およびデバッグします。
このチュートリアルで取り上げる内容の概要は次のとおりです。
このチュートリアルのコードは、この GitHub リポジトリにあります:
新しい conda 環境を作成します。
次のコマンドを実行して、アクティブ化された環境に必要なすべての依存関係をインストールします。
検索拡張生成 (RAG) は、独自のデータを使用してカスタムの会話型 AI アプリケーションを構築できる人気の手法です。RAG の原理は非常に単純です。テキスト データをベクトル埋め込みに変換し、これをベクトル データベースに挿入します。次に、このデータベースは大規模言語モデル (LLM) にリンクされます。ユーザーのクエリに回答するために事前の知識に頼るのではなく、LLM が独自のデータベースから情報を取得するように制限します。次のいくつかの手順では、セマンティック リサーチ ペーパー エンジンでこれを行う方法を詳しく説明します。rag_test.py というテスト スクリプトを作成し、RAG パイプラインのコンポーネントを理解して構築します。これらは、Copilot 統合 Chainlit アプリケーションの構築時に再利用されます。
アカウントを登録して OpenAI API キーを確保します。完了したら、プロジェクト ディレクトリに .env ファイルを作成し、次のように OpenAI API キーを追加します。
この .env には、プロジェクトのすべての API キーが格納されます。
このステップでは、特定のユーザークエリの研究論文を保存するデータベースを作成します。これを行うには、まずクエリの arXiv API から関連論文のリストを取得する必要があります。API のやり取りを抽象化し、論文を取得してさらに処理するため、LangChain の ArxivLoader() パッケージを使用します。これらの論文を小さなチャンクに分割して、後で効率的な処理と関連情報の取得を確実に行うことができます。これを行うには、ドキュメントを分割しながら情報の意味的保持を保証する LangChain の RecursiveTextSplitter() を使用します。次に、HuggingFace の sentence-transformers 埋め込みを使用して、これらのチャンクの埋め込みを作成します。最後に、これらの分割されたドキュメントの埋め込みを Chroma DB データベースに取り込み、さらにクエリを実行します。
特定のトピックのデータベースが作成されると、このデータベースをリトリーバーとして使用し、提供されたコンテキストに基づいてユーザーの質問に答えることができます。LangChain は、リトリーバー用にいくつかの異なるチェーンを提供していますが、最もシンプルなのは、このチュートリアルで使用する RetrievalQA チェーンです。from_chain_type() メソッドを使用して、モデルとリトリーバーを指定して設定します。LLM へのドキュメントの統合には、すべてのドキュメントを 1 つのプロンプトに詰め込む stuff チェーン タイプを使用します。
arXiv API からのオンライン取得と RAG パイプラインの取り込みおよび取得手順について説明したので、セマンティック リサーチ エンジン用の Web アプリケーションを開発する準備が整いました。
Literal AI は、実稼働グレードの LLM アプリを構築するための可観測性、評価、分析プラットフォームです。Literal AI が提供する主な機能は次のとおりです。
可観測性とプロンプト反復機能を使用して、セマンティック リサーチ ペーパー アプリで行われた呼び出しを評価およびデバッグします。
会話型 AI アプリケーションを作成する場合、開発者はプロンプトの複数のバージョンを反復処理して、最良の結果を生成するものを見つける必要があります。プロンプト エンジニアリングは、ほとんどの LLM タスクで重要な役割を果たします。わずかな変更で言語モデルからの応答が大幅に変わる可能性があるためです。Literal AI のプロンプト プレイグラウンドを使用すると、このプロセスを効率化できます。モデル プロバイダーを選択すると、最初のプロンプト テンプレートを入力し、追加情報を追加して、プロンプトを繰り返し調整し、最適なものを見つけることができます。次のいくつかの手順では、このプレイグラウンドを使用して、アプリケーションに最適なプロンプトを見つけます。
Literal AI ダッシュボードに移動して API キーを作成します。アカウントを登録し、プロジェクト ページに移動して新しいプロジェクトを作成します。各プロジェクトには固有の API キーが付属しています。[設定] タブの [API キー] セクションで API キーを見つけます。それを .env ファイルに追加します。
左側のサイドバーで、「プロンプト」をクリックし、「新しいプロンプト」に移動します。これにより、新しいプロンプト作成セッションが開きます。
プレイグラウンドに入ったら、左側のサイドバーのテンプレート セクションに新しいシステム メッセージを追加します。括弧内のものはすべて変数に追加され、プロンプトの入力として扱われます。
右側のサイドバーで、OpenAI API キーを入力できます。モデル、温度、最大長などのパラメータを選択して、プロンプトを操作してください。
プロンプトのバージョンに満足したら、[保存] をクリックします。プロンプトの名前とオプションの説明を入力するように求められます。このバージョンをコードに追加できます。search_engine.py という新しいスクリプトに、次のコードを追加します。
Literal AI では、バージョン機能を使用して、プロンプトのさまざまな実行を保存できます。また、各バージョンが前のバージョンとどのように異なるかを確認することもできます。デフォルトでは、チャンピオン バージョンがプルされます。バージョンをチャンピオン バージョンに変更する場合は、プレイグラウンドでそのバージョンを選択し、[プロモート] をクリックします。
上記のコードを追加すると、Literal AI ダッシュボードで特定のプロンプトの世代を表示できるようになります (これについては後で詳しく説明します)。
Chainlit は、本番環境に対応した会話型 AI アプリケーションを構築するために設計されたオープンソースの Python パッケージです。いくつかのイベント (チャットの開始、ユーザー メッセージ、セッションの再開、セッションの停止など) のデコレータを提供します。より詳しい説明については、以下の記事をご覧ください。
特にこのチュートリアルでは、Chainlit を使用して RAG アプリケーション用のソフトウェア コパイロットを構築することに焦点を当てます。Chainlit Copilot は、アプリケーション内でコンテキスト ガイダンスと自動化されたユーザー アクションを提供します。
アプリケーション Web サイトにコパイロットを埋め込むと、いくつかの理由で便利です。セマンティック リサーチ ペーパー エンジン用のシンプルな Web インターフェイスを構築し、その中にコパイロットを統合します。このコパイロットにはいくつかの異なる機能がありますが、最も顕著なものは次のとおりです。
次のいくつかの手順では、Chainlit を使用してセマンティック リサーチ エンジンのソフトウェア コパイロットを作成する方法について詳しく説明します。
最初のステップでは、chainlit アプリケーションのロジックを記述します。ユースケースでは、2 つの chainlit デコレータ関数 @cl.on_chat_start と @cl.on_message を使用します。オンライン検索と RAG パイプラインのロジックをこれらの関数に追加します。覚えておくべきことがいくつかあります。
研究トピックの受信からデータベースの作成、ドキュメントの取り込みまでのプロセス全体を @cl.on_chat_start デコレータ内にカプセル化します。search_engine.py スクリプトで、必要なすべてのモジュールとライブラリをインポートします。
ここで、@cl.on_chat_start デコレータのコードを追加しましょう。複数のタスクを同時に実行できるように、この関数を非同期にします。
この関数にラップしたコードを確認してみましょう。
ここで、@cl.on_message 関数を定義し、RAG パイプラインの生成部分を追加しましょう。ユーザーは取り込んだ論文から質問することができ、アプリケーションは関連する回答を提供する必要があります。
上記の関数のコードの内訳は次のとおりです。
2 番目のステップでは、コパイロットをアプリケーション Web サイトに埋め込みます。デモ用に簡単な Web サイトを作成します。index.html ファイルを作成し、次のコードを追加します。
上記のコードでは、アプリをホストしている Chainlit サーバーの場所を指定して、コパイロットを Web サイトに埋め込みました。window.mountChainlitWidget は、Web サイトの右下隅にフローティング ボタンを追加します。それをクリックすると、コパイロットが開きます。コパイロットが正しく動作していることを確認するには、まず Chainlit アプリケーションを実行する必要があります。プロジェクト ディレクトリ内を移動して、次を実行します。
上記のコードは、https://localhost:8000 でアプリケーションを実行します。次に、アプリケーションの Web サイトをホストする必要があります。ブラウザ内で index.html スクリプトを開いても機能しません。代わりに、HTTPS テスト サーバーを作成する必要があります。これを行うにはさまざまな方法がありますが、最も簡単な方法の 1 つは npx を使用することです。npx は、Node.js に付属する npm (Node Package Manager) に含まれています。npx を取得するには、システムに Node.js をインストールするだけです。ディレクトリ内を移動して、次を実行します。
上記のコマンドを実行すると、https://localhost:8080 で当社の Web サイトが提供されます。このアドレスに移動すると、コパイロットが埋め込まれたシンプルな Web インターフェイスが表示されます。
ユーザーを歓迎するために @cl.on_chat_start ラッパー関数を使用するので、ちらつきを避けるために Chainlit 構成で show_readme_as_default を false に設定できます。構成ファイルは、プロジェクト ディレクトリの .chainlit/config.toml にあります。
Copilot 内でのみコードを実行するには、以下を追加します。
このブロック内のコードは、Copilot 内からアプリケーションを操作する場合にのみ実行されます。たとえば、https://localhost:8000 でホストされている Chainlit アプリケーション インターフェイスでクエリを実行する場合、クライアント タイプが Copilot であると想定されているため、上記の if ブロック内のコードは実行されません。これは、Chainlit アプリケーションで直接実行されるアクションと Copilot インターフェイスを通じて開始されるアクションを区別するために使用できる便利な機能です。これにより、リクエストのコンテキストに基づいてアプリケーションの動作を調整し、より動的で応答性の高いユーザー エクスペリエンスを実現できます。
Copilot は、Web サイトの関数を呼び出すことができます。これは、モーダルを開く、新しいドキュメントを作成するなど、ユーザーに代わってアクションを実行する場合に便利です。Chainlit デコレータ関数を変更して、2 つの新しい Copilot 関数を含めます。Chainlit バックエンド アプリケーションの Copilot 関数がアクティブ化されたときにフロントエンドがどのように応答するかを index.html ファイルで指定する必要があります。具体的な反応は、アプリケーションによって異なります。セマンティック リサーチ ペーパー エンジンでは、ユーザーのクエリに応じて関連する論文やデータベースの回答を表示する必要があるときはいつでも、フロントエンドでポップアップ通知を生成します。
アプリケーションに 2 つの Copilot 関数を作成します。
まず、search_engine.py スクリプトでバックエンド ロジックを設定し、@cl.on_chat_start 関数を変更します。
上記のコードでは、showArxivResults という Copilot 関数が定義され、非同期的に呼び出されます。この関数は、arXiv 論文のフォーマットされたリストを Copilot インターフェースに直接表示するように設計されています。関数のシグネチャは非常に単純です。関数の名前と、関数が返す引数を指定します。この情報を index.html ファイルで使用して、ポップアップを作成します。
次に、取り込んだ論文に基づいてユーザーが質問したときに実行される 2 番目の Copilot 関数を使用して、@cl.on_message 関数を変更する必要があります。
上記のコードでは、非同期で呼び出される showDatabaseResults という 2 番目の Copilot 関数を定義しています。この関数は、データベースから取得した結果を Copilot インターフェイスに表示します。関数シグネチャは、関数の名前と、関数が返す引数を指定します。
次に、index.html ファイルを編集して、次の変更を加えます。
まず、Copilot関数のイベントリスナーを追加する必要があります。