(LangChain編)マルチモーダルRAGのリファレンス実装

本記事は日本オラクルが運営する下記Meetupで発表予定の内容になります。発表までに今後、内容は予告なく変更される可能性があることをあらかじめご了承ください。

https://oracle-code-tokyo-dev.connpass.com/event/307174/

本記事は下記記事の補足記事となります。

https://qiita.com/ksonoda/items/28586434904c26ec465b

※セミナー実施時の動画は以下。

<iframe width="560" height="315" src="https://youtu.be/bEDgf5avZjA?si=PBbbkS3wv29ZLlXx" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>


# 実装の概要

LangChainを使ったマルチモーダルRAGのリファレンス実装概説です。プライベートなデータ(架空の企業の製品概要資料)を埋め込みモデルCLIPでベクトル化し、ベクトルデータベースChromaにロードします。

このRAGの環境で、LangChainのプレイグラウンドからプロンプトを入力し、GPT4にとって未知の情報をベクトルデータベース内のデータと組み合わせてうまくテキスト生成できるか、を試してみます。

構成図は以下の通り。

- MLLM : GPT4-V
- 画像データ埋め込みモデル：CLIP
- ベクトルデータベース：Chroma
- オーケストレーションツール：LangChain

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109260/3264cb02-5858-03cd-5edc-228b49bd6023.png)


この構成を作るべく下記設定を行います。

# 設定
### python仮想環境の作成とライブラリのインストール

まず、langchainのリポジトリをクローンします。このサンプルコードはpythonの仮想化機能であるpoetryで動作させることになるのでその設定を行います。

```shell-session
pip install --upgrade pip
git clone https://github.com/langchain-ai/langchain.git
cd ./langchain/templates/rag-chroma-multi-modal
pip install poetry
poetry install
```

これでこのリファレンス実装を稼働させるためのコアライブラリがバージョン一貫性を保った状態でpoetryの仮想環境にインストールされました。更に追加で下記ライブラリをインストールします。

```shell-session
pip install open_clip_torch torch
pip install langchain_experimental
pip install langchain_community
pip install -U langchain-cli
pip install chromadb
pip install pydantic==1.10.13
pip install pypdfium2
```

この状態でLangChain、CLIP、Chroma(ベクトルデータベース)がセットアップされています。



### データの埋め込み処理とベクトルデータベースへのロード

環境がセットアップされた状態なので、実際にRAGの対象となるドキュメントデータをベクトルデータベースにロードします。

#### ドキュメントデータ

langchain/templates/rag-chroma-multi-modal/docs のディレクトリにサンプルデータとして「DDOG_Q3_earnings_deck.pdf」というPDFファイルがあります。下記のような30ページ程度のプレゼンテーション資料です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109260/04d2b7f9-b538-8024-e27e-745fb51bec2b.png)

これをそのまま使ってもいいですが、今回は以下のような日本語の資料を作ってみたので置き換えてみたいと思います。架空の会社のプレゼンテーション資料のイメージで3ページのPDFです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109260/986df3e1-59e1-df77-a54b-ce5e404dd509.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109260/84772439-d4a2-83af-9c24-e09b338942c9.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109260/7ef2495a-7b0e-a019-7401-92015161fafe.png)

#### 埋め込みとデータのロード

ドキュメントローダーでPDFファイルを読み込み、画像ファイル(jpg)に変換し、CLIPで埋め込み処理をし、生成したベクトルデータをChromaにロードします。この処理は同じpoetryのプロジェクトディレクトリにある ingest.py が全て実行してくれます。



下記のようにingest.pyを実行し、chromaにこのデータをベクトルデータとしてロードします。

```bash
python ingest.py
```

数分経過後処理が完了します。

参考までに、このpython スクリプトでは下記のような処理を行っています。

- PDFファイルをドキュメントローダーに取り込み、一ページ毎に区切る
- PDFをJPEGファイルに変換(このデータの場合はこの時点で3つのJPEGファイルが出来上がっています。)
- このJEPEGファイルをCLIPで埋め込み
- ベクトルデータベースにロードしインデックス作成


#### プレイグラウンドのサービスを起動

LangChainにはLangServeというプレイグランドの機能があります。このサービスを起動するために以下の設定を行います。

まず、poetryのプロジェクトディレクトリに下記を記載した server.py というファイルを作成します。

```python
from rag_chroma_multi_modal import chain as rag_chroma_multi_modal_chain

add_routes(app, rag_chroma_multi_modal_chain, path="/rag-chroma-multi-modal")
```

OpenAIのAPIキーを環境変数で設定し、poetryの仮想環境から下記コマンドでLangServe Playgroundのサービスを起動します。

```bash
export OPENAI_API_KEY=xxxxxx
poetry shell
langchain serve
```

下図のようにエラーなくLANGSERVEのテキストアートが表示されればサービス起動成功です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109260/a7b76347-d51b-47ec-d541-c9f00af0fd2c.png)

ブラウザからプレイグラウンド(http://localhost:8000)にアクセスすると下図のようにLangServe Playgroundが表示されます。(リモートのインスタンスでサービスを起動している場合はポートフォワーディングなどしてください。)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109260/09c42f2f-5839-1459-1ca0-cdd018e9b6e4.png)

### 質問を入力してみる

プレイグラウンドの画面から質問を入力してみます。ベクトルデータベースに入っているデータがないと答えられない質問をいくつかしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109260/68f27bec-3904-162a-582e-5798bf065667.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109260/55fe3263-0199-0c52-9a38-7b7ff3320fdd.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109260/108740af-d001-be4a-6e8e-f4f082df7fa8.png)

MLLMで応答できない質問については、ベクトルデータベースの情報をもとに、テキスト生成をしていることが確認できました。

# 大規模言語モデル関連のその他の記事

https://qiita.com/ksonoda/items/ba6d7b913fc744db3d79

https://qiita.com/ksonoda/items/b767cbd283e379303178

https://qiita.com/ksonoda/items/b9fd3e709aeae79629ff

https://qiita.com/ksonoda/items/6b06b789ac0d0d102598

https://qiita.com/ksonoda/items/60ccc2a4fde15906654a

https://qiita.com/ksonoda/items/28586434904c26ec465b