RAG (Retrieval-Augmented Generation) とは、自然言語処理(NLP)の分野におけるアプローチで、事前に学習された大規模言語モデル(LLM)と情報検索技術を組み合わせて、応答の生成や質問応答を行う手法です。
今回は、次の書籍を教科書として読み進めていきます。かなり詳しく「大規模言語モデル」について書かれた本です。
LLMに関する内容が広範囲にわたって解説されています。RAGについては13章に記載があります。
Colabでのサンプルコードも用意されているので併せて読みすすめると良いと思います。
https://github.com/ghmagazine/llm-book/tree/main/chapter13
使用するモデル
https://huggingface.co/llm-book/Swallow-7b-hf-oasst1-21k-ja
Swallowは、東京工業大学の岡崎研究室と横田研究室、そして産業技術総合研究所の共同研究チームによって開発された、日本語対応の大規模言語モデル(LLM)です。このモデルは、Meta社のLlama 2を基盤としており、日本語の文法や表現のニュアンスを深く理解し、高度な言語処理タスクに対応できるよう設計されています。
Swallowモデルのライセンスは、ベースとなるLlama 2の「Llama 2 Community License」を継承しています。このライセンスに従う限り、研究および商業目的での利用が可能です。詳細は、Meta社の公式ライセンスページをご確認ください。
RAG (Retrieval-Augmented Generation) とは、自然言語処理(NLP)の分野におけるアプローチで、事前に学習された大規模言語モデル(LLM)と情報検索技術を組み合わせて、応答の生成や質問応答を行う手法です。
基本構造
RAGの仕組みは以下のように分けられます:
- 情報検索(Retrieval)
- ユーザーからの質問や入力に基づいて、外部のデータベースやドキュメントから関連情報を検索します。
- この検索には、従来の検索エンジンやベクトル検索技術(例: ElasticSearch、FAISS)を使用します。
- 検索結果は、関連する文章やコンテキスト(例: 複数のパラグラフ)です。
- 生成(Generation)
- 検索した情報をもとに、LLM(例: GPT、BERT、T5など)が応答を生成します。
- モデルは検索された内容を取り込みながら、人間にとって自然で正確な回答を生成します。
RAGの利点
- スケーラビリティ
モデルはすべての知識を内部に保持せず、必要に応じて外部から情報を引き出すため、膨大な知識を扱うことが可能。 - 最新情報へのアクセス
LLMの知識が固定された事前学習データに依存するのに対し、RAGはリアルタイムで外部データを参照できるため、最新情報を含む回答が可能。 - 軽量化
モデル自体が知識を持つ必要がないため、モデルのサイズが小さく、計算リソースを節約できる。 - 応用の幅広さ
質問応答システム、カスタマーサポート、文書要約、教育用途など、多様な分野に応用可能。
応用例
- カスタマーサポート
FAQや製品マニュアルから関連情報を引き出して回答を生成。 - 学術リサーチ
論文や書籍のデータベースを検索し、質問に対する学術的な回答を生成。 - ニュースの要約や生成
最新のニュース記事を検索し、要約を生成。
代表的なRAGの実装
- Facebook AI Research (FAIR) が提案した「RAGモデル」
- BERTやDPR(Dense Passage Retrieval)を使った検索モジュールと、生成モジュール(例えばBART)を組み合わせた構造。
- OpenAI や Hugging Face が提供するフレームワークでも、RAGの実装が可能。
RAGは、「モデル単体での限界」を克服する手段として注目されており、膨大な外部知識を活用した実用的なAIソリューションに適しています。
LLMによる推論とRAGによる推論
LangChain
LangChainというライブラリを活用してRAGを構築します。
LangChainとは?
LangChain は、大規模言語モデル(LLM)の能力を活用するアプリケーションを開発するためのフレームワークです。特に、LLMを外部データソースやツールと連携させることで、応答生成やタスク実行の精度や実用性を向上させることを目的としています。
LangChainの特徴
- 外部データとの統合:
- データベースやドキュメント、APIなどの外部リソースを活用可能。
- 情報検索(Retrieval)や質問応答システムの構築が容易。
- LLMとツールの連携:
- 計算ツールやデータベース操作、コード生成など、LLMを補完するツールと連携できる。
- コンポーネントベースの設計:
- フレームワークがモジュール化されており、個別のコンポーネント(プロンプトテンプレート、チェーン、エージェントなど)をカスタマイズして組み合わせ可能。
- マルチステップのワークフロー:
- 複数のタスクを連続的に実行するような複雑なフローを構築できる。
- 例: 質問を受けて情報を検索し、その情報をもとに要約を生成する。
- エージェントの活用:
- エージェントとは、LLMが外部ツールを使用してタスクを動的に解決する仕組み。
- 例えば、計算ツールを使った数値計算や、API呼び出しを通じたデータ取得が可能。
LangChainの主要コンポーネント
- Prompt Templates:
- LLMに渡すプロンプトを動的に構築するためのテンプレート。
- 例: 「{クエリ}に関する詳細を教えてください」という形式。
- Chains:
- 一連の操作を定義し、データフローを設計。
- 例: 情報検索→生成された情報の要約→出力。
- Retrievers:
- 外部データから関連情報を検索するコンポーネント。
- 例: ベクトル検索、データベースクエリ。
- Vector Stores:
- ベクトルデータ(例えば、埋め込み表現)を格納し、検索するための仕組み。
- 例: FAISS、Pinecone。
- Agents:
- LLMが環境と動的にやり取りし、複数のツールを利用してタスクを解決する仕組み。
LangChainの応用例
- カスタマーサポートボット:
- FAQデータを活用し、ユーザーの質問に応答。
- 情報検索エンジン:
- 文書やウェブから情報を取得して回答を生成。
- コンテンツ生成ツール:
- キーワードやテーマを元にした記事やブログの自動生成。
- 教育・学習ツール:
- 教材やトピックについての対話型解説を提供。
LangChainのメリット
- LLMを活用した高度なアプリケーションを迅速に構築可能。
- モジュール化された設計により、カスタマイズや拡張が容易。
- 強力な情報検索とLLMの組み合わせにより、最新情報や外部リソースを活用可能。
LangChainは、RAG(Retrieval-Augmented Generation)をはじめとした高度なNLPタスクを効率よく実現するための重要なツールです。
Hugging Faceへのログイン
Hugging Faceは、AIモデルやデータセットを共有・利用できるプラットフォームです。アカウントを作成することで、モデルのダウンロードやアップロード、コミュニティへの参加などが可能になります。以下に、Hugging Faceへのログイン方法を簡単に説明します。
1. アカウント作成
初めて利用する場合は、以下の手順でアカウントを作成してください。
- 公式サイトにアクセス: Hugging Face公式サイトにアクセスします。
- サインアップ: 右上の「Sign Up」ボタンをクリックし、メールアドレスとパスワードを入力して「Next」を押します。
- プロフィール情報の入力: ユーザー名や氏名などの必要情報を入力し、利用規約と行動規範に同意して「Create Account」をクリックします。
- メール認証: 登録したメールアドレスに届いた認証メール内のリンクをクリックして、メールアドレスを確認します。
詳細な手順は、以下のページでも解説されています。
2. ログイン方法
既にアカウントをお持ちの場合、以下の手順でログインできます。
- 公式サイトにアクセス: Hugging Face公式サイトにアクセスします。
- ログイン: 右上の「Log In」ボタンをクリックし、メールアドレスとパスワードを入力してログインします。
3. アクセストークンの取得
コマンドラインやAPI経由でHugging Faceのモデルやデータセットにアクセスする際には、アクセストークンが必要です。以下の手順で取得できます。
- 設定ページにアクセス: ログイン後、右上のプロフィールアイコンをクリックし、「Settings」を選択します。
- アクセストークンの作成: 左側のメニューから「Access Tokens」を選び、「New token」ボタンをクリックします。
- トークン情報の入力: トークンの名前を入力し、必要に応じて権限を設定して「Generate a token」をクリックします。
- トークンの保存: 生成されたトークンをコピーし、安全な場所に保管します。
アクセストークンの詳細な作成手順は、以下のページで詳しく解説されています。
これらの手順を踏むことで、Hugging Faceの各種サービスを活用できるようになります。
notebok_login()を実行すると下記のような画面になる。your Hugging Face tokens page のリンクよりAccess Tokenを 「Create new token」で作成する。
なお、TokenはpCoudPassに安全に保存しておきます。
LangChainでLLMを扱う際、LLMコンポーネントを中心に使用することで、シンプルかつ柔軟に大規模言語モデル(LLM)を利用できます。このコンポーネントは、特定のLLMに依存しない抽象化を提供しており、モデルの選択や切り替えが簡単です。以下に、このLLMコンポーネントの特徴と利用方法を詳しく解説します。
LLMコンポーネントの基本構造
LLMコンポーネントは、以下の3つの主要機能を提供します:
- モデルへのインターフェース:
- OpenAI、Hugging Face、Anthropicなど、複数のLLMプロバイダーに対応。
- プラグアンドプレイ型で、異なるプロバイダー間で簡単に切り替え可能。
- プロンプトの送信と応答の受信:
- 任意のテキスト(プロンプト)を送信し、その応答を簡単に取得可能。
- 設定のカスタマイズ:
- 温度(生成のランダム性)やトークン制限など、モデルの挙動を細かく設定可能。
1. LLMコンポーネントのセットアップ
LangChainのLLMコンポーネントを利用するには、まずインポートと初期化を行います。
OpenAIモデルを使用する場合
from langchain.llms import OpenAI
# OpenAIのモデルを初期化
llm = OpenAI(
model_name="text-davinci-003", # 利用するモデル
temperature=0.7, # 応答のランダム性
max_tokens=200 # 応答のトークン上限
)
# プロンプトを送信して応答を取得
response = llm("What is the capital of France?")
print(response) # 出力: "The capital of France is Paris."
Hugging Faceモデルを使用する場合
from langchain.llms import HuggingFaceHub
# Hugging Faceのモデルを初期化
llm = HuggingFaceHub(
repo_id="google/flan-t5-large", # モデルのリポジトリID
model_kwargs={"temperature": 0.5} # モデル固有の設定
)
# プロンプトを送信
response = llm("Translate 'Hello' to French.")
print(response) # 出力: "Bonjour"
2. LLMの設定オプション
LLMコンポーネントは、以下のような設定で挙動を制御できます:
temperature
: 応答の多様性を設定(0に近いほど確定的)。max_tokens
: 生成するトークンの上限。top_p
: 確率分布に基づくサンプリングの範囲を設定。frequency_penalty
: 生成テキスト内での単語の繰り返しを制御。
例:
llm = OpenAI(
model_name="text-davinci-003",
temperature=0.3,
max_tokens=150,
frequency_penalty=0.5
)
3. 複数のプロバイダーの切り替え
LangChainでは、異なるLLMプロバイダーを簡単に切り替えることが可能です。同じコードベースで、OpenAIからHugging Faceモデルへの切り替えが容易です。
例:
from langchain.llms import OpenAI, HuggingFaceHub
# OpenAIモデル
llm_openai = OpenAI(model_name="text-davinci-003")
# Hugging Faceモデル
llm_huggingface = HuggingFaceHub(repo_id="google/flan-t5-large")
# 選択的に使用
response_openai = llm_openai("What is AI?")
response_huggingface = llm_huggingface("What is AI?")
4. LLMの応用: プロンプトテンプレートと連携
LLMコンポーネントは、プロンプトテンプレートやチェーンと連携させることで、より高度な操作が可能です。
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
# プロンプトテンプレートの作成
template = PromptTemplate(
input_variables=["city"],
template="What is the population of {city}?"
)
# チェーンの作成
chain = LLMChain(llm=llm, prompt=template)
# プロンプトを送信して応答を取得
response = chain.run(city="Tokyo")
print(response)
Chat Modelコンポーネント
LangChainのChat Modelコンポーネントは、チャット型の大規模言語モデル(LLM)を簡単に利用できるように設計されたインターフェースです。従来のLLMコンポーネントが1つのプロンプトを入力して1つの応答を得る仕組みだったのに対し、Chat Modelコンポーネントでは、複数のメッセージ(会話履歴)をやり取りできる点が特徴です。
Runnableとは
LangChainにおけるRunnableは、タスクの一貫性や再利用性を向上させるための標準化された操作単位(モジュール)を指します。特に、チェーンやモデル、データ操作プロセスを統一的に扱うために設計されています。
Runnableは、データの入力から出力までの処理を抽象化し、他のコンポーネントと連携しやすくするための汎用的なインターフェースです。
Runnableの特徴
- 汎用性:
- モデル呼び出し、プロンプト生成、データ変換など、任意の処理をカプセル化。
- 任意の入力形式や出力形式を統一的に処理。
- 再利用性:
- 一度定義したRunnableは、他のプロセスやワークフローで簡単に再利用可能。
- チェーンの構築が容易:
- 複数のRunnableを連結して、複雑な処理フローを簡単に実現可能。
- 標準インターフェース:
- すべてのRunnableは統一されたインターフェース(
invoke
メソッド)を持ち、操作が直感的。
- すべてのRunnableは統一されたインターフェース(
Runnableの基本的な使い方
1. Runnableの作成
任意の処理を行うRunnableを作成できます。
from langchain.schema.runnable import Runnable
class MyRunnable(Runnable):
def invoke(self, input_data):
return f"Hello, {input_data}!"
# インスタンス化と実行
runnable = MyRunnable()
result = runnable.invoke("World")
print(result) # 出力: "Hello, World!"
2. モデルをRunnableとして利用
LLMやチェーンを直接Runnableとして利用可能です。
from langchain.llms import OpenAI
from langchain.schema.runnable import Runnable
# OpenAIモデルをRunnableとして利用
llm = OpenAI(model_name="text-davinci-003")
result = llm.invoke("What is AI?")
print(result) # 出力: "AI is the simulation of human intelligence by machines."
3. チェーンの構築
複数のRunnableを組み合わせて、より複雑な処理フローを作成可能です。
from langchain.schema.runnable import RunnableMap, RunnableSequence
# 複数のRunnableを組み合わせ
sequence = RunnableSequence([
MyRunnable(),
llm
])
# 実行
result = sequence.invoke("LangChain")
print(result) # MyRunnableが処理した後、LLMが応答を生成
Runnableの応用例
- データ前処理:
- テキストの正規化やフィルタリング処理をRunnableとして実装。
- マルチタスク:
- 複数のモデルを並列に実行して結果を統合。
- カスタムワークフロー:
- ユーザー固有のビジネスロジックを簡単に統合。
埋め込みモデル
LangChainで文埋め込みモデルを使う方法を解説します。LangChainは、埋め込みモデルを使ってテキストをベクトル化し、そのベクトルを基に検索やクラスタリングを行うタスクを簡単に実装できます。
LangChainで文埋め込みモデルを使う手順
1. LangChainのインストール
pip install langchain openai sentence-transformers
2. Embedding Modelのセットアップ
LangChainは複数の埋め込みモデルをサポートしています。ここでは、OpenAIとHugging Faceのモデルを例に解説します。
(A) OpenAIの埋め込みモデルを使う
from langchain.embeddings import OpenAIEmbeddings
# OpenAIの埋め込みモデルをセットアップ
embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")
# 文を埋め込みに変換
text = "I love cats."
embedding_vector = embeddings.embed_query(text)
print(embedding_vector) # 文の埋め込みベクトル
(B) Hugging Faceの埋め込みモデルを使う
from langchain.embeddings import HuggingFaceEmbeddings
# Hugging Faceの埋め込みモデルをセットアップ
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
# 文を埋め込みに変換
text = "I love cats."
embedding_vector = embeddings.embed_query(text)
print(embedding_vector) # 文の埋め込みベクトル
3. Vector Storeの作成
埋め込みベクトルを保存・検索するために、ベクトルストアを使用します。
from langchain.vectorstores import FAISS
# ベクトルストアにデータを追加
texts = ["I love cats.", "I enjoy playing video games.", "Cats are wonderful pets."]
embeddings_list = [embeddings.embed_query(text) for text in texts]
faiss_store = FAISS.from_embeddings(embeddings_list, texts)
# クエリを使って類似文検索
query = "Tell me about cats."
query_embedding = embeddings.embed_query(query)
results = faiss_store.similarity_search_by_vector(query_embedding, k=1)
print(results) # クエリに最も類似した文を出力
4. LangChainのRetrievalを利用
埋め込みモデルを情報検索と組み合わせて使うには、LangChainのRetriever
を利用します。
from langchain.chains import RetrievalQA
from langchain.llms import OpenAI
# Retrieverの作成
retriever = faiss_store.as_retriever()
# QAチェーンの作成
llm = OpenAI(model_name="text-davinci-003")
qa_chain = RetrievalQA(llm=llm, retriever=retriever)
# 質問をして回答を取得
response = qa_chain.run("What can you tell me about cats?")
print(response)
LangChainで文埋め込みモデルを使う利点
- 簡単な統合: LangChainは複数の埋め込みモデル(OpenAI、Hugging Faceなど)を一貫したインターフェースで利用可能。
- 検索・クラスタリングの自動化: 埋め込みモデルとベクトルストアの組み合わせで、類似性検索が簡単。
- 情報検索と連携: LLMと埋め込みを組み合わせることで、強力な質問応答や検索システムを構築可能。
LangChainを使えば、文埋め込みモデルを基盤とした高度なNLPアプリケーションを効率的に開発できます。
LangChainのDocument Loaderコンポーネントは、外部データをロードして処理可能な形式(テキストや構造化データ)に変換するためのコンポーネントです。このデータは後に埋め込みやLLMを活用するタスクに利用されます。
主な特徴
- データソースの対応範囲が広い:
- PDF、CSV、HTML、Markdown、データベース、APIなど、多種多様なデータ形式に対応。
- データの標準化:
- すべてのデータを統一された
Document
オブジェクト形式に変換。
- すべてのデータを統一された
- 埋め込みや検索タスクとの統合:
- データをロード後、埋め込みモデルやベクトルストアに直接送ることが可能。
基本的な使い方
1. インストール
pip install langchain pypdf pandas
2. シンプルなドキュメントロード
- 例: PDFからデータをロード
from langchain.document_loaders import PyPDFLoader
# PDFファイルをロード
loader = PyPDFLoader("sample.pdf")
documents = loader.load()
# ロードされたドキュメントを確認
for doc in documents:
print(doc.page_content) # 各ページのテキスト
- 例: CSVファイルからデータをロード
from langchain.document_loaders import CSVLoader
# CSVファイルをロード
loader = CSVLoader(file_path="data.csv")
documents = loader.load()
# ロードされたドキュメントを確認
for doc in documents:
print(doc.page_content) # 各行のデータ
Documentオブジェクトの構造
Document
オブジェクトには以下のような情報が含まれます:
page_content
: テキストデータ。metadata
: ドキュメントに関連するメタデータ(例: ページ番号、ソースファイル名など)。
例:
doc = documents[0]
print(doc.page_content) # ドキュメントのテキスト
print(doc.metadata) # メタデータ
Document Loaderの応用例
- FAQデータベースの作成:
- サポート文書やFAQデータをロードし、埋め込みモデルと統合。
- 情報検索システムの構築:
- PDFやウェブ記事をロードして、検索や質問応答に活用。
- データクレンジング:
- ドキュメントのロードと同時に、特定の形式に変換やフィルタリング。
利点
- 多種多様なデータソースに対応。
- データの標準化が容易で、後続の処理に直接利用可能。
- 他のLangChainコンポーネント(埋め込みやLLM)との統合がスムーズ。
LangChainのDocument Loaderコンポーネントを利用することで、外部データの取り込みと処理を効率化できます。
LangChainでRetrieverを設定することで、埋め込みモデルやベクトルストアを活用して効率的な情報検索が可能になります。Retrieverは、埋め込みベクトルを基にクエリに最も関連性の高いデータを検索・取得する役割を果たします。
Retrieverの設定手順
1. 必要なライブラリをインストール
まずは必要なライブラリをインストールします。
pip install langchain faiss-cpu
2. ベクトルストアの作成
Retrieverはベクトルストアを基盤として動作します。
例: FAISSを使用したベクトルストアの作成
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS
# OpenAI埋め込みモデルの初期化
embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")
# データとその埋め込みを作成
texts = ["I love programming.", "Python is a versatile language.", "Artificial Intelligence is fascinating."]
doc_texts = [{"content": text} for text in texts] # 文書データを準備
embeddings_list = [embeddings.embed_query(text) for text in texts]
# FAISSベクトルストアの作成
vectorstore = FAISS.from_texts(texts, embeddings)
3. Retrieverの初期化
作成したベクトルストアからRetrieverを生成します。
# Retrieverの作成
retriever = vectorstore.as_retriever()
4. クエリを使って検索
Retrieverを使ってクエリに関連する文書を検索します。
query = "Tell me about Python."
results = retriever.get_relevant_documents(query)
# 検索結果を表示
for result in results:
print(result.page_content) # 関連文書のテキスト
Retrieverの設定オプション
Retrieverにはさまざまな設定が可能です。以下に主要なオプションを示します。
- 検索結果の数を制御
- デフォルトではトップkの結果を返します。
k
を変更することで、結果の数を調整可能です。
- デフォルトではトップkの結果を返します。
retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
- 類似性スコアのしきい値
- 類似性スコアが一定以上の結果のみを返すよう設定できます。
retriever = vectorstore.as_retriever(search_kwargs={"score_threshold": 0.8})
- フィルタリング条件の設定
- メタデータを基に特定の条件に合致する文書だけを検索することが可能です。
retriever = vectorstore.as_retriever(search_kwargs={"filters": {"category": "AI"}})
RetrieverをQAチェーンと統合
Retrieverを質問応答(QA)システムに組み込む場合、RetrievalQA
を使用します。
from langchain.chains import RetrievalQA
from langchain.llms import OpenAI
# OpenAIモデルの初期化
llm = OpenAI(model_name="text-davinci-003")
# RetrievalQAチェーンの作成
qa_chain = RetrievalQA(llm=llm, retriever=retriever)
# 質問を投げかけて回答を取得
response = qa_chain.run("What is Python?")
print(response)
まとめ
LangChainでRetrieverを設定する方法は、以下の手順で構築されます:
- 埋め込みモデルの選択とベクトルストアの作成。
- ベクトルストアからRetrieverを初期化。
- クエリを用いた関連文書の検索。
Retrieverを活用することで、埋め込みベクトルを用いた効率的な情報検索が可能になり、質問応答システムや情報検索エンジンの構築に役立ちます。