11
8

Dify+Firecrawlでお手軽にパーソナルRAGを構築

Last updated at Posted at 2024-08-02

はじめに

Open SourceのLLMアプリ開発プラットフォームを活用して、自分のオリジナルRAG環境を構築してみることとする
自身のWindows端末上のPodman DesktopにContainer版のDifyをデプロイし、合わせてFirecrawlもデプロイして、WEBクローリングでRAGのナレッジを収集する
また、自身が所属しているプロジェクトはRedmineを使ってタスク管理を行ってノウハウを集約しているため、Redmineチケットの内容もRAGのナレッジに登録してみる

環境情報

  • OS: Windows 11 Pro 23H2
  • RAM: 16.0GB
  • SSD: 256GB
  • Podman Desktop: v1.11.1
  • Podman: v5.1.1

Difyのインストール(Dify関連コンテナの起動)

Difyのデプロイ

GithubのGithub Dify のリポジトリをクローンする

PS C:\WINDOWS\system32> git clone https://github.com/langgenius/dify.git

次に、ローカルで起動するために.envファイルを用意します

# ディレクトリに移動
PS C:\WINDOWS\system32> cd dify

# サンプルの環境変数をコピー
PS C:\WINDOWS\system32> cp ./docker/.env.example ./docker/.env

DifyのListen Portを変更したかったため .envの以下部分を編集

.env

...
EXPOSE_NGINX_PORT=80 -> EXPOSE_NGINX_PORT=11080
EXPOSE_NGINX_SSL_PORT=443 -> EXPOSE_NGINX_SSL_PORT=11443
...

podman machine上でpodman-composeコマンドを利用するので、Windows PowerShell(管理者)にてWSLでpodman-machine-defaultに接続する

PS C:\WINDOWS\system32> wsl -d podman-machine-default

You will be automatically entered into a nested process namespace where
systemd is running. If you need to access the parent namespace, hit ctrl-d
or type exit. This also means to log out you need to exit twice.

[user@hostname ~]$

docker-compose podman-composeに読み替えて実行したところ、以下エラーで失敗

[user@hostname ~]$ podman-compose up -d
podman-compose version: 1.1.0
['podman', '--version', '']
using podman version: 5.1.1
Traceback (most recent call last):
  File "/usr/bin/podman-compose", line 33, in <module>
    sys.exit(load_entry_point('podman-compose==1.0.6', 'console_scripts', 'podman-compose')())
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/podman_compose.py", line 2940, in main
    podman_compose.run()
  File "/usr/lib/python3.11/site-packages/podman_compose.py", line 1420, in run
    self._parse_compose_file()
  File "/usr/lib/python3.11/site-packages/podman_compose.py", line 1567, in _parse_compose_file
    raise RuntimeError(f"missing networks: {missing_nets_str}")
RuntimeError: missing networks: default

issue を参考にdocker-compose.yamlを一部修正

docker-compose.yaml
...
networks:
  # create a network between sandbox, api and ssrf_proxy, and can not access outside.
  ssrf_proxy_network:
    driver: bridge
    internal: true
  milvus:
    driver: bridge
  opensearch-net:
    driver: bridge
    internal: true
  default:  <- 追加
    driver: bridge <- 追加

podman-composeを再実行。エラーで失敗したときはpodman-compose downで念のためコンテナを削除してから再実行してみる

[user@hostname ~]$ podman-compose down
[user@hostname ~]$ podman-compose up -d

次はdocker_db_1コンテナが起動/停止を繰り返す事象
以下コマンドでログ確認したところ、同じメッセージが出続けている

[user@hostname ~]$ podman logs docker_db_1
...
fixing permissions on existing directory /var/lib/postgresql/data/pgdata ... The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.

Dify on WSL2の起動時にpostgresがエラーを出力する を参考にdocker-compose.yamlを編集
postgresql用のデータ領域としてvolumeを作成して、そちらを利用するように書き換える

...
  # The postgres database.
  db:
    image: postgres:15-alpine
    restart: always
    environment:
      PGUSER: ${PGUSER:-postgres}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-difyai123456}
      POSTGRES_DB: ${POSTGRES_DB:-dify}
      PGDATA: ${PGDATA:-/var/lib/postgresql/data/pgdata}
    volumes:
      - ./volumes/db/data:/var/lib/postgresql/data -> db_data:/var/lib/postgresql/data
...
volumes:
  oradata:
  db_data: <- 追加

再度podman-composeを実行

[user@hostname ~]$ podman-compose up -d

コンテナのステータスを確認する

[user@hostname ~]$ podman ps
CONTAINER ID  IMAGE                                    COMMAND               CREATED             STATUS
      PORTS                                                  NAMES
cf78ff1321ad  docker.io/langgenius/dify-web:0.6.13                           About a minute ago  Up About a minute            3000/tcp                                               docker_web_1
1050c5515fec  docker.io/library/postgres:15-alpine     postgres              About a minute ago  Up About a minute (healthy)  5432/tcp                                               docker_db_1
d792d2821884  docker.io/library/redis:6-alpine         redis-server --re...  About a minute ago  Up About a minute (healthy)  6379/tcp                                               docker_redis_1
ed29715b3809  docker.io/langgenius/dify-sandbox:0.2.1                        About a minute ago  Up About a minute                                                                   docker_sandbox_1
3d1ec8fb577f  docker.io/ubuntu/squid:latest                                  About a minute ago  Up About a minute            3128/tcp                                               docker_ssrf_proxy_1
faf6e1e7c36b  docker.io/langgenius/dify-api:0.6.13                           About a minute ago  Up About a minute            5001/tcp                                               docker_api_1
1b32ebb48a5e  docker.io/langgenius/dify-api:0.6.13                           About a minute ago  Up About a minute            5001/tcp                                               docker_worker_1
1007d6723ea1  docker.io/library/nginx:latest                                 About a minute ago  Up About a minute            0.0.0.0:11080->80/tcp, 0.0.0.0:11443->443/tcp, 80/tcp  docker_nginx_1

.envファイルでCOMPOSE_PROFILES=${VECTOR_STORE:-weaviate}にてCOMPOSE_PROFILE環境変数にてベクターDBを設定し、docker-compose.yaml内のprofileにてデプロイするベクターDBのコンテナを選択している
なぜかCOMPOSE_PROFILES環境変数が効かずに、weaviateコンテナがデプロイされないので、podman-compose実行時にprofileを指定して実行した

podman-compose -f docker-compose.yaml --profile weaviate up -d

再度コンテナのステータスを確認するとweaviateコンテナが起動している

[user@hostname ~]$  podman ps
CONTAINER ID  IMAGE                                       COMMAND               CREATED         STATUS
 PORTS                                                  NAMES
55403e1e4c6b  docker.io/langgenius/dify-web:0.6.13                              27 minutes ago  Up 27 minutes
 3000/tcp                                               docker_web_1
eca999d7c3d2  docker.io/library/postgres:15-alpine        postgres              27 minutes ago  Up 27 minutes (healthy)  5432/tcp                                               docker_db_1
4e19335435a7  docker.io/library/redis:6-alpine            redis-server --re...  27 minutes ago  Up 27 minutes (healthy)  6379/tcp                                               docker_redis_1
c25b168f7991  docker.io/langgenius/dify-sandbox:0.2.1                           27 minutes ago  Up 27 minutes
                                                        docker_sandbox_1
1003b5bdd142  docker.io/ubuntu/squid:latest                                     27 minutes ago  Up 27 minutes
 3128/tcp                                               docker_ssrf_proxy_1
a3ec3e6eeaf9  docker.io/semitechnologies/weaviate:1.19.0  --host 0.0.0.0 --...  27 minutes ago  Up 27 minutes
                                                        docker_weaviate_1
061db32e8ed2  docker.io/langgenius/dify-api:0.6.13                              27 minutes ago  Up 27 minutes
 5001/tcp                                               docker_api_1
d4b662460cf2  docker.io/langgenius/dify-api:0.6.13                              27 minutes ago  Up 27 minutes
 5001/tcp                                               docker_worker_1
d127b93ed7c5  docker.io/library/nginx:latest                                    27 minutes ago  Up 27 minutes
 0.0.0.0:11080->80/tcp, 0.0.0.0:11443->443/tcp, 80/tcp  docker_nginx_1

Difyへのアクセス

プラウザからhttp://localhost:11080/installへアクセスするとDifyのページが表示されるためユーザを作成する
image.png

以下ログインページが表示されたら先ほど設定したユーザでログインする
image.png

ログインが完了すると以下のページが表示される
image.png

Difyのデプロイはいったん完了

モデルの設定

利用するLLMを設定する
今回はOpenAIを利用してみる

OpenAIのAPIキー取得

OpenAI APIにログインする
OpenAIがFree trialだとエラーとなってしまうため、支払情報を登録した上でDashboardをクリックする
image.png

API keysをクリックする
image.png

Create new secret key をクリックする
image.png

Nameを入力してCreate secret keyをクリックする
image.png

APIキーが生成されるのでテキストファイルに保存しておく
image.png
image.png

Difyのモデルの追加

Difyの右上隅のアカウントアイコンをクリックし、設定 -> モデルプロバイダーを選択する
OpenAI -> セットアップ を選択する
image.png

生成したAPIキーを入力して保存をクリックする
image.png

上部に表示されているシステムモデル設定をクリックする
image.png

【24年最新版】ChatGPT(OpenAI)のAPI料金体系まとめを参考になるべくコストがかからないものを選択して保存をクリックした
image.png

OpenAIでテストボットを作る

動作確認のためにテストボットを作ってみる

アプリの作成

最初から作成をクリックする
image.png

チャットボットを選択してアプリの名前説明を入力して作成するをクリックする
image.png

右上のモデルでgpt 3.5-turboを選択して公開するをクリックの上で更新をクリックする
image.png

image.png

アプリが作成される
image.png

Firecrawlのインストール(コンテナ起動)

RAGデータをWebサイトのクローリングで登録するためにFirecrawlを利用する
FirecrawlはSaaS版もあるが、今回はOSS版をローカルにコンテナで起動する構成とする

Firecrawlのデプロイ

GithubのGithub Firecrawlのリポジトリをクローンする

PS C:\WINDOWS\system32> git clone https://github.com/mendableai/firecrawl.git

次に、ローカルで起動するために.envファイルを用意します

# ディレクトリに移動
PS C:\WINDOWS\system32> cd firecrawl

# サンプルの環境変数をコピー
PS C:\WINDOWS\system32> cp ./apps/api/.env.example ./.env

コピーした .envファイルをエディタで開いて以下のようにREDIS_URL , USE_DB_AUTHENTICATION , TEST_API_KEYに変更を加える

  • REDIS_URLは、立ち上がったRedisコンテナに向き先を変更
  • USE_DB_AUTHENTICATIONは無効とする
  • TEST_API_KEYはAPI Keyを意味している。この値は、fc-xxxxの形式であれば何でもOK。今回は「fc-test」を設定した
.env

...
REDIS_URL=redis://localhost:6379 -> REDIS_URL=redis://redis:6379
...
USE_DB_AUTHENTICATION=true -> USE_DB_AUTHENTICATION=false
...
TEST_API_KEY= -> TEST_API_KEY=fc-test
...

podman machine上でpodman-composeコマンドを利用するので、Windows PowerShell(管理者)にてWSLでpodman-machine-defaultに接続する

PS C:\WINDOWS\system32> wsl -d podman-machine-default

You will be automatically entered into a nested process namespace where
systemd is running. If you need to access the parent namespace, hit ctrl-d
or type exit. This also means to log out you need to exit twice.

[user@hostname ~]$

podman-composeを実行してコンテナを起動

[user@hostname ~]$ cd firecrawl/.
[user@hostname ~]$ podman-compose up -d

以下コマンドを実行してHello, World!が出たらデプロイ成功

[user@hostname ~]$ curl -X GET http://localhost:3002/test
Hello, world!

ローカルのDifyとの繋ぎこみ

次に、ローカルのDifyと繋ぎ込みを行う
Difyのナレッジ -> 知識を作成 -> Configureを選択する
image.png
image.png

次にWebsite -> Configure を選択する
image.png

Firecrawlの設定モーダルが表示されるので、先程環境変数で設定した TEST_API_KEYの値(fc-test)とBase URLにhttp://host.docker.internal:3002を入力して保存 をクリックする
image.png

Activeになればつなぎこみ成功
image.png

Webサイトのナレッジ登録

動作確認として、Red Hat Openstackの公式ドキュメントをナレッジとして登録してみる
対象のリンクとしてhttps://docs.redhat.com/ja/documentation/red_hat_openstack_platform/16.2を設定してRunを選択
Limitは読み込む最大ページ数を指定する
Max depthはサブページを何階層まで読み込むかを指定する
image.png

問題なければ下記のようにクローリングした結果が表示される
ナレッジ登録するページにチェックすればOK
今回はReset Allにチェックして全選択して次へを選択する
image.png
image.png

前処理画面が出てくるので必要に応じて設定して保存して処理を選択すればナレッジ登録が始まる
image.png

ナレッジの登録が完了する
image.png

Redmineチケットのナレッジ登録

Redmineにはチケットをcsvエクスポートする機能がある
これを利用してチケットデータをナレッジとして登録する

Redmineチケットのエクスポート

一度にエクスポート可能なチケットの件数はデフォルトでは最大500となっているため必要に応じて上限を変更しておく
変更は管理 -> 設定 -> チケットトラッキングからエクスポートするチケット数の上限を変更して保存をクリックする
image.png
image.png
image.png

チケットタブの右下にあるcsvをクリックする
image.png

すべての項目を選択し、説明,最新のコメントにチェックを入れてエクスポートをクリックする
csvファイルを適切なフォルダに保存する
image.png

Difyのナレッジ登録

出力したcsvファイルをナレッジとして登録する
ナレッジ -> 知識を作成+をクリックする
image.png

テキストファイルからインポートを選択し、ファイルをドラッグ&ドロップするか 参照 のところにcsvファイルをドラッグ&ドロップして次へをクリックする
テキストファイルとあるが、TXT,MARKDOWN,PDF,HTML,XLSX,XLS,DOCX,CSVがサポートされている
image.png

いったんはデフォルトの状態で保存して処理をクリックする
image.png

しばらく待つと処理が完了する
image.png

RAGのチャットボットの作成

今まで登録したナレッジをRAGとして利用するチャットボットを作成する

RAGの機能を持ったチャットボットの作成

スタジオ -> テンプレートから作成 をクリックする
image.png

テンプレート一覧が表示されるのでKnowledge Retrieval + Chatbot を選択する
image.png

アプリの名前説明を入力して作成 をクリックする
image.png

Knowledge Retrieval をクリックし、右側の知識の右側の+ をクリックする
image.png

Red Hat Openstack 16公式ページのナレッジを選択して追加をクリックする
ナレッジは複数追加することもできる
image.png

RAGのデータ登録が完了する
image.png

LLMをクリックし、右側のモデルgpt-3.5-turboを選択する
image.png

Knowledge Retrievalの回答をGPTの入力に設定する
LLMブロックをクリック後のパネルのコンテキストよりKnowledge Retrieval > result Array[Object]を選択する
これにより直前のKnowledge Retrievalの回答をそのまま LLM の入力として設定できる
SYSTEMの部分にはプロンプトを入力する
テンプレートからアプリを作成しているのでもともと英語でプロンプトが入力済みだが、日本語のコンテンツに対して日本語で質問するので日本語でプロンプトを入力してみた
image.png

入力したプロンプトは以下の通り

あなたはRed Hat Openstack 16に関する質問をサポートするアシスタントです
`コンテキスト`の情報を元に回答してください
`コンテキスト`の情報は以下の<context></context>というXML タグの中にあります
<context>
{{#context#}}
</context>
`コンテキスト`の情報から回答できない場合は`わかりません`と答えてください
回答で使用する各事実には必ず出典名(`コンテキスト`のURL。例だと`http://index1.html`や`https://index2.html`など)を行の末尾に記載します
出典名は必ず一つずつブラケット[]で囲んでください。例えば、`http://index1.html`なら、`[http://index1.html]`です。
ちなみに、`http://index1.html`や`http://index2.html`は架空の資料なので使用しないでください
質問者の言語に応じて回答してください

アプリを公開

右上の公開 -> 更新 をクリックするとアプリが公開される
image.png

お試し利用

デバッグとプレビューをクリックするとアプリを実行できる
image.png

それっぽい回答が応答されるのでうまく動いているように見える
image.png

おわりに

以上でDify+Firecrawlをデプロイして自分用のRAGアプリを構築できる環境を作ることができた
個人のローカル環境で手軽に利用できる生成AIを活用したアプリ開発のテストベッドとして有効活用していきたい

参考ページ

11
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
8