Closed3

オープンソースのRAGソリューション「RAG-SaaS」を試す

kun432kun432

ここで知った。どうやらLlamaIndex製。

https://twitter.com/adithya_s_k/status/1829196138995667047

GitHubレポジトリ
https://github.com/adithya-s-k/RAG-SaaS

特徴など

RAG SaaS

RAGソリューションを迅速にシップ⚡

referred from https://github.com/adithya-s-k/RAG-SaaS

検索拡張生成(RAG)とエージェントベースのアプリケーションのためのエンドツーエンドのSaaSソリューション およびエージェントベースのアプリケーション。

機能

  • 🔐 ベーシック認証
  • 💬 チャット履歴の追跡
  • 🧠 複数のRAGのバリエーション
    • 基本的なRAG
    • 2つの追加構成
  • 👨‍💼 管理ダッシュボード
    • 📥 データ取り込み
    • 📊 監視
    • 👁️ 観測可能性
    • 🔄 RAG設定の切り替え
  • 🗄️ PDFアップロードのためのS3統合
  • 🐳 Docker / Docker Compose による容易なデプロイ

技術スタック

  • 🦙 LlamaIndex: RAGパイプラインの構築と調整用
  • 📦 MongoDB:通常のデータベースとベクトルデータベースの両方として使用
  • ⚡ FastAPI:バックエンドAPIフレームワーク
  • ⚛️ Next.js: フロントエンドフレームワーク
  • 🔍 Qdrant: 効率的な類似性検索のためのベクトルデータベース
  • 👁️ Arize Phoenix: RAGシステムの監視/評価を行うための観測プラットフォーム

🌟どうしてRAG-SaaSなのか?

信頼性の高いRAGシステムの構築には、時間と労力がかかります。RAG-SaaSを利用すれば、開発者は>RAGパイプラインの微調整や開発に集中でき、アプリケーションとしてパッケージ化することに頭を悩ませる必要がなくなります。LlamaIndexのcreate-llamaを基盤として構築されたRAG-SaaSは、RAGベースのプロジェクトに強固な基盤を提供します。

RAGの構築だけでなく運用も含めてフルパッケージ化されたRAGソリューションという感じ。

なお、ライセンスはデュアルライセンスになっている。

  • 学生、開発者、個人向け: Apache License 2.0
  • 企業および商用利用の場合: GPL v3.0
kun432kun432

Getting Started

https://github.com/adithya-s-k/RAG-SaaS?tab=readme-ov-file#-getting-started

ローカルのMac上で試してみる。

まずレポジトリクローン。

$ git clone https://github.com/adithya-s-k/RAG-SaaS.git && cd RAG-SaaS

環境設定を行っていく。フロントエンド・バックエンド・docker-compose.yamlでそれぞれ環境変数の設定が必要なのだが、

  • フロントエンド・バックエンドとdocker-compose.yamlで環境変数が冗長
    • docker-compose.yamlで設定しているならそれでいいのでは?と思ったけど、それだけだとダメなものがあった。
  • URLを設定する箇所が複数あって、その際のホスト名を、dockerネットワーク内でのもの(コンテナ名)にすべきなのか、外から見たもの(今回の例だとlocalhost)にすべきなのかに迷う
    • コンテナ内から"localhost"でアクセスするためにはhost.docker.internalにしないといけないはず
    • ブラウザでアクセス(フロントエンドが生成するURLでバックエンド参照する場合とか)するには"localhost"にしないといけないはず

あたりがあって、結構試行錯誤した。なので一応動いたというだけで、間違っている可能性はある点についてはあらかじめご了承を。

フロントエンド

$ cp -pi frontend/.env.example frontend/.env
frontend/.env
NEXT_PUBLIC_SERVER_URL=http://localhost:8000
NEXT_PUBLIC_CHAT_API=${NEXT_PUBLIC_SERVER_URL}/api/chat

バックエンド

$ cp -pi backend/.env.example backend/.env
backend/.env
MODEL_PROVIDER=openai
MODEL=gpt-4o-mini
EMBEDDING_MODEL=text-embedding-3-small
EMBEDDING_DIM=1536
CONVERSATION_STARTERS="RAGについて教えて。\nLlama Indexについて教えて。"
OPENAI_API_KEY=sk-XXXXXXXXXX
STREAM_TIMEOUT=60000
QDRANT_URL=http://localhost:6333
QDRANT_COLLECTION=default
QDRANT_API_KEY=
FILESERVER_URL_PREFIX=http://localhost:8000/api/files
APP_HOST=0.0.0.0
APP_PORT=8000
SYSTEM_PROMPT='あなたは、ユーザからの質問に答える、親切な日本語のアシスタントです。'
SYSTEM_CITATION_PROMPT='You have provided information from a knowledge base that has been passed to you in nodes of information. Each node has useful metadata such as node ID, file name, page, etc. Please add the citation to the data node for each sentence or paragraph that you reference in the provided information. The citation format is: . [citation:<node_id>]()

Example:
We have two nodes:
  node_id: xyz
  file_name: llama.pdf

  node_id: abc
  file_name: animal.pdf

User question: Tell me a fun fact about Llama.
Your answer:
A baby llama is called "Cria" [citation:xyz]().
It often lives in desert [citation:abc]().'
JWT_SECRET_KEY=jwt_secret_key
JWT_REFRESH_SECRET_KEY=jwt_refresh_secret_key
MONGODB_URI=mongodb://admin:password@mongodb:27017/
MONGODB_NAME=RAGSAAS
ADMIN_EMAIL=admin@example.com
ADMIN_PASSWORD=examplepassword
ARIZE_PHOENIX_ENDPOINT=http://localhost:4317

docker-compose.yaml

docker-compose.yaml
(snip)

  backend:
(snip)
    ports:
      - '8000:8000'
    environment:
      # MongoDB Configuration
      MONGODB_NAME: RAGSAAS
      MONGODB_URI: mongodb://admin:password@mongodb:27017/
      # Qdrant Configuration
      QDRANT_COLLECTION: default
      QDRANT_URL: http://qdrant:6333
      # QDRANT_API_KEY:
      OPENAI_API_KEY: sk-XXXXXXXXXX
      # Backend Application Configuration
      MODEL_PROVIDER: openai
      MODEL: gpt-4o-mini
      EMBEDDING_MODEL: text-embedding-3-small
      EMBEDDING_DIM: 1536
      FILESERVER_URL_PREFIX: http://backend:8000/api/files
      SYSTEM_PROMPT: 'あなたは、ユーザの質問に答える、親切な日本語のアシスタントです。'
      APP_HOST: 0.0.0.0
      APP_PORT: 8000
      ADMIN_EMAIL: admin@example.com
      ADMIN_PASSWORD: examplepassword
      JWT_SECRET_KEY: jwt_secret_key
      JWT_REFRESH_SECRET_KEY: jwt_refresh_secret_key
      ARIZE_PHOENIX_ENDPOINT: http://arizephoenix:6006
    depends_on:
(snip)

  frontend:
(snip)
    ports:
      - '3000:3000'
    environment:
      NEXT_PUBLIC_SERVER_URL: http://localhost:8000
      NEXT_PUBLIC_CHAT_API: http://localhost:8000/api/chat
    depends_on:
(snip)

起動

$ docker compose up -d
 ✔ Network ragsaas-network         Created                                                                                                  0.0s
 ✔ Volume "rag-saas_mongodb_data"  Created                                                                                                  0.0s
 ✔ Container qdrant                Started                                                                                                  0.5s
 ✔ Container mongodb               Started                                                                                                  0.5s
 ✔ Container arizephoenix          Started                                                                                                  0.5s
 ✔ Container backend               Started                                                                                                  0.4s
 ✔ Container frontend              Started

色々立ち上がっている。

$ docker compose ps
NAME           IMAGE                         COMMAND                   SERVICE        CREATED          STATUS          PORTS
arizephoenix   arizephoenix/phoenix:latest   "/usr/bin/python3.11…"   arizephoenix   18 seconds ago   Up 17 seconds   0.0.0.0:4317->4317/tcp, 0.0.0.0:6006->6006/tcp, 9090/tcp
backend        ragsaas/backend:latest        "python main.py"          backend        18 seconds ago   Up 17 seconds   0.0.0.0:8000->8000/tcp
frontend       ragsaas/frontend:latest       "docker-entrypoint.s…"   frontend       17 seconds ago   Up 17 seconds   0.0.0.0:3000->3000/tcp
mongodb        mongo:latest                  "docker-entrypoint.s…"   mongodb        18 seconds ago   Up 17 seconds   0.0.0.0:27017->27017/tcp
qdrant         qdrant/qdrant:latest          "./entrypoint.sh"         qdrant         18 seconds ago   Up 17 seconds   0.0.0.0:6333-6334->6333-6334/tcp

ブラウザで3000番ポートにアクセスするとトップ画面が表示されるので、右上の「Sign in」をクリック。

ADMIN_EMAIL/ADMIN_PASSWORDに設定したメアド・パスワードでログイン。

ログインした。トップ画面はこんな感じ。で、入力したくなるところだけど、一旦我慢。

ブラウザで別タブを開いて、QdrantのUI http://localhost:6333/dashboardにアクセスすると、Qdrantのコレクションの一覧画面が表示される。

設定では"default"という名前のコレクションを指定していたはずだが、作成されていない。この作成プロセスが考慮されているのかがわからないのだが、この設定がないとチャットが失敗する。ということで手動で作成する。

Qdrantのコンソールから以下を入力。

PUT collections/default
{
  "vectors": {
      "size": 1536,
      "distance": "Cosine"
  } 
}

実行

右側のペーンに結果が出力される。こんな感じで出力されていればOK。コレクション画面に戻る。

"default"コレクションが作成されている。これでQdrantはOK。

RAG-SaaSの画面に戻ってチャットしてみる。せっかくなのでスターターメッセージをそのまま使ってみる。

こんな感じでレスポンスが返ってくる(実際にはストリーミング)。次の質問へのヒントなども出力されているので、あとはチャットしていけばいい。なお、日本語IMEの変換確定ENTERで送信されてしまうのはもはやお約束。

実行したチャットはスレッドとして管理される。左上のメニューをクリックすると、ChatGPTライクな感じでスレッドになっているのがわかる。

RAGをやってみる。チャット画面からはファイルアップロードするようなメニューが見当たらないが、管理者ダッシュボードから行える。管理者ダッシュボードはhttp://localhost:3000/adminでアクセスできる。

管理者ダッシュボードでできることは以下の3つ

  • ユーザ管理
  • RAGのドキュメント登録
  • RAGの設定

ユーザ管理は割愛。まず、RAGの設定画面を見てみる。

この画面ではシステムプロンプトとスターターメッセージを設定できる。

次に、RAGの設定画面を見てみる。

ここでRAGのコンテキストとなるドキュメントをアップロードできる。ドキュメントについてはチャンク分割等の設定を行いたいところではあるが、そのあたりは現時点ではComing Soonになっている。とりあえず適当なPDFをアップロードしてみる。

神戸市が公開している観光に関する統計・調査資料の「令和4年度 神戸市観光動向調査結果について」というPDFを使う。

https://www.city.kobe.lg.jp/a64051/shise/toke/sightseeing.html

PDF直
https://www.city.kobe.lg.jp/documents/15123/r4_doukou.pdf

アップロードしたら"Ingest File"をクリック

どうやら30個のチャンクに分割された様子。

チャット画面に戻って、新しいスレッドを開いて、先程のPDFに関する質問を投げてみる。

神戸までの主な利用交通機関の内訳を教えて。

結果はこんな感じ。ドキュメントの内容を参照して回答していることがわかる。

"Sources: 1"となっている箇所をクリック。

ここにソースとなるドキュメントが表示されるようだが、読み込みに失敗している模様。

コードを読んでみた限り、どうもアップロードしたデータ先パスが初回起動時には存在しなくて、FastAPIで公開できていない様子。なので、docker compose restartしてやれば次回以降は正しく表示される。

なお、アップロードしたドキュメントの管理、みたいなメニューは現時点ではないので、後からアップロードしたドキュメント一覧を確認するには直接パスを見に行くしかなかったり、チャットのスレッドで読み込まれるドキュメントを選択するといったこともできないので、複数ドキュメントをアップロードするとどうもすべからく横断的に検索する模様。

最後に、実行したチャットの内容はArize Phoenixでトレーシングを確認できる。Arize Phoenixの管理画面はhttp://localhost:6006でアクセスできる。 以下のようにプロジェクト一覧が表示される。

プロジェクトは3つあるが、"default"はArize Phoenixのデフォルトで使わない。チャットのトレーシングは"RAGSAAS-Chat"で、ドキュメント登録時のトレーシングが"RAGSAAS-Data-Ingest"になる。"RAGSAAS-Chat"をクリックすると、トレーシングが表示される。

kun432kun432

まとめ

LlamaIndexがコアとして使われているというところでRAG-SaaSを取り上げてみた。公開されたばかりだし、個人の方によるプロジェクトという点を踏まえると企業が作ったOSSとは機能的に物足りない点が多い。なので、社内向け・プライベートの両面でも現時点では採用しにくいとは思う。

ただ、RAGをコアにしたプラットフォームサービスを作って運用まで考えると、最低限これぐらいの機能は求められるライン、というものさしにはなると思うし、色々周辺コンポーネントのインテグレーションも取捨選択が必要だと感じる。

このスクラップは4ヶ月前にクローズされました