RAGシステムを実装してみた
RAGについて調べ、実際にRAGシステムを実装してみました。
RAGとは
RAG(Retrieval-Augmented Generation)は、AIや自然言語処理における技術の一つで、生成モデルと検索エンジンのような情報取得機能を組み合わせた手法です。このアプローチでは、生成モデル(たとえば、GPTなど)が直接すべての知識を保持するのではなく、必要に応じて外部のデータベースや検索エンジンを利用して関連情報を取得し、その情報をもとに回答を生成します。
「Retrieval-augmented Generation」は日本語で「検索拡張生成」や「取得拡張生成」と訳されます。
RAGのメリット
- 知識の最新化: モデルがトレーニングされた後も、最新の情報を取得し反映できるため、時間に依存する内容や頻繁に変化する内容にも柔軟に対応できます。
- 情報の補完: モデルに直接含まれていない情報を検索から取得できるため、広範な情報を網羅した回答が可能です。
- 精度の向上: 専門的な内容や詳細な情報が必要な場合に検索した情報を補強することで、より正確な回答を生成できます。
具体的な仕組み
RAGモデルでは、以下の2つのステップが組み合わされています:
- 情報検索(Retrieval): 与えられた入力に対して関連する外部データを検索して取得します。たとえば、データベースやドキュメント、インターネットから必要な情報を取り出すことができます。
- 生成(Generation): 取得した情報をもとに、生成モデルが最終的な回答を生成します。この生成ステップで取得された情報を参照し、自然な形でユーザーに答える文章を作成します。
この技術は、企業のFAQシステムやカスタマーサポートなどでも活用されており、ユーザーに対してより豊富な情報を効率的に提供できるといった利点があります。
実装してみよう
の記事で作成したベクトルストアを使って、RAGシステムを実装してみました。
-
知識ベースの準備:次の3つの記事を外部情報として使います。
-
ベクトルストアの作成
-
GPT-4モデルの準備:OpenAIのチャットモデルを作成します
-
RAGシステムの構築:Q&A機能を持つ、システムを構築します
-
RAGシステムの使用:RAGシステムに質問を投げます
my-rag-system.pyCopied!!import os from langchain_openai import OpenAIEmbeddings from langchain_community.document_loaders import WebBaseLoader from langchain_community.vectorstores import FAISS from langchain_openai import ChatOpenAI from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain.chains import RetrievalQA # OpenAI APIキーの設定 os.environ["OPENAI_API_KEY"] = ( "OpenAIのAPIキー" ) # 1. 知識ベースの準備 web_loader = WebBaseLoader( [ "https://www.takeo-blog.jp/posts/tech/java-jit-sample", # JavaのJITについてのブログ "https://www.takeo-blog.jp/posts/tech/python-pickle", # Pyhtonのpickleについてのブログ "https://www.takeo-blog.jp/posts/tech/process-thread-relation", # プロセスとスレッドの関係についてのブログ ] ) web_docs = web_loader.load() text_splitter = RecursiveCharacterTextSplitter(chunk_size=150, chunk_overlap=100) splits = text_splitter.split_documents(web_docs) # 2. ベクトルストアの作成 embeddings = OpenAIEmbeddings() vectorstore = FAISS.from_documents( documents=splits, embedding=embeddings, ) # 3. GPT-4モデルの準備 llm = ChatOpenAI(model_name="gpt-4o", temperature=0.7) # 4. RAGシステムの構築 qa = RetrievalQA.from_chain_type( llm=llm, chain_type="stuff", retriever=vectorstore.as_retriever() ) # 5. RAGシステムの使用 def rag_response(query): return qa.invoke(query) # 使用例 query = "JITとはなんですか?" print(rag_response(query)) query = "プロセスとスレッドの関係を説明してください" print(rag_response(query))
実行結果
実行結果は下記のようになりました。ブログで使われていた言葉や情報を使って回答をしています!
Copied!!$ python3 takeo/rag-sample.py USER_AGENT environment variable not set, consider setting it to identify your requests. {'query': 'JITとはなんですか?', 'result': 'JIT(Just-in-Time)コンパイルとは、Javaなどの一部のプログラミング言語における実行時の最適化技術の一つです。プログラムを実行するタイミングでコードを機械語にコンパイルすることで、実行パフォーマンスを向上させます。特に繰り返し実行される「ホットスポット」に対して最適化を行い、効率的な動作を可能にします。'} {'query': 'プロセスとスレッドの関係を説明してください', 'result': 'プロセスとスレッドの関係は以下の通りです。\n\nプロセス:\n- プロセスは処理の実行単位です。\n- プロセスはメモリを共有しません。\n\nスレッド:\n- スレッドは、同じプロセス内での実行単位です。\n- スレッドはメモリを共有します。\n\nこのように、プロセスは独立したメモリ空間を持ち、スレッドは同じプロセス内でメモリを共有しながら実行されます。並列処理は主にマルチプロセスやマルチプロセッシングを使用し、並行処理はマルチスレッドやマルチスレッディングによって実現されます。'}
このように、既存の大規模言語モデル(LLM)に、外部情報(今回は3つのブログ)を与えてあげることで、外部情報を使って回答を生成することができます!
まとめ・所感
RAGは、既存のLLMに外部情報を与えることで、その外部情報を元にした回答を生成する技術のこと
- 簡単に実装できた
- 組織やチームの固有ルールに基づいたチャットシステムの開発に利用できそう
- 毎日更新される情報(株価・天気など)を使ってレコメンドシステムの開発ができそう