はじめに
生成AIにRAGで独自の情報を追加して、自分用にカスタマイズしてみます。AIが自分の記憶だけで話すのではなく、手元の参考書を見ながら答えるイメージです。生成AIにRAGで独自の情報を追加して、自分用にカスタマイズしてみます。まずはお試しとして、Geminiの無料枠を使います。
RAGとは
RAG(Retrieval-Augmented Generation / 検索拡張生成)は、ChatGPTなどの生成AIに、「外部の最新情報や独自のデータ」を組み合わせて回答させる技術のことです。RAGを使うことで、まるで「辞書やマニュアルを引きながら答える」ようなことが可能になります。
APIキーの入手
Google AI Studio より、「APIキーを生成」をクリックします。
入力データの用意
今回は夏目漱石の「坊ちゃん」のテキストデータを入力として使います。大量のデータを使うと無料枠を使い切ってしまうので、まずは冒頭の数行で試します。
my_data.txt というファイル名で保存します。
坊っちゃん
親譲の無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて(以下略)
【実装】コードを書いてみる
LangChain というライブラリを使い、PythonでRAGを構築します。
ライブラリのインストール
pip install -U langchain_classic langchain-google-genai langchain-community chromadb
コード
import os
from langchain_google_genai import GoogleGenerativeAIEmbeddings, ChatGoogleGenerativeAI
from langchain_community.document_loaders import TextLoader
from langchain_text_splitters import CharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain_classic.chains.retrieval_qa.base import RetrievalQA
# 1. APIキーの設定
os.environ["GOOGLE_API_KEY"] = "上記で入手したAPIキー"
# 2. データの読み込み
loader = TextLoader("./my_data.txt", encoding="utf-8")
all_docs = loader.load()
# 3. テキストの分割(チャンク分け)
text_splitter = CharacterTextSplitter(chunk_size=2000, chunk_overlap=200)
texts = text_splitter.split_documents(all_docs)
# 4. ベクトル化と保存(Embedding)
embeddings = GoogleGenerativeAIEmbeddings(model="gemini-embedding-001")
vectorstore = Chroma.from_documents(texts, embeddings)
# 5. RAGシステムの構築
# Geminiを使い、作成したデータベースから検索して答える設定にする
llm = ChatGoogleGenerativeAI(model="gemini-2.5-flash")
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=vectorstore.as_retriever()
)
# 6. 質問してみる
question = "読み込ませたファイルの内容について簡単に教えてください"
response = qa_chain.invoke(question)
print(response["result"])
実行結果
読み込まれたファイルの内容は、夏目漱石の小説『坊っちゃん』の冒頭部分です。
主人公が子供の頃からの「無鉄砲」な性格で損ばかりしていることを語り、小学校時代に学校の二階から飛び降りて一週間ほど腰を抜かしたエピソードが語られています。それは同級生に「弱虫」とからかわれたためで、家に帰ると父親に叱られながらも、次こそは腰を抜かさずに飛んでみせると答えるという、主人公のやんちゃな性格がわかる導入部分です。
ハマりポイントとまとめ
・入力するデータが大きすぎると「429 RESOURCE_EXHAUSTED.」というエラーになります。数時間経過すると、リセットされるようです。
・利用できるAIモデルは常に変わります。「ModuleNotFoundError」が出たら、モデルを変えてみてください。
・LangChainは1.0以降でライブラリ構造が大きく変わっています。そのため、今回はclassic版を使っています。
・Chromaでベクトル化したデータをローカル保存すると、再利用することができます。
・PythonでUIを作るのも面白そうです。