2026年10月7日時点で、ShifterはOxylabsやBright Dataを上回る、最大規模の米国ライブIPプールを保有しており、しかもコストはその一部で済みます。Shifterは現在、稼働中の米国IPの中で最大のプールを保有しています

ベンチマークを見る

AIトレーニングパイプラインにおけるプロベナンス:データセットの出所を証明する

AIトレーニングデータのプロベナンスが実務で意味すること:すべてのドキュメントについて保持すべき記録、EU AI Actのサマリーが求める内容、そしてそれを一貫して引き継ぐ方法。

データサイエンス · 2026年10月24日に更新 · 4分で読めます
取得抽出重複排除トレーニングsha256 · url · fetched_at除外済み: 2
各トレーニングコピーは取得元にリンクしています。アンバーの記録は除外され、ログに記録され続けています。
ナレッジ
このページについて
  1. provenanceが要件となった理由
  2. すべての文書について記録すべきこと
  3. コードで見るprovenanceレコード
  4. パイプライン全体を通じてprovenanceを引き継ぐ
  5. 参考にすべき標準
  6. provenanceが破綻しやすい箇所
  7. 結論
  8. 出典および参考資料

AIチームにあるトレーニング文書の出所を尋ねると、返ってくるのはデータセット名であって情報源ではないことが多い。規制当局、顧客、裁判所が今求めているのは次の答えだ。どのページを、いつ取得し、どの条件のもとで、トレーニング前にどんな処理を施したのか。ウェブデータからモデルを構築するチームにとって、provenance(来歴)はもはや望ましい慣行ではなく、示せなければならないものになった。

難しいのはタイミングだ。provenanceの記録に必要な情報のほとんどは、収集した瞬間にしか存在しない。本ガイドでは、この問題がなぜ急務になったのか、すべての文書について保持すべき記録とは何か、そして抽出・フィルタリング・重複排除を経てもその記録をどう引き継ぐかを扱う。

provenanceが要件となった理由

3つの動きが、provenanceを研究課題からコンプライアンス業務へと変えた。

EU AI Actが公開要約を求めている。 第53条1項(d)は、汎用AIモデルの提供者に対し、AI Officeが用意するテンプレートを用いて「トレーニングに使用されたコンテンツに関する十分に詳細な要約」を公開することを義務付けている。この義務は2025年8月2日から適用され、それ以前に既に市場に出ているモデルについては2027年8月2日までの猶予がある。欧州委員会は2025年7月にこのテンプレートを提示し、その使用は義務であると明言している。

テンプレートは具体性を求めている。 スクレイピングしたデータについては、使用したクローラーの名称、収集期間、そして最も関連性の高いドメイン名のリスト、すなわちスクレイピングされたコンテンツ量の上位10%にあたるドメイン(中小企業の場合は上位5%または1,000ドメインのいずれか低い方)を求めている。また、テキスト・データマイニングのオプトアウトを「データ収集の前および収集中に」どう尊重したかを説明するよう求めている。第53条1項(c)は別途、こうした留保を特定し遵守する著作権ポリシーを義務付けている。

コモンズは縮小しており、記録の質は低かった。 Data Provenance Initiativeは2023年に1,800以上のテキストデータセットを監査し、広く使われているホスティングサイトでライセンス表記の欠落率が70%超、誤り率が50%超であることを発見した。これに続く14,000のウェブドメインを対象とした監査では、わずか1年のうちにC4の全トークンの約5%、そして最も活発に維持されている情報源の28%が、robots.txtによって完全に制限されるようになっていたことが判明した。クロールした時点では許容されていたデータセットが、今日クロールするには許容されないかもしれない。そしてその違いを示せるのは、当時の状態を記録していた場合に限られる。

すべての文書について記録すべきこと

provenanceの記録は、取得時にクローラーによって一度だけ書かれる。その後の工程はすべて、それを置き換えるのではなく、そこに追記していく。

フィールド重要な理由
ソースURLドメインリストと削除要請の基礎となる
取得日時(UTC)収集期間とその日時点でのオプトアウト状態を証明する
レスポンスステータス実際のコンテンツをブロックページやエラーと区別する
生の本文のハッシュ後のすべてのコピーを、実際に受信したものと紐付ける
観測地点同じURLでも国やネットワークによって異なるコンテンツを返す場合がある
robots.txtの判定取得時点で有効だった規則をクローラーが遵守したことを示す
確認されたTDM留保EUの著作権規則とテンプレートが注目するオプトアウト
明示されたライセンスまたは利用規約ページに再利用について何が書かれていたか
クローラー名とバージョンテンプレートはクローラー名を求める。バージョンは挙動の変化を説明する
親レコード整形または重複排除後のコピーを元のソースに結び付ける

見落とされがちなフィールドが2つある。1つ目は観測地点だ。あるページを1つの国やネットワークから観測した場合と、別の場所から同じURLを見た場合とでは内容が異なることがある。これはウェブデータの観測地点を記録するという記事の論点でもある。2つ目は生の本文そのものだ。ハッシュはどのバイト列を受信したかを証明するが、レスポンスそのものを保持すること、例えばWARCファイルでページをアーカイブすることで、それを実際に示すことができる。

コードで見るprovenanceレコード

以下の例は、取得した文書ごとに1件のレコードを書き込み、取得時点で許可されかつ留保されていなかった文書のみを保持し、抽出された各コピーをハッシュによって元のソースに結び付ける。また、要約テンプレートが求めるドメインのランキングも生成する。Python 3.9以降で、標準ライブラリのみで動作する。

from __future__ import annotations

import hashlib
import json
from collections import Counter
from dataclasses import asdict, dataclass, field
from datetime import datetime, timezone
from urllib.parse import urlsplit


def sha256(data: bytes) -> str:
    return hashlib.sha256(data).hexdigest()


@dataclass
class Provenance:
    """One record per fetched document, written at collection time."""
    url: str
    fetched_at: str            # ISO 8601, UTC
    status: int
    content_sha256: str        # hash of the raw response body
    vantage: str               # where it was observed from, e.g. "residential:de"
    robots_allowed: bool       # robots.txt decision for our crawler, at fetch time
    tdm_reserved: bool         # machine-readable TDM opt-out seen, at fetch time
    license: str | None        # licence or terms as stated on the page, if any
    collector: str             # crawler name and version
    parents: list[str] = field(default_factory=list)  # hashes this record derives from
    step: str = "fetch"        # fetch, extract, filter, dedup ...


def fetched(url, body, status, vantage, robots_allowed, tdm_reserved, license=None,
            collector="corpus-crawler/1.4"):
    return Provenance(
        url=url,
        fetched_at=datetime.now(timezone.utc).isoformat(timespec="seconds"),
        status=status,
        content_sha256=sha256(body),
        vantage=vantage,
        robots_allowed=robots_allowed,
        tdm_reserved=tdm_reserved,
        license=license,
        collector=collector,
    )


def derived(parent: Provenance, new_body: bytes, step: str) -> Provenance:
    """A transformed copy keeps the source fields and points back at its parent."""
    rec = Provenance(**{**asdict(parent), "parents": [parent.content_sha256], "step": step})
    rec.content_sha256 = sha256(new_body)
    return rec


def eligible(rec: Provenance) -> bool:
    """Only documents that were allowed and not reserved at fetch time go further."""
    return rec.status == 200 and rec.robots_allowed and not rec.tdm_reserved


def domain_summary(records, top_share=0.1):
    """Domains by document count, and the top share of them, for a training-data summary."""
    counts = Counter(urlsplit(r.url).hostname for r in records)
    ranked = [d for d, _ in counts.most_common()]
    keep = max(1, round(len(ranked) * top_share))
    return counts, ranked[:keep]


if __name__ == "__main__":
    raw = [
        fetched("https://news.example/a", b"<html>a</html>", 200, "residential:de", True, False),
        fetched("https://news.example/b", b"<html>b</html>", 200, "residential:de", True, False),
        fetched("https://shop.example/p/1", b"<html>p1</html>", 200, "residential:fr", True, True),
        fetched("https://blog.example/x", b"<html>x</html>", 403, "residential:us", True, False),
        fetched("https://forum.example/t/9", b"<html>t9</html>", 200, "residential:us", False, False),
    ]
    kept = [r for r in raw if eligible(r)]
    texts = [derived(r, r.url.encode() + b" text", "extract") for r in kept]

    with open("manifest.jsonl", "w") as f:
        for rec in raw + texts:
            f.write(json.dumps(asdict(rec)) + "\n")

    counts, top = domain_summary(raw)
    print(f"fetched {len(raw)}, eligible {len(kept)}, extracted {len(texts)}")
    print("domains:", dict(counts))
    print("top domains:", top)
    child = texts[0]
    print("lineage ok:", child.parents == [kept[0].content_sha256], child.step, child.url)

Output:

fetched 5, eligible 2, extracted 2
domains: {'news.example': 2, 'shop.example': 1, 'blog.example': 1, 'forum.example': 1}
top domains: ['news.example']
lineage ok: True extract https://news.example/a

留保されたページ、ブロックされたページ、robots.txtによって許可されなかったページも、すべてマニフェストに残っている。これが重要な点だ。使わなかったものの記録自体が、証拠の一部をなす。テンプレートはスクレイピングされたコンテンツ量でドメインを順位付けするため、本番環境では文書数ではなくバイト数やトークン数を数えること。

パイプライン全体を通じてprovenanceを引き継ぐ

取得時に書かれたレコードは、以降のすべての工程がその紐付けを保持して初めて役に立つ。

  • 抽出。 トレーニングに使うテキストは、取得したHTMLそのものではない。抽出されたテキストには独自のハッシュを与え、上記のderived()が行うように、生のレコードを指し示すようにする。
  • フィルタリング。 文書が除外された事実だけでなく、その理由もログに残す。「品質閾値未満」と「TDM留保」は、規制当局にとって異なる答えだ。
  • 重複排除。 ほぼ重複する文書を統合する際は、残ったコピーが代表するすべてのソースの一覧を保持する。そうしなければ、あるURLに対する削除要請が、それが最終的にどの文書に含まれたのかを見つけられなくなる。
  • 混合とサンプリング。 各トレーニング実行がどのマニフェストのバージョンを使用したかを記録し、要約がモデルが実際に見たデータを記述するようにする。
  • 削除。 URLとハッシュをキーとする削除リストを保持する。あるサイトが後日権利を留保した場合や、権利者から削除要請があった場合、同じキーを使ってすべての派生データセットからその文書を見つけられる。

オプトアウトの状態には特に注意が必要だ。robots.txtファイルやテキスト・データマイニングの留保は、クロール後にどちらの方向にも変化しうる。取得時点で下した判断を記録し、新たな収集を行う前には再確認すること。昨年の答えが今も有効だと仮定してはならない。

参考にすべき標準

スキーマをゼロから考案する必要はない。

  • Datasheets for Datasets(Gebru他、Communications of the ACM、2021年)は、すべてのデータセットがその動機、構成、収集プロセス、推奨される用途を文書化することを提案している。データセット単位の要約にふさわしい形式だ。
  • Data & Trusted AI AllianceによるData Provenance Standardsは、ソース、provenance、用途の3グループに分かれた22のメタデータフィールドを定義しており、データ生成の期間、方法、使用ライセンス、同意が文書化されている場所などを含む。バージョン1.0.0は2024年7月にリリースされた。
  • C2PA Content Credentialsは、署名付きのprovenanceマニフェストを個々のメディア資産に付加する。画像、音声、動画において、資産自体が記録を持ち運べる点で最も有用だ。

provenanceが破綻しやすい箇所

  • 後から追加される。 文書単位の記録を欠いたクロールは、データセットカードがどれほど優れていても、後から監査できない。
  • ライセンスがデータセットカードから単純にコピーされる。 前述の監査で、ここに誤りが集中していることが判明した。ソースが実際に何と述べていたかを記録し、集約されたラベルは確認すべき主張として扱うこと。
  • ブロックページがコンテンツとして数えられる。 ステータス200のレスポンスでも、チャレンジページであることがある。ステータスコードとコンテンツの確認は、記録に含めるべきものだ。
  • 観測地点が不明。 各市場をローカルのレジデンシャル接続から収集することは、記録に各取得がどの国とネットワークを使用したかが書かれている場合にのみ、provenanceの役に立つ。

結論

provenanceは収集時に書くのは安価だが、後から復元するのはほぼ不可能だ。取得時に文書ごとに1件のレコードを書き、すべての変換を通じてハッシュを引き継ぎ、採用したものだけでなく除外したものも保持する。そうすれば、AI Actが求める要約は、調査ではなく単なる問い合わせになる。

出典および参考資料

よくある質問

AIトレーニングデータにおけるデータプロベナンスとは何ですか。

それは、各トレーニングデータがどこから来て、どのような経緯をたどったかの記録です。ソースURLやデータセット、いつどこから収集されたか、その時点でのオプトアウトとライセンスの状態、そしてトレーニングミックスに組み込まれるまでに加えられたすべての変換処理が含まれます。

EU AI法はURLごとのプロベナンスを要求していますか。

いいえ。汎用AIモデルの提供者は、欧州委員会のテンプレートを用いてトレーニングコンテンツの要約を公開する必要があります。これには主要なデータセット、最も関連性の高いスクレイピング対象ドメイン、クローラー名、収集期間、オプトアウトがどのように尊重されたかが求められます。個々のURLを列挙することは任意ですが、文書単位の記録がなければ必要な要約を確実に作成することはできません。

データセット構築後にプロベナンスを再構築することはできますか。

部分的にしかできません。ソースURLは復元できる場合がありますが、オプトアウトの状態、実際に受信したレスポンス、取得時点の観測地点は、その瞬間が過ぎてしまえば失われます。だからこそ、プロベナンスは後から追加するのではなく、クローラーが記録しなければならないのです。

文書ごとに最低限必要なプロベナンス記録とは何ですか。

ソースURL、UTCでの取得時刻、レスポンスステータス、生データ本体のハッシュ値、観測された地点、取得時点におけるrobots.txtおよびテキスト・データマイニングのオプトアウト判定、記載されているライセンス、クローラー名とバージョン、そして派生元となった記録へのリンクです。

始める準備はできていますか?

Shifterのレジデンシャルプロキシをお試しください。IP 205M+件、195+カ国、$0.10/GBから。

始める