Skip to content

필사 모드: 하네스 지문과 버전 관리 — 기록 없는 변경을 추적 가능하게

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

다시, 커밋 없는 6퍼센트포인트

이 시리즈의 출발점이 된 이전 글은 구성한 사례 하나로 시작했습니다. 성공률이 지난주보다 6퍼센트포인트 올랐는데 프롬프트 커밋도 모델 변경도 없고, 알고 보니 도구 설명 한 줄, 재시도 상한, 파일 읽기 줄 수 상한이 각기 다른 사람 손에 바뀌어 있었다는 이야기입니다. 다음 주에 성공률이 떨어지면 무엇을 되돌려야 할까요. 기록이 없으면 답할 수 없습니다.

이 글은 그 사건을 답 가능하게 만드는 최소 장치, 하네스 지문을 다룹니다. 미리 말해 두면, 지문이라는 장치는 Lilian Weng의 하네스 글이 제안한 것이 아니라, 그 글이 그어 준 경계를 운영에 옮기기 위해 이 블로그가 구성한 접근입니다.

하네스는 버전이 붙는 배포물입니다

지문의 전제는 관점 전환입니다. 하네스를 흩어진 설정 모음이 아니라 하나의 배포물로 봅니다. 배포물이면 버전이 있어야 하고, 버전이 있으면 두 시점의 차이를 물을 수 있습니다. Weng의 정의가 유용한 이유가 여기 있습니다. 모델의 사고와 행동, 컨텍스트, 산출물, 평가를 조율하는 층 전부라는 경계가 있어야, "이 변경이 하네스 변경인가"라는 질문에 일관되게 답할 수 있습니다. 도구 설명 한 줄을 다듬는 것도, 재시도 상한을 올리는 것도 경계 안이므로 버전을 움직이는 변경입니다.

지문 만들기: 정규화가 절반입니다

지문 자체는 짧습니다. 하네스를 구성하는 결정들을 직렬화해 해시를 뜨면 됩니다. 어려운 절반은 정규화입니다. 의미가 같은 하네스는 같은 지문을 가져야 하는데, 순진하게 직렬화하면 도구 등록 순서만 바뀌어도 지문이 달라집니다. 그래서 도구 목록은 이름으로 정렬하고, JSON 키는 정렬된 순서로 고정하고, 의미에 영향을 주지 않는 공백이나 필드 순서는 직렬화 전에 통일합니다. 반대로 실행마다 달라지는 값, 타임스탬프나 실행 ID 같은 것은 지문에 넣으면 안 됩니다. 넣는 순간 모든 실행이 서로 다른 하네스가 되어 버립니다.

무엇이 들어가고, 무엇이 빠지나

들어가는 것은 에이전트의 행동을 바꾸는 모든 결정입니다. 모델 식별자, 시스템 프롬프트, 도구 스키마 전체, 재시도 상한과 정지 조건, 컨텍스트 정책, 권한 범위, 그리고 평가자의 버전까지. 평가자를 넣는 이유는 5편과 6편에서 본 그대로입니다. 채점 기준이 바뀌면 같은 하네스도 다른 점수를 받으므로, 채점 기준의 변경도 추적 대상입니다.

빠지는 것은 두 부류입니다. 하나는 실행 속성입니다. 과제 입력, 실행 시각, 난수 시드는 실행의 메타데이터이지 하네스가 아닙니다. 다른 하나가 더 중요합니다. 로깅과 관측 설정은 지문에서 뺍니다. 당신이 무엇을 볼 수 있는지는 에이전트가 무엇을 하는지를 바꾸지 않기 때문입니다. 관측 설정을 지문에 넣으면, 행동이 같은 결과들이 비교 불가능한 조각으로 쪼개집니다. 이 원칙은 이 블로그의 하네스 RPG에도 그대로 구현되어 있습니다. 관측 장비는 진행에 따라 열리지만 지문은 움직이지 않습니다.

결과에 지문이 붙어야 비교가 성립합니다

지문의 용도는 평가 결과에 도장을 찍는 것입니다.

{
  "run_id": "2026-08-12T03:14:07Z-a41",
  "harness_fingerprint": "3f9c1d2ab714",
  "suite": "issues-50",
  "success_rate": 0.62,
  "counter_metrics": { "deleted_tests": 0, "avg_tool_calls": 11.4 }
}

이 한 줄이 생기면 규칙 두 개가 따라옵니다. 첫째, 비교는 같은 지문끼리만 성립합니다. 지문이 다른 두 성공률을 나란히 놓는 것은 비교가 아니라 실험이고, 실험이면 무엇이 달랐는지 diff를 말할 수 있어야 합니다. 둘째, 지문을 움직이는 모든 변경은 평가를 다시 돌려야 하는 변경입니다. 도구 설명 한 줄의 수정이 프롬프트 개편과 같은 급으로 취급되기 시작하고, 그것이 정확히 의도된 효과입니다.

롤백과 회귀 이등분

성공률 그래프에 계단이 생기면, 지문 이력이 용의자 목록을 만들어 줍니다.

def regression_boundary(runs):
    """성공률이 꺾인 지점의 지문 경계를 찾는다 (구성한 예시)."""
    runs = sorted(runs, key=lambda r: r["ts"])
    for prev, cur in zip(runs, runs[1:]):
        if cur["success_rate"] < prev["success_rate"] - 0.03:  # 잡음 여유
            return prev["harness_fingerprint"], cur["harness_fingerprint"]
    return None

# 경계의 두 지문에 해당하는 스펙의 diff가 곧 용의자 목록이다.
# 용의자가 여럿이면 절반씩 되돌리며 이등분 탐색을 한다.

두 지문 사이의 스펙 diff가 후보 변경들입니다. 후보가 하나면 그것을 되돌려 재평가하고, 여럿이면 git bisect와 같은 요령으로 절반씩 좁힙니다. 롤백도 같은 이력 위에서 정의됩니다. 이전 지문의 스펙을 다시 배포하고, 배포된 것의 지문이 목표 지문과 일치하는지 확인하면 롤백이 완료된 것입니다. 지문이 없던 시절의 "아마 이 설정이었을 것"이 "해시가 일치한다"로 바뀝니다.

직접 연습하기

하네스 엔지니어링 RPG의 1티어 "관측과 지문"의 첫 시나리오가 정확히 이 글의 서두 사건입니다. 지난주의 6퍼센트포인트를 재현하기 위해 하네스를 조립하다 보면, 지문이 어떤 변경에 반응하고 어떤 변경에 반응하지 않는지 몸으로 익히게 됩니다.

참고 자료

현재 단락 (1/30)

이 시리즈의 출발점이 된 [이전 글](/blog/llm/2026-08-09-harness-engineering-self-improvement)은 구성한 사례 하나로 시작했습니다. ...

작성 글자: 0원문 글자: 2,761작성 단락: 0/30