RAGのための意味的チャンクing: ウェブデータパイプラインの構築
Advanced Data Extraction Specialist
TL;DR:
- セマンティックチャンク化は、意味の変化を使用してテキストをグループ化します。 定義されたセグメンテーションメソッド、埋め込みモデル、およびチャンクの終了位置を決定するためのルールが必要です。
- クリーンなソーステキストは、検索品質の一部です。 ナビゲーションメニューや繰り返しのバナーは、検索者がそれらを見る前にチャンクを歪めることがあります。
- 各チャンクはそのソースと位置を保持する必要があります。 系譜は、取得したパッセージを引用や診断に役立つものにします。
- セマンティックスプリッターにはベースライン比較が必要です。 余分な埋め込み作業は、より単純な分割戦略よりも良い回答を保証するものではありません。
- 無料で始めることができます。 Scrapelessアカウントクレジットを使用して、小さな承認済み文書セットで上流収集ステップを評価します。
はじめに:取得はベクターストアの前から始まる
リトリーバーは、そのインデックスに保存されたパッセージのみを返すことができます。検索拡張生成では、取得した証拠が生成の入力の一部を形成します。パッセージが説明の半分を含んでいる場合や、政策声明を無関係なナビゲーションテキストと組み合わせている場合、回答生成者は、類似度スコアが強く見える場合でも、不完全なコンテキストを受け取ります。
セマンティックチャンク化は、これらのパッセージが始まる場所と終わる場所を変更します。固定の長さでのみ切断するのではなく、スプリッターは隣接する文の表現を比較し、その意味が十分に分岐したときに境界を作成します。サイズ制限は依然として重要であり、一貫したトピックはダウンストリームモデルが受け入れられるよりも長い場合があります。
この記事は、取得レイヤーとしてScrapeless、変換レイヤーとして透明なPythonスプリッターを使用したWebからRAGへのパイプラインを説明します。これは、言語モデルを用いた構造化抽出を補完します:抽出はタスクフィールドを生成し、チャンク化は後の取得のためにパッセージを準備します。
セマンティックチャンク化の機能
セマンティックチャンク化は、意味の表現を使用してテキストの境界を選択します。一般的な実装は、ドキュメントを文に分割し、これらの文を埋め込み、隣接するベクトルを比較し、十分に大きな変化があったときに新しいグループを開始します。
文の埋め込み方法は、文のテキストを類似性を比較できるベクトルにマッピングします。類似性スコアの意味はモデルと入力に依存するため、数値的境界設定はトピックの変更の普遍的な定義ではなく、評価するためのパラメーターです。
| 戦略 | 境界ルール | 便利な出発点 | 主なトレードオフ |
|---|---|---|---|
| 固定サイズ | 設定された長さ | シンプルなベースライン | 説明を切る可能性があります |
| 構造意識 | 見出しと段落の区切り | 整理された参照ページ | クリーンなドキュメント構造に依存します |
| セマンティック | 埋め込みの類似性の変化 | トピックの移行があるテキスト | モデルの計算とチューニングが追加されます |
| ハイブリッド | 構造、セマンティックチェック、および制限 | 混合ドキュメントコレクション | 評価するための設定が増えます |
見出し、テーブル、コードブロック、およびリストには特別な処理が必要です。文のスプリッターは、値を列ラベルから切り離すことでテーブルを傷つける可能性があります。これらのユニットは前処理中に維持するか、構造意識パスにルーティングしてください。
パイプラインの概要
パイプラインは、キャプチャしたWebドキュメントをその起源を保持したインデックス付きパッセージに変換します。そのステージは、取得 → テキスト正規化 → 文のセグメンテーション → 埋め込み → チャンク形成 → 取得評価です。
Scrapeless Web Unlockerがターゲットリクエストを処理します。あなたのアプリケーションは、返されたコンテンツをクリーンアップし、選択したモデルを通じて埋め込みを生成し、結果として得られるパッセージを保存します。Web取得自体は、ベクトルインデックスを作成したり、正しいチャンク化戦略を選択したりするものではありません。
変換前に元の応答を保存してください。要求されたURL、確立された標準URL、収集時間、ページタイトル、および正規化されたテキストのハッシュを保持します。標準URLはソースの証拠から得る必要があります。パスセグメントを削除することによってそれを製造しないでください。
前提条件
承認済みの公的ソースページのセット、取得用のScrapeless APIキー、処理用のPython、およびローカルまたは選択したプロバイダーを通じて実行できる埋め込みモデルが必要です。プロバイダーまたはモデルは、埋め込み設定とアクセス要件を決定します。
このチュートリアルのスプリッターは、sentences.jsonファイルを消費し、source_url文字列、順序付きのsentencesリスト、および各文ごとに1つの数値ベクトルを含むembeddingsリストを取ります。特定のホスト型モデルやベクトル寸法を想定していません。同じモデルは、1回の実行で各文に対して使用する必要があります。
認証されたページ取得および埋め込み生成は、この例のためにエンドツーエンドで実行されていない前提条件です。スプリッターは独立してチェックできますが、ローカルアルゴリズムチェックでは回収品質や成功したモデル統合を確立することはできません。
ステージ1: ソースドキュメントの取得とクリーンアップ
有用なドキュメントは、チャレンジページ、ログインフォーム、またはナビゲーションシェルではなく、意図したページコンテンツから始まります。Web Unlockerリクエストインターフェースを通じてページを取得し、テキストを抽出する前に期待されるコンテンツが存在することを確認してください。
受け入れられた各ページについて、スクリプト、スタイル、繰り返しナビゲーション、関連のないプロモーショナルブロックを削除します。見出しや段落の境界を保持します。ページが動的にレンダリングされる場合は、文書化されたレンダリング設定を使用し、返されたコンテンツが関連するテキストを含むことを確認してください。
生のコンテンツと正規化されたコンテンツを別々に保存します。これにより、悪い取得された段落が収集、クリーンアップ、セグメンテーション、または埋め込みモデルのいずれから来たのかを診断することが可能になります。ソースデータと派生データの間の出所関係はここで役立ちます: チャンクは正規化されたドキュメントの特定のバージョンから派生しています。
一方のページのボディを別のページのタイトルや出版日と静かに結合しないでください。フィールドが利用できない場合は、設定せずにおいておきます。ページ収集時間とソース公表時間は異なるメタデータフィールドです。
ステージ2: 文のセグメンテーションと一貫した埋め込みの生成
文のセグメンテーションは、セマンティックスプリッターが比較する順序付けられたテキストユニットを生成します。言語に適したセグメンターを使い、サンプル文書の略語、十進法、見出し、及び箇条書きの扱いを検査してください。
基本的な句読点分割がすべてのページで機能するとは主張しないでください。略語やコード例を含む段落は誤解を招く断片に分かれる可能性があります。短い参考ページの場合、見出しや段落の境界が、セマンティックな処理なしでも十分な構造を提供している可能性があります。
各文に対して1つの埋め込みを生成し、正確な順序を保持します。モデル識別子、正規化設定、及びソーステキストのハッシュをベクトルとともに記録します。欠落したベクトル、不整合のある次元、または有限でない値を拒否した後に類似性を計算します。
段落レベルのコンテキストウィンドウは、一部の文表現を改善できる可能性がありますが、実験が変わります。スプリットルールを比較する際は、その設定を固定しておき、埋め込み入力の変更が境界アルゴリズムに誤って帰属されないようにします。
Scrapelessでスクレイピングを始める
Scrapelessでウェブスクレイピングと自動化のワークフローを強化しましょう!
今日はサインアップして**$5の無料クレジット**をゲットしましょう — クレジットカードは不要です。今すぐScrapeless Dashboardで無料クレジットを請求してください。
ステージ3: 制約されたセマンティックチャンクの作成
以下のスプリッタは、隣接する文の類似度が設定されたしきい値を下回るか、文字数の予算を超える場合に新しいチャンクを開始します。chunk_sentences.pyとして保存します。
注: このスクリプトは、取得したテキストと埋め込みモデルから生成された実際の
sentences.jsonファイルを必要とします。埋め込み生成は前提条件として残ります; この例には作成されたベクトルセットは含まれず、測定された取得改善を主張することはありません。
python
import json
import math
import os
from pathlib import Path
source = json.loads(Path("sentences.json").read_text())
sentences = source["sentences"]
vectors = source["embeddings"]
threshold = float(os.environ["SIMILARITY_THRESHOLD"])
max_chars = int(os.environ["MAX_CHUNK_CHARS"])
if not -1 <= threshold <= 1 or max_chars <= 0:
raise ValueError("Invalid chunking configuration")
if not sentences or len(sentences) != len(vectors):
raise ValueError("Each sentence needs one embedding")
dimension = len(vectors[0])
if not dimension:
raise ValueError("Embeddings must not be empty")
for text, vector in zip(sentences, vectors):
if not isinstance(text, str) or not text.strip():
raise ValueError("Sentence text must be nonempty")
if len(text) > max_chars:
raise ValueError("Segment oversized sentences before chunking")
if len(vector) != dimension or not all(math.isfinite(v) for v in vector):
raise ValueError("Invalid embedding dimension or value")
if sum(v * v for v in vector) == 0:
raise ValueError("A zero vector has no cosine direction")
def cosine(a, b):
numerator = sum(x * y for x, y in zip(a, b))
denominator = math.sqrt(sum(x*x for x in a) * sum(y*y for y in b))
return max(-1.0, min(1.0, numerator / denominator))
chunks, start, current = [], 0, []
for index, sentence in enumerate(sentences):
topic_change = index > 0 and cosine(vectors[index-1], vectors[index]) < threshold
too_long = len(" ".join(current + [sentence])) > max_chars
if current and (topic_change or too_long):
chunks.append({"start_sentence": start, "end_sentence": index,
"text": " ".join(current)})
current, start = [], index
current.append(sentence)
chunks.append({"start_sentence": start, "end_sentence": len(sentences),
"text": " ".join(current)})
records = [dict(chunk, source_url=source["source_url"], chunk_index=index)
for index, chunk in enumerate(chunks)]
Path("chunks.json").write_text(json.dumps(records, ensure_ascii=False, indent=2))
print(json.dumps({"chunk_count": len(records)}))
文の間隔は、包括的な開始と排他的な終了を使用します。この慣例により、正確にどの入力文がチャンクを生成したのかを再構築することが可能になります。空の入力や無効なベクトルは、明示的に失敗し、見かけ上成功した空のインデックスを生成することはありません。
ここでのサイズ制限は文字をカウントします。トークン制限ではありません。あなたの埋め込みまたは生成システムにトークンの予算がある場合は、テキストを送信する前にそのシステムのトークナイザーでトークンを測定します。コードは、上流のセグメンターが慎重に処理できるように、過剰な長さの文を拒否します。
この実装は意図的にシンプルです: 隣接する文のベクトルを比較します。ドキュメントの遠く離れた部分にわたるクラスタリング、適応パーセンタイルしきい値、または訓練された境界分類器は実装していません。これらは、それぞれ独自の評価を必要とする別個のアプローチです。
ステージ4: ソースを失うことなくパッセージをインデックス化
インデックス作成は、取得したチャンクをそのソースドキュメントに再接続するのに十分なメタデータを保持する必要があります。チャンクテキスト、ソースURL、テキストハッシュ、チャンクインデックス、文の範囲、収集時間、および埋め込みモデル識別子を保存します。
最終チャンクテキストからチャンク埋め込みを作成する場合、それがリトリーバーが使用する表現である場合です。文埋め込みを平均化することは異なるデザインの選択であり、それが組み立てられたパッセージを埋め込むことと同じリトリーバルランキングを生み出すとは限りません。
ソースドキュメントが変更された場合、古いバージョンと新しいバージョンを区別できるようにします。基盤となるテキストを変更しながら同じチャンク識別子を再利用すると、保存された引用が曖昧になる可能性があります。正規化されたソースハッシュに基づくバージョンキーは、観察を分離するのに役立ちます。
ベクターストアは、一つの可能なインデックスに過ぎません。小規模な評価により、メモリ内のパッセージを取得できます。各質問に返されるテキストを確認できる最もシンプルな配置から始めましょう。
ステージ 5: リトリーバルを比較する、チャンクの外観だけではない
セマンティックチャンク化は、アプリケーションが回答する必要のある質問に対して評価されるべきです。視覚的に整然としたパッセージのセットは、リトリーバーが正しい証拠を返すことを証明するわけではありません。
元のドキュメントにマークされたサポートパッセージを持つ小さな質問セットを構築します。同じ正規化されたコンテンツに対して、固定サイズのベースライン、構造を考慮したベースライン、およびセマンティックスプリッターを実行します。埋め込みモデル、リトリーバル設定、および回答評価は一定に保ちます。
| 測定値 | 回答する質問 |
|---|---|
| サポートパッセージのリトリーバル | 必要な証拠が取得されましたか? |
| 無関係な取得テキスト | どれだけのコンテキストが無駄になりましたか? |
| 回答のサポート | 生成された回答は証拠に従っていますか? |
| 処理時間 | セグメンテーションと埋め込みにかかるコストは何ですか? |
| 入力ボリューム | 各モデルステップに到達したテキストはどれくらいですか? |
セマンティックチャンク化の計算トレードオフに関する研究は、この方法を経験的な選択として扱うことを支持しています。追加の作業は、すべてのタスクとデータセットで一貫した改善を生み出すわけではありません。
ステージごとに失敗を確認します。生のキャプチャにおける証拠の欠如は取得問題です。壊れた段落はクリーンアップの問題です。無関係なパッセージの下にランク付けされた関連パッセージは、埋め込みまたはリトリーバル設定の問題を示唆するかもしれません。これらの問題には異なる変更が必要です。
Scrapeless pricingを通じて取得コンポーネントを別に追跡します。埋め込みおよびインデクシングコストはダウンストリームスタックに属し、Web Unlockerの使用として報告すべきではありません。
結論: より良い証拠を取得するスプリッターを選ぶ
セマンティックチャンク化は、文書内で意味が変化する場合に便利で、単純な境界では捕捉できない方法です。実用的なワークフローは、クリーンなソーステキストを保持し、一貫した埋め込みを生成し、パッセージ制限を施行し、より単純な代替案とリトリーバルを比較することです。
ソースメタデータは常にまつわりつけておきます。取得したパッセージは、アプリケーションがどこから来たのか、どのバージョンのドキュメントを表しているのかを示すことができると、はるかに有用になります。
ウェブデータパイプラインを構築する準備はできましたか?
DiscordおよびTelegramでウェブデータ収集に取り組む開発者に参加してください。
Scrapelessアカウントを作成し、ワークフローを承認されたデータソースに適応させてください。
FAQ
Q: セマンティックチャンク化は常に固定サイズのチャンク化よりも優れていますか?
いいえ。その利点はドキュメント、埋め込みモデル、リトリーバル設定、およびタスクに依存します。一つを選ぶ前に、共有評価セットで戦略を比較してください。
Q: Scrapelessはこのワークフローで埋め込みを生成しますか?
いいえ。Scrapelessは上流のウェブアクセスステップを提供します。選択した埋め込みモデルとインデックスが下流の表現とリトリーバルを担当します。
Q: テーブルやコードブロックはどのようにチャンク化すべきですか?
その構造を保持するか、専用の構造を考慮したスプリッターを経由させます。文境界だけでは、ヘッダーから値を切り離したり、コードコンテキストを壊すことがあります。
Q: 取得されたページに課題や異なるHTMLが含まれている場合はどうすればよいですか?
ソース契約に失敗するコンテンツを拒否し、取得またはパーサーステージを確認してください。セマンティック類似性は、誤ったソースドキュメントを修復することはできません。
Q: 収集には別のプロキシが必要ですか?
選択したWeb Unlockerリクエストのルーティングオプションを使用します。収集後に実行されるチャンク化アルゴリズムからプロキシ要件を推測しないでください。
Q: パイプラインはAIエージェントなしで実行できますか?
はい。アプリケーションはドキュメントを取得し、自治的なエージェントなしで埋め込みベースのチャンク化を実行できます。ただし、セマンティック比較には依然として埋め込みモデルが必要です。
Q: パラレルソース収集に適用すべき制限は何ですか?
制限されたコレクションから始めて、ホストごとに3人を超えないワーカー数を守り、より厳格なターゲットおよびアカウント制限を遵守してください。埋め込みバッチには、モデル固有の制限があります。
Q: すべての公開ページをRAGインデックスに追加できますか?
公開されているだけでは、すべてのコレクションや再利用の許可を確立するものではありません。インジェストする前に、ソースの条件、適用される権利、および意図されたデータ処理を確認してください。
Scrapelessでは、適用される法律、規制、およびWebサイトのプライバシーポリシーを厳密に遵守しながら、公開されているデータのみにアクセスします。 このブログのコンテンツは、デモンストレーションのみを目的としており、違法または侵害の活動は含まれません。 このブログまたはサードパーティのリンクからの情報の使用に対するすべての責任を保証せず、放棄します。 スクレイピング活動に従事する前に、法律顧問に相談し、ターゲットウェブサイトの利用規約を確認するか、必要な許可を取得してください。



