0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Gemini Notebookの参照更新をPythonで検知する

0
Posted at

実は、ノートブックに資料を足すほど、回答の根拠は追いにくくなる。Gemini Notebookのように、資料を集めた場でコードまで動かせるようになると、なおさらだ。URLだけを残して「この資料を見た」で済ませる運用は、長く動くほど危ない。

Googleは7月16日、NotebookLMをGemini Notebookへ改称し、ノートブックごとのクラウド実行環境を導入すると発表した。自分はこのニュースを見て、モデルより先に資料の版を固定したくなった。資料が更新されたのに前回と同じ根拠として扱うと、回答だけを再評価しても原因まで辿れないからだ。

そこで、ノートブックへ入れる前の資料をディレクトリに置き、ファイルのSHA-256をJSONへ記録する小さな検査を書いた。外部ライブラリは使わない。

Gemini Notebookへ渡す前に資料の版を記録する

source_manifest.py として保存する。snapshot は資料一式を記録し、diff は2つの記録を比べる。更新日時ではなく内容のハッシュを見るので、コピーや同期で時刻が変わっても判定がぶれない。

import argparse
import hashlib
import json
from pathlib import Path

def snapshot(root: Path) -> dict:
    files = {}
    for path in sorted(p for p in root.rglob("*") if p.is_file()):
        relative = path.relative_to(root).as_posix()
        files[relative] = {
            "bytes": path.stat().st_size,
            "sha256": hashlib.sha256(path.read_bytes()).hexdigest(),
        }
    return {"root": str(root.resolve()), "files": files}

def changes(before: dict, after: dict) -> dict:
    old_files = before["files"]
    new_files = after["files"]
    old_names, new_names = set(old_files), set(new_files)
    return {
        "added": sorted(new_names - old_names),
        "removed": sorted(old_names - new_names),
        "changed": sorted(
            name for name in old_names & new_names
            if old_files[name]["sha256"] != new_files[name]["sha256"]
        ),
    }

def main(argv=None) -> int:
    parser = argparse.ArgumentParser()
    commands = parser.add_subparsers(dest="command", required=True)
    take = commands.add_parser("snapshot")
    take.add_argument("root", type=Path)
    take.add_argument("output", type=Path)
    compare = commands.add_parser("diff")
    compare.add_argument("before", type=Path)
    compare.add_argument("after", type=Path)
    args = parser.parse_args(argv)

    if args.command == "snapshot":
        data = snapshot(args.root)
        args.output.parent.mkdir(parents=True, exist_ok=True)
        args.output.write_text(
            json.dumps(data, ensure_ascii=False, indent=2, sort_keys=True) + "\n",
            encoding="utf-8",
        )
        print(f"saved: {args.output} ({len(data['files'])} files)")
        return 0

    before = json.loads(args.before.read_text(encoding="utf-8"))
    after = json.loads(args.after.read_text(encoding="utf-8"))
    print(json.dumps(changes(before, after), ensure_ascii=False, indent=2))
    return 0

if __name__ == "__main__":
    raise SystemExit(main())

資料を取り込む直前と、回答を再実行する直前にスナップショットを取る。

python3 source_manifest.py snapshot sources manifests/before.json
# sources/ の資料を更新した後
python3 source_manifest.py snapshot sources manifests/after.json
python3 source_manifest.py diff manifests/before.json manifests/after.json

before.jsonafter.jsonsources/ の外に置く。資料と同じ場所へ置くと、次のスナップショットで記録ファイル自身まで資料として数える。こういう自己参照は、差分が毎回出る原因になる。コマンド側で親ディレクトリを作るようにしてあるので、最初に manifests/ を用意する必要はない。

さっき、2ファイルの資料で確認した。一方を書き換え、一方を消し、1ファイルを追加したときの出力はこれだった。

{
  "added": ["limits.md"],
  "removed": ["policy.txt"],
  "changed": ["price.md"]
}

changed だけでなく removed を出すのがポイントになる。前回の回答が消えた資料を引用しているなら、追加資料より先に見直す必要がある。ファイル名を変えただけでも removedadded に分かれるので、意図した移動かどうかもここで拾える。

ハッシュだけでは回答の正しさを保証しない

この検査が分かるのは、入力が前回と同じかどうかまでだ。PDFの表現が変わったが意味が同じか、逆に数値の一行だけが変わって回答に効くかは、人か別の評価処理が見る。ここを混ぜると、差分検出が急に曖昧になる。

URLをそのままノートブックへ渡す場合も、取得した本文やPDFを一度この sources/ に保存してから記録する。URLは場所であって、内容の識別子ではない。SaaSの料金表や社内規程のように静かに更新される資料ほど、この区別が効く。

もう一つだけ運用を決めておく。資料の取得時点で、取得元URLと取得日時を別のメタデータに残す。ハッシュだけでは、同じ本文をどこから取ったかは分からない。出所の追跡と内容の追跡は役割が違うので、JSONを一枚に詰め込まず分けた方が後で扱いやすかった。

差分が出た資料だけを、回答前のレビュー対象に寄せます。

以前書いた出典の更新台帳は、変更を誰が確認したか残すための運用の話だった。今回のスクリプトは、その台帳に載せるべき変更を機械的に絞る入口になる。

おわりに

Gemini Notebookのような実行環境が資料のそばに来ると、試作はかなり速くなる。その一方で、速くなった回答を後から説明するには、入力の版を残す必要がある。最初から全文を比較する仕組みまで作らなくていい。まずハッシュで変更箇所を出し、変わった資料だけを再確認する。この順番なら、ノートブックを増やしても根拠の確認場所は増えにくい。

参考: NotebookLM is now Gemini Notebook

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?