Alibaba CloudにてMinIOというS3準拠オブジェクトストレージを立ち上げて爆速でS3-RAGサービスを作る

2024年12月27日掲載

キービジュアル

現在、生成AIおよびRAGを使ったサービスがホットになっています。RAGは(Retrieval Augmented Generation)の略称で、生成AIを使いながら前のデータを整理し、ユーザーが自然言語による文章ベースで質問をついでに、応じて関連する文章を検索・滞在し、質問文に対する回答文を生成し放棄する技術です。このRAGは生成AI - LLMが登場するよりずっと前からメタ社による自然言語処理技術として展開されていますが、LLMの登場により大いに普及しています。

現在、Alibaba Cloudを含めPublic Cloud上でRAGによるサービスの作り方はかなり普及していますが、今回はMinIOというAWS S3と互換性のあるオブジェクトストレージが構築できる便利なオープンソースの紹介もあわせて、オブジェクトストレージを使ったシンプルなRAGアプリケーションの作り方を解説します。

目次

1. 今のLangChainがサポートするデータソース領域について

生成AI - RAGアプリケーション構築フレームワークとして、オープンソースのLangChainサポートするデータソース一覧をみてみました。その結果、Alibaba Cloudは現状MaxComputeのみサポートという状況です(2024/7/24時点)

 

ベンダー/クラウド名

データベース

分析基盤

ストレージ

AI

ユーティリティ

Google

Google AlloyDB for PostgreSQL, Google Cloud SQL for SQL server, Google Cloud SQL for MySQL, Google Cloud SQL for PostgreSQL, Google Firestore in Datastore Mode, Google Firestore (Native Mode), Google Memorystore for Redis, Google Spanner

Google BigQuery, Google Bigtable

Google Cloud Storage Directory, Google Cloud Storage File, Google Drive

Google Speech-to-Text Audio Transcripts

Google El Carro for Oracle Workloads

Alibaba Cloud

 

Alibaba Cloud MaxCompute

   

Amazon

 

Athena 

AWS S3 Directory, AWS S3 File

Amazon Textract

 

Microsoft

  

Azure Blob Storage Container, Azure Blob Storage File

Azure AI Data

Azure AI Document Intelligence

Tencent

  

Tencent COS Directory, Tencent COS File

  

Oracle

Oracle Autonomous Database, Oracle AI Vector Search: Document Processing

    

Huawei

  

Huawei OBS Directory, Huawei OBS File

  

Airtable

    

Airtable

AssemblyAI

   

AssemblyAI Audio Transcripts

 

AstraDB

AstraDB

    

ArcGIS

    

ArcGIS

Apify

  

Apify Dataset

  

Cube

  

Cube Semantic Layer

  

Datadog

  

Datadog Logs

  

Dropbox

  

Dropbox

  

Git

  

Git, GitBook, GitHub

  

Notion

Notion DB 1/2, Notion DB 2/2

    

Rockset

  

Rockset

  

Slack

     

Snowflake

 

Snowflake

   

SurrealDB

 

SurrealDB

   

Alibaba CloudでLangChainによる生成AIアプリケーション開発は難しそうですね。一方AWS S3はサポートしているようです。なので、それをカバーするために今回はAWS S3と互換性のあるオープンソースのMinIOをAlibaba Cloudに立ち上げながら、Alibaba Cloud内でS3とのRAGによる生成AIアプリケーションを構築してみます。

※補足として、Alibaba CloudはLangChainをサポートしていない、というわけではなく、バージョンによってはサポートしているものもあります。例えば今のLangChainバージョンv2.0ではAnalyticDB for PostgreSQLをサポートしていませんが、バージョンv0.1 ではAnalyticDB for PostgreSQLをサポートしています。そういう意味ではLangChainのバージョンによってサポート有無が変わるので、詳しくはLangChain公式サイトを参照してください。

MinIOはAWS S3と互換性のあるオブジェクトストレージをどこでも立ち上げることが出来るオープンソースです。その功績が評価され、MinIOはCNCF(Cloud Native Computing Foundation)ことクラウドネイティブに関連するミドルウェアのオープンソースとして登録されています。

Build a CI/CD Pipeline for your AI/ML infrastructure

2. 全体構成図

Alibaba Cloud上でMinIOを立ち上げる方法は色々ありますが、今回はシンプルにECSこと仮想コンピューティング3台で立ち上げます。MinIOはHA構成として構築もできるので、ECS1台でも100台でも問題ないです。もちろんAlibabaCloudのFunctionComputeやContainer Service for Kubernetes (ACK)でMinIOを立ち上げることもできます。ECSでMinIOによるオブジェクトストレージを立ち上げたあと、その1つのECSにLangChain+Pythonによるアプリケーションを配置し、実行するだけです。今回はテックブログ用にクイックなDemoなので、かなり簡略化した手順となりますがご了承ください。

3. MinIOの導入

MinIOは Kubernetes、Linux、dockerなど様々な方法でインストールすることができます。今回はECS Ubuntu上で構築するため、 minio.debらパッケージファイルを入手し、立ち上げます。
※事前にECSのSecurity groupでPort 9000、9001を解放しておく必要があります。

SSHでログイン後、 minio.debらパッケージファイルを入手し、立ち上げます。

wget https://dl.min.io/server/minio/release/linux-amd64/archive/minio_20240716234641.0.0_amd64.deb -O minio.deb
dpkg -i minio.deb

MinIOサービスファイルを作成します。

tee /etc/systemd/system/minio.service <<EOF

[Unit]
Description=MinIO
Documentation=https://min.io/docs/minio/linux/index.html
Wants=network-online.target
After=network-online.target
AssertFileIsExecutable=/usr/local/bin/minio

[Service]
WorkingDirectory=/usr/local
User=minio-user
Group=minio-user
ProtectProc=invisible

EnvironmentFile=-/etc/default/minio
ExecStartPre=/bin/bash -c "if [ -z \"${MINIO_VOLUMES}\" ]; then echo \"Variable MINIO_VOLUMES not set in /etc/default/minio\"; exit 1; fi"
ExecStart=/usr/local/bin/minio server $MINIO_OPTS $MINIO_VOLUMES

Restart=always
LimitNOFILE=65536
TasksMax=infinity
TimeoutStopSec=infinity
SendSIGKILL=no

[Install]
WantedBy=multi-user.target
EOF

MinIOユーザーとグループを作成します。

groupadd -r minio-user
useradd -M -r -g minio-user minio-user
mkdir -p /mnt/disk{1..4}
chown minio-user:minio-user /mnt/disk{1..4}

MinIO環境ファイルを作成します。

tee /etc/default/minio <<EOF

MINIO_VOLUMES="http://10.2.0.29:9000/mnt/disk{1..4}/minio http://10.2.0.28:9000/mnt/disk{1..4}/minio http://10.2.0.27:9000/mnt/disk{1..4}/minio"

MINIO_OPTS="--console-address :9001"

MINIO_ROOT_USER=minioadmin

MINIO_ROOT_PASSWORD=minio-secret-key-CHANGE-ME

EOF

これで導入は完了です。しかし、異なるVM間で連結できているかlsblkとmountを試したところ、その出力結果から、マウントポイントが設定されていないことが判明します。

root@iZ6wea00iajgu2rabxroi9Z:~# lsblk 
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS 
loop0 7:0 0 61.9M 1 loop /snap/core20/1405 
loop1 7:1 0 79.9M 1 loop /snap/lxd/22923 
loop3 7:3 0 38.8M 1 loop /snap/snapd/21759 
loop4 7:4 0 63.9M 1 loop /snap/core20/2318 
loop5 7:5 0 87M 1 loop /snap/lxd/29351 
vda 252:0 0 100G 0 disk 
├─vda1 252:1 0 1M 0 part 
├─vda2 252:2 0 200M 0 part /boot/efi 
└─vda3 252:3 0 99.8G 0 part / 
root@iZ6wea00iajgu2rabxroi9Z:~# 
root@iZ6wea00iajgu2rabxroi9Z:~# mount | grep /mnt 
root@iZ6wea00iajgu2rabxroi9Z:~#

なので、マウントポイントの作成、設定を行います。

mkdir -p /mnt/disk{1..4}
dd if=/dev/zero of=/mnt/disk1/disk.img bs=1M count=1024 
dd if=/dev/zero of=/mnt/disk2/disk.img bs=1M count=1024 
dd if=/dev/zero of=/mnt/disk3/disk.img bs=1M count=1024 
dd if=/dev/zero of=/mnt/disk4/disk.img bs=1M count=1024 
mkfs.ext4 /mnt/disk1/disk.img sudo mkfs.ext4 /mnt/disk2/disk.img 
mkfs.ext4 /mnt/disk3/disk.img sudo mkfs.ext4 /mnt/disk4/disk.img 
mount -o loop /mnt/disk1/disk.img /mnt/disk1 
mount -o loop /mnt/disk2/disk.img /mnt/disk2 
mount -o loop /mnt/disk3/disk.img /mnt/disk3 
mount -o loop /mnt/disk4/disk.img /mnt/disk4

マウントポイントの作成、設定が終われば、MinIOサービスを再起動します。

sudo systemctl daemon-reload 
systemctl restart minio.service

これで、ブラウザからMinIOコンソールにアクセスで操作できるようになります。

ログイン情報はcat /etc/default/minio で見れます。

MinIO からAccess Keyを発行し、セキュリティ対策を図ることもできます。

4. APIでMinIOとの疎通テスト

うまくいきました。ここからMinIOと疎通テストをしてみます。

import boto3
import os        
from datasets import load_dataset


s3_resource = boto3.resource(
    's3',
    endpoint_url='http://47.xx.xxx.244:9000',
    aws_access_key_id='kFSxFDn1QFN1GxvrMK0o',
    aws_secret_access_key='xxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
)


s3_resource.create_bucket(Bucket="rag-service")

5. LangChainを使ってRAGアプリケーション構築

MinIOのObjectStorageができたら、早速RAGアプリケーションを試してみます。

今回は、huggingface の wiki ダンプ データセットを使用します。このデータセットをダウンロードし、アップロードしておきます。

# Hugging Faceのデータセットをロード
dataset = load_dataset("AhmedSSabir/Japanese-wiki-dump-sentence-dataset")


# データセットを一時的にローカル保存し、MinIOへアップロード
for split in dataset.keys():
    split_dataset = dataset[split]
    local_file_path = f"/tmp/{split}.jsonl"    
    split_dataset.to_json(local_file_path, orient='records', lines=True)    
    s3_resource.Bucket(bucket_name).upload_file(local_file_path, f"{split}.jsonl")    
    os.remove(local_file_path)

あとは以下のPythonコードにてendpoint_url、aws_access_key_id、aws_secret_access_keyを入力し実行するだけです(テックブログ用の簡易なコードなのでチューニングや最適化はしていません)

なお LangChain の Repo でS3処理Class コードには S3接続設定はそこまで厳密に求めているわけではないようです。  

import openai
import chromadb
import os
import sys
from langchain_community.document_loaders import S3DirectoryLoader
from langchain.chains import ConversationalRetrievalChain, RetrievalQA
from langchain_community.chat_models import ChatOpenAI
from langchain_community.llms import OpenAI
from langchain.text_splitter import CharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain.indexes.vectorstore import VectorStoreIndexWrapper
from langchain_openai import OpenAIEmbeddings

# OpenAI APIキーの設定
os.environ["OPENAI_API_KEY"] = ""

query = sys.argv[1] if len(sys.argv) > 1 else None

# S3バケットからドキュメントをロード
s3_loader = S3DirectoryLoader(
                "s3",
                endpoint_url="http://47.xx.xxx.244:9000",
                aws_access_key_id="kFSxFDn1QFN1GxvrMK0o",
                aws_secret_access_key="xxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
docs = s3_loader.load()
splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
split_texts = splitter.split_documents(docs)

# ドキュメントのベクトル化と検索
embeddings = OpenAIEmbeddings()
vector_store = Chroma.from_documents(split_texts, embeddings)

# QAオブジェクトの作成
qa_system = RetrievalQA.from_chain_type(llm=OpenAI(), chain_type="stuff", retriever=vector_store.as_retriever())

# 会話型検索チェーンの作成
conv_chain = ConversationalRetrievalChain.from_llm(
    llm=ChatOpenAI(model="gpt-3.5-turbo"),
    retriever=vector_store.as_retriever(search_kwargs={"k": 1}),
)

chat_history = []
while True:
    if not query:
        query = input("プロンプト: ")
    if query in ['quit', 'q', 'exit']:
        sys.exit()
    result = conv_chain({"question": query, "chat_history": chat_history})
    print(result['answer'])
    chat_history.append((query, result['answer']))
    query = None

学生の夏休みがうらやましいですね。

6. さいごに

本記事ではクイックにS3互換性のあるオブジェクトストレージとLangChainによるRAGサービスの構築方法を紹介しました。MinIOはどのクラウド、オンプレミスでも立ち上げることが出来ますので、気になる方は試してみてください。

関連サービス

Alibaba Cloudは中国国内でのクラウド利用はもちろん、日本-中国間のネットワークの不安定さの解消、中国サイバーセキュリティ法への対策など、中国進出に際する課題を解消できるパブリッククラウドサービスです。

MSP(Managed Service Provider)サービスは、お客さまのパブリッククラウドの導入から運用までをトータルでご提供するマネージドサービスです。

おすすめの記事

条件に該当するページがございません