DifyとXinferenceを使ってローカルのみでrerankありRAGを試す

# はじめに

[Dify](https://dify.ai/)はRAGなどの様々なLLMアプリをノーコードで実現できますが、RAGで真価を発揮するにはrerankモデルが使いたくなります。しかし、rerankはCohereなど一部のサービスでしか提供されておらず(2024/5時点)、気軽に試す事が困難です。一方、[Xinference](https://inference.readthedocs.io/)はローカルでrerankモデルを動かす事ができ、DifyはモデルプロバイダーとしてXinferenceが使えます。そこで、DifyとXinferenceを使ってローカルのみでrerankありのRAGを実行してみました。

# セットアップ

## Xinference

https://qiita.com/orca13/items/ab2dc275f75a2b22f398

で紹介した様に、Xinferenceをセットアップします。その後、モデルを起動します。今回は以下のモデルを使用しました。

* LLM: llama-3-instruct(8B-Q5_K_M)
* EMBEDDING: bge-m2
* RERANK: bge-reranker-v2-m3

なお、Difyから使用する前に、モデルを起動しておく必要があります。

## Dify

基本的な使い方は各所で紹介されているので省略します。
今回、モデルプロバイダーにXinferenceを用いるので、Difyの起動に使うdocker-compose.ymlに以下を追加して、Xinferenceが同時に立ち上がる様にします。

```yaml
services:
# ... (中略) ...
  xinference:
    image: xprobe/xinference
    container_name: xinference
    ports:
      - 9997:9997
    volumes:
      - $HOME/.xinference:/root/.xinference
      - $HOME/.cache/huggingface:/root/.cache/huggingface
      - $HOME/.cache/modelscope:/root/.cache/modelscope
    command: "xinference-local -H 0.0.0.0"
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]
```

Difyを起動させたら、http\://localhost/ にアクセスし、モデルプロバイダーからXorbits Inference(Xinference)のモデルを追加します。

![DifyModelProviders](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791334/3a969cbc-f6a3-ed9c-421e-ff302feae948.png)

まず、LLMを登録します。その際、各パラメータは以下の様に設定します。

* Model Name: 任意の文字列
* Server url:  http\://xinference:9997/ (docker-compose.ymlを上記の通り設定した場合)
* Model uid: Xinferenceのモデル毎のID

![XinferenceLLM](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791334/c7c286f3-7a62-e8b5-64cc-06aa6f2a1d1e.png)

一つモデルを登録すると、Xorbits Inferenceが上に来るので、Add ModelからText EmbeddingモデルとRerankモデルを追加します。今回は使いませんが、画像にある様にSpeech2textモデルも設定できます。

![XinferenceAdd](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791334/935490d8-3fa0-b67c-4179-7ba650649bdb.png)

![XinferenceEmbedding](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791334/ac49b7ea-7e75-7725-9436-cb687aa63619.png)

![XinferenceRerank](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791334/9439409f-3cc6-ce0c-b7fa-49ea6f10fa28.png)

最後に、システムモデル設定を行います。上記登録後すぐだと、追加したモデルが出てこないかもしれません。その場合は、ページを開きなおしてみてください。

![SystemModel](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791334/e45d00b3-d9d0-7a4d-00d0-1e89ad5b6854.png)

これで、DifyからXinferenceを通してローカルの各モデルが使える様になりました。

# RAG

## 知識作成

まず、ナレッジから知識を作成します。
今回は、arXivからKANの論文を使用させていただきました。

https://arxiv.org/abs/2404.19756

1. ドキュメントを選択

   ![DocSelect](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791334/f1ca7ce4-6d9c-ae7e-08e7-6c639f4ed02b.png)

1. 検索設定はハイブリッド検索

   ![DocSetting](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791334/a7651282-c5af-469c-02b0-6792a24b431f.png)

1. ナレッジ作成完了

   ![DocComp](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791334/d5ae7fca-73d1-8402-a899-bb343f6a1d9e.png)


ローカルLLMなのでコストは$0です(電気代は除く)。

## RAGアプリ作成

ナレッジを追加したら、RAGを構築します。

1. 探索からRAGのテンプレートを選択

   ![RagTemplate](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791334/c785ff32-4a3e-9c25-359e-006e64ac0458.png)

1. Knowledge Retrievalブロックの知識を追加

   ![KnowledgeRetrieval](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791334/22b331b9-1db8-4afc-37e5-c39c6a1035bf.png)

1. Knowledge Retrievalブロックでマルチパスリトリーバルを選択

   ![MultiPathRetrievall](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791334/41040bc4-78a6-6aef-ea60-8675bdbde3ea.png)

1. LLMブロックのコンテキストを設定し、モデルを修正

   ![LLM](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791334/3154507c-546b-eae9-bc7e-5d547fc2fbb7.png)

以上でRAGが構築できたので、実行してみます。

![RAG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791334/29014571-5aba-38d4-d445-fde4fc1e9480.png)

この程度の問いであればrerankを使うまでもありませんが、正しい回答が得られました。

# まとめ

DifyとXinferenceを使ってローカルのみでrerankありのRAGを実行してみました。rerankなしとの比較や商用rerankモデルとの比較はしていないため、どの程度rerankが有効なのかは不明ですが、正しい回答が得られる事を確認できました。