はじめに
世間をざわつかせているDeepSeek-R1を試してみたかったのと、RAGをデプロイするくらいはやっておかないと世間に置いていかれる危機感がした。
- DifyでRAGを実装するのが簡単らしい
- Ollama経由でhuggingfaceのモデルをロードできる
- XinferenceでRerankが使えるようになる
前評判どおりならプライベート環境にサービス展開してもイケるかもしれない期待。。。
モチベーション
- 職場のマニュアルと規約が大量に散らばっているので、蓄積してRAGで検索して楽したい(あくまで個人的な利用)。
手元の環境
- OS: Ubuntu 22
- CPU: AMD Ryzen
- GPU: NVIDIA RTX A6000(VRAM 48GB) x 2枚 ここまでのVRAMは不要
- Docker 27.5.0, Docker Compose 2.32.3
docker-compose
公式のYAMLファイルにOllamaとXinferenceのコンテナを加えて起動するように加筆する。
公式のまま起動して、個別にOllamaとXinferenceのコンテナを立てると連携が面倒なので一括起動とする。
dify/docker/docker-compose.yamlをいじって下さい。
以下、servicesにollamaとxinferenceを挿入、volumesにollamaを挿入。
depends_onにollamaとxinferenceも追加。
services:
# API service
api:
# ... (中略) ...
depends_on:
- db
- redis
+ - ollama
+ - xinference
# ... (中略) ...
worker:
# ... (中略) ...
depends_on:
- db
- redis
+ - ollama
+ - xinference
# ... (中略) ...
# Ollama service
ollama:
image: ollama/ollama
container_name: ollama
restart: always
ports:
- "11434:11434" #デフォルトのポート番号
volumes:
- ./volumes/ollama:/root/.ollama
deploy:
resources:
reservations:
devices:
- driver: nvidia
capabilities: [gpu]
device_ids: ["0"] # GPUの指定。1枚ならdevice_idsはコメントアウト
# xinference
xinference:
image: xprobe/xinference:latest
container_name: xinference
restart: always
ports:
- "9997:9997" #デフォルトのポート番号
volumes:
- ./volumes/xinference/xinference:/root/.xinference
- ./volumes/xinference/cache/huggingface:/root/.cache/huggingface
- ./volumes/xinference/cache/modelscope:/root/.cache/modelscope
deploy:
resources:
reservations:
devices:
- driver: nvidia
capabilities: [gpu]
device_ids: ["1"] # GPUの指定。1枚ならdevice_idsはコメントアウト
command: ['xinference-local', '-H', '0.0.0.0']
# ... (中略) ...
volumes:
+ ollama: # 不要かも
oradata:
dify_es01_data:
docker-compose.yamlのカレントディレクトリでコンテナ群を起動させる。
sudo docker compose up -d
動作設定
Difyの初期化
NginxのおかげでWebサーバの80番、443番ポートが開いているので、ブラウザでローカルページ http://localhost/ を開き、管理者設定して入る。
Ollamaでhuggingfaceからモデルをロード
GGUFファイルであればhuggingfaceからロードできるため、大抵のLLMが扱えます。
今回はcyberagentの日本語でファインチューニングしたQwenベースのDeepSeek-R1をGGUF形式にしたモデルを適用する。
Ollamaのコンテナ内で実行せねばならないので、ここはどうにかならないか。。。
ひとまず以下を実行してLLMのモデルをロードする。
cyberagentの日本語DeepSeek-R1(Qwen)をGGUF化したモデル
docker exec -it ollama ollama run hf.co/mmnga/cyberagent-DeepSeek-R1-Distill-Qwen-32B-Japanese-gguf
ollamaのコンテナ内で次のようにollama run hf.co/
に続けてロードしたいGGUF形式のモデルを指定するだけ。
ollama run hf.co/{ユーザー名}/{リポジトリ}
XinferenceでEmbeddingとRerankerをロード
ブラウザでローカルページ http://localhost:9997/ を開きローカルのXinferenceのページを開く。
Xinferenceは英語モデルばかりなので、LLMはhuggingfaceにまかせて、embeddingとrerankerをXinferenceで用意する。
docker-compose.yamlでGPU1で処理させており、VRAMは4108MBを消費している様子。
RAG用にEMBEDDING MODELSで jina-embeddings-v3 をロード
Rerank用にRERANK MODELSで bge-reranker-v2-m3 をロード
登録のModel UIDをDifyで認識させる際に同じUIDで渡すので、とりあえずモデル名と同じにしておく。
左下のロケットボタンでLaunch。
DifyでLLM, Embedding, Rerankerを指定
Difyに入って、右上のアカウントから設定に入り、モデルプロバイダーを選択
Ollama
- Model Name: 任意の名前
- Base URL: http://ollama:11434
Xorbits Inference(Xinference)
- Model Type
- EMBEDDING MODELSの jina-embeddings-v3 はText Embedding
- RERANK MODELSの bge-reranker-v2-m3 はRerank
- Model Name: 任意の名前
- Server url: http://xinference:9997/
- Model uid: Xinferenceでモデルをロードした際に付けたUID
それぞれ登録が成功すると次のようになる。
RAG
RAGはまずナレッジデータベースに書類やテキストをEmbedding modelでベクトルとして取り込みます。
そしてユーザーが入力したテキストのベクトルと近い知識を引いて生成する仕組み。
ナレッジのデータベースを作成
詳細は他のサイトが詳しいので譲るとして、上部メニューのナレッジから取り込みます。
RAGアプリ作成
- 上部メニューのスタジオから、テンプレのKnowledge Retreival + Chatbotを選択
-
KNOWLEDGE RETRIEVALブロックで作ったナレッジを選択し、Rerankモデルを指定する。
- Rerankで精度を上げるためにハイブリッド検索とRerankerのモデルを指定
-
LLMブロックでモデルをロードしたLLMを選択し、最後まで生成してもらうためにNum Predictを
-2
に指定する。
- 最初に与えるコンテキスト(プロンプト)は一般化されたものは無いので、プロンプトチューニングとして各自で調べて試して下さい。
掲載しているものはdifyがデフォルトで用意しているテンプレで、定番のロールを与えて、思考する条件を明記する感じです。
※ このままアプリを実行したらコンテキストが無いって文書が生成されたので、コンテキストを末尾にしたら直りました(バグ?)。
ナレッジの埋め込み設定と合わせてプロンプトの入れ方を考えないといけないのかな〜。よきサイトがございましたら教えて下さい。
- 右上の公開するから公開してアプリを実行で、もうRAGを試せます。簡単すぎて感動。
気になるVRAMの消費
定常状態は次のLLMに23GB弱とEmbed/Rerankに4GB強。
コスパのいいRTX 5090(32GB)で動かせる!?
Mac mini/studioのユニファイドメモリのほうがコスパいいけど、レスポンスはどうかな
さいごに
Dify+Ollama+Xinferenceでhuggingfaceに公開されている豊富なモデルからRAGを試せるようになりました。
API化できるみたいだし、他のアプリに出力だけインプリメントできそうw