Open WebUI (Formerly Ollama WebUI) がすごい２（RAGもすごい）

先日Open WebUIについて投稿したところ、多くの反響をいただきましたので、第２弾の投稿です。

https://qiita.com/moritalous/items/1cad6878ea750d18747c

Open WebUIのRAG機能を深堀りします。

https://docs.openwebui.com/tutorial/rag

:::note
前回構築した環境をベースとして解説します。

<details><summary>docker-compose.yaml</summary>

```yaml:docker-compose.yaml
services:
  open-webui:
    image: ghcr.io/open-webui/open-webui
    container_name: open-webui
    volumes:
      - open-webui:/app/backend/data
    ports:
      - 8080:8080
    environment:
      - 'WEBUI_SECRET_KEY='
      - 'ENABLE_OLLAMA_API=false'
      - 'OPENAI_API_BASE_URL=http://litellm:4000'
      - 'OPENAI_API_KEY=sk-12345'

  litellm:
    image: ghcr.io/berriai/litellm:main-stable
    volumes:
      - ~/.aws:/root/.aws
      - ./litellm/config.yaml:/config.yaml
    command: [ "--config", "/config.yaml" ]

volumes:
  open-webui: {}
```

BedrockのClaude 3 Haikuを使って試しました。

</details>

<details><summary>litellm/config.yaml</summary>

```yaml:litellm/config.yaml
model_list:
  - model_name: claude-3-sonnet
    litellm_params:
      model: bedrock/anthropic.claude-3-sonnet-20240229-v1:0
      aws_region_name: us-east-1
  - model_name: claude-3-haiku
    litellm_params:
      model: bedrock/anthropic.claude-3-haiku-20240307-v1:0
  - model_name: command-r-v1:0
    litellm_params:
      model: bedrock/cohere.command-r-v1:0
  - model_name: command-r-plus-v1:0
    litellm_params:
      model: bedrock/cohere.command-r-plus-v1:0
```

</details>

:::

## ドキュメントを添付して質問する

チャットの際にドキュメントの添付ができます。`Upload Files`からドキュメントを選択します。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/bda97341-a4c0-ef52-9ebe-4b83526f3bcf.png)

ドキュメントの内容について質問ができます。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/fdb9364a-5e2a-9ebc-1f16-1113ca6813de.png)

:::note
Knowledge bases for Amazon Bedrockでいうところの`Chat with your document`みたいな感じです。
:::

ファイル名をクリックすると、抽出した文字列が確認できます。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/df6389de-793b-2041-7c4b-d61048c20f33.png)

ドキュメントは複数指定可能です。また、チャットの途中で追加することもできます。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/c34738d8-efc6-4fd3-d759-9b040203c94d.png)

以下のプロンプトが使用されています。（変更可能）

> Use the following context as your learned knowledge, inside <context></context> XML tags.
> <context>
>     [context]
> </context>
> 
> When answer to user:
> - If you don't know, just say that you don't know.
> - If you don't know when you are not sure, ask for clarification.
> Avoid mentioning that you obtained the information from the context.
> And answer according to the language of the user's question.
> 
> Given the context information, answer the query.
> Query: [query]

このことを頭に入れておかないと期待する答えが得られません。

例えば **「添付ファイルについて教えて」** と質問すると、「添付ファイルがありません」と言われてしまいます。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/4bd880a3-4e07-f20f-7693-1e33186aa2b1.png)

:::note

Open WebUIはドキュメントがあまり整備されていません。
例えば、どういったファイルフォーマットに対応しているかは、ドキュメントに明記されておらず、「[get_loader関数](https://github.com/open-webui/open-webui/blob/2fa94956f4e500bf5c42263124c758d8613ee05e/backend/apps/rag/main.py#L328)をみてね」とソースコードへのリンクがあるのみです。

「まだまだ未熟だ」と捉えることもできますが、伸びしろ（調べしろ）があって楽しいです🤩。

:::

## URLを指定して質問する

チャット欄に「#http」で始まる文字列を入力すると、参照URLとして判断されます。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/76aacf14-b675-f18e-21bd-adffaee45159.png)

エンターを押すとHTMLが取得され、参照ドキュメントとして利用できます。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/1912698c-eda9-68bb-892e-9bf41ef9e501.png)

## Web検索する

外部APIを使い、Web検索が可能です。
対応しているAPIは以下のとおりです。

*  SearXNG search API
*  Google Programmable Search Engine (PSE) service
*  Brave Search API
*  Serpstack search API
*  Serper search API

Brave Search APIを使って解説します。

`docker-compose.yaml`に環境変数を追加します。

```diff_yaml:docker-compose.yaml
  services:
    open-webui:
      image: ghcr.io/open-webui/open-webui
      container_name: open-webui
      volumes:
        - open-webui:/app/backend/data
      ports:
        - 8080:8080
      environment:
        - 'WEBUI_AUTH=false'
        - 'WEBUI_SECRET_KEY='
        - 'ENABLE_OLLAMA_API=false'
        - 'OPENAI_API_BASE_URL=http://litellm:4000'
        - 'OPENAI_API_KEY=sk-12345'
  
+       - 'ENABLE_RAG_WEB_SEARCH=true' # Web検索を有効
+       - 'RAG_WEB_SEARCH_ENGINE=brave' # Web検索で使用するサービス
+       - 'BRAVE_SEARCH_API_KEY=*****' # Brave APIのAPI Key
  
    litellm:
      image: ghcr.io/berriai/litellm:main-stable
      volumes:
        - ~/.aws:/root/.aws
        - ./litellm/config.yaml:/config.yaml
      # ports:
      #   - "4000:4000"
      command: [ "--config", "/config.yaml" ]
  
  volumes:
    open-webui: {}
```

編集後、`docker compose down && docker compose up`を実行します。

ドキュメントアップロードの場所に`Web Search`のトグルが追加されます。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/dd909f98-9a1b-3a48-236c-191d642d3edd.png)

Web Searchを有効にして質問します。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/f1f3be53-a27a-31b5-9dfb-7002a0705ba3.png)

Web検索をして回答してくれました。

初回の回答が英語だったので、「日本語で回答して」と追加で問いかけると「日本語で回答して」をWeb検索した結果も追加されて回答生成されました。

こちらも情報源の確認ができます。
ただ、すごく短いコンテンツしか取得できていないので、もう少し込み入った質問だとうまく回答できないかもしれません。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/f06e619f-1700-2f5a-e3a6-d6f091da45d1.png)

## 事前準備ドキュメントを埋め込みして利用する

ドキュメントをベクトル化して使用するパターンです。これが一般的な「RAG」だと思います。

埋め込みにはTitan Text Embedding V2を使用するので、LiteLLMの設定ファイルに追加します。

```diff_yaml:litellm/config.yaml
  model_list:
    - model_name: claude-3-sonnet
      litellm_params:
        model: bedrock/anthropic.claude-3-sonnet-20240229-v1:0
        aws_region_name: us-east-1
    - model_name: claude-3-haiku
      litellm_params:
        model: bedrock/anthropic.claude-3-haiku-20240307-v1:0
        aws_region_name: us-east-1
    - model_name: command-r-v1:0
      litellm_params:
        model: bedrock/cohere.command-r-v1:0
        aws_region_name: us-east-1
    - model_name: command-r-plus-v1:0
      litellm_params:
        model: bedrock/cohere.command-r-plus-v1:0
        aws_region_name: us-east-1
+   - model_name: amazon.titan-embed-text-v2:0
+     litellm_params:
+       model: bedrock/amazon.titan-embed-text-v2:0
+       aws_region_name: us-east-1
```

`docker-compose.yaml`に環境変数を追加します。


```diff_yaml:docker-compose.yaml
  services:
    open-webui:
      image: ghcr.io/open-webui/open-webui
      container_name: open-webui
      volumes:
        - open-webui:/app/backend/data
+       - ./docs:/data/docs # ドキュメントを格納するフォルダーをマウント
      ports:
        - 8080:8080
      environment:
        - 'WEBUI_AUTH=false'
        - 'WEBUI_SECRET_KEY='
        - 'ENABLE_OLLAMA_API=false'
        - 'OPENAI_API_BASE_URL=http://litellm:4000'
        - 'OPENAI_API_KEY=sk-12345'
  
       - 'ENABLE_RAG_WEB_SEARCH=true'
       - 'RAG_WEB_SEARCH_ENGINE=brave'
       - 'BRAVE_SEARCH_API_KEY=*****'

+     - 'DOCS_DIR=/data/docs' # ドキュメントを格納するフォルダー
+     - 'RAG_EMBEDDING_ENGINE=openai' # 埋め込みに使用するモデル。未指定（local model）、ollama、openaiのいずれか
+     - 'RAG_OPENAI_API_BASE_URL=http://litellm:4000' # OpenAI APIのエンドポイント
+     - 'RAG_OPENAI_API_KEY=sk-12345' # OpenAI APIのAPIキー　ダミーの値でOK
+     - 'RAG_EMBEDDING_MODEL=amazon.titan-embed-text-v2:0' # LiteLLMで定義したモデル名

    litellm:
      image: ghcr.io/berriai/litellm:main-stable
      volumes:
        - ~/.aws:/root/.aws
        - ./litellm/config.yaml:/config.yaml
      # ports:
      #   - "4000:4000"
      command: [ "--config", "/config.yaml" ]
  
  volumes:
    open-webui: {}

```

docker-compose.yamlがあるフォルダーに`docs`フォルダーを作成し、ドキュメントを格納します。

こんな感じでツリー構造にしてみます。

```
docs
├── ai
│   ├── genai
│   │   └── bedrock.md
│   └── sagemaker.md
└── compute
    └── ec2.md

3 directories, 3 files
```

内容はこのようなテキストです。

* bedrock.md
>Amazon Bedrock は、単一の API を介して AI21 Labs、Anthropic、Cohere、Meta、Mistral AI、Stability AI、および Amazon といった大手 AI 企業からの高性能な基盤モデル (FM) を選択できるフルマネージドサービスで、セキュリティ、プライバシー、責任ある AI を備えた生成 AI アプリケーションを構築するために必要な幅広い機能を提供します。Amazon Bedrock を使用すると、ユースケースに最適な FM を簡単に試して評価したり、微調整や検索拡張生成 (RAG) などの手法を使用してデータに合わせてカスタマイズしたり、エンタープライズシステムとデータソースを使用してタスクを実行するエージェントを構築したりできます。Amazon Bedrock はサーバーレスであるため、インフラストラクチャを管理する必要がありません。また、使い慣れた AWS サービスを使用して、生成 AI 機能をアプリケーションに安全に統合してデプロイできます。

* sagemaker.md
>Amazon SageMaker は、あらゆるユースケースで高性能で低コストの機械学習 (ML) を実現する幅広いツールを統合した完全マネージド型サービスです。SageMaker では、ノートブック、デバッガー、プロファイラー、パイプライン、MLOps などのツールを使用して、ML モデルを大規模に構築、トレーニング、デプロイできます。しかも、すべてを 1 つの統合開発環境 (IDE) で行えます。SageMaker は、アクセス制御の簡素化と ML プロジェクトの透明性により、ガバナンス要件をサポートします。さらに、FM の微調整、実験、再トレーニング、デプロイを行うための専用ツールを使用して、独自の FM、つまり膨大なデータセットでトレーニングされた大規模モデルを構築できます。 SageMaker では、公開されている FM を含む何百もの事前トレーニング済みモデルにアクセスでき、数回クリックするだけでデプロイできます。

* ec2.md
> Amazon Elastic Compute Cloud (Amazon EC2) は、極めて幅広く、奥深いコンピューティングプラットフォームを提供します。また、ワークロードのニーズに最も適切に対応できるように、750 を超えるインスタンスを提供するほか、最新のプロセッサ、ストレージ、ネットワーク、オペレーティングシステム、購入モデルを選択できます。当社は、インテル、AMD、Arm の各プロセッサに対応した初めての大手クラウドプロバイダーです。さらに、オンデマンドの EC2 Mac インスタンスを備えた唯一のクラウドであり、400 Gbps のイーサネットネットワークを備えた唯一のクラウドでもあります。機械学習のトレーニングでは最高のコストパフォーマンスを実現し、1 つの推論インスタンスあたりのコストもクラウドの中では最も低く抑えられています。他のどのクラウドよりも多くの SAP、ハイパフォーマンスコンピューティング (HPC) 、機械学習、および Windows のワークロードが AWS で実行されています。

準備ができたらコンテナを再起動します。`docker compose down && docker compose up`を実行します。

左下のメニューから、`Admin Panel`を選択します。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/8084ce17-6c25-c348-4fc2-bfe4e48c8f2c.png)

`Settings`タブを選択後、`Documents`を選択します。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/3d55f88c-33a2-0812-2326-ec00b40307b9.png)

`Scan for documents from DOCS_DIR (/data/docs)`にある`Scan`ボタンをクリックすると、埋め込みが開始します。1分ぐらいで完了します。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/4abe65db-9bdd-15cf-44f2-83daf9ab425b.png)

ドキュメントの登録が完了したので、チャットで質問をしましょう。（左上の鉛筆（？）マークをクリックすると、チャット画面に戻ります）

`#`を入力すると、登録したドキュメントがリストアップされます。

フォルダー単位での選択ができます。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/5722d5e9-1396-8da2-8b5c-98bee0301ebe.png)

ファイル単位での選択も可能です。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/33a9129c-eabb-ab07-1daa-f5859aed0cac.png)

親階層を選ぶと子階層のドキュメントも検索対象となります。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/705a8521-8fea-cc5c-78ea-20a9221dd2bc.png)

もちろん、ファイルとフォルダーの組み合わせもバッチリです。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/97efb764-c42d-9e4d-05bd-de8b5780fd3e.png)

もうこれでよくない？