同じ文字列なら同じハッシュ値、と思っていた。自分はLLMのキャッシュキーを確かめていて、別プロセスに同じJSONを渡したらhash()の一致判定がFalseになった。永続キャッシュの空振り。
ディスクやRedisに残すキーには、入力を決まった形式でJSON化し、SHA-256を使いたい。
hash()はどうして変わる?
標準設定では文字列のハッシュにランダムなシードが入る。同じプロセス内では固定だが、起動をまたぐ一致は保証されない。同梱のpython3 --help-envでも、PYTHONHASHSEEDの説明を確認した。プロセスごとのシード。
シードを1と2に固定し、差を再現する。外部APIは呼ばず、キーだけ比較した。
SHA-256へ替えるだけでいい?
その前にJSONのキー順と空白を揃える。CPython同梱のjson/encoder.pyでは、sort_keys=Trueで辞書の項目をソートしていた。以下はCPython 3.14.8で実行済み。cache_key.pyに保存し、python3 cache_key.pyで動く。
import json, os, subprocess, sys
q = {"model": "demo-v1", "prompt": "要約して"}
s = json.dumps(q, sort_keys=True, ensure_ascii=False,
separators=(",", ":"), allow_nan=False)
code = "import sys,hashlib; s=sys.argv[1]; print(hash(s)); print(hashlib.sha256(s.encode()).hexdigest())"
out = []
for seed in ("1", "2"):
out.append(subprocess.check_output(
[sys.executable, "-c", code, s], text=True,
env=dict(os.environ, PYTHONHASHSEED=seed)).splitlines())
print("hash一致:", out[0][0] == out[1][0])
print("SHA-256一致:", out[0][1] == out[1][1])
hash一致: False
SHA-256一致: True
キーの挿入順を逆にした辞書でも、上のJSON化で同じ文字列になった。JSONの空白までキーに入るの、地味に面倒なんだよね。
実運用ではモデルの版や生成設定も入力に含める。JSON化のルールにも版を付けておけば、変更時に古いキャッシュを区別できる。ここで確認できたのはキーの一致までで、LLMの回答が毎回同じになる保証はない。
