DataStax Langflow と Amazon Bedrock を使ってノーコードで RAG を構築

# 概要

簡単にセットアップできる DataStax の Astra DB と、GUI で LLM アプリケーションを作れる Langflow を使って RAG を構築して API を作成します。この記事は、以前投稿した記事「[Astra DBとLangflowでRAGを構築](https://qiita.com/harusamet/items/0fb314014bbc7f1bd00e)」のアップデート版です。以前の記事では、LLM に OpenAI を、RAG 構築にOSS の Langflow を利用する方法を説明しましたが、今回は LLM を Amazon Bedrock、RAG 構築に DataStax のマネージドな Langflow を使った方法を説明します。

### 前提
DataStax のアカウントと、Amazon Bedrock を利用可能な AWS アカウントの Credential 情報 (AWS アクセスキー ID、AWS シークレットアクセスキー、必要に応じて AWS セッショントークン) を用意してください。
DataStax のアカウントはクレジットカード登録なしで無料で作成できます。後述する作成方法を参照してください。

### 利用するデータ
今回は経済産業省のデジタル時代の人材政策に関する検討会が作成しているレポート「生成AI時代のDX推進に必要な人材・スキルの考え方2024」のPDFをデータとして RAG をやってみます。以下のページから、概要ではなくて全文版のPDFをダウンロードしておきます。
https://www.meti.go.jp/shingikai/mono_info_service/digital_jinzai/20240628_report.html

### 作業全体の流れ
1. Astra Serverless DB (Vector) をセットアップする。
1. Langflow を使って Astra Serverless DB にベクトルデータを投入する。
1. Langflow を使って RAG を設計して API を作成する。

## Astra Serverless DB (Vector) をセットアップ

### アカウント作成
Astra DB を使うために DataStax のアカウントを作成しましょう。[DataStax](https://www.datastax.com/) のページに移動して、右上の TRY FOR FREE からアカウント作成に進みます。Free Plan は無料で利用できます。利用できる容量や read/write の回数に制限がありますが、PoC には十分です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279199/f741c1c7-b7f8-3ce5-bc32-3fa6c0d5fa1a.png)


### データベースの作成
アカウントができたら[Astra Portal](https://astra.datastax.com)に移動してログインします。ログインすると以下のような画面が表示されますので、右側にある Create Serverless Database をクリックしましょう。
Astra DB には、大きく分けて2つの DB があり、新しいのが Serverless Database、以前からあるものが Classic Database です。Serverless のほうは、その名前の通りでインフラの設定・管理をする必要がありません。有料の Pay As You Go プランの場合は、DB は負荷に応じて自動的にスケールし、ユーザは利用した分だけ料金を支払います。Classic の場合、あらかじめスペックを決めてDBをデプロイし、それ以降は起動時間に応じて料金を支払います。Serverless のほうはベクトルデータベースに特化した機能も提供しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279199/faf3150c-9ff3-ca27-cc45-f43a2ac8dfce.png)

作成画面は以下のようになっていて、RAG ではベクトルデータベースを使うので、Serverless (Vector) を選びます。Vector 形式を選択しても、ベクトル以外の情報（例えば、顧客の氏名や年齢といった情報) も入れることはできます。適当に名前をつけて Provider と Region を選んで Create Database をクリックします。ここでは、AWS の us-east-2 を選びました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279199/bdaaf905-3d9c-1de6-4ca0-22d94fd20496.png)


### コレクションの作成

数分すると DB が作成され、以下の画面が表示されます。この画面から Create Collection をして Collection を作成します。Collection とはベクトルデータ用のテーブルのことです。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279199/068b6a83-7d7b-ccc7-d7c7-3e8b4d799266.png)

Collection を作成する際、デフォルトで Vector-enabled collection が ON になっていると思います。そうすると、データを投入するときに自動的にEmbeddingしてベクトルデータを投入してくれたり、ここで指定した類似度尺度 (Similarity Metrics) に従ってデータを検索できます。自動で Embeddings してくれる機能を [Astra Vectorize](https://www.datastax.com/jp/blog/simplifying-vector-embedding-generation-with-astra-vectorize)と呼んでいて、デフォルトでは NVIDIA の Embeddings モデルを利用できます。自分でベクトル化して投入する場合は Bring my own を指定します。

この記事では Amazon Bedrock で利用可能な [Amazon Titan Embeddings モデル](https://docs.aws.amazon.com/ja_jp/bedrock/latest/userguide/titan-embedding-models.html)を利用しますので、その次元数である 1024 を Dimensions で選択します。また類似尺度は Cosine を選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279199/f2275f7f-03c9-0760-f523-7ec388fe0fdd.png)


## Langflow で Astra DB にベクトルデータを投入

それでは Langflow を使って Astra DB にベクトルデータを投入していきます。Langflow に OSS で利用できるものと、DataStax がクラウドで提供しているものがあります。この記事では DataStax が提供しているものを利用します。データベース作成画面の左上の方に Astra DB と表示されてドロップダウンで選択できるとことがありますので、そこをクリックして Langflow を選択しましょう。DataStax が提供する Langflow は 2024/9/30時点で Preview で提供されており無料で利用することができます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279199/6424fe96-8220-da6e-8d4d-6d7cec83589b.png)

クリックして Langflow へアクセスすると以下の画面が表示されます。新しく Project を作るために New Project をクリックします。いくつかテンプレートを選べるので、Vector Store RAG を選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279199/dce3bfd1-b934-1871-a0b3-f29dd1a0dad5.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279199/2af4d905-3e7d-b6e6-c0e3-99d36504272a.png)

以下のような上下二つに分かれたフローが表示されます。上のフローはベクトルデータベースのセットアップが完了してから、実際にチャットで問い合わせを送るのに利用します。下のフローはファイルを読み込んで、ファイルを細かく分割 (Chunking) して Embedding してベクトルDBに投入します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279199/cfd023de-7cd5-845e-62a0-24ad9c11f99c.png)

### Amazon Bedrock Embeddings の追加

まずは下のほうのフローに着目してベクトルデータを追加するところから始めます。今回ベクトル化には Amazon Bedrock が提供する Amazon Titan Embeddings の V2 のモデルを使います。デフォルトで Amazon Bedrock のコンポーネントが提供されているので、まずは下の図に従って、左のメニューから Embeddings -> Amazon Bedrock Embeddings を探してドラッグアンドドロップで右のワークスペースに置きましょう。残念ながら2024/10/1時点では  Amazon Titan Embeddings の V1 しか選べないので、コンポーネントにマウスをフォーカスすると上に出てくる4つのボタンの一番左 (Code) を開いて、コードを修正し"amazon.titan-embed-text-v2:0"を選択できるようにします。**以下の修正を反映したコードをこちらに置いていますのでコピペで使ってもいいです**[[gist](https://gist.github.com/harusametime/eb2fdf565f340389973208e455acbc29)]。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279199/aff92e4e-2338-2961-abab-c1b32a78b8f3.png)


#### コードの修正: Titan Embeddings v2 への変更
Code をクリックすると以下の画面が表示されるので紫で囲った部分を、図下のコードで置き換えましょう。`v1` を `v2:0` に変更します。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279199/0a28aaeb-a69f-abb2-b60a-c998cec5df1f.png)

```python
inputs = [
        DropdownInput(
            name="model_id",
            display_name="Model Id",
            options=["amazon.titan-embed-text-v2:0"],
            value="amazon.titan-embed-text-v2:0",
        ),
```

#### (Option) コードの修正: RAG でセッショントークンを利用する場合

Amazon Bedrock を期間限定のセッショントークンで利用する場合は、セッショントークンを設定できるように追加でカスタマイズする必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279199/b1d460c2-e652-9644-f679-f9a4045ca3d0.png)

追加・修正するコードは、以下のセッショントークンを取り込むフォームを追加するコード

```python
SecretStrInput(name="aws_session_token", display_name="Session Token"),
```
とセッショントークンが与えられ場合に boto3 の引数に渡すコードです。

```python
if self.aws_session_token:
    session = boto3.Session(
    aws_access_key_id=self.aws_access_key,
    aws_secret_access_key=self.aws_secret_key,
    aws_session_token=self.aws_session_token 
)
else:
    session = boto3.Session(
    aws_access_key_id=self.aws_access_key,
    aws_secret_access_key=self.aws_secret_key
)
```

**編集が終わったらコードエディタの右下の Check & Save をクリックして保存しましょう。**
そうすると以下の図のように Embeddings のコンポーネントがアップデートされて、Model ID に `amazon.ttian-embed-text-v2:0` が選択され、Session Token のフォームも追加されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279199/9e1eba0a-2f2e-b9c2-bf93-8b285a834a63.png)


### AWS の Credential を登録する

このフォームに AWS アクセスキー等を打ち込めば使えるようになるのですが、もし今後、Langflow の内容をエクスポートすることがあれば、これらの情報もエクスポートされるため Credential が流出するリスクがあります。右上の Setting から Global Variables で Credential 情報を登録することができます。Add New ボタンから Credential 情報を登録しましょう。`Variable Name`はわかりやすい名前を、`Value` に実際の Credential の値を入れます。例えば、`Variable Name` を`AWS_ACCESS_KEY_ID` と設定し、`Value`は `ABCD...`のような実際の値です。Global Variablesを変更したい場合は、再度開いて Update するよりも、一度削除して再作成するほうが良さそうです。2024/10/1時点では Update がうまく反映されていませんでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279199/f04c0aaa-5e7d-c895-5c06-63596bbba639.png)

画面中央の `My Collection` から一覧画面に戻り、フロー作成の元の画面に戻ります。先程の Amazon Titan Embeddings のブロックで、Access Key のところの右横の地球儀のようなマークをクリックすればさきほど設定したものを選択できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279199/c4628c14-7125-7701-32cd-9bf34eba3863.png)

### フローを完成させる

以下の図に従ってフローを完成させましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279199/3ecf9219-a3c8-ff53-2db9-fab0645ab2ff.png)

- 先ほど作成した Amazon Titan Embeddings を Astra DB に接続して、データを入力するときにベクトル化できるようにします。
- テキストのチャンク分割の separator は、デフォルトでは改行が指定されています。より意味のあるまとまりとするために、段落の区切り (\n\n) を指定します。
- Astra DB 側は、Collection Name はコレクションを作成するときに指定した名前（上の例では vectors)を指定します。Astra DB Application Token は Astra Portal のデータベースの画面 (下図) からアクセスしGenerate して利用します。Database は作成した Database の名前を指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279199/e7ec71ef-b002-c273-c52f-85c747922ee6.png)


### ベクトルデータの投入

それではデータを読み込んでベクトル化して Astra DB に投入しましょう。手順を図に書き込みましたが、PDFファイルを指定して一番右の再生ボタンをクリックするとそれまでに必要なすべてのステップが実行されます。もし途中結果としてチャンクの内容を見たい場合は Split Text のボックスの右下の Chunks をクリックすれば見ることができます。途中で Chunk サイズが大きいなどのエラーがあればエラーメッセージも表示されるので Chunk Sizeを調整します。追加のファイルがある場合はファイルを選びなおせば Astra DB に追加されていきます。もし Astra DB の内容をリセットして新規で書き込みたい場合は Astra DB のブロックをクリックして３点リーダ(...)を表示し、Advanced -> Pre Delete Collection を ON にすれば良いです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279199/9bca08ff-fafa-30f9-1798-f1158a079c42.png)


### ベクトルデータの確認

Astra Portal で作成したコレクションのページにいくとデータが登録されていることを確認できます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279199/844a2034-3f44-c63b-96e5-1bc32a006ba5.png)


## Langflow でチャットのフローを設計して API を作成

### 既存フローのカスタマイズ
Langflow の RAG のテンプレートで上部のフローをカスタマイズして使います。以下の図に示すように変更箇所は3箇所あります。

1. 最初の左の Embeddings は Open AI が接続されていますが、データをいれる場合と同じ Amazon Bedrock Embeddings をコピーして接続します。作成した Amazon Bedrock Embeddings をクリックすると、上部に3点リーダ (...) が表示されるので、duplicate を選択するとコピーできます。一つのAmazon Titan Embeddingsから2つ接続線をつなぐことは可能ですが、チャット時に2つのフローが動いてしまうためおすすめできません。
1. Astra DB のところは先程と同じ DB を使うので同じ設定を行います。
1. 一番右の Amazon Bedrock の部分はチャットの出力を生成する LLM で Claude 3 を選択できるようになっています。あとはアクセスキーやシークレットキーを Amazon Bedrock Embeddings と同様に入れます。もしセッショントークンも必要の場合は、Amazon Bedrock Embeddings と同様にコードを修正します。修正コードはコピペできるようこちらにおいています [[gist](https://gist.githubusercontent.com/harusametime/44c48b148d8e74ca5a155113e083b3b0/raw/46abae22c5aea25697f922aec09d285aee95ed35/Langflow_Amazon_Bedrock.py)]。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279199/790c5ad9-5797-39d3-9417-a6652fd16fd9.png)



### フローのテスト

すべての設定が終わったら左上の Chat Input に入力を入れてみて、一番右の Chat Output の再生ボタンを押してフローを実行してみます。✕が出ることなく✓が出ればフローはエラーなく動いています。各ブロックの右下のテキスト (Message など)をクリックすると、ブロックの出力を確認することができます。最後の Chat Output の Message をクリックすれば最終的なチャットの返答を見ることができます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279199/76129a2e-c55c-caed-1366-b1dd8cb0d0b4.png)

もしエラーが出る場合は、エラーが出ている場所に✕が表示されます。詳細なエラーは、画面右上の🔔のマークをクリックするとみることができます。例えば下図では、Bedrock で利用が許可されていないモデルを指定してしまった場合のエラーが出ています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279199/9f62264f-f92c-e8e3-c8f5-702206cc8193.png)

右下の Playground のボタンからチャットのウィンドウを表示してテストすることも可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279199/99847aba-be63-d34f-02dd-505069b09680.png)


それでは Playground を試してみましょう。RAGが機能しているか確認するために、PDFに答えが書いてある質問「生成 AI がもたらす潜在的な経済効果はどの程度ですか」を聞いてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279199/32d0dded-d74e-23c5-dfcd-ea03e99d26ac.png)

PDFの中にも同じ記述があるので RAG で正しく答えられています！次は Langflow の画面上だけではなくて、API から同じ質問をしてみたいと思います。API は先ほどの Playground の横にある API をクリックするとサンプルが表示されますのでこれを利用しましょう。
利用するためには以下の図の Generate Token を押して Application Token を作成し、下のサンプル (黒い背景のところ) の `<YOUT APPLICATION TOKEN>` を置き換えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279199/ae3088b3-2400-3677-941e-0d930105fd15.png)

cURL がインストールされた環境で上記のコマンドを実行してみます。`"input_value": "message"`の部分を置き換えます。忘れずに`<YOUT APPLICATION TOKEN>` も自分のに置き換えてください。

```shell
curl -X POST \
    "https://api.langflow.astra.datastax.com/lf/ebb6f6e5-26aa-439a-8426-1fd0ff893e8c/api/v1/run/d7b81c73-40b5-446b-b328-ebccf0fe4019?stream=false" \
    -H 'Content-Type: application/json'\
    -H "Authorization: Bearer <YOUR_APPLICATION_TOKEN>"\
    -d '{"input_value": "生成 AI がもたらす潜在的な経済効果はどの程度ですか",
    "output_type": "chat",
    "input_type": "chat",
    "tweaks": {
  "ChatInput-mIX9u": {},
  "AstraVectorStoreComponent-NH0hx": {},
  "ParseData-m4QKN": {},
  "Prompt-NA5CU": {},
  "ChatOutput-tyfBQ": {},
  "SplitText-cJmBb": {},
  "File-6eRco": {},
  "AstraVectorStoreComponent-Iavl3": {},
  "OpenAIEmbeddings-gl3bA": {},
  "OpenAIEmbeddings-faMhG": {},
  "OpenAIModel-jvqhL": {},
  "AmazonBedrockEmbeddings-elQja": {},
  "AmazonBedrockModel-ssjW6": {}
}}'
```

コマンドの実行結果です。ちょっとみにくいですが、結果は返ってきています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279199/16ba1cfc-16d7-ae66-3433-6e08cb073d40.png)

見やすくするために適当に改行してみました。

```
{
"session_id":"d7b81c73-40b5-446b-b328-ebccf0fe4019",
"outputs":[
    {"inputs":{"input_value":"生成 AI がもたらす潜在的な経済効果はどの程度ですか"},
    "outputs":[{"results":
        {"message":{"text_key":"text",
            "data":{"text":"生成 AI がもたらす潜在的な経済効果は以下のように
            非常に大きいと考えられます:
            McKinsey & Company の分析によると、生成 AI を活用した63件の
            ユースケース全体で「年間2.6～4.4兆ドル相当もの価値をもたらす可能性」
            があると予想されています。
            さらに、この試算には「上記のユースケース以外のタスクに使用されている
            既存のソフトウェアに生成 AIを組み込んだ場合のインパクトも加味すれば、
            ...

}