本文へスキップ
BecomeCoder

RAGコース · 第1章 RAGとは何か · レッスン4

はじめてのRAGを動かす ― 最小パイプライン

ブラウザで完結

導入

理屈はここまでにして、まず動く最小のRAGを作ってみましょう。「検索して、その結果をもとに答える」という一直線の流れを、実際にコードで体験します。

説明

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity

# 小さな知識ベース(英語の文書。日本語だとTF-IDFがうまく分割できない)
docs = [
    "The Eiffel Tower is located in Paris, France.",
    "Mount Fuji is the highest mountain in Japan, at 3776 meters.",
    "Python is a popular programming language for data science.",
    "The Great Wall of China is more than 20000 kilometers long.",
]

# ① 文書をベクトル化しておく(インデックス作成)
vectorizer = TfidfVectorizer()
doc_vectors = vectorizer.fit_transform(docs)

def retrieve(query, k=1):
    # ② 質問をベクトル化し、コサイン類似度が高い文書を取ってくる
    q = vectorizer.transform([query])
    scores = cosine_similarity(q, doc_vectors)[0]
    top = scores.argsort()[::-1][:k]
    return [docs[i] for i in top]

def answer(query):
    context = retrieve(query, k=1)[0]
    # ③ 本物のLLMの代わりに、取ってきた文をそのまま答えに使う(第4章で本物APIに置換)
    return f"Q: {query}\nRetrieved context: {context}\nAnswer: {context}"

print(answer("How tall is Mount Fuji?"))
print()
print(answer("Where is the Eiffel Tower?"))

最初の実行は少し待ちます:scikit-learn を使う回は、初回だけライブラリの読み込みに数十秒かかることがあります(2回目以降は速くなります)。「読み込み中…」と出たら、そのまま待ってください。

コードは3つの部分に分かれています。

  • vectorizer.fit_transform(docs):知識ベースの全文書をベクトル化し、あとで検索できるように索引を作っています。これがレッスン2でいう「インデックス作成フェーズ」です。
  • retrieve(query, k=1):質問を同じ方法でベクトル化し(vectorizer.transform)、cosine_similarity でベクトル同士の近さを計算して、最も近い文書を返します。これが「検索」です。
  • answer(query):検索で見つけた文書をそのまま答えとして返しています。まだ本物の生成ではありません。テンプレートに埋め込んでいるだけです。第4章で、この部分を本物のLLM呼び出しに置き換えていきます。

print(answer("How tall is Mount Fuji?")) を実行すると、富士山についての文書が検索で見つかり、それが「答え」として使われている様子が分かります。

やってみよう

answer("What is Python used for?") を試して、どの文書が検索されるか確かめてみましょう。docs に自分で1文足して、その内容について質問してみるのもおすすめです。

演習

retrieve 関数k=2 で呼び出し、上位2件の文書を1行ずつ表示するコードを書いてください。

ヒント1を見る

for d in retrieve("...", k=2): print(d) のように、上位2件をループで表示します。

ヒント2を見る

k を2にするだけで、関連度の高い順に2件のリストが返ってきます。

まとめ

  • 最小のRAGは「①索引作成(fit_transform)→ ②検索(transform + cosine_similarity)→ ③答えを組み立てる」の3ステップ。
  • 今回の③はまだ「検索結果をそのまま返す」だけの仮の生成。本物のLLM呼び出しへの置き換えは第4章で行う。
  • 検索の仕組みそのものは、これで一通り動かせるようになった。

実際に動かしてみよう

下のエディタにPythonを書いて「実行」を押すと、scikit-learn(TF-IDF)とnumpyで本物の「検索」をその場で動かせます。RAGの検索フェーズ――文書のチャンク分割・ベクトル化・類似度計算・並べ替え――が実際に動きます。scikit-learn を使う回は初回の読み込みに数十秒かかることがあります。検索デモのサンプル文書は英語です(TF-IDFの既定トークナイザが日本語を分割できないため。日本語検索の対処は読み物で解説します)。LLMの生成や本物の埋め込みAPIは、APIキーが要るため読み物の回でコードを示します。

Python — ライブラリ付きで実行(Pyodide)

numpy / pandas / matplotlib が使える本物のPython(Pyodide)を読み込みます。初回のみ読み込みに少し時間がかかります(以降はブラウザにキャッシュされます)。
スクロールして表示された時点でも自動で読み込まれます。