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?

PythonのhashでLLMキャッシュキーが別プロセスで変わる

0
Posted at

同じ文字列なら同じハッシュ値、と思っていた。自分は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を2つのプロセスでハッシュ化する流れ。シード1と2のhash()は不一致、UTF-8のバイト列から作るSHA-256は一致した。

実運用ではモデルの版や生成設定も入力に含める。JSON化のルールにも版を付けておけば、変更時に古いキャッシュを区別できる。ここで確認できたのはキーの一致までで、LLMの回答が毎回同じになる保証はない。

参考:Python公式のPYTHONHASHSEED

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?