はじめに
お疲れ様です。yuki_inkです。
「生成AIでRAGやりたい!」と言われると、反射神経で「S3!Kendra!Bedrock!」などと言ってしまうのですが、いざRAGで扱うドキュメントが自社やお客様の機密文書レベルになってくると、途端にその声のトーンは小さくなってしまいます。
え、そもそもこのドキュメント、クラウドに上げられます、、?
なるほど、ローカルPCで全部完結すれば万事解決ですわ!!
というモチベーションで色々やってみたという記事です。
前提条件
以下2点を前提条件とさせていただきます。
- 固定IPがPCに割り当てられていること
- PC(Windows)の管理者権限が利用できること
なお、この記事では、プロキシの IP アドレスを 192.168.11.9
、プロキシのポートを 3128
として説明します。
この記事を参考にされる際は、実際のプロキシの情報に置き換えて設定してください。
以下の手順は、PC(Windows)の管理者権限を持つローカルユーザで操作を行ってください。
ドメインユーザの場合、ドメインポリシーによる制限がかかり、想定通りの操作ができない場合があります。
※特にOllamaが謎のエラーを吐く場合があります。
事前準備
Difyの導入までは、以下の記事を参照してください!!
(ついでに「いいね」と「ストック」もお願いしますw)
参照いただきたい箇所は以下の通りです。
以下に記載する手順は、Dify導入までが完了していることを前提としています。
やったこと
- 環境変数の設定
- Ollama のインストール
- Dify の設定(モデルの追加)
- Dify でRAGアプリを作成
- PC起動時にWSLが自動起動するようにしておく
本題は #1〜#4 。#5 はついでです。
(1) 環境変数の設定
こちらの記事を参考に、PCの環境変数を設定します。
変数 | 値 |
---|---|
HTTP_PROXY | http://192.168.11.9:3128 |
HTTPS_PROXY | http://192.168.11.9:3128 |
NO_PROXY | 0.0.0.0 |
OLLAMA_HOST | 0.0.0.0 |
ユーザ環境変数の設定が終わったら、設定反映のためOS再起動をしておきます。
【参考にした記事】
(2) Ollama のインストール
(1) 環境変数の設定 で作業したユーザと同じユーザで作業してください。
こちらのWebページからOllamaのインストーラを入手します。
Download for Windows (Preview)
ボタンをクリックして、インストーラ OllamaSetup.exe
を取得。
インストーラ OllamaSetup.exe
を起動し、Install
ボタンをクリック。
「完了しました」的な画面は表示されませんでしたが、インストールは完了した模様。
スタート画面のアイコンがかわいい。
続いてモデルをダウンロード。
今回はphi3を利用します。
コマンドプロンプトを立ち上げて、以下のコマンドを打鍵。
※カレントディレクトリはどこでも大丈夫です(カレントディレクトリにモデルの各種ファイルがダウンロードされるということはなかった)
ollama run phi3
初回はモデルのダウンロードに少し時間がかかります。
モデルのダウンロードが完了したら、自動でチャットセッションが開始されます。
「大規模言語モデルについて簡潔に教えて」と聞いてみます。
日本語で回答を返してくれました。
ブラウザを起動し、http://(PCのIPアドレス):11434/
にアクセスします。
Ollama is runnning
と表示されればOK!
なお、PCのIPアドレスは、コマンドプロンプトで ipconfig
コマンドを実行して確認できます。
以下の例だと 172.19.11.1
がPCのIPアドレスになります。
※WSLと書いてある方ではないことに注意
> ipconfig
Windows IP 構成
イーサネット アダプター イーサネット 2:
接続固有の DNS サフィックス . . . . .:
IPv4 アドレス . . . . . . . . . . . .: 172.19.11.1
サブネット マスク . . . . . . . . . .: 255.255.xx.xx
デフォルト ゲートウェイ . . . . . . .: 172.19.xx.xx
イーサネット アダプター vEthernet (WSL):
接続固有の DNS サフィックス . . . . .:
リンクローカル IPv6 アドレス. . . . .: 1234:567:890a::bcde:f1a2:b3c4
IPv4 アドレス . . . . . . . . . . . .: 172.20.22.2
サブネット マスク . . . . . . . . . .: 255.255.xx.xx
デフォルト ゲートウェイ . . . . . . .:
【参考にした記事】
Windows WSL2 dockerでOllamaを起動し検証をしたが最初の読み込みの時間が遅く、使い勝手が悪かったので、docker抜きで検証することにした。結論、ロードのスピードが早くなり、レスポンスも向上した。
プロダクションでOllamaを使う場合は、Dockerは使わないほうがよいかなといった印象。そもそも、Docker使う場合、色々とケアする項目(Dockerの設定など)増えるので、プロダクションでのOllama利用は、サーバーに直接Ollamaをインストールして扱うほうが無難かも。
WSL上のDockerを使ってOllamaを導入するという手段もありましたが、この記事を読んで、PCに直接インストールしようと思い至りました。
【余談】
おお!!確かに!!
(3) Dify の設定(モデルの追加)
Difyへのログインがまだの場合、ブラウザから http://localhost/signin
にアクセスし、Difyにログインします。
画面右上のユーザー名をクリックし、表示されるメニューから 設定
を選択。
左のメニューから モデルプロバイダー
を選択します。
セットアップ画面を開き、パラメータを入れていきます。
Base URL
には、先ほどの手順でブラウザに入れたURL http://(PCのIPアドレス):11434/
を入れます。
> Model Name
phi3
> Base URL
http://(PCのIPアドレス):11434/
※他はひとまずデフォルト値
各パラメータの詳細はこちらの記事に詳しく記載されていました。
是非参照してください。
【余談】
今回の検証で一番詰まったところがここの手順でした、、
最後の章「苦労したこと」にまとめていますので、よかったらお目通しください。
特に、「なんでIPアドレスで通信させとん?」と思った方は是非!w
(4) Dify でRAGアプリを作成
前回は「ワークフロー」を利用したので、今回は「チャットボット」を使ってみたいなと!!
今回は以下の記事を参考に、RAGを活用したチャットボットを作っていきます。
ナレッジにするドキュメントの用意
ナレッジにするドキュメントとして、今回はQiita CLIの README を利用します。
Qiita CLIのリポジトリから README.md
をダウンロード。
一応、拡張子を txt
に変えておきます。
ファイル名を README.txt
として、一応文字化けがないか確認します。
ナレッジの準備
まずは、ナレッジを準備しましょう。
上部のナビゲーションに「ナレッジ」があるのでクリックします。
「知識を作成」をクリックします。
ナレッジにするドキュメントをアップロードして、「次へ」をクリックします。
先ほど用意した README.txt
をアップロードします。
TXT, MARKDOWN, PDF, HTML, XLSX, XLS, DOCX, CSVをサポートしています。1つあたりの最大サイズは15MBです。
とのことで、PDFに加え、Excel、Wordファイルにも対応しているようです。
素敵!ついでにPowerPointも対応してほしいw
次へ
ボタンをクリックすると、「テキストの前処理とクリーニング」画面に遷移します。
今回はデフォルト値を維持します。
右横のプレビュー画面で、どんな感じでチャンクが切られているか確認できます。
Ollama経由でphi3のみを利用する環境では、インデックスモード
で 高品質
は選べないようです。
以下の記事では 高品質
or 経済的
による動作の違いが分かりやすく記載されていましたので、参考までに。
【参考】Dify やってみた
保存して処理
ボタンをクリックすると、「ナレッジが作成されました」と表示されます。
チャットボットの作成
上部のナビゲーションの「スタジオ」をクリックします。
「最初から作成」をクリックします。
「チャットボット」を選択して「作成する」をクリックします。
「コンテキスト」の「追加」をクリックします。
先ほど追加したナレッジを選択して、「追加」をクリックします。
下の方にある「機能を追加」をクリックします。
「引用と帰属」をOnにします。
Onにすることで、チャットボットの回答に引用元が表示されるようになります。
今回は「引用と帰属」に加えて「フォローアップ」もOnにしてみました。
仕上げに、「手順」のところに以下の "おまじない" を書いておきます。
あなたはQiitaの専門家です。
ルール(<rules>)に基づいて、質問に答えてください。
<rules>
必ず日本語で回答すること。
誤字・脱字がなく、日本語の文法として正しい文章であること。
答えを知っているか、あるいは十分な推測ができる場合のみ、質問に回答すること。
</rules>
最後に、画面右上に表示されているモデルが、(3) Dify の設定 で追加したものになっていることを確認します。
問題なければ、右上の 公開する
ボタンをクリックし、続いて 更新
ボタンをクリックして、設定を保存しておきます。
動かしてみる
まずは、スタジオ画面右横の「デバックとプレビュー」ですぐに動かしてみます!
「Qiita CLI の導入条件は?」と聞いてみます。
お~、よさげ!
プレビュー段階では大丈夫そうですね!
続いて、先ほどクリックした 更新
ボタンの下にある アプリを実行
ボタンをクリックして、専用のチャット画面を開いてみます。
開いたチャットで「Qiitaで新しい記事を作成する際のコマンドを教えてください。」と聞いてみます。
お~~~~!!!よさげ~~~~!!!
次の質問のリコメンドもちゃんと出してくれました(ちょっと微妙ですがw)
【参考にした記事】
(5) PC起動時にWSLが自動起動するようにしておく
本題は以上なんですが、ここからはちょっと横道にそれて、ついでに作業しておきたい内容です。
作業中にWindows Updateが走ってしまったので、PCを再起動して、Difyに再度接続しようとしたら、接続できませんでした。
どうやら、WSLはPCを起動しただけでは起動しないらしい。
PCを起動し、ログイン後、WSLのターミナルを立ち上げて初めて起動するとのこと。
……面倒くさ!
ということで、以下の記事を参考に、PC起動時にWSLが自動起動するようにしておきます。
WSLの場所
WSLを起動する実行ファイルは%userprofile%\AppData\Local\Microsoft\WindowsApps
の中に "ubuntu2204.exe" のようなファイルで存在します。スタートアップへの設置
起動したいWSLのディストリビューションのショートカットをスタートアップに置きます。スタートアップフォルダーは、ファイルを指定して実行 (Windows + R キー)で開いて、以下を入力します。
shell:common startup
ショートカットを設置したら、プロパティの「実行時の大きさ」を「最小化」にしておけばあまり邪魔になりません。
これで、WSLのターミナルが自動起動するようになりました。
環境の都合で、shell:common startup
で開いたフォルダ上にショートカットを配置できなかった場合、shell:startup
で開いたフォルダで代替します。
【参考にした記事】
苦労したこと
以下の記述は今回の構築には役に立ちませんが、色々試行錯誤した結果を供養します。。
DNSエラーとの遭遇
DifyにOllamaをモデルとして追加する際、Base URL
には http://host.docker.internal:11434
という値を入れるんですよ、と案内されている記事が多く見られました。
(例1) ノーコードLLM統合アプリのdifyでollamaと連携してみた
(例2) 🐢Dify | インストール
いざその通りにモデルを追加しようとすると、DNSエラーが発生し、モデルの追加ができませんでした。
docker exec -it (コンテナID) bash
で起動しているコンテナに入り、/etc/hosts
を見てみると、うーん、確かにダメそう。
※例として docker-nginx-1
のコンテナ
# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.18.xx.xx a24698b8a393
docker-compose.yaml をいじってみる(うまくいかなかった)
色々調べて、以下の情報にたどり着きました。
Ollamaと同じマシンで動かしているため、OllamaのBASE URLをDifyに設定しやすいように、Difyのdocker-compose.yamlにhost側を見る様に設定する。
docker-compose.yamlのservices:api:以下にextra_hostsを加える。extra_hosts: - host.docker.internal:host-gateway
ということで、docker-compose.yaml
の各サービス配下に、上記の通り extra_hosts
を追加していった。
コンテナを再作成した後、再び /etc/hosts
を確認すると、それらしきエントリを確認。
※例として docker-nginx-1
のコンテナ
# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
+ 172.17.0.1 host.docker.internal
172.18.xx.xx 75d51a410196
しかし、改めて Base URL
に http://host.docker.internal:11434
を入れてリトライしても、エラーが再発し、DifyからOllamaの連携はうまくいかなかった。。
原因と対応
さらに調査を進めると、どうやら今回作った環境がイケてないことが分かりました。
WSL上で稼働しているDocker(Docker CE)では、"host.docker.internal" はWindows PC(ホスト)ではなく、WSLインスタンスを指すらしい。
理解のために、こちらの図が大変分かりやすかったです。
(出典)WSLとは?「WSL1とWSL2の違い」などをわかりやすく解説!
こりゃ "host.docker.internal" にこだわって頑張るのは大変そう!
ポートフォワーディングとか頑張ればどうにかなるのかもですが、、
面倒くさいしローカルPC内の通信だし、IPベースでやったらええかw
という経緯で (3) Dify の設定(モデルの追加)で記載した手順に至りました。
以上、供養でした🙏
こんな設定いれたら"host.docker.internal" でもいけるよ、というご指摘があれば、コメントいただけるととても嬉しいです!!
【参考にした記事】
色々調べる中で、「そもそもDocker Composeって何だっけ、、?」となり、以下の記事に助けられました。
終わりに
以上、プロキシ環境下のローカルPCに "Dify" と "Ollama" を導入して、インターネットを通らない「完全ローカルRAGアプリ」を作ってみました!
今回の検証に着手する前は、「Ollama入れて、Difyのモデルに追加するだけやろ?楽勝~~」と思っていましたが、思わぬ沼にはまり、結局今回も大変でしたw
が、沼から得られた知識も結構あり、この学びこそが「やってみた」の良いところだなと思ったりもします。
今回の検証のなかで、インデックスモードで 高品質
が選べないという発見もありました。
どうにかローカルLLMで 高品質
を利用する方法がないか、探ってみたいと思います!
最後までお目通しいただき、ありがとうございました。