
나의 허술한 베이스라인이 게이트 클래스의 절반에서 내 설계안을 이겼다
요약
에이전트 체인의 출처(provenance) 압축 방식에 따른 게이트 결정의 정확도를 실험하기 위해 테스트 환경을 구축하고 비교 분석한 글입니다. 설계된 구조적 압축 방식과 LLM 기반 요약 방식(prose)을 비교하여 데이터 기반의 성능을 측정합니다.
핵심 포인트
- 출처 벡터 압축이 게이트 결정에 미치는 영향을 측정하기 위한 실험 환경 구축
- 구조적 압축(structural_min, structural_perhop)과 LLM 요약(prose) 방식 비교
- 단순한 LLM 요약 기반의 베이스라인이 특정 조건에서 설계안보다 우수한 성능을 보임
- 오라클(ground_truth)을 기준으로 압축 방식별 불일치 데이터를 정밀 측정
Part 4는 제가 답할 수 없는 질문으로 끝났습니다. 게이트 결정(gate decisions)이 재구성된 출처 벡터(reconstructed provenance vector)에서 원래의 벡터와 비교했을 때 실제로 어떤 영향을 미치는지 측정한 사람이 있을까요? 제1원리(first principles)에 근거한 논쟁이 아니라, 실제로 측정한 데이터 말입니다.
댓글에는 아무도 데이터가 없었습니다. 저 역시 마찬가지였습니다. 그래서 저는 테스트 환경(harness)인 provenance-compaction-lab을 구축했습니다.
네 개의 팔, 하나의 오라클 (one oracle)
네 개의 출처 추적(provenance-tracking) 팔이 동일한 합성 궤적(synthetic trajectory)을 관찰합니다. 동일한 시드(seed), 동일한 저하 이벤트(degradation events), 동일한 병합(merges)을 사용합니다. 이들은 결정(decisions) 사이에 출처(provenance)에 어떤 일이 일어나는지만 다릅니다.
- ground_truth — 전체 벡터, 전체 계보(lineage), 압축되지 않음. 다른 모든 것을 판단하는 기준이 되는 오라클(oracle)입니다.
- structural_min — Part 4의 설계안입니다. 축 점수(Axis scores)는 계속해서 최소값(running min)을 유지합니다. 매 C 단계마다 계보는 마지막 K 홉(hops)으로 잘립니다. 접힌 접두사(folded prefix)에 부착된 오염 ID(taint ids)는 삭제되며, 오직 개수(count)만 남습니다. 압축 페널티(compression penalty)는
reconstruction으로 곱해지며, 이는 다른 축과 마찬가지로 최소값(min)으로 접힙니다. - structural_perhop —
reconstruction이 최소값으로 접히지 않는다는 점을 제외하면 동일합니다. 이는 구조적으로(n_compactions, worst_penalty)형태로 유지되어 게이트(gates)에 데이터로 전달됩니다. - prose — 제안이 아닌, 정직하지만 순진한 베이스라인(baseline)입니다. 매 C 단계마다 LLM이 현재 상태(출처 포함)를 150단어 이하로 요약하며, 두 번째 호출을 통해 점수와 오염(taints)을 다시 추출합니다. 왕복 과정(round trip)에서 살아남은 것이 이 팔이 아는 전부입니다.
병합(Merge)은 Part 3 이후 변경되지 않았습니다 — 요소별 최소값(element-wise min) 방식입니다:
def merge(vectors: Iterable[ProvenanceVector]) -> ProvenanceVector:
"""Merge = 입력값들에 대한 요소별 최소값 (Part 3)."""
vs = list(vectors)
...
5단계마다 9개의 게이트 정책(gate policies) — 점수 임계값(score thresholds), 재구성 결합(reconstruction-coupled), 계보 블랙리스트(lineage blocklist), 계보 화이트리스트(lineage allowlist), 그리고 몇 가지 플래그가 지정된 되돌릴 수 없는(irreversible) 정책들 — 이 네 가지 암(arms) 모두에 대해 실행되며, 오라클(oracle)과의 모든 불일치는 로그에 기록됩니다. 매트릭스 설정: 500단계 지평선(horizons), 주기(cadences) C ∈ {10, 25, 50}, K=5, 화이트리스트 윈도우 W=8 (> K, 기아 현상(starvation)을 의도적으로 보여주기 위함), 압축(compaction)당 0.02의 재구성 페널티(reconstruction penalty), 3가지 성능 저하 프로필(degradation profiles), 셀당 20개의 시드(seeds). 네 가지 가설 모두 첫 번째 코드 라인을 작성하기 전에 명세(spec)에 기록되었습니다. 전체 모의 매트릭스(mock matrix)는 몇 초 안에 재실행되며, 시드별로 결정론적(deterministic)입니다.
한 가지 미리 제한 사항을 말씀드리자면: 궤적(trajectories)은 합성된(synthetic) 것입니다. 생성기(generator)는 여러분의 자체 트레이스(traces)로 교체해야 하는 구성 요소입니다 — 이에 대한 자세한 내용은 마지막에 설명하겠습니다.
하나의 잘못된 진행(false-proceed)의 해부
통계적인 수치를 보기 전에, 하나의 결정이 단계별로 어떻게 잘못되는지 살펴보겠습니다.
시드 0, C=25, 중간(med) 프로필. 25단계에서의 결정, 게이트 payment_no_untrusted_taint — 되돌릴 수 없으며(irreversible), unverified_web 및 tool_flaky 오염(taints)에 대해 차단합니다. 25단계에서 작동 중인 값의 전체 오염 계보(taint history)는 다음과 같으며, 이것이 오라클이 보는 내용입니다:
taint:unverified_web:2 ← unverified web fetch, 2단계
taint:tool_flaky:6 ← flaky tool call, 6단계
taint:tool_flaky:7 ← flaky tool call, 7단계
...
25단계에서 첫 번째 압축(compaction)이 실행됩니다. 이것은 의도적인 손실 단계(lossy step)이며, 리포지토리(repo)의 내용을 그대로 가져왔습니다:
def truncate_lineage(state: ValueState, keep_hops: int) -> None:
"""마지막 K hops까지 자릅니다; 접두사(prefix)를 집계된 카운트로 접고(fold)
``tainted_by``에서 접힌 taint id를 제거합니다 (카운트만 남습니다)."""
...
계보(lineage)는 마지막 K=5 hops까지 잘립니다. 접힌 접두사(folded prefix)에 부착된 모든 taint는 사라집니다. structural_min이 여전히 보고 있는 것은 다음과 같습니다:
taint:fallback_model:24
오라클(oracle)이 결제를 차단합니다 — 게이트와 관련된 네 개의 테인트(taint)가 존재합니다. structural_min은 게이트와 관련된 테인트를 0개로 인식하고 진행합니다. 살아남은 상태(surviving state) 중에는 검사가 건너뛰어졌음을 암시하는 것이 아무것도 없습니다. 폴드 카운터(n_taints_folded)가 유일한 흔적이지만, 기본 허용(default-allow) 게이트가 이를 살펴볼 이유는 없습니다.
다른 두 가지 계보 전략(lineage strategies) 하에서도 동일한 상태가 나타납니다. 이는 가설이 아닌 측정된 결과입니다. Degrade-to-untrusted는 n_taints_folded > 0을 확인하고 동작을 거부합니다. 여기서는 운 좋게 정답을 맞혔지만, 만약 폴드된 테인트들이 무해(benign)했다면 동일한 거부 동작이 잘못된 중단(false-stop)이 되었을 것입니다. Rehydrate는 추가 전용 로그(append-only log)에서 값의 병합된 조상으로부터 21개의 폴드된 홉(folded hops)을 가져오며 — 2.6 KB 읽기 — 오라클의 차단 사항을 정확히 복구합니다.
매트릭스 전반에 걸쳐 반복되는 이 단일 메커니즘이 첫 번째 헤드라인 수치를 만들어냅니다.
헤드라인 수치 (The headline numbers)
- **3.47%**의 되돌릴 수 없는 동작 결정(결제, 전송)이 압축되지 않은 오라클이 차단을 명령했을 때 진행되었습니다 —
structural_min, C=25, 중간 프로필(med profile). structural_min메모리는 압축 주기(compaction cycle) ≈ 35에서 소멸합니다: 해당 주기 이후부터 재구성(reconstruction)과 결합된 모든 게이트는 영구적으로 차단됩니다 (0.98³⁵ ≈ 0.493 < 0.5).structural_perhop은 결코 소멸하지 않습니다.- Prose 대 structural 반전 비율(flip ratio): 1.39배 — 모든 게이트를 통합했을 때, Prose는 결정의 9.97%에서 오라클과 불일치하며,
structural_min은 7.16%에서 불일치합니다. - Rehydration: 계보-게이트(lineage-gate) 결정 100회당 459회의 콜드 스토리지(cold-storage) 조회를 통해 반전율(flip rate)을 8.01%에서 0.00%로 낮춥니다.
세부 사항을 다루기 전에 한 가지 분류를 하자면, 이 목록은 두 종류의 수치를 혼합하고 있습니다. 소멸 주기(death cycle)는 실험실 가운을 입은 산술적 수치입니다 — 0.98³⁵ < 0.5를 계산하려면 하네스(harness)가 아니라 계산기가 필요합니다. 그리고 두 섹션 아래의 오류 극성(error polarity)은 게이트 정의를 명시하고 나면 그 정의로부터 도출됩니다. 반면, 다른 수치들의 경우 하네스가 사실(fact)이 아닌 비용(price tag)을 제공합니다. 수치 1, 3, 4는 측정값입니다: 설정상 3.47%가 12%가 되지 않아야 할 이유가 없으며, Prose가 두 게이트 클래스에서는 승리하면서도 전체적으로는 패배하거나, Rehydration 비용이 40회가 아닌 4.6회의 조회를 소모해야 할 이유도 없습니다.
Boyko의 말은 두 번 맞았다
파트 4에서 Nazar Boyko는 가설로 사전 등록할 만큼 날카로운 두 가지 주장을 했습니다.
첫 번째 주장: 축 점수(axis scores)는 양측(arms) 간에 밀접하게 추적될 것이며, _계보(lineage)_를 검사하는 게이트(gates)에서 결정이 갈릴 것이다. 확인되었습니다 — 다만 한 가지 설명이 필요합니다. 두 구조적 암(structural arms) 모두에서 점수 게이트(Score-gate)의 반전율(flip rate)은 0.00%이며, 이 수치는 발견된 것이 아니라 구조적으로(by construction) 결정된 것입니다. 압축(compaction)은 베이스 축(base axes)의 실행 중인 최솟값(running min)에 절대 영향을 주지 않으며, 하네스(harness)는 정확히 그 불변성(invariant)을 속성 테스트(property-tests)합니다 (오라클(oracle) 대비 베이스 축 드리프트(base-axis drift): 모든 결정 지점, 모든 설정에서 0.0000). 측정값이 추가로 보여주는 것은 점수가 배제되었을 때 발산(divergence)이 집중되는 지점입니다: 계보 게이트(lineage gates)는 8.01%의 결정을 무작위로 반전시키며, 재구성 결합 게이트(reconstruction-coupled gates)는 그보다 더 나쁜 결과를 보입니다.
두 번째 주장: 재귀(recursion)입니다. 만약 압축 페널티(compression penalty)가 실행 중인 최솟값(running min)에 포함된다면, 각 개별 홉(hop)이 얼마나 깨끗한지와 상관없이 reconstruction은 단조 감소(monotonically decays)하여 0을 향하게 됩니다. 데스 스파이럴(death-spiral) 실행 — 5,000 스텝, C=25, 200 압축 — 이 이를 확인해 줍니다: 내려가는 내내 단조적이며, 35 사이클에서 0.5 게이트 임계값(threshold)을 통과합니다. 그 시점부터 모든 재구성 결합 게이트(reconstruction-coupled gate)는 영구적으로 차단됩니다. 점수는 깨끗하고, 메모리는 기술적으로 살아있지만, 그 어떤 것도 그 메모리에 작용할 수 없습니다.
압축을 통합하는 대신 (n_compactions, worst_penalty)를 유지하는 structural_perhop는 동일한 게이트에서 **0.00%**의 반전율을 기록하며 결코 죽지 않습니다. 드리프트(Drift) 또한 다른 각도에서 같은 사실을 말해줍니다: structural_min의 유일하게 드리프트되는 축은 reconstruction이며, 오라클 대비 0.2100 MAE를 기록합니다; 반면 perhop는 이를 0.0191로 유지합니다.
오류의 방향은 설계의 선택이다
두 가지 계보 게이트 (lineage gate) 스타일은 의도적으로 하네스 (harness)에 포함되었으며, 기아 현상 (starvation)이 드러나도록 W > K를 의도적으로 선택했습니다.
블랙리스트 게이트 (Blocklist gates) — 기본 허용 (default-allow): "tainted_by에 taint:unverified_web:*가 하나라도 나타나면 차단한다." 이들은 위험한 방식으로 실패합니다: 8.50%의 허위 진행 (false-proceeds), 0.00%의 허위 차단 (false-stops). 압축 (fold) 과정에서 오염 (taints) 정보가 누락되면, 게이트는 반대할 대상을 찾지 못합니다.
화이트리스트 게이트 (Allowlist gates) — 기본 차단 (default-deny): "최근 8번의 홉 (hop) 내에 폴백 홉 (fallback hop)이 없음을 계보가 증명할 때만 진행한다." 이들은 비용이 많이 드는 방식으로 실패합니다: 7.53%의 허위 차단 (false-stops), 0.00%의 허위 진행 (false-proceeds). 증명 정보가 압축되어 사라지면, 게이트는 진행을 거부합니다.
완벽한 양극화 (polarization)이며, 두 경우 모두 동일한 압축 (compaction)이 발생합니다. 압축은 정보가 손실될 것임을 결정하고, 정보가 누락되었을 때 게이트의 기본 설정이 실패할 '방향'을 결정합니다. 따라서 액션 클래스 (action class)별로 극성을 선택하십시오: 되돌릴 수 없는 모든 것에 대해 기본 차단 (default-deny)을 적용하십시오. 과잉 차단 (over-blocking)으로 대가를 치르게 됩니다. 그 대안은 실제 현금으로 대가를 치르게 됩니다.
이 결과의 방향은 정의로부터 예측 가능했습니다. 바로 그 점 때문에 사전 등록 (preregistered) 단계에서 깔끔하게 통과되었습니다. 하지만 이러한 저하율 (degradation rates)에서의 규모 (magnitudes)는 예측할 수 없었습니다.
허수아비 공격 (Strawman)은 죽지 않는다
H4, 사전 등록된 바와 같이: 산문 반전율 (prose flip rates)이 모든 게이트 클래스에서 구조적 팔 (structural arms)을 압도한다. 판결: 실패 (FAIL). 게이트 클래스, 모의 채널 (mock channel), 블라인드 모드 (blind mode)별 결과:
| 게이트 클래스 (gate class) | 산문 (prose) | structural_min | structural_perhop |
|---|---|---|---|
| 점수 (score) | 2.44% | 0.00% | 0.00% |
| ... |
허수아비 모델 (strawman)이 4개 클래스 중 2개에서 Part 4 스킴 (scheme)을 이깁니다. 재구성 결합 게이트 (reconstruction-coupled gates)의 경우, 최소 압축 페널티 (min-folded penalty)가 노이즈 채널 (noisy channel)보다 더 큰 부패 (corruption)의 원인이 됩니다. 즉, 데스 스파이럴 (death spiral)은 산문 노이즈가 따라잡기 전에 structural_min을 먼저 처벌합니다. 블랙리스트 게이트의 경우, 결정론적 절단 (deterministic truncation)은 손실 압축 추출기 (lossy extractor)와 거의 유사한 비율로 오염 (taints) 정보를 망각합니다.
나의 첫 번째 직관은 모의 채널 (mock channel)이 산문 (prose)에 불리하게 조작되었다는 것이었습니다. 즉, 오염 (taint) 회상률 (recall)이 0.6으로
가정되어 있었습니다. 그래서 실제 채널인 gpt-5-mini를 사용하여 실제 요약→추출 (summarize→extract) 왕복 과정을 실행했습니다. 위에서 다룬 예제의 정확히 6개의 오염 (taint) 상태에 대해 모델이 생성한 데이터 덩어리 (blob)는 다음과 같습니다:
작업 기억 (Working memory) 상태: 신선도 (freshness) 0.700, 능력 (capability) 0.650, 도구 무결성 (tool_integrity) 0.650, 검증 (verification) 0.450, 재구성 (reconstruction) 1.000. 부착된 오염 (taints): taint:fallback_model:24, taint:stale_cache:16, taint:tool_flaky:6, taint:tool_flaky:7, taint:unverified_web:11, taint:unverified_web:2. 전반적으로, 이 기억은 재구성이 온전하며 중간 정도의 신선도와 능력을 갖추고 있으나, 도구 무결성이 저하되어 있고 검증 수준이 낮습니다. 이는 도구나 외부 콘텐츠에 의존한 출력물에 대한 신뢰도가 감소했음을 나타냅니다. 여러 오염 (taints) 정보는 폴백 모델 (fallback model)의 사용, 오래된 캐시 (stale cache) 데이터, 두 번의 불안정한 도구 (flaky tools) 사례, 그리고 두 개의 검증되지 않은 웹 소스를 나타내며, 이 상태를 사용하거나 재검증할 때 이를 고려해야 합니다.
추출 (Extraction) 결과, 5개의 점수 모두를 정확하게 복구하였고 6개의 오염 (taint) ID를 모두 찾아냈습니다. 993번의 추출 결과: 파싱 실패 (parse failures) 0건, 오염 회상률 (taint recall) 0.893, 정밀도 (precision) 0.904 (245개의 허위 오염 생성), 점수 평균 절대 오차 (score MAE) ≈ 0.0001입니다. 최신 소형 모델 (small model)은 산문 (prose)을 통해 명시적인 값들을 거의 손실 없이 복사합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기
