技術は私たちの力。技術は私たちの楽しみ。 Creative Developer BLOG 技術部ブログ
Technology is our strength. Technology is what we enjoy.

ローカルLLMでRAG構築:ゼロからの挑戦

2024-08-26 勉強会
タイトル
こんにちは。
システム部の植木です。

第3次AIブーム真っ只中の現在、新しい概念が次々と登場しています。
特にOpenAIの「ChatGPT」はすっかり市民権を得て、今も勢力を拡大しています。

ただ、便利な反面セキュリティ面についても多様な攻撃方法や情報流出も社会的な問題になっています。

そこで、情報ソースを限定して調べて会話が出来るようなシステムをクローズドな環境で構築する事の価値も上がっていると思います。

昨今では「RAG(Retrieval-Augmented Generation)」と呼ばれる技術も出現してきています。

今回は、RAGとローカルLLMを組み合わせて構築し、実際に使えるのかを検証する入門記事を書きました。最後までお付き合いください。

ローカルLLMの構築

ベースとなるLLMをローカルで構築していきます。
今回は「LM Studio(https://lmstudio.ai)」等ではなく、WSL2とDockerを用いてローカルで作成して行く予定です。

環境

今回準備した環境は

・Ubuntu24.04 LTS (WSL2)
・Docker Desktop for Windows 4.33.1
・NVIDIA Container Toolkit
→こちらはDocker上でグラボを利用する為に必要なツールです。CPUのみで実装する場合は不要です。

→グラボは「GeForce RTX 4070Ti SUPER」を用いて実験してみました

利用モデル

利用するモデルは「Ollama」を使ってみます。
この「Ollama」はオープンソースのLLMとして有名で、ローカルで構築するには良いツールなので採用しました。
単純に私が使ってみたかっただけなのもあります。

コンテナのPullと起動

コンテナをPullします。
docker pull ollama/ollama

コンテナ起動

今回はGPUを利用して動作させるので、下記コマンドでイメージを立ち上げます
docker run -d --gpus=all -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama

docker ps
起動後に無事にOllamaのコンテナが起動していることを確認します

モデルについて

405Bのようなより大規模なモデルは処理負荷が高すぎるため、今回は8Bのモデルを使用します。

導入完了

無事にOllamaの3.1の8Bが導入出来ました。

ローカルLLMの設定完了

こんにちは!Ollama!
まずはベースとなるローカルのLLMが完成しました。
WebUI等で質問出来る様にするのは今回の目的とは違うので一旦ペンディングです。

RAGの環境構築

さて、RAGに利用するツールを導入していきます。
まずはPythonの環境作成を行うので、minicondaを導入します。
https://docs.anaconda.com/miniconda/
シェルを叩いてインストールします。
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh

bash Miniconda3-latest-Linux-x86_64.sh

パスの指定
export PATH=/インストールしたディレクトリ/miniconda3/bin:$PATH

conda create -n myenv python=3.9
conda activate myenv
パスは各々変更しましょう。
パスが通ったら新しい仮想環境を作成します。

最終的にはCreateした環境をアクティベートして利用します。

LlamaIndex

https://docs.llamaindex.ai/en/latest/index.html
LlamaIndexはRAGシステムを構築する時に利用されるフレームワークです。
自身が保持しているデータからデータを参照しつつLLM経由で回答が出来るというなかなか熱いアレです。

有名なLangChainよりもサクッとRAGを構築出来ると巷で話題(?)です。

JupyterLab

便利なツールのJupyterLabも一緒に導入します。
JupyterLabは便利なIDEです。
※詳しい解説は割愛します
conda install -c conda-forge jupyterlab

LlamaIndexセットアップ

JupyterLab上のコードセルから必要なものをインストールします
!pip install llama-index
!pip install llama-index-llms-ollama
!pip install llama-index-embeddings-huggingface

必要なものがインストールされます。

インストール完了後に別のノートブックを起動して、こちらはOllamaのモデル設定を行います。
from llama_index.llms.ollama import Ollama
llm = Ollama(model="llama3.1:8b", request_timeout=30.0)
今回はVectorStoreIndexを用いてデータのインデックスを生成します

https://docs.llamaindex.ai/en/stable/module_guides/indexing/vector_store_index/

RAGに食べさせる面白みの無いデータ

読み込む対象のデータを指定して、QueryEngineを経由して答えを返してもらいます。
from llama_index.core import SimpleDirectoryReader, VectorStoreIndex

reader = SimpleDirectoryReader(input_files=["./data/rag_data.txt"])
data = reader.load_data()


response = query_engine.query(
"このファイルの所有者を**日本語**で簡潔に説明してください。 "
" page reference after each statement."
)
response.print_response_stream()

大変簡素な答えに感銘を受ける

しっかりと読み取ったデータから返事を返してくれています。
簡潔でいいですね。

これで「限られた環境化のデータを参照してローカルでチャットで答えてくれる」というRAGの下地は出来ました。
後はWebUI等をこしらえたり、精度を高めてチューニングを施していけば実現可能な気がします。

変に気を使う

なお、余談ですが、冗長かつ名前の由来の考察を入れてもらうようにしたら、「知的で細やかな性格からつけられたものだと言われています」と急によいしょし始めたのでこのぐらいにしておきましょう。

サスケWorksのヘルプセンターの文章を読み取れるのか

さて、ここまではテキストベースでデータを読んでいましたがHTML等は出来るのでしょうか?

https://help.works.app/hc/ja

我らがサスケWorksのヘルプセンターから「サスケWorksへのログイン」のHTMLをダウンロードしました。

すべてはここから始まる

質問してみました。

質問の内容的には「ログイン方法を教えて下さい」です。
あえて細かく聞かないで簡潔な質問により、データソースがしっかりと「サスケWorksへのログインの記事」を読み込んでいるのかを確認するためです。

Ollamaさん賢い

しっかりと記事の内容を反映しているように見えます。
もっとチューニングをすれば精度は上がりそうですが、一旦は上々の結果です。

1記事だけじゃあ使い物にならないよね?

という事で、「はじめましょう!」セクションにある記事の3つを持ってきました。

・サスケWorksへのログイン
・サスケWorksスタートガイド
・レコードとサブレコードとは

フォルダの内容を全て読み込み

from llama_index.core import SimpleDirectoryReader, VectorStoreIndex

reader = SimpleDirectoryReader("./data/saaske/")
data = reader.load_data()
index = VectorStoreIndex.from_documents(data, embed_model=embed_model)
ではログインの情報では出ないはずの「レコードとサブレコード」について教えてもらいましょう。

果たしてしっかり回答が返ってくるのでしょうか?

Ollamaさん賢い(2回目)

データソースを参照した内容が記載されていますね!

レコードとサブレコードについて熱く語った上に、最後にしっかり公式のURLなんかも出力してくれましたね。
※実際に記事に飛ぶ事が出来るURLでした

細かい粒度やチューニング等はまだまだ必要ですが、実現出来ればセキュリティが必要な内容等をネットワークを意識せずに貯めておけるのはかなり重要な気がします。

最後に

技術の進化は常に驚くべきスピードで進んでいるということです。今回の「RAG」も、数年前には想像もしなかった技術でした。しかし、実際に手を動かして構築してみると、その可能性と課題が鮮明に見えてきました。

この経験を通じて、改めて感じたのは実践の重要性です。ネット上の情報だけでなく、実際に技術に触れ、試行錯誤を重ねることで、真の理解が得られるのは今も変わらない事かなと感じております。

また実用的にもAWSを用いた方法等も加味すると、弊社内のナレッジや製品ヘルプセンターの情報を効率的に検索・活用できるようになれば理想的です。

これは、情報の死蔵を防ぎ、組織全体の知識レベルを底上げする可能性を秘めています。

「興味を持って実際にやってみる」という姿勢の重要性は、これからも変わらないでしょう。この姿勢こそが、私たち技術者の成長を支える礎なのです。

次回記事を書くときにはどの様な技術が生まれているのかを楽しみにしましょう。

ここまでお読みいただき、ありがとうございました。
記事一覧へ

Member

システム部開発ユニット
システム部SIユニット
クリエイティブ戦略部デザインユニット
クリエイティブ戦略部プランニングユニット
管理部