ChatGPT APIとPyMuPDFを使用してRAGチャットボットGUIを構築する

![py-blog-rag-3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573216/13be0dd5-3d49-cb11-993d-f3f3ea12bafa.jpeg)


このチュートリアルでは、ウェブブラウザ向けの独自のチャットボットを作成する方法について説明します。**PyMuPDF** を含むさまざまな **Python** ライブラリと、お使いの **ChatGPT API**キーを使用して、ユーザーがアップロードした**PDF**ドキュメントに対して入力された質問に答えることができる、グラフィカルユーザーインターフェース（**GUI**）を作成します。バックエンドとフロントエンドの技術を組み合わせて、**Web**向けの効果的なソリューションを提供する方法を実証します。

# はじめに
当社のソリューションは、次の3つのキーとなるライブラリに依存しています。

- [**LangChain**](https://www.langchain.com/)（**LLM**を利用したアプリケーションを構築するためのフレームワーク - チャットボットのI/Oを管理するために使用されます）
- [**Gradio**](https://www.gradio.app/)（**Web**ブラウザでチャットボットの**GUI**を作成して提供するために使用されます）
- [**PyMuPDF**](https://pymupdf.readthedocs.io/ja/latest/)（チャットボット用にアップロードされたドキュメントを読み込み、レンダリングするために使用されます）
基本的に、バックエンドに**LangChain**、フロントエンドに**Gradio**を使用し、その間の重要なインターフェースとして**PyMuPDF**を使用しています。

# 依存関係のインストール
両方のために必要なものを確実に持っているために、次のように**pip** を使用してこれらの依存関係をインストールする必要があります：

```
pip install -U langchain

pip install -U langchain-community

pip install -U langchain-openai

pip install -U gradio

pip install -U pymupdf
```

# ソースコードのダウンロード
以下の**URL**からサンプルコードをクローンまたはダウンロードしてください：[github.com/pymupdf/RAG](https://github.com/pymupdf/RAG)。ローカルにコピーができたら、**Python**のソースコードは「**GUI**」フォルダの内容を参照してください。

# デモの実行
コンソールを開き、「**GUI**」フォルダから次のコマンドを実行してください：

`python browser-app.py`

デモはローカルホスト環境で実行され、以下のような**GUI**が表示されるはずです：

![gui-app-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573216/51e8eca2-2b9f-027b-1428-3702f25eb114.png)



# デモの動作方法
このデモでは、以下の操作が可能です：

- チャットセッションで使用するための**OpenAI API**キーを入力する <font color="cc0000">*</font>
- **PDF**ドキュメントをアップロードする
- ドキュメントに対してクエリを送信し、継続的な**Q&A**セッションを提供します

ドキュメントをアップロードして、ボットに「これは何ですか？」と尋ねてみてください。その結果として、ドキュメントのトピックの要約が返されるはずです。たとえば：

![gui-app-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573216/582ae6ad-17d5-ead5-f523-85761c0e736e.png)

<font color="cc0000">*</font> 注意：**OpenAI API**キーがない場合、必要なサービスへのアクセス権が必要なため、セッションから情報を取得することができません。まだ**API**キーをお持ちでない場合は、**OpenAI**から取得してください。

# バックエンドコードの説明
デモのバックエンドの動作を説明するために、**Python**コードの主な領域を見てみましょう。これは理解を深めるためのものです - スクリプトを調整する必要はありません。

## APIキーの設定
最初に、**API**キーの入力を処理するための関数を提供します。

```
def set_apikey(api_key: str):

    print("API Key set")

    app.OPENAI_API_KEY = api_key

    return disable_box
```

注意：後でこれを**Gradio GUI**に接続します。

## アプリケーションクラス

「**my_app**」という単一のクラスがあり、次のようにインスタンス化されます：

**app = my_app()**

ここには、コンストラクタと呼び出し可能なメソッド以外に、主要なメソッドが次のようにあります：

**process_file**

これは、ユーザーが提供した**PDF**ドキュメントをロードするために[**LangChain**の**PyMuPDFLoader**](https://python.langchain.com/docs/modules/data_connection/document_loaders/pdf#using-pymupdf)を使用します。

**build_chain**

これは、会話ダイアログのために**LangChain**でチェーンを構築します。

## 本体メソッド
**Python**コードのメインボディ（ "**my_app**"クラスの外）には、いくつかの他の重要なメソッドがあります。

**get_response**

これは、クエリとチャット履歴をチェーンに送信し、最も関連性の高い回答を持つページ番号を取得し、その回答をフロントエンドに提供します。

**render_file**

これは、ユーザーがさまざまなクエリを送信すると呼び出されます。チャットボットからの成功した応答がある場合、特定のドキュメントページを参照する場合、コードはユーザーに対して興味のあるページをレンダリングするために**PyMuPDF**を使用します。

**purge_chat_and_render_first**

これは実際には、ユーザーがドキュメントをアップロードした後に最初に呼び出されるメソッドであり、以前のチャット履歴を削除し、次にドキュメントの最初のページをユーザーにレンダリングして、ドキュメントが準備されたことを知らせます。 注意：これらの行は以前のセッションを削除するために重要です：

```
app.chat_history = []
app.count = 0
```

これがないと、チャットセッションが前のドキュメントの「知識」を持ち、関連のない情報を返そうとする可能性があるため、混乱することがあります。

##フロントエンドコードの説明

フロントエンドコードは、**Python**コードの**Gradio**部分です。

```
with gr.Blocks() as demo:

    with gr.Column():

        with gr.Row():

            with gr.Column(scale=1):

                api_key = gr.Textbox(

                  . . .
```

このコードは、**GUI**のグリッドレイアウトを記述しています。これは、入力テキストフィールドの領域、チャットボットの結果やクエリの送信、そしてドキュメントの領域を整理します。ここでは**Gradio**に関する別のチュートリアルには触れず、[Gradioガイド](https://www.gradio.app/guides)で詳細を調べることをお勧めします。

**Gradio**コードの重要な部分の1つは、関数や変数を**UI**コントロールに割り当てる部分です。たとえば、**API**フィールドは次のように割り当てられます：

```
api_key.submit(

        fn=set_apikey,

        inputs=[api_key],

        outputs=[

            api_key,

        ],

    )
```

これにより、提出された際に使用する関数が`set_apikey`に設定され、関連する入力と出力が使用する変数が宣言されます。

もう1つの重要な関数は、アップロードボタンに`purge_chat_and_render_first`が割り当てられています。この関数は、前のチャットセッションを削除し、その後、**PyMuPDF**を使用してドキュメントの最初のページを**GUI**にレンダリングします。

最後に、デモを起動して**Web**アプリケーションを開始します。

# 結論
既存の**Python**テクノロジーを活用して比較的簡単にインタラクティブなチャットボットを作成する方法を示せたかどうかを願っています。バグに遭遇した場合や提案がある場合、またはさらなる改善点を考えついた場合は、**GitHub**でお知らせください。


# ソースコード
[github.com/pymupdf/RAG](https://github.com/pymupdf/RAG) を参照してください。

# 関連ブログ

[RAG/LLMとPDF：PyMuPDFを使用したMarkdownテキストへの変換](https://qiita.com/jamie-lemon/items/1f2eb43f439fd28202a0)

[ChatGPTとPyMuPDFを使用したRAGチャットボットの作成](https://qiita.com/jamie-lemon/items/df6703906392ae8295f3)

[RAG/LLMとPDF: テキスト抽出の強化](https://qiita.com/jamie-lemon/items/455e14f83b4f5c81034b)