見出し画像

時代はRAGらしいので、オンプレRAGシステムをどうやったら作れるのか調べてみる

はじめに

モチベーション

  • notebookLMを触ってみたら面白かったので、「似たことをするにはどうなるんだろう」とか、「NDA結んだとて気軽にはクラウドに情報を上げられない企業において、オンプレでサクッと似たシステムを作る需要はあるんじゃない?」と思ったので、どうなってるのか今更ながら知りたくなった。

このnoteの内容

  • ハイブリッドとかAdvancedの前に、そもそもRAGシステムがどのように構築されるのかのステップを知りたかったので、(1)データ準備や前処理部分、(2)オンプレでのRAG実装について、の二つに着目してPerplexityで調査。


データ準備や前処理の具体的手順を知る

クエリの結果

Perplexityに「社外秘の情報を扱うことを想定してオンプレでRAGを実装する際のデータ準備や前処理についての具体的手順」を表で返すようにお願いした。(実際には何回かのクエリによって生成しているが割愛)

PerplexityによるCitation

https://ai-market.jp/technology/rag/
https://aismiley.co.jp/ai_news/what-is-rag/
https://aws.amazon.com/jp/what-is/retrieval-augmented-generation/
https://neo4j.com/labs/genai-ecosystem/langchain/
https://note.com/ippei_suzuki_us/n/n4670c893829a
https://note.com/ippei_suzuki_us/n/nc728cc2f742f
https://nuco.co.jp/blog/article/K_nlpAOV
https://qiita.com/Dataiku/items/4a306ec4f77582ab8724
https://solution.netone-pa.co.jp/blog/495
https://tech.dentsusoken.com/entry/parameter_tuning_for_rag
https://www.ashisuto.co.jp/glean_blog/article/hybrid-vs-rag-vector.html
https://zenn.dev/adamsmith/articles/0180fdee13bc09
https://zenn.dev/nishijima13/articles/ae763750111455

ねえPerplexity、RAGシステムを作りたいよ

クエリの結果

「オンプレでRAGを構築したい」とPerplexityに聞いた結果を抜粋。コードも一緒に教えてくれた。

オンプレミスでRAGを実装するには、以下のような手順が考えられます:

1. 必要なコンポーネントの準備:
- 大規模言語モデル(LLM): オープンソースのLLMを使用します。例えばLlama 2やGPT-Jなどが選択肢となります。
- ベクトルデータベース: Faiss、Milvus、Qdrantなどのオープンソースのベクトルデータベースを使用します。
- 埋め込みモデル: HuggingFaceのSentence Transformersなどのオープンソースモデルを利用できます。

2. データの準備と前処理:
- 社内文書やナレッジベースなどの文書データを収集します。
- 文書をチャンク(小さな断片)に分割します。
- 埋め込みモデルを使用して各チャンクをベクトル化します。

3. ベクトルデータベースの構築:
- ベクトル化されたチャンクをベクトルデータベースにインデックス化します。

4. RAGパイプラインの実装:
- ユーザーのクエリを受け取り、埋め込みモデルでベクトル化します。
- ベクトルデータベースで類似度検索を行い、関連するチャンクを取得します。
- 取得したチャンクとクエリをLLMに入力し、回答を生成します。

5. システムの統合:
- 上記のコンポーネントを統合し、エンドツーエンドのRAGシステムを構築します。
- APIやWebインターフェースを通じてユーザーがアクセスできるようにします。

Perplexityに「オンプレでRAGを実装する」とクエリを投げた結果

以下は、Perplexityが返してきたコード。

from sentence_transformers import SentenceTransformer
from langchain.llms import LlamaCpp
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.vectorstores import FAISS
from langchain.text_splitter import CharacterTextSplitter
from langchain.chains import RetrievalQA

# 文書の準備とチャンク分割
with open('document.txt', 'r') as f:
    text = f.read()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
texts = text_splitter.split_text(text)

# 埋め込みモデルの準備
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")

# ベクトルデータベースの構築
db = FAISS.from_texts(texts, embeddings)

# LLMの準備
llm = LlamaCpp(model_path="./llama-2-7b-chat.gguf", n_ctx=2048)

# RAGチェーンの構築
qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",
    retriever=db.as_retriever(search_kwargs={"k": 3}),
)

# クエリの実行
query = "What is the capital of France?"
result = qa_chain({"query": query})
print(result['result'])

コードをUbuntuで動かすまでのメモ(準備)

  • 準備として、sentence_transformersやlangchain、Llamaなどをpipした。LlamaのモデルはTheBloke作成の量子化されたモデルをダウンロードした[リンク]。[Llamaのライセンスのリンク]。

  • コード実行時に多くのwarning発生。今回のモジュールは互換性があるみたいで、そのまま実行はできたが、いつ動かなくなってもおかしくない。

    • 今回はとりあえず動かしたかった&Perplexityでどこまで動くものが簡単に作れるか試したかったのでそのまま突っ込んだが、(当たり前だが)ちゃんとオフィシャルドキュメントを読むべき。

  • 次節の実験のため、またデータのパスを踏まえてコードは微修正した。

コードをUbuntuで動かしてみる(実行結果)

そのまま動かすというのもよいのだが、RAGによってドキュメントを引用していることがわかるように、以下の条件のもとで(A)フランスの首都、(B)日本の首都、を問う。

  1. RAGで利用するInputであるdocumentに「test」としか書かない。

  2. 読み込むdocument.txtに嘘情報(Japan capital is Kyoto.)のみ記載。

以下、実験結果。Result1=フランスの首都を問うた場合、Result2=日本の首都を問うた場合、の結果を示す。

  • 1. documentにtestとしか書かない場合。

1.  documentにtestとしか書かない場合に与えた2つのクエリの結果。
Result1: "What is the capital of France?"、Result2="What is the capital of Japan?"
  • 2.嘘情報を食わせた場合の結果

2. 嘘情報を食わせた場合に与えた2つのクエリの結果。
Result1: "What is the capital of France?"、Result2="What is the capital of Japan?"

実験結果に対する簡単な考察

実験1. では、同じようなプロンプトを入れているにも関わらず、日本の首都では付随するContextの回答がなされた。OSSの理解が浅すぎるため、モジュールの利用方法に誤りがあって適切なアウトプットが出ていない可能性もある。
実験2. の結果として、嘘情報を回答させることはできなかった。たった一文与えた位では回答結果に影響しなかったようだ。どの程度の量を嘘情報として与えるとLLMに誤った回答をさせることができるのか気になるところ。RAGのチャンクサイズや、同じ文言を大量に貼り付けるなどすると効果があるか、などは追検証してもいいかもしれない。

今回の調査の感想と今後やりたいこと

RAGを動かす過程で使うOSSやそのフローをざっくり理解できた。
ただ、全体として、そもそもRAGの実験というよりはLLMを動かしてみたにとどまっているので、RAGシステムを作ってみたいという目的は達成できていないのが心残り。
RAGの性能評価できるようにテスト用社外秘を模したデータのようなものを用意してみて、あらためて実験が必要。

その他、今後やりたいこととして今思いつくものは以下。

  • RAGのシステムを踏まえた際の課題として重要なデータ準備や前処理を深掘りし、社外秘のようなデータを効率的に扱うためにできる方策や、現状の課題を把握する。

  • RAGの精度や速度、プロンプトの使いやすさ、といった課題ポイントに対するアプローチとして現状何があるのかを整理し、OSSで利用可能なものを自分の手元でも実装してみる。

    • 何らかの根拠に紐づけて説明するためには、RAG+アルファ(AdvancedRAG)が良さそう。ナレッジグラフとの組み合わせとか、全文検索との組み合わせたハイブリッドRAGなども良さそうっぽい。この辺りの技術を全然知らないので、知りたい。

  • RAGに対する攻撃についても考えてみたい。この例ではいわゆるModel Poisoningにあたると思う。どの程度の量までは影響しない(LLMで学習した内容に対して影響を与えられるほどのデータ量にはならない)かなど、閾値を分析するのは面白いかも。関係ありそうな論文もあるのでこちらを読んで理解を深めてみたい。[https://arxiv.org/abs/2402.07867]。

    • 社内でのみの利用では攻撃というよりは誤情報の入力などがありうるが、前処理で取り切れるのか、取り切れずにInputとして入ってしまったデータをどのように無視するのか、影響はどの程度なのか、を考慮するのは面白そう。

PerplexityによるCitation

https://zenn.dev/adamsmith/articles/0180fdee13bc09
https://zenn.dev/bashow0316/articles/9ed0c695e4eea2
https://www.idnet.co.jp/column/page_187.html
https://qiita.com/t_serizawa/items/a2ced4441da714b3076f
https://weel.co.jp/media/tech/ragfusion/

その他参考

いいなと思ったら応援しよう!