見出しのない表の行
断片の質とは、文書の一部が、それだけで見つかり、それだけで分かることです。検索は断片を返すので、見出しや表の見出し行を失った断片は、何も語りません。
手数料の表が一行ずつに切られます。「大, 500円」という行が、「大きい荷物はいくらか」の答えとして返ります。その 500円が何の料金かは、行からは分かりません。
このレッスンのゴール
メモ
構造のある文書を、各断片が見出しと表の見出し行と出典を保つように分割できる。
キーワード
| ことば | いみ |
|---|---|
| 断片 | 索引に入れる、文書の一部 |
| 見出しの道筋 | 断片の上にある題を、上から順に並べたもの |
| メタデータ | 断片のそばに残す情報。出典など |
| 表の見出し行 | 各列の名前を示す最初の行 |
| パンくず | 見出しの道筋を一行に書いたもの |
| 孤立した断片 | 周りがないと意味を失う断片 |
学生が入力するセルは、このプレビューでは空白です。
各断片に見出しの道筋を残す
検索拡張生成のモジュールでは、文書をサイズと見出しで分けました。次は、見出しを残します。「返品 > 手数料」の下の断片は、その道筋を持つべきで、パンくずの形で書きます。店舗マニュアル > 返品 > 手数料。
道筋を本文と一緒に索引に入れます。すると、本文に「返品」と一度もなくても、「返品 手数料」の検索で断片が見つかります。
表の行には見出し行が要る
表は、見出し行と複数の行でできています。一行ずつ切ると、各行は見出しを失います。そこで、各行を見出しを含む語に変えます。「品目: 大, 手数料: 500円」のようにします。
箇条書きも同じです。各項目に、それを導く文を残します。さもないと、項目が単独で宙に浮きます。
例: 同じ行の前と後
| 版 | 索引に入るもの |
|---|---|
| 切り離しただけ | | 大 | 500円 | |
| 見出し行を付けた | 品目: 大, 手数料: 500円 |
| 道筋も付けた | 店舗マニュアル > 返品 > 手数料: 品目: 大, 手数料: 500円 |
学生が入力するセルは、このプレビューでは空白です。
メタデータとサイズの検査
各断片のそばにメタデータを残します。元のファイル、見出し、あとで持ち主や日付も加えます。メタデータがあると、回答は出どころを引用でき、レッスン 5 では絞り込みに使います。
そのあとサイズを検査します。ほかよりずっと長い節には、二つの考えが入っています。もう一度分けます。長すぎる見出しを報告します。
よくある間違い
注意
500 文字ごとに切れば、どんな文書でも十分だと考える人がいます。その切り方は表や見出しを横切り、孤立した断片を残します。まず構造で切り、まだ長すぎるものを分けるときだけサイズを使います。
分割するプログラムを書く(1)
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const doc = [' ' \"# 店舗マニュアル\",' ' \"## 営業時間\",' ' \"平日は午前9時に開店します。\",' ' \"## 返品\",' ' \"### 期限\",' ' \"荷物は30日以内に返送してください。\",' ' \"### 手数料\",' ' \"| 品目 | 手数料 |\",' ' \"| 小 | 200円 |\",' ' \"| 大 | 500円 |\",' '];' > chunk1.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
分割するプログラムを書く(2)
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function cells(line) {' ' return line.split(\"|\").map(function (c) { return c.trim(); }).filter(function (c) { return c.length > 0; });' '}' >> chunk1.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
分割するプログラムを書く(3)
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function chunks(lines, source) {' ' const path = [];' ' const out = [];' ' let head = null;' ' lines.forEach(function (line) {' ' const m = line.match(/^(#+) (.*)/);' ' if (m) {' ' path.length = m[1].length - 1;' ' path.push(m[2]);' ' out.push({ source: source, heading: path.join(\" > \"), rows: [] });' ' head = null;' ' return;' ' }' >> chunk1.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
分割するプログラムを書く(4)
docker exec -w /home/node/project agent sh -c "printf '%s\n' ' const now = out[out.length - 1];' ' if (line.startsWith(\"|\") === false) { now.rows.push(line); return; }' ' const c = cells(line);' ' if (head === null) { head = c; return; }' ' now.rows.push(head.map(function (h, i) { return h + \": \" + c[i]; }).join(\", \"));' ' });' ' return out;' '}' >> chunk1.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
分割するプログラムを書く(5)
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'console.log(\"切り離された表の行:\", doc[9]);' 'chunks(doc, \"manual.md\").filter(function (c) { return c.rows.length > 0; }).forEach(function (c) {' ' console.log(c.source + \" | \" + c.heading + \" | \" + c.rows.join(\" / \"));' '});' >> chunk1.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
実行して断片を読む
docker exec -w /home/node/project agent node chunk1.jsここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
これは練習用の代用品です
Run は、作り物の Markdown の十行を読みます。本物の文書は、PDF でも、Web ページでも、表計算でもあり、それぞれに解析器が要ります。考え方は同じで、構造を見つけ、それを残します。
Run はモデルを呼びません。
Run の出力
| 断片 | 残ったテキスト |
|---|---|
| 店舗マニュアル > 営業時間 | 平日は午前9時に開店します。 |
| 店舗マニュアル > 返品 > 期限 | 荷物は30日以内に返送してください。 |
| 店舗マニュアル > 返品 > 手数料 | 品目: 小, 手数料: 200円 / 品目: 大, 手数料: 500円 |
学生が入力するセルは、このプレビューでは空白です。