素朴な RAG の限界 — 100 行で動くけど「使える」とは言えない理由

(更新: 2026-05-24) by ZeroZawa

2026-05-24 改訂: 本シリーズは API キー無しの完全ローカル環境 (Ollama + Qwen3) で再現できる 構成に作り直しました。本文の検索スコア・回答例は、すべて qwen3-embedding:0.6b + qwen3:8b実測した値 です。題材は架空企業「ナギサ・パートナーズ」の社内 wiki に統一し、companion repo の corpus も差し替えています。ollama pull だけで手元で同じ数字を再現できます。なお速度の目安として、Part 1-3・5 の 単発クエリは数秒 で返りますが、Part 4 の一括評価 (RAGAs 30 件 × 3 パイプライン) は Apple Silicon で 1 時間強 かかります (Part 4 で代表 10 件の短縮経路も案内します)。「無料 (0 円)」と「高速」は別物で、ローカル LLM では一括バッチが律速になります。

「ChatGPT に社内ドキュメントを参照させたい」「自社の FAQ から正確に答えてほしい」。RAG (Retrieval-Augmented Generation) はこの種の要望にもっともよく当てはまる手法 で、検索すれば「RAG 入門」記事は無数に出てきます1。けれど、ほとんどは「動くサンプル」で止まり、本番投入したらすぐに「あれ、これは使えないぞ」と気付くことになる。

この記事では、まず 100 行強の Python で素朴な RAG を組み立てます。ローカルの Ollama に載せた埋め込みモデルと LLM の組み合わせで、corpus 読み込みから生成まで本当に短く書ける。その上で、動いて見える その実装が なぜ本番では使えないか を、実際に流して観察します。読み終わったとき、シリーズの残り 4 部 (Retrieval / Generation / Evaluation / Operations) で何を解決したいかが、読者自身の言葉で言えるようになる、というのが Part 1 の目標です。

naive RAG パイプラインの全体像と「動く / 使える」の谷

RAG の定義と解く課題

RAG とは何で、何ではないか

RAG は 検索 (retrieval) を組み合わせて、生成 (generation) を補強する 手法群の総称です。Lewis et al. の論文 (2020)1 で QA タスク向けに導入され、現代では「LLM が訓練時には知らなかった外部知識を、推論時に context として差し込む」という汎用パターンの総称として使われます。

「LLM がそのまま答えても良いタスク (要約・翻訳・自由作文)」は RAG ではありません。RAG は 答えのために事実が必要で、その事実が学習データに含まれていない (または古い) タスクに使います。

実装パターンには Naive / Advanced / Modular という分類があり2、本シリーズの Part 1 は最も素朴な Naive RAG を扱います。後続の Part で改善要素を 1 つずつ載せていく形です。

いつ RAG を使うべきか

  • 社内 wiki / 製品 FAQ / 技術文書のような 更新頻度が高く、ドメイン特異な知識 を扱う用途
  • 「答えの根拠を提示できる」ことが要求されるアシスタント (法務 / 医療 / 経理など)
  • LLM の知識更新を fine-tuning で行うには 更新頻度が早すぎる、または学習データが足りない ケース

いつ使うべきでないか

  • 創造的タスク (小説・コピーライティング)。事実より文体の方が大切で、retrieval が邪魔をする
  • 軽量モデルで十分な分類タスク。RAG の overhead を払う意味がない
  • リアルタイム性が極端に要求される (1 秒以内の応答) 用途。embedding + retrieval + LLM 呼び出しは合計で数百 ms 〜 数秒かかる

判断軸は「変更頻度正確性要求 をかけ算したときに、fine-tuning より RAG の方が割に合うか」です。社内 wiki なら毎週変わるので RAG、ブランドガイドラインなら年単位なので fine-tuning でも良い、というように。

100 行最短実装

ここから手を動かします。完成形は 100 行強の Python で、構成は以下のとおりです。

[corpus 読み込み]
[固定長 chunk 分割]
[qwen3-embedding:0.6b でベクトル化 (Ollama)]
[クエリも同じ embedding で表現 → cosine top-K]
[qwen3:8b に context として注入 → 生成 (Ollama)]

セットアップ

Python は 3.11 以上、パッケージマネージャは uv を使います。LLM と埋め込みは Ollama でローカルに動かす のが本シリーズの既定経路です。

Terminal window
# モデルを取得 (合計 ~6 GB、16 GB Mac 想定)
ollama pull qwen3:8b
ollama pull qwen3-embedding:0.6b
# サンプルリポジトリを clone
git clone https://github.com/zawazawa5809/rag-fundamentals-companion.git
cd rag-fundamentals-companion
git checkout part-01
# 依存導入
uv sync --frozen
# Ollama 経路を既定にする
cp .env.example .env
echo "RAG_PROVIDER=ollama" >> .env

API キーすら用意したくない場合は --mock を付けます。挙動の流れは確認できますが、本物の cosine 類似度の振る舞いは見られません。OpenAI / Anthropic の API 経路でも全く同じインターフェースで動きます (RAG_PROVIDER=anthropic_openai、詳細は companion repo の README)。

corpus と chunking

corpus は架空の中堅 SIer「ナギサ・パートナーズ株式会社」(社員約 600 名、横浜みなとみらい本社 + 大阪関西支店、受託開発 7 割 + 自社 SaaS「Mirage」3 割) の社内 wiki 風 Markdown を 15 件用意しました (corpus/v2/ 配下、全文 CC0 1.0)。意図的に「実在する社内 wiki あるある」を仕込んであります。

  • そのまま正解になる文書 (5 件): リモートワーク制度 / 経費精算 / 障害対応フロー / 社内ヘルプデスク FAQ / 自社プロダクト Mirage の現行アーキ (v3.2)
  • 語が一致するが意味は別物の trap (3 件): ランニング部の練習「計画」/ 顧客満足度 (CSAT) 調査の「顧客」/ 物流倉庫の「ロールバック」(誤出荷品のパレット戻し作業)
  • 構造・テンプレが似ているだけの trap (3 件): ボードゲーム同好会の月例「post-mortem」/ 社内 LT 大会の「評価基準」/ オフィス入退館の物理「セキュリティ」
  • 古い版が archive されず残っている trap (2 件): 経費精算の 2023 旧版 / Mirage アーキ v2 (2023 公開、現行は v3.2)
  • どのクエリにも当たらない雑文書 (2 件): お菓子コーナー運用 / 新人 onboarding チェックリスト

「同じ製品の設計書が v2 と v3 で並んでいて、どれが正かわからない」「物流の『ロールバック』と IT の『ロールバック』が同じ言葉で書かれている」「同好会の振り返りが障害対応の post-mortem と全く同じテンプレで書かれている」 — これは 多くの企業の社内 wiki にある現実そのまま で、本シリーズで取り組む課題の本丸です。

CHUNK_SIZE = 600
CHUNK_OVERLAP = 100
def chunk(docs):
"""Fixed-size sliding window. Returns [(chunk_id, text), ...]."""
out = []
step = CHUNK_SIZE - CHUNK_OVERLAP
for doc_id, body in docs:
n = max(len(body) - CHUNK_OVERLAP, 1)
for i, start in enumerate(range(0, n, step)):
piece = body[start : start + CHUNK_SIZE]
if piece.strip():
out.append((f"{doc_id}#{i:02d}", piece))
return out

固定 600 字 / overlap 100 字 という値は LangChain や LlamaIndex のデフォルト周辺の典型値です34意図的に意味境界 (文末・段落・H2) を尊重していません。これは Part 2 で recursive / semantic chunking との差を作る伏線です。この素朴な分割で 15 docs が 47 chunk になります。

埋め込み

埋め込みは Ollama 経由の qwen3-embedding:0.6b を使います。qwen3-embedding ファミリは MTEB 多言語リーダーボードで上位 (8B 版が 2025 年 6 月時点で 1 位)5 で、その最軽量 0.6B 版は 16 GB Mac でも軽く動きます (47 chunk の埋め込みは数秒)。日本語の社内文書でも十分な検索品質が出ます。埋め込みは軽い一方、生成・評価に使う 8B の LLM がローカルでは律速になる点は後で効いてきます。

class _OllamaEmbed:
def __init__(self, model="qwen3-embedding:0.6b"):
from ollama import Client
self._model = model
self._client = Client()
def embed(self, texts):
res = self._client.embed(model=self._model, input=texts)
return [list(v) for v in res.embeddings]

corpus 側のベクトルは offline で一度だけ計算し、クエリ側はリクエストごとに計算します。本格運用なら vector DB を挟みますが、Part 1 はメモリ上の numpy 配列で十分です。OpenAI text-embedding-3-small などに差し替えても同じ embed(texts) インターフェースで動きます。

Retrieval (cosine top-k)

def cosine_topk(query_vec, doc_vecs, k):
q = np.array(query_vec, dtype=np.float32)
M = np.array(doc_vecs, dtype=np.float32)
sims = M @ q / (np.linalg.norm(M, axis=1) * np.linalg.norm(q) + 1e-9)
idx = np.argsort(-sims)[:k]
return [(int(i), float(sims[i])) for i in idx]

M @ q で全 chunk と一発で内積を取り、/ (||M|| * ||q||) で正規化して cosine 類似度を得る、numpy 一行勝負です。corpus が数万件を超える前は素朴な行列演算で十分速い。+ 1e-9 はゼロ除算回避。

生成 (Qwen3)

def build_prompt(query, retrieved):
ctx = "\n\n".join(f"### {cid}\n{txt}" for cid, txt, _ in retrieved)
return (
"<context>\n"
f"{ctx}\n"
"</context>\n\n"
f"<question>{query}</question>\n\n"
"上の context のみを根拠に、3-4 文で答えてください。"
)

XML タグでセクションを区切るのは多くの LLM で有効な指針で6、ここでも <context><question> で構造化しています。生成自体は Ollama の chat() を 1 回呼ぶだけ (qwen3:8b)。Claude を使う場合は client.messages.create(...) に差し替えるだけです。

完成形のフルコード (約 105 行) は companion repo の examples/naive_rag.py で見られます。

動かして眺める

ここからが本題です。1 つの素直なクエリと、3 つの「困る」クエリを流して挙動を観察します。

: 以下の transcript は RAG_PROVIDER=ollama で実際に流した結果です。検索スコア (cosine) は決定的で安定 していますが、qwen3:8b の生成文言は run ごとに揺らぐので、自分で再現する場合は wording が異なる可能性があります。uv run python -m examples.naive_rag --query "..." で確かめてみてください。

§3.1 素直なクエリ: 「リモートワーク手当はいくら?」

まずは制度ものから。社内 bot として最も多い類型の質問です。

Terminal window
uv run python -m examples.naive_rag --query "リモートワーク手当はいくら?"
[corpus] 15 docs, 47 chunks
[retrieve] top-k:
0.5202 nagisa-remote-work#00
0.4043 nagisa-remote-work#01
0.3840 nagisa-onboarding-checklist#02
[answer]
リモートワーク手当は、月に5営業日以上在宅勤務した場合、月額10,000円が支給され
ます。この金額は、2024年度までの5,000円から2025年4月に増額されたものです。支給
対象月は出勤記録(kintone)で自動判定され、在宅勤務日数が5日未満の月は対象外です。

観察ポイント: 「リモートワーク」「手当」というクエリ語彙が nagisa-remote-work.md と一致し、top-1・top-2 をその文書が占めます。回答は金額・改訂・判定条件まで正確です。これが「動く RAG の最良ケース」、すなわち クエリ語彙と文書語彙が一致した社内 FAQ の挙動です。社内 bot で多くの質問はこのパターンで答えられます。

なお top-1 の cosine が 0.52 と、ベクトル検索のイメージより低めに見えるかもしれません。これは qwen3-embedding が日本語短文クエリと長文 chunk の間で出す典型値で、絶対値の高さより「正解 chunk が他を引き離して 1 位か」が本質 です。この後の trap では、この「引き離し」が崩れます。

§3.2 古い設計書が先頭に来る: 「Mirage 現行アーキテクチャの認証経路は?」

ここから雲行きが怪しくなります。同じ製品の設計書が v2 と v3 で並んでいる corpus に対して、エンジニアが普通に訊きそうな質問を投げます。

Terminal window
uv run python -m examples.naive_rag --query "Mirage 現行アーキテクチャの認証経路は?"
[corpus] 15 docs, 47 chunks
[retrieve] top-k:
0.6515 mirage-architecture-v2-archive#00
0.5998 mirage-architecture-v3#00
0.5770 mirage-architecture-v3#04
[answer]
Mirage 現行アーキテクチャ(v3)の認証経路は、Keycloak(OIDC provider)を採用して
います。v2 の BASIC 認証 + JWT から置換され、OIDC サービスとして統合されています。
認証フローは Keycloak が担い、トークンの発行・検証が行われます。

観察ポイント: 答え自体は正しい (現行 v3 は Keycloak/OIDC)。しかし top-k を見てください。「現行アーキテクチャ」と訊いたのに、top-1 は mirage-architecture-v2-archive — 2023 年の旧版設計書 です。現行の mirage-architecture-v3 (0.5998) を、archive 済みの旧版 (0.6515) が押しのけて 1 位に来ています。

なぜか。旧版の冒頭には「Mirage アーキテクチャ v2 (2023 年度版・旧版)」という見出しと構成サマリが詰まっていて、「Mirage」「アーキテクチャ」「認証」というクエリ語との表層一致が現行版より濃い のです。embedding は「これは archive 済みの古い文書だ」というメタ情報を区別しません。

今回 LLM はたまたま v2/v3 の差を読み取って正しく答えました。でも、それは です。素朴な RAG には「現行を旧版より優先する」仕組みが一切ありません。旧版 chunk が context の先頭を占め続ければ、いつか「Mirage の認証は BASIC + JWT です」と、2 年前に廃止された方式を自信満々に答える日が来ます。

mirage-architecture-v2-archive.md の冒頭にはちゃんと「⚠️ Archive 注記: 現行は v3」と書いてあります。けれど、その注記が 検索された chunk に含まれていなければ生成側には存在しないも同然 です。固定長分割は注記とは無関係な場所で chunk を切るので、注記が落ちることが珍しくありません。

これは Part 2 (metadata 保持型 chunking で版・status を chunk に焼き込む) + Part 5 (freshness / status filter で archive を index から外す運用) の二段で扱います。

§3.3 語が一致するだけの trap: 「ロールバックの手順を教えて」

今度は、エンジニアが Mirage の障害対応を念頭に「ロールバック」を訊いたつもりのクエリです。

Terminal window
uv run python -m examples.naive_rag --query "ロールバックの手順を教えて"
[corpus] 15 docs, 47 chunks
[retrieve] top-k:
0.6501 mirage-architecture-v2-archive#02
0.6074 lumen-rollback-pallet#00
0.5825 lumen-rollback-pallet#01
[answer]
ロールバック手順は、発生場所によって分かれます。倉庫内での発見の場合、該当パレット
を退避し WMS で「ロールバック中」とステータス更新後、再検品・理由入力を行い元の棚に
戻します。配送中での発覚は、配送業者に「全件戻し」を連絡し再配送を依頼、受け取った
パレットを一時ヤードに保管し、翌営業日に再検品・再格納を行います。

観察ポイント: 回答が 完全に物流倉庫の話 になっています。パレット、WMS、再検品、配送業者 — IT デプロイのロールバック (mirage-architecture-v3.md の blue-green switch back) とは何の関係もありません。

corpus には lumen-rollback-pallet.md という、大手物流顧客 Project Lumen の倉庫オペレーション手順書が入っています。物流業界では「ロールバック」「巻き戻し」「戻し作業」「再格納」が 誤出荷品をパレット単位で倉庫に戻す作業 を指します。クエリに「Mirage」も「デプロイ」も付けなかったため、embedding は「ロールバック」という 語の表層一致 だけで物流文書を top-2/3 に引き上げ、LLM はそれを忠実に要約しました。

これが 表層一致トラップ です。cosine 0.60 は嘘ではありません — 「ロールバック」という語が本当に何度も出てくるのです。けれど 語が一致することと、意味が関連することは別 で、素朴な RAG はそれを区別できません。(おまけに §3.2 と同じく、ここでも archive 済み v2 が top-1 に居座っています。)

これは Part 3 (cross-encoder reranker で意味的関連性を再採点 + 引用付き生成で「どの文書由来か」を露出) で扱うパターンです。

§3.4 構造が似ているだけの trap: 「月例の振り返り会はどう進めればいい?」

最後は、運用改善の文脈で「振り返り会の進め方」を訊いた、ごく自然な質問です。

Terminal window
uv run python -m examples.naive_rag --query "月例の振り返り会はどう進めればいい?"
[corpus] 15 docs, 47 chunks
[retrieve] top-k:
0.4938 nagisa-boardgame-monthly#02
0.4886 nagisa-boardgame-monthly#04
0.4507 nagisa-boardgame-monthly#03
[answer]
月例振り返り会は、blameless な姿勢で「タイムライン・直接原因・根本原因・次回アク
ション」を軸に進めます。社内 wiki に月次集計を投稿し、卓リーダーが初期対応を確認した
インシデントを対象に議論します。今月は P1 課題として、post-mortem 型から「やったこと
/学び/次やる」型のテンプレートに簡素化し、5 月幹事会で議論する必要があります。

観察ポイント: top-3 をすべて nagisa-boardgame-monthlyボードゲーム同好会の 4 月活動報告 が占めています。回答には「blameless」「タイムライン・直接原因・根本原因」「卓リーダー」「P1 課題」「初動 acknowledge」 — 障害対応 post-mortem の語彙と、同好会の「卓リーダー」がシュールに混ざっています。

なぜか。ボードゲーム同好会の月例報告は、業務の incident post-mortem テンプレを意図的に流用 して書かれているのです (「TL;DR / やったこと / 振り返り / Next Action」「acknowledge」「初動 SLA」「エスカレーション基準」)。embedding は 意味よりも文体・構造・段落リズムを強く拾う ため7、「振り返り会の進め方」というクエリに対して、本物の障害対応フロー (nagisa-incident-flow.md) ではなく、構造がそっくりな同好会の報告を「似ている」と判定しました。

これが 構造類似トラップ です。見かけ上の出力が流暢なので、読者が「卓リーダーって何?」と引っかかるまで誰も間違いに気付きません。社内ナレッジボットで最も発見が遅れる失敗です。Part 2-3 の cross-encoder reranker で部分解消するパターンです。

観察した失敗を分類する

§3 で 4 つのクエリを流しました。1 つは成功、3 つで「retrieval が間違った文書を拾う」様子を見ました。抽象化すると、素朴な RAG の弱点は 3 つのグループ に整理できます。

グループ A: retrieval が「間違った文書」を拾う

corpus に紛れた trap 文書を、本物より上位に引き上げてしまうパターン。3 類型あります。

#trap 類型§3 の実例なぜ起きる解決する Part
A-1表層一致 (surface)§3.3 物流ロールバック語が一致するだけで意味は無関係Part 3 (rerank + 引用)
A-2構造類似 (semantic)§3.4 ボドゲ post-mortemテンプレ・文体が同じPart 3 (rerank)
A-3古い記述 (stale)§3.2 Mirage v2 archive旧版が現行を押しのけるPart 2 (部分) + Part 5 (filter)

A-1 と A-2 は「距離は近いのに内容は無関係」という同じ根を持ちます。embedding は語の表層や文章構造を拾うので、「ロールバック」という単語や「post-mortem テンプレ」という骨格が一致しただけで高スコアを出す。cross-encoder reranker (Part 3) はクエリと chunk を 同時にエンコードして相互注意で関連性を再採点 するので、表層・構造の一致に引きずられにくくなります。

A-3 (古い記述) は別の根です。文書は本物 (Mirage の設計書) なのに 版が古い。これは「どれが現行か」という メタ情報の問題 で、retrieval スコアだけでは解けません。Part 2 で版・status を chunk に焼き込み、Part 5 で「archive を index から外す」運用に落とします。

グループ B: retrieval が「正しい文書」を取りこぼす

逆に、本物の文書が 語彙のズレ で圏外に落ちるパターンです。社内文書あるあるで「リモワ」「テレワーク」「WFH」「在宅勤務」がすべて同じ制度を指す、「障害」「インシデント」「トラブル」「P1」が併用される — のような synonym / acronym 過密ドメイン で頻発します8

たとえば「テレワークの補助金はある?」と訊いたとき、nagisa-remote-work.md が「在宅勤務手当」と表記しているために cosine が下がり、回答に必要な doc が top-3 圏外に落ちることがあります (§3.1 では「リモートワーク手当」と語が揃っていたので拾えました)。

Part 2 で解決: BM25 (sparse) + embedding (dense) を組み合わせ、Reciprocal Rank Fusion (RRF) でスコアを合成する hybrid search にすると、acronym 一致 (BM25 が拾う) と意味類似 (embedding が拾う) を両取りできます。

グループ C: generation 側で壊れる

retrieval が正しくても、生成の段で品質が落ちるパターンが 2 つあります。

C-1 引用 (出典) が消える: build_prompt### mirage-architecture-v3#00 のようなラベルを context に入れても、生成では chunk ID への参照が出力に残らない ことが多い。すると、本物の回答であっても 「どこから来た事実か」を読者が検証できません9。§3.2 で見た「現行 v3 か旧版 v2 か」を読者が見分けられないのと直結します。Part 3 で解決: [citation: doc_id] 形式の明示要求 + parser、または Anthropic の Citations API9 (doc_id + 該当箇所の charspan まで返す) を使う設計に切り替えます。

C-2 コンテキスト爆発: 「精度が悪い、もっと取れば?」と top-k を 3 → 10 → 30 に増やすと、input token が増えてコストが跳ね、long context の needle-in-a-haystack 性能はむしろ劣化し10、関連しない chunk が増えて hallucination も増えます。top-k を増やすほど答えが良くなる、わけではないPart 3-4 で解決: reranker で top-k=20 → top-3 に絞り、Part 4 で Context Precision / Context Recall を数値で測定 して trade-off を可視化します。

なぜ Part 2 以降が必要か

失敗 → 残り Part の対応

ここまでで見た失敗が、残りの Part にどう対応するかの全体像です。

グループ失敗解決する Part主要手段
A-1/A-2表層・構造の trapPart 3cross-encoder reranker + 引用付き生成
A-3古い記述 trapPart 2 (部分) + Part 5metadata 保持型 chunking + freshness / status filter
B同義語で取りこぼしPart 2BM25 + dense hybrid + RRF
C-1引用喪失Part 3citation 設計 / Anthropic Citations API
C-2context 爆発Part 3-4reranker で k を絞る + Part 4 で測定
(運用全般)劣化への追従Part 5logging safety / drift / cost / index 鮮度

「動いているように見えるが、何が動いているかは検証していない」

ここまでの実装には 致命的な欠陥 があります。わたしたちは、いま動いているかどうかを 1 度も測定していません

§3 で 4 つのクエリの代表例を見せましたが、それは恣意的な選別です。本当に動く RAG にしようとするなら:

  • Faithfulness: 答えが retrieved context に裏付けされているか
  • Answer Relevance: 答えが質問への直接の答えになっているか
  • Context Precision: retrieve した chunk のうち、答えに寄与したものの割合
  • Context Recall: 答えに必要な事実が retrieve できた割合

4 つを数値で測定 する必要があります。これらは Part 4「評価」 でクライマックスとして扱います。Part 1-3 の改善のすべてが、Part 4 のスコア改善として 客観的に確認できる 構造を、シリーズ全体で目指します。

次の Part への準備

companion repo の part-01 tag は本記事の実装そのものです。clone して動かしながら、または読みながら、自分の手で「動くけど使えない」を体感してみてください。

Terminal window
ollama pull qwen3:8b && ollama pull qwen3-embedding:0.6b
git clone https://github.com/zawazawa5809/rag-fundamentals-companion.git
cd rag-fundamentals-companion
git checkout part-01
uv sync --frozen
echo "RAG_PROVIDER=ollama" >> .env
uv run python -m examples.naive_rag --query "あなたの試したいクエリ"

API キーを使いたい読者へ: companion repo は Anthropic Claude + OpenAI Embedding 経路も一級サポートしています。.envRAG_PROVIDER=anthropic_openai と各 API キーを置けば切り替わります (Part 3 で扱う Anthropic Citations API は Anthropic 経路でのみ動作)。本シリーズ本文の数値は、誰でも 0 円で再現できる Ollama 経路で統一しています。

そして、自分なりに「これは使えないな」というクエリを 3 つ見つけたら、それを覚えておいてください。Part 2 で同じクエリを叩いて、改善を 数値ではなく感覚 で先に体験してから、Part 4 で 改善が本物だったか を測定する流れになります。


シリーズ全体: 今更聞けない RAG の作り方、評価の仕方

次回 Part 2: 「Retrieval を真面目に — chunking と hybrid search で recall を数値改善する」

参考文献

Footnotes

  1. Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks — Lewis et al., NeurIPS 2020. RAG という用語の原典 2

  2. Retrieval-Augmented Generation for Large Language Models: A Survey — Gao et al., 2023 (随時更新)。Naive / Advanced / Modular RAG の分類

  3. LangChain - Text splitters — chunking デフォルト値

  4. LlamaIndex - Production RAG chunking — 跨ぎ問題と semantic chunking

  5. Qwen3 Embedding — qwen3-embedding ファミリの MTEB 多言語ランキングとスペック

  6. Anthropic - Use XML tags to structure your prompts — XML タグでの context 構造化指針

  7. Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks — Reimers & Gurevych, EMNLP 2019. sentence embedding の表層類似性質

  8. The Probabilistic Relevance Framework: BM25 and Beyond — Robertson & Zaragoza。BM25 の同義語問題

  9. Anthropic - Citations API — RAG grounding / citation 設計 2

  10. Anthropic - Context windows — long context の trade-off