← /geode/portfolioGEODE . 문서
GitHub
설정
레퍼런스

프롬프트 해싱

의도치 않은 prompt drift 발생 시 CI를 중단시키는 SHA-256 해시 잠금장치 (Karpathy P4). 핵심 템플릿이 핀으로 고정되고, 재핀(re-pin) 절차가 문서화되어 있습니다.

두 개의 함수

# core/llm/prompts/__init__.py
def _hash_prompt(text: str) -> str:
    return hashlib.sha256(text.encode()).hexdigest()[:12]

# core/llm/prompts/axes.py
def _hash_axes(data) -> str:
    return hashlib.sha256(
        json.dumps(data, sort_keys=True).encode()
    ).hexdigest()[:12]

12자리 hex = 48비트. 닫힌 prompt 집합에서 충돌 확률은 무시할 수 있습니다. 목표는 탐지이지 암호학적 보안이 아닙니다.

axes 해시는 YAML 파서 버전과 Python dict 순서에 걸쳐 JSON 직렬화가 결정적이도록 sort_keys=True를 사용합니다.

고정 엔트리

PROMPT_VERSIONS / _PINNED_HASHES (sorted)

  AGENTIC_SUFFIX             5630f3a61683
  ANALYST_SPECIFIC           44136fa355b3
  ANALYST_SYSTEM             b800a57a4599
  ANALYST_TOOLS_SUFFIX       36055d5618f4
  ANALYST_USER               63711de6c099
  COMMENTARY_SYSTEM          488d8916d958
  COMMENTARY_USER            2024ac4eba69
  CROSS_LLM_DUAL_VERIFY      602669128ae2
  CROSS_LLM_RESCORE          163b08e97d66
  CROSS_LLM_SYSTEM           bf303f600fce
  EVALUATOR_AXES             44136fa355b3
  EVALUATOR_SYSTEM           93ecabb14a72
  EVALUATOR_USER             ad832adfadf0
  PROSPECT_EVALUATOR_AXES    44136fa355b3
  ROUTER_SYSTEM              c4220baeb6c0
  SYNTHESIZER_SYSTEM         1cbe199613a1
  SYNTHESIZER_TOOLS_SUFFIX   1fd89d3ece5a
  SYNTHESIZER_USER           e0bb4afab940

두 dict 모두 동일한 key set을 가집니다.

verify_prompt_integrity

def verify_prompt_integrity(*, raise_on_drift: bool = False) -> list[str]:
    drifted = []
    for name, pinned in _PINNED_HASHES.items():
        if computed[name] != pinned:
            drifted.append(f"Prompt drift: {name} pin={pinned} now={computed[name]}")
    if drifted and raise_on_drift:
        raise RuntimeError(...)
    return drifted

이 함수는 tests/test_karpathy_prompt_hardening.py::TestPromptDriftDetection에서 raise_on_drift=False (리스트 반환, 비어 있어야 함) 와 raise_on_drift=True (예외가 발생하지 않아야 함) 양쪽 모드로 호출됩니다.

재핀(re-pin) 절차

의도적으로 prompt를 변경했을 때.

  1. .md 파일을 편집합니다 (예. analyst.md).
  2. 새 해시를 계산합니다.
    uv run python -c "
    from core.llm.prompts import PROMPT_VERSIONS as V
    import json
    print(json.dumps(dict(sorted(V.items())), indent=2))
    "
  3. _PINNED_HASHES의 해당 엔트리를 업데이트합니다.
  4. uv run pytest tests/test_karpathy_prompt_hardening.py를 실행합니다.
  5. prompt 변경과 핀 업데이트를 한 커밋으로 함께 묶어 커밋합니다.

prompt 변경과 핀 업데이트를 두 커밋으로 나누면 git history에 CI 실패 상태의 커밋이 남게 됩니다. bisect 친화적인 커밋이라면 핀과 prompt가 같은 보폭으로 움직입니다.

왜 잠금장치인가

해시 잠금장치는 Karpathy의 P4 원칙을 GEODE 식으로 표현한 것입니다. 한 번 통과한 품질 게이트는 조용히 후퇴해서는 안 된다는 원칙. prompt 변경은 우연히도 쉽게 일어납니다. 병합 충돌 해결, 자동 포매터, IDE rename 등. 그리고 그 변경이 모델 동작에 미치는 영향을 미리 예측하기는 어렵습니다. 잠금장치는 모든 prompt 변경을 의식적인 단계를 거치도록 강제합니다.

잠금장치가 다루지 않는 것

  • .geode/skills/skill 본문 PROMPT_ASSEMBLED 훅 페이로드로 관찰되지만 핀으로 고정되지는 않습니다. prompt 주입된 skill 변경은 CI 실패가 아닙니다.
  • 렌더링된 prompt (.format() 변수 치환 이후) 는 해싱되지 않습니다. hash_rendered_prompt()는 존재하지만 호출자가 없습니다. geode-prompt-evolution P2 #3 참조.
  • 디스크 무결성은 런타임에 재검증되지 않습니다. 해싱은 패키지 import 시점에만 일어납니다.