出発点・難しさ・読み方(飛ばしても構いません)
ガイド · 出発点
なぜこの実験をしたか、誰に向けて書いたか
- 出発点
- 多くの RAG のチュートリアルは技術ごとに進みます。まず分割、次に embedding、次に rerank……どの段階も役に立ちそうに見えます。ここでは逆にします。小さくても完結した RAG を作り、本物のドキュメントに本物の質問をして、実際に起きた失敗を一つ最後まで追いかけ、それぞれの仕組みがどの種類の失敗に効くのかを見ます。
- 想定する読者
- 「ドキュメントをもとに質問に答える」仕組みを作っている、あるいは作ろうとしているエンジニアやプロダクト担当。基本的な RAG は動かしたことがあり、「取れてきたものはどれも関連しているのに、答えが不完全」という経験がある人。
- 学べること
- 実際の baseline がどう動くか
- 「関連している」と「答えるのに十分」は別のこと
- 「コーパスに根拠がない」と「検索が見つけられなかった」の見分け方
- Top-k、重複の除去、リランカー、質問の分割、言い換え、embedding の変更が、それぞれどの失敗に対応し、どんなときに効かないか
- 検索が届かないとき、システムがユーザーを続けて助ける方法
- 向かない人
- ゼロから作るインストール手順を求める人、「最良の RAG 設定」やモデルのランキングを探している人、Graph RAG・エージェント・ファインチューニングを知りたい人、そのまま公開できる本番向けガイドが必要な人。
ガイド · この記事の位置づけ
何についての記事で、どれくらいかかるか
- 性質
- 実際のエンジニアリング実験の調査記録です。チュートリアルではなく、Cloudflare 公式のガイドでもありません。結論は、このスナップショット(26 ページ、2026-10-04 取得)、このベンチマーク、いくつかのケースに基づきます。質問は中国語、ドキュメントは英語で、目標は答えの一文ごとに根拠があることです。
- 難しさ
- 中級。チャンク、embedding、ベクトル検索が何かをおおよそ知っていれば十分です(01 で一言ずつ説明します)。コードを書く必要はありません。
- 読む時間
- 通読で約 25 分。結論だけなら 07 を読んで約 3 分。
- 浅いところから深いところへ
- 01–03 基礎:baseline、うまくいくケース一つ、根拠がないケース一つ
- 04–05 応用:不完全になる質問一つと、順に潰していく六つの仮説
- 06 総合:検索が届かないときどうするか
- 07 結論、08 再現ノート
- 読み方
- 順に読むのがいちばんスムーズです。基礎に慣れている方は 04 から。結論だけなら 07、自分で再現したいなら 08 へ。
01 · Baseline · 基礎
あえて単純にした RAG
このあと調べるのは失敗であって、チューニングではありません。だからどの段階もできるだけ単純にしてあります。この節を読み終えたら、次の流れだけ覚えておけば十分です。
- 公式ドキュメント
- 構造に沿ってチャンクへ
- embedding
- cosine 検索
- Top-5 を根拠に
- Qwen が生成
- 引用チェック
- コーパス
- Cloudflare 公式ドキュメント 26 ページ(Pages、Workers、R2、D1、Wrangler、バインディング、変数とシークレット、上限と料金)、スナップショット
v1-2026-10-04 - 分割
- 336 個のチャンク。そのうち 334 個は本文があり embedding できます(残り 2 個は見出しだけ)。長さの中央値は 827 文字
- 検索
bge-m3(1024 次元)+ フラットな cosine で、Top-5 を生成に渡す- 生成
qwen3.8-flash:渡された根拠だけを使い、チャンクを引用して、原文をそのまま引用する。引用が本当に存在するかはシステムが検証する- 足りるか
- 根拠が答えに足りるかは、手書きの「根拠チェックリスト」で判断します。足りなければ回答を断り、モデルは呼びません(このリストは一つのケースのためだけに書いたもので、汎用ではありません)
初めて見る言葉は?
- チャンク
- ドキュメントから切り出した小さな断片。検索と引用の最小単位
- embedding
- 質問とチャンクをベクトルに変換し、距離で意味の近いものを探す
- cosine
- 二つのベクトルの向きがどれだけ近いかのスコア。高いほど似ている
- Top-k
- スコアの高い順に k 個のチャンクを根拠として取る
- 引用チェック
- 回答の引用はすべて、実際に取得したチャンクに対応していなければならず、引用した原文はそのチャンクにそのまま現れていなければならない
チャンクの切り方、使ったモデル、環境については最後の「再現ノート」にあり、ここでは触れません。
02 · うまく動くとき · 基礎
成功したケース:Q5
質問怎么给 Pages Functions 配置 R2 bucket 绑定,并在代码里访问它?訳: Pages Functions に R2 バケットのバインディングを設定し、コードからアクセスするには?
まず、正常に動くとどうなるかを見ます。そうすれば、このあと失敗が出てきても、システム全体が動いていないせいではないとわかります。
1 位のチャンク一つに、「Pages プロジェクトに R2 バインディングを設定する方法」「再デプロイが必要なこと」「context.env でアクセスすること」が全部書かれているので、根拠の状態は sufficient(十分)です。 Qwen は順位 1、2、3、4 のチャンクを 4 か所で引用し、どの引用も原文がそのまま存在していて、チェックは通りました。
成功したケースにも隙間があります。Pages の Wrangler 設定の書き方を載せたチャンクは 8 位で、Top-5 の外です。この隙間は記録しましたが、埋めてはいません。
03 · 根拠がないとき · 基礎
Q9a:コーパスに全く書かれていないことを聞く
質問Workers KV 的免费额度是多少?超出后如何计费?訳: Workers KV の無料枠はどれくらいですか。超えた分はどのように課金されますか?
まずコーパスを調べます。このスナップショットで KV に触れているチャンクは 34 個(13 ページ)ありますが、すべてバインディングや設定の使い方で、無料枠も課金も書かれていません。これは検索の失敗ではありません。検索が「取りこぼした」チャンクは一つもないのです。
それでも検索は 5 個のチャンクを返しました。スコアは 0.574–0.593、内容は Workers・Pages・R2 の上限と無料枠です。 Q5 の 5 位のスコアは 0.608。スコアだけでは、「根拠がある」と「根拠がない」を見分けられません。
- 通常の経路:根拠の状態は insufficient、システムは回答を断り、モデルを呼びません。
- 実験ではわざとこの関門を迂回し、同じ 5 個の邪魔なチャンクを Qwen に渡しました。その答えは「提供的证据中未包含 Workers KV 的免费额度及超出后的计费信息。訳: 提供された証拠には、Workers KV の無料枠と、超えた分の課金についての情報は含まれていません。」。数字はなく、他の製品の枠を KV のものとして語ることもなく、引用もありませんでした。
「渡された根拠には書かれていない」を、「Cloudflare のドキュメントには書かれていない」と書いてはいけません。コーパスにない ≠ 検索が見つけられなかった ≠ 公式にない。モデルを呼んだのは 1 回だけで、今回は越権しなかったことしか示さず、安定しているとは言えません。また、事柄がまるごと欠けている場合は、いちばん断りやすいタイプでもあります。
04 · 本当に厄介な質問 · 応用
Q7:どれも関連していそうなのに、答えが不完全
質問环境变量、secret 和普通配置应该分别怎么设置?本地开发和线上部署有什么区别?訳: 環境変数、secret、通常の設定は、それぞれどう設定すればよいですか。ローカル開発と本番デプロイでは何が違いますか?
完全な答えには、次の四つの材料が必要です。
まず Top-10 を見ます。見出しを読むかぎり、検索はうまくいっているように見えます。
どれも secrets、ローカル開発、環境変数についてで、話題から外れたものは一つもありません。それでも必要な四つのうち覆えたのは 1/4、C4 だけです。 C1、C2、C3 はコーパスの中にあり、上位 60 件にも入っていますが、順位は 52、36、36 位でした。
semantic similarity ≠ evidence sufficiency。「質問に関連している」と「質問に答えるのに十分」は別のことです。検索がするのは前者です。
ラベル付けの未決事項が一つあります。「Compare secrets and environment variables」のようなチャンクは、ベンチマークでは無関係とされていますが、人が読めば C1/C2 の助けになります。これを根拠と数えるかどうかは、著者がまだ見直していない Gold の問題で、ここでは何も変えておらず、そのためにスコアも調整していません。
05 · どの層かを判断してから実験 · 応用
六つの仮説、すべて実際に走らせた
まず、失敗がどの層にあるかを判断します。根拠がコーパスにない? いいえ、C1–C3 は上位 60 件にあります。ちょうど Top-5 の外? それも違い、36–52 位にいます。つまり「ある、でも深い」です。以下の各仮説はよくある仕組みに対応していて、どの段階も、仮説 → 実験 → 結果 → 判断の順です。効果のなかった実験もここに書きます。技術は足せば効くものではなく、仕組みごとに対応する失敗が違うからです。
ATop-k が小さすぎるのか?
Q8 には部分的に有効 · Q7 には無効
- 仮説
- 必要なチャンクが 6–10 位にあり、Top-5 で切り捨てられている。
- 実験
- k だけを変える:3、5、6、10。同じ順位の先頭部分を使う。
- 結果
- Q8(Pages と R2 の無料枠は共通か)は、k=6 で初めて足りなかった一片が加わります。カバーは 1/2 → 2/2。 Q7 は k=3 から 10 までずっと 1/4 のままです。k を 10 に広げると、四つの質問の無関係なチャンクは合計で 8 から 24 に増え、プロンプトの長さは約 1.6 倍になります。
- 判断
- Q8 は本物の打ち切りの問題です。Q7 は違い、足りないものは 36–52 位にあります。k は 5 のままにします。
B重複したチャンクが場所を取っているのか?
重複は現象であって、根本原因ではない
- 仮説
- 同じ文章が何ページにも出てきて Top-5 を埋めている。重複を除けば、足りない根拠が上がってくる。
- 実験
- 上位 60 件の候補プールに、三つのやり方を 1 回ずつ(パラメータは事前に固定、調整しない):完全に同じチャンクを一つだけ残す、ほぼ同じものも畳む、MMR(λ=0.2)。
- 結果
- 重複は確かに多く、上位 60 件の中に完全な重複が 6 個、ほぼ重複が 13 個(前者を含む)あり、Top-5 のうち 4 個が冗長でした。ただし、三つのやり方とも Top-10 のカバーは 1/4 のままです。重複を除くと、空いた場所は別の secrets やローカル開発のチャンクで埋まります。MMR はむしろ C1 を 52 位から 59 位に押し下げました(候補プール全体を MMR の順で並べた場合)。
- 判断
- 重複は場所を無駄にしていますが、足りない根拠が深くにある原因ではありません。重複の除去は役に立ちますが、解決するのは別の問題です。
MMR は初めてですか? 関連性に加えて、すでに選んだ結果と似すぎているチャンクを減点し、結果を散らします。
Cもっと強い関連度スコアで救えるのか?
上がるが、Top-10 には入らない
- 仮説
- embedding は粗い順位づけにすぎない。より強いモデルで「質問とチャンク」の関連度を一つずつ判定すれば、正しいものが上がってくる。
- 実験
- 上位 60 件を
BAAI/bge-reranker-v2-m3 で並べ替える。見るのはリランカーのスコアだけで、元の cosine とは混ぜない。 - 結果
- C2、C3 は 36 位から 18 位へ、C1 は 52 位から 49 位へ上がりましたが、Top-10 のカバーは 1/4 のままです。「本番でシークレットをどう設定するか」に答える
wrangler secret put のチャンクは、むしろ 43 位から 55 位に下がり、remote bindings についての無関係なチャンクは 29 位から 8 位に上がりました。Top-10 の半分は、やはり重複した内容です。 - 判断
- より強い関連度スコアラーでも、自動的には解決しません。質問に「違い」と「ローカル開発」の両方が入っているので、スコアラーはその二つに引きつけられ、やり方を直接答えるチャンクを低く評価しました。
リランカーは初めてですか? まず候補をまとめて取り出し、そのあと重いモデルで質問とチャンクの関連度を一つずつ判定し直します。
D一文に多くを詰め込みすぎなのか?
影響はあるが、主因ではない
- 仮説
- 二つの質問が混ざっていて、embedding がどちらか一方に引っ張られている。
- 実験
- 「?」で機械的に二文に分け(言い回しは変えない)、それぞれ検索して、結果を交互に混ぜる。一文目は変数とシークレット、二文目はローカルと本番。
- 結果
- 一文目だけで聞くと、C1 は 52 位から 39 位に、C2、C3 は 36 位から 19 位に上がりますが、Top-10 の外のままです。二文目では必要な一片が一つも見つからず、C4 でさえ 37 位になってようやく出てきます。混ぜたあとの Top-10 のカバーも 1/4 のままでした。
- 別の例
- Q8 でも、手書きで質問を分けて試しました。「Pages の無料枠」と「R2 の無料枠」の二つの小質問で、混ぜた 10 件の候補が覆えたのは 1 種類だけ。分けない元の質問は、Top-10 で 2 種類を覆えています(欠けた一片は 6 位)。分けても役に立たず、検索の回数が一回増えただけでした。
- 判断
- 複合的な質問は確かにシグナルを薄めます(十数位ほど上がりました)。しかし分けても、根拠が Top-10 に入るようにはなりません。
Eユーザーの言い方とドキュメントの表現が合っていないのか?
スコアは上がったが、根拠は上がらない
- 仮説
- ドキュメントの言葉で聞けば、検索はもっと正確になる。
- 実験
- 事前に書いておいた言い換えを 1 回ずつ:一つは中国語のまま Cloudflare の用語に置き換えたもの、もう一つはドキュメントの表現をそのまま写した英語です。後者は答えの漏れを疑われるので、上限を測るためだけに使いました。
- 結果
- どちらの版も、元の質問より cosine は高くなりましたが、C1/C2/C3 は深いままです。中国語の言い換えは 85 / 107 / 72、英語の言い換えは 53 / 48 / 44(元の質問は 52 / 36 / 36)。Top-10 のカバーはどちらも 1/4 でした。
- 判断
- ドキュメントに似ていることは、根拠としての価値が高いことではありません。cosine が高いのは、その文章の近くにいるというだけのことです。
二つの言い換えの原文を見る
中国語の用語版:Cloudflare Workers 里的 environment variables、secrets 和普通配置(vars)应该分别怎么设置?本地开发(Wrangler)和线上部署(production)有什么区别?
(日本語訳:Cloudflare Workers で、environment variables、secrets、通常の設定(vars)は、それぞれどう設定すればよいですか。ローカル開発(Wrangler)と本番デプロイ(production)では何が違いますか?)
ドキュメントに合わせた英語版:How do I configure plain text environment variables in the Wrangler configuration file, add encrypted secrets with wrangler secret put for production, and use .dev.vars or .env files for local development in Cloudflare Workers and Pages?
- 仮説
- 第一段階の表現である bge-m3 自体が原因だ。
- 実験
- モデルだけを替え、モデルごとにドキュメントのベクトルを作り直す:bge-m3(baseline)、nomic-embed-text-v1.5、snowflake-arctic-embed-l-v2.0。
- 結果
- nomic は Q7 では局所的にはっきり良く、C2、C3 は 2、3 位に上がり、Top-10 のカバーは 3/4 です。ただし「普通の変数」の一片は 134 位に落ちます。arctic は bge-m3 と同じで、Top-10 は 1/4 だけです。ベンチマーク全体(中国語の質問)に戻ると、完全に採点できる 4 問では、どちらも Recall@5 は 0.56 ですが、MRR は 0.88 対 0.54。部分的にしか採点できない 4 問では、Recall@5 は 0.88 対 0.38 です。
- 判断
- 一つの失敗ケースを救うために、全体の baseline を替えてはいけません。bge-m3 はベンチマーク全体で選んだもので、nomic が Q7 で得た利点は、別のところでの損失と引き換えです。nomic は英語寄りで、なぜ中国語の質問をこう並べるのかは、まだ確かめていません。
並べて見る
下は、試すたびに C1、C2、C3 が最初に現れた位置です。緑は Top-10 に入ったものです。
六つのやり方のうち、C1–C3 がすべて Top-10 に入ったものは一つもありません。仕組みごとに対応する失敗は違います。この質問の失敗は、そのどれが働く層にもありません。
06 · Recovery Loop · 総合
見つからないとき、ユーザーが続けられるよう助ける
ここまでで、Q7 は「見つからないから、わからない」で止めることもできます。けれど別の道もあります。システムが根拠の不足を認め、ユーザーが質問をもっと答えやすい形に直すのを助けるのです。
- 元の質問根拠が不完全
- Qwen がより狭い質問を 3 つ出す
- ユーザーが一つ選ぶ新しい普通のクエリとして扱う
- 再検索
- 根拠のある回答+ 引用チェック
「Recovery Loop」はこのやり方に私がつけた名前で、一般的な用語ではありません。モデルが見るのは元の質問と、現在の Top-5 の根拠だけです。ルールは汎用的で、元の質問には答えない、Cloudflare の事実を補わない、より狭い質問を 2–3 個だけ出す、というもの。カテゴリも、どのチャンクの順位が低いかも、それまでにどんな実験をしたかも、「正しい分け方」も伝えていません。パラメータはこれまでと同じで、qwen3.8-flash、temperature 0、thinking はオフ、呼び出しは 1 回だけ。提案は生成したらそのまま固定し、再試行も手直しもせず、そのあとで検索します。
モデルが挙げた理由は、「原问题同时询问了环境变量、secret和普通配置的设置方法,以及本地与线上部署的区别,涉及多个独立主题且当前证据主要聚焦于本地开发中的 secret 处理。訳: 元の質問は、環境変数・secret・通常の設定の設定方法と、ローカルと本番デプロイの違いを同時に尋ねていて、独立した複数のテーマにまたがります。一方、現在の証拠は主にローカル開発での secret の扱いに集中しています。」。提案された質問は次のとおりです。
- S1在 Cloudflare Workers 中,如何区分设置普通环境变量(vars)和敏感信息(secrets)?訳: Cloudflare Workers で、通常の環境変数(vars)と機密情報(secrets)は、どう分けて設定しますか?
- S2线上部署时,如何通过 Wrangler CLI 或 Dashboard 为 Worker 添加 secrets?訳: 本番デプロイのとき、Wrangler CLI または Dashboard から Worker に secrets を追加するには?
- S3本地开发和线上部署在加载 .dev.vars/.env 文件与生产环境配置时有何具体区别?訳: .dev.vars/.env ファイルと本番環境の設定を読み込むとき、ローカル開発と本番デプロイでは具体的に何が違いますか?
ユーザーが S2 を選んだとします。これは新しい普通のクエリで、使うのは同じ bge-m3、何も変えていません。三つの提案それぞれの結果は次のとおりです。
上位三つは Via the dashboard、Via Wrangler、Upload secrets alongside code です。dashboard での手順、wrangler secret put、そしてコードと一緒にシークレットをアップロードする --secrets-file。
S2:C3 は 36 位から 2 位へ。元の質問では 36 位だった一片が、「本番でシークレットをどう設定するか」だけを聞く質問に替えると、上位 3 位に入りました。
S2 だけについて、最終的な回答を 1 回出します(S2 自身の Top-5 を使い、引用のルールは同じ)。
デプロイ後に Worker へシークレットを追加する方法は二つあります [1][2]。一つは dashboard の Workers & Pages → 対象の Worker → Settings → Variables and Secrets で、種類に Secret を選んで追加し、Deploy する方法。もう一つは wrangler secret put <KEY> で、新しいバージョンを作ってすぐデプロイします。gradual deployments を使う場合は、代わりに wrangler versions secret put を使います。--secrets-file を使って、コードと一緒にアップロードすることもできます [3]。
以上は完全な回答の言い換えです。引用は 3 か所で、チェックは通りました。引用したチャンクはすべて S2 自身の Top-5 から来ていて、原文もそのまま存在します。
モデルの回答の全文を見る
在线上部署时,可以通过以下两种方式添加 Worker secrets:
1. **通过 Dashboard**:
- 在 Cloudflare dashboard 中进入 **Workers & Pages** 页面 [1]。
- 选择你的 Worker > **Settings** [1]。
- 在 **Variables and Secrets** 下选择 **Add** [1]。
- 选择类型 **Secret**,输入 **Variable name** 和 **Value**(值将在 Wrangler 和 dashboard 中隐藏)[1]。
- 可选地,选择 **Add variable** 以添加更多 secrets [1]。
- 最后选择 **Deploy** 以实施更改 [1]。
2. **通过 Wrangler CLI**:
- 使用 `wrangler secret put <KEY>` 命令。这会创建一个新的 Worker 版本并立即部署 [2]。
- 如果使用 gradual deployments,则使用 `wrangler versions secret put <KEY>` 命令。这仅创建新版本,随后需使用 `wrangler versions deploy` 进行部署 [2]。
- 注意:Wrangler 3.73.0 之前的版本需要指定 `--x-versions` 标志 [2]。
- 此外,可以使用 `--secrets-file` 标志在部署代码的同时上传 secrets,例如 `npx wrangler deploy --secrets-file .env.production` 或 `npx wrangler versions upload --secrets-file secrets.json` [3]。
日本語訳:
本番デプロイでは、次の二つの方法で Worker の secrets を追加できます。
1. **Dashboard から**:
- Cloudflare dashboard で **Workers & Pages** のページを開きます [1]。
- 対象の Worker > **Settings** を選びます [1]。
- **Variables and Secrets** で **Add** を選びます [1]。
- 種類に **Secret** を選び、**Variable name** と **Value** を入力します(値は Wrangler と dashboard では表示されません)[1]。
- 必要に応じて **Add variable** を選び、secrets を追加します [1]。
- 最後に **Deploy** を選んで変更を反映します [1]。
2. **Wrangler CLI から**:
- `wrangler secret put <KEY>` コマンドを使います。新しい Worker のバージョンが作られ、すぐにデプロイされます [2]。
- gradual deployments を使う場合は、`wrangler versions secret put <KEY>` コマンドを使います。これは新しいバージョンを作るだけなので、そのあと `wrangler versions deploy` でデプロイします [2]。
- 注意:Wrangler 3.73.0 より前のバージョンでは `--x-versions` フラグの指定が必要です [2]。
- また、`--secrets-file` フラグを使えば、コードのデプロイと一緒に secrets をアップロードできます。例:`npx wrangler deploy --secrets-file .env.production`、`npx wrangler versions upload --secrets-file secrets.json` [3]。
限界も残しておきます。recovery は万能ではありません。
- S1(普通の変数とシークレットの違い)は解決していません。C1 は 31 位、C2 は 16 位に上がりましたが、Top-10 の外のままです。Q7 でいちばん基本の一片は、結局取り戻せていません。
- S3(ローカル開発と本番の設定)は、もともと見つかっていた C4 を覆っているだけで、新しい進展はありません。
- ケースは一つ、提案も一組、呼び出しも 1 回です。最終回答では「根拠チェックリスト」の関門を使っていません。この質問にはそのリストを書いていないからです。
良い RAG は、すべての質問に一度で答えられなくてもかまいません。根拠が足りないときにそれがわかり、ユーザーが続けられるよう助けられることが大切です。ここでの結果は partial です。一つの小質問には根拠つきで完全に答えられ、もう一つには答えられませんでした。
07 · 今の判断と振り返り
RAG の失敗に出会ったらこう考える。効いたこと、効かなかったこと、やらなかったこと
関連している ≠ 十分Q7 の Top-10 には話題から外れたものが一つもないのに、必要な四つのうち 1/4 しか覆えていません。
cosine が高い ≠ 答えられるコーパスに KV の枠がないとき、Top-5 のスコアは 0.574–0.593。答えのある Q5 の 5 位は 0.608 です。スコアのしきい値では防げません。
コーパスにない ≠ 検索が見つけられなかった検索を疑う前に、まずコーパスを調べる。回答でも言えるのは「渡された根拠には書かれていない」までで、「公式ドキュメントにはない」とは言えません。
リランカー、重複の除去、言い換え、質問の分割には、それぞれ効く条件があるQ8 の問題は k=6 で埋まりました。Q7 では、どれも足りない根拠を Top-10 に入れられませんでした。失敗がどの層で起きているかを見極めてから、仕組みを選びます。
一つのクエリのために baseline を過剰に合わせないnomic は Q7 では局所的に良いものの、ベンチマーク全体では bge-m3 のほうが強い。baseline を替えるなら一つのケースではなく、ベンチマーク全体で判断します。
複合的な質問の recovery は製品の機能にできる。検索を積み増し続けなくてよいシステムが根拠の不足をはっきり伝え、より狭い質問を出すだけで、S2 は C3 を 36 位から 2 位に引き上げ、引用つきの回答を得ました。
振り返り:今回やったこと
- 効いた
- 根拠があるときは引用つきで答え、コーパスにないときはでっち上げずに断る(Q5、Q9a)。
- 典型的な失敗を突き止めた:Q7 の Top-10 には話題から外れたものがないのに、答えに必要な材料のうち 1/4 しか覆えていない。
- Top-k は Q8 に有効:k=6 にすると、足りなかった一片が埋まった(1/2 → 2/2)。
- システムにまず根拠の不足を認めさせ、そのうえでより狭い質問を出させる:足りなかった「本番でのシークレット設定」が 36 位から 2 位に上がり、引用つきの回答が得られた。
- 効かなかった
- Top-k、重複の除去、リランカー、質問の分割、言い換え:Q7 に足りない根拠を Top-10 に入れたものは一つもない。
- embedding の変更:nomic は Q7 で 3/4 まで補ったが、「普通の変数」の一片は 134 位に落ち、ベンチマーク全体でも bge-m3 に及ばない。
- 「普通の変数」と「シークレットは暗号化される」の二つの一片は、bge-m3 の baseline では recovery のあとでも Top-10 に入っていない。
- やらなかった
- 製品ではない:画面もオンラインへのデプロイもなく、ベクトルデータベース、BM25 / ハイブリッド検索、メタデータによる絞り込みもなく、ファインチューニングもしていない。
- リランカー、言い換え、重複の除去は実験にとどまり、baseline には入っていない。
- 評価の規模は小さい:9 問で、Q7 はその一つにすぎない。モデルを使う実験は各 1 回だけ。
- 生成の品質は評価しておらず、異なる生成モデルも比べていない。
まだ解決していないこと
- Q7 の C1/C2(普通の変数とシークレットの違い)は、専用の質問をしても取り戻せていない。
- 「Compare secrets and environment variables」のようなチャンクを根拠と数えるかどうかは、著者が見直す Gold の問題。
- 結論はすべて、このスナップショット、このベンチマーク、いくつかのケースから来ている。どの実験も 1 回しか走らせていないので、モデルや方法が安定しているとは言えない。
読み終えたら答えられるようになっていてほしいのは、検索の失敗に直面したとき、まず何を判断するかです。根拠がコーパスにないのか、上位 k の外なのか、そこにあるのに深いのか。そしてそのとき、システムがまず足りないことを認め、人が続けられるよう助けられるかどうか。
08 · 再現ノート
自分で再現したいなら、おおよそ何が必要か
これは完全なセットアップガイドではありません。経験のあるエンジニアに、材料がどこから来たか、何を使ったか、実験がどこにあるかを伝えるものです。コードとコーパスは著者のリポジトリにあり、今のところ公開しておらず、このページにダウンロードもありません。
- データ
- Cloudflare 公式ドキュメント。各ページの Markdown エクスポート(
index.md)を取り、全 26 ページ、スナップショットのバッチは v1-2026-10-04、2026-10-04 のごく短い時間内に取得し終え、ファイルごとに sha256 を記録しています。これはデータを取った期間であり、公式リポジトリのある一つのコミットには対応しません。あとで更新するときは新しいバッチを作り、これを上書きしません。三つの層の関係は、raw(保存したままのレスポンス)→ normalized(ドキュメントが記録する UI 要素だけを除き、六つの話題が混ざった長いページは関連する章だけを残す)→ チャンク。 - 分割
- 構造に沿って切ります。見出し、段落、リスト項目、表、コードブロック、
<details> がそれぞれ一つのブロック。見出しはすぐ下の説明と結びつけ、チャンクは見出しをまたがず、各チャンクはできるだけ約 2400 文字を超えないようにし、隣り合うチャンクの重なりはゼロ。表とコードブロックは分けません。コーパス全体で上限を超えるチャンクは一つだけ(5759 文字、互換性マトリクスの表)で、表ごと残しました。チャンクの id には本文のハッシュが入っています。 - Embedding
- 入力 = ドキュメントのタイトル + 見出しのパス + チャンク本文。baseline は
bge-m3(1024 次元)。比較したのは nomic-embed-text-v1.5 と snowflake-arctic-embed-l-v2.0。もっと前の bake-off では bge-small-en-v1.5(512 トークンのウィンドウで、57 個のチャンクが切り詰められる)も走らせました。現在の baseline は引き続き bge-m3 です。 - Reranker
BAAI/bge-reranker-v2-m3。Q7 の実験でだけ使い、baseline には入っていません。サードパーティの ONNX エクスポートを CPU で動かしました。- 生成
qwen3.8-flash(Alibaba Cloud Model Studio の OpenAI 互換インターフェース)、temperature 0、enable_thinking=false、JSON 出力。キーとアドレスは環境変数からだけ読みます:DASHSCOPE_API_KEY、DASHSCOPE_BASE_URL。- 環境
- Python 3.11、ONNX Runtime 1.30.0、numpy 2.4.6、CPU スレッド 4、GPU なし。モデルファイルはローカルのキャッシュにあり、リポジトリには入れていません。
実験材料の場所(著者のリポジトリ)
experiments/rag/cloudflare-docs-practice-03/
snapshots/ コーパスのスナップショット(raw、normalized、manifest)
ingest/ 分割のルールとチャンク
embedding/ embedding の bake-off とベンチマーク
case-01/ Q5 の全工程、Q9a の境界テスト
q8-decomposition/ 手書きの質問分割
topk-sensitivity/ Top-k
q7-diversity/ 重複の除去と MMR
q7-reranker/ reranker
q7-query-split/ 文ごとの分割
q7-query-rewrite/ 言い換え
q7-embedding-comparison/ embedding の比較
q7-recovery-loop/ 提案、再検索、最終回答
各実験のフォルダーには、それぞれの report.md とオフラインの検査スクリプトがあります。このページの数字は、そこの results.json から来ています。