正解のページが四位にある
再ランキングとは、検索が返した短いリストを、もう一度よく見て並べ替えることです。一回目の検索は速い代わりに大ざっぱで、答えのページが一位とは限らないので、役に立ちます。
お金を返してもらう方法を聞く人がいます。返金の規約のページは四位で、一位はカード払いのページです。二回目の目で、返金の規約のページが一位に上がります。
このレッスンのゴール
メモ
短い結果リストを二回目の通過で並べ替え、それがコストに見合ったかを説明できる。
キーワード
| ことば | いみ |
|---|---|
| 一回目の通過 | 索引全体に対する速い検索 |
| 二回目の通過 | 上位の結果だけを時間をかけて見ること |
| 再ランカー | 短いリストをもう一度採点するもの |
| 候補 | 二回目が並べ替えてよい結果 |
| 再現率の天井 | 一回目が決める、到達できる最良の値 |
| 上位 k のヒット | 出典が上位 k に入った質問の割合 |
学生が入力するセルは、このプレビューでは空白です。
広くて安い通過のあと、狭い通過
すべてのページを念入りに見るのは遅すぎます。そこで検索は二段階で動きます。一回目は安くて広く、数百万ページを数十ページに絞ります。二回目は遅くて狭く、残った分だけを読みます。
下の数字は作り物ですが、形は本物です。念入りに見るのは、短いリストだからできます。
例: 各通過のコスト
| 通過 | 見るページ数 | 一ページの時間 | 合計の時間 |
|---|---|---|---|
| 一回目 | 1,000,000 | 0.00002 ms | 20 ms |
| 二回目 | 20 | 5 ms | 100 ms |
| 全部に二回目 | 1,000,000 | 5 ms | 5,000 秒 |
学生が入力するセルは、このプレビューでは空白です。
再ランカーは単純な規則でもよい
再ランカーは、短いリストをもう一度採点するものです。学習済みのモデルでも、言語モデルでも、自分で書いた規則でもかまいません。Run の規則は、題に質問の語があれば 3 点、本文にあれば 1 点です。
言語モデルの再ランカーは読みが深い代わりに、質問ごとに呼び出しとトークンと時間がかかります。まず規則で始め、測ります。
よくある間違い
注意
再ランカーは、一回目が見落としたページを見つけられると考える人がいます。できません。渡されたものを並べ替えるだけなので、天井は一回目が決めます。答えが上位 20 に入っていなければ、二回目でも出てきません。
モデルの補助を書く(1)
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' '// 応答に含まれるトークン数。なければ null。' 'function count(data, name) {' ' return data.usage && typeof data.usage[name] === \"number\" ? data.usage[name] : null;' '}' > model.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
モデルの補助を書く(2)
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function ask(messages, sample, max) {' ' try {' ' const res = await fetch(base + \"/v1/chat/completions\", {' ' method: \"POST\",' ' headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' ' body: JSON.stringify({ model: \"lab\", messages: messages, max_tokens: max || 100 }),' ' signal: AbortSignal.timeout(30000),' ' });' ' if (res.ok === false) throw new Error(\"status \" + res.status);' ' const d = await res.json();' ' return { text: d.choices[0].message.content, inTokens: count(d, \"prompt_tokens\"), outTokens: count(d, \"completion_tokens\"), recorded: false };' ' } catch (error) {' ' console.log(\"記録済みサンプル: モデルが答えませんでした (\" + error.message + \")。\");' ' return { text: sample, inTokens: null, outTokens: null, recorded: true };' ' }' '}' 'module.exports = { ask };' >> model.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
再ランカーを書く(1)
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' 'const query = [\"返金\", \"お金\", \"返品\"];' 'const found = [' ' { id: \"c1\", title: \"カード 支払い\", body: \"お金 アカウント 引き落とし\" },' ' { id: \"c2\", title: \"返金 期限\", body: \"お金 戻る 返品 承認 5日\" },' ' { id: \"c3\", title: \"荷物 追跡 注文番号\", body: \"番号 入力 場所 確認\" },' ' { id: \"c4\", title: \"返金 お金 返品 規約\", body: \"30日 以内 荷物 返送 返金 申請\" },' ' { id: \"c5\", title: \"メールアドレス 変更\", body: \"アカウント 開く 編集\" },' '];' > rerank1.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
再ランカーを書く(2)
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function count(text) {' ' const w = text.toLowerCase().split(\" \");' ' return query.filter(function (q) { return w.includes(q); }).length;' '}' 'function points(c) { return 3 * count(c.title) + count(c.body); }' 'function ids(list) { return list.map(function (c) { return c.id; }).join(\" \"); }' >> rerank1.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
再ランカーを書く(3)
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' ' console.log(\"一回目:\", ids(found));' ' const second = found.slice().sort(function (a, b) { return points(b) - points(a); });' ' console.log(\"二回目:\", second.map(function (c) { return c.id + \"=\" + points(c); }).join(\" \"));' ' console.log(\"二回目が読んだ箇所の数:\", found.length);' ' const top = second.slice(0, 3);' ' const lines = top.map(function (c, i) { return (i + 1) + \". \" + c.title; });' ' const prompt = \"質問「お金を返してもらうには」に最も合う箇所はどれですか。番号だけで答えてください。\" + lines.join(\" \");' ' const reply = await ask([{ role: \"user\", content: prompt }], \"1\", 5);' ' const pick = Number(reply.text.trim().charAt(0));' ' console.log(\"モデルの選択:\", pick >= 1 && pick <= 3 ? top[pick - 1].id : \"はっきりした選択なし\");' '}' 'main();' >> rerank1.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
実行して順を比べる
docker exec -w /home/node/project agent node rerank1.jsここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
二回目が見合わないとき
上位の数か所のヒット率を、前と後で測ります。ほとんど動かなければ、その通過はやめます。一回目がすでに正しいとき、リストが短いとき、遅れが遅延の予算を超えるときも同じです。
Run は代用品で、記録済みの候補五つと規則です。本物は本物の索引と本物のモデルを使います。
出力の例
| 行 | 意味 |
|---|---|
| 一回目: c1 c2 c3 c4 c5 | 記録済みの一回目の順 |
| 二回目: c4=10 c2=5 c1=1 ... | 規則が c4 を先頭に上げる |
| 二回目が読んだ箇所の数: 5 | コスト。読んだ箇所で数える |
| モデルの選択: c4 | 本物の選択か、記録済みサンプル |
学生が入力するセルは、このプレビューでは空白です。