
내 AI 코딩 에이전트들은 실제로 학습하고 있을까? 이를 측정할 방법을 만들었습니다
요약
AI 코딩 에이전트가 리뷰 과정에서 동일한 유형의 오류를 반복하는지 측정하기 위한 방법론을 제안합니다. 에이전트의 실제 학습 여부를 확인하기 위해 결과물의 재발률을 지문화(fingerprinting)하여 분석하는 도구를 개발했습니다.
핵심 포인트
- AI 에이전트의 리뷰 결과 중 22%가 동일한 패턴으로 재발함을 확인
- 단순 처리량(throughput)이 아닌 실제 학습 및 개선 여부 측정의 중요성 강조
- 문구 변화에 대응하기 위해 결과물의 식별자(identity)를 정의하는 지문화 기술 활용
- 에이전트의 성능 개선을 검증하기 위한 정량적 측정 도구의 필요성
저는 약 40개의 리포지토리(repos)에 걸친 1년 치 리뷰 결과들을 지문화(fingerprinted)했습니다. 그 결과 22%가 재발했습니다. 저를 불안하게 만든 것은 그 수치가 아니었습니다. 그것이 개선되고 있는지 확인할 방법이 전혀 없다는 사실을 깨달은 것이었습니다.
저는 AI 코딩 에이전트 군단(fleet)을 운영하고 있습니다. 이들은 약 40개의 리포지토리에 걸쳐 풀 리퀘스트(pull requests)를 리뷰합니다: 정확성(correctness), 보안(security), 데이터 무결성(data integrity)을 검토합니다. 매일 이들은 결과물(findings)을 만들어냅니다. 매일 누군가가, 때로는 다른 에이전트가 그 결과물들을 수정합니다. 대시보드는 계속 초록색을 유지합니다. 처리량(throughput)은 실재합니다. 마치 시스템이 점점 좋아지고 있는 것처럼 느껴집니다.
어느 날 저녁, 저는 분명 전에 본 적이 있다고 확신하는 경고를 발견했습니다. 같은 버그는 아니었습니다. 하지만 같은 종류의 버그가, 같은 파일에서, 같은 방식으로 표시되었습니다. 찾아보니 처음이 아니었습니다. 동일한 형태가 여러 달에 걸쳐 반복해서 나타났습니다.
그것은 작은 일입니다. 하지만 제가 조심스럽게 묻지 않았던 질문을 수면 위로 끌어올렸습니다: 내 에이전트들이 실제로 학습하여, 이번 달의 리뷰를 지난달보다 더 낫게 만드는 무언가를 축적하고 있는가? 아니면 나는 매일, 진전처럼 보이기만 하는 루프 속에서 똑같은 문제들을 재발견하기 위해 비용을 지불하고 있는 것인가?
저는 전자를 가정해 왔습니다. 하지만 그에 대한 증거는 없었습니다. 가정은 측정이 아니며, 그 둘 사이의 간극이 바로 스스로를 속이게 되는 지점입니다. 그래서 저는 가정을 멈추고 이를 알아내기 위한 무언가를 만들었습니다.
측정 도구 (The instrument)
"내 에이전트들이 학습하고 있는가?"라는 질문은 측정하기에 너무 모호합니다. 저는 더 좁고 기계적인 질문이 필요했습니다: 동일한 클래스의 결과물(finding)이 계속해서 다시 나타나는가? 만약 에이전트 군단이 학습하고 있다면, 재발하는 결과물은 시간이 지남에 따라 더 드물어져야 합니다. 만약 그렇지 않다면, 그것들은 계속해서 나타날 것입니다.
"동일한 클래스"를 세기 위해서는, 문구(rewording)가 바뀌어도 유지되는 발견 사항(finding)의 식별자(identity)가 필요했습니다. 리뷰어는 10개월 동안 하나의 문제를 10가지 다른 방식으로 표현할 수 있으며, 설명(description)을 문자열 매칭(string-matching)하는 것은 가망이 없습니다. 그래서 저는 모든 발견 사항을 거친 지문(coarse fingerprint)으로 축소했습니다. 즉, 산문(prose)이 변하더라도 안정적으로 유지되는 부분들로 말입니다.
from collections import defaultdict
def fingerprint(finding):
...
이 방식은 의도적으로 투박합니다. (repo, file, severity) 조합은 우연히 파일과 심각도(severity)를 공유하는 서로 다른 문제들을 하나로 합쳐버리고, 파일 이름이 변경되면 실제로 반복되는 문제조차 분리해 버립니다. 이러한 투박함이 어떤 대가를 치르게 하는지는 나중에 다시 다루겠습니다. 하지만 이 방식에는 정밀도(precision)보다 제가 더 중요하게 생각했던 한 가지 속성이 있습니다. 바로 리뷰어의 표현 방식에 의존하지 않기 때문에, 1년 동안의 변화(drift) 속에서도 동일한 것을 측정할 수 있다는 점입니다.
저는 제가 가진 모든 리뷰 산출물(artifact)에 이 방식을 적용했습니다. 발견 사항당 하나의 구조화된 기록(structured record)을 만들고, 각각이 어떤 리뷰에서 왔는지 태그를 달았습니다. 따라서 지문(fingerprint)의 집계는 해당 지문이 나타난 서로 다른 리뷰의 횟수가 됩니다. 코퍼스(corpus)는 365일의 기간 동안 약 40개의 리포지토리(repository)에 걸쳐 있는 572개의 리뷰와 842개의 발견 사항으로 구성되었습니다. 만약 학습이 일어나고 있다면 수치로 나타날 수 있을 만큼 충분한 이력입니다.
도구 전체는 약 30줄 정도입니다. 이것을 여기에 공개하는 이유가 바로 이것입니다. 이것은 연구용 장치(research apparatus)가 아닙니다. 지문을 키(key)로 하고 "동일함"에 대한 정의를 담은 사전(dictionary)입니다. 만약 구조화된 데이터를 기록하는 에이전트(agent)를 운영하고 있다면, 오늘 오후에 바로 여러분만의 버전을 계산해낼 수 있습니다. 어려운 점은 결코 코드가 아니었습니다. 어려운 점은 그것이 반환한 결과를 기꺼이 마주하는 것이었습니다.
첫 번째 읽기
결과는 다음과 같았습니다: 모든 발견 사항의 22%가 재발(recurrence)이었습니다. 842개의 발견 사항 중 186개가 최소 하나 이상의 다른 발견 사항과 지문을 공유했습니다. 이 186개는 68개의 고유한 지문으로 압축되었습니다. 즉, 제 에이전트들이 두 번 이상 표시한 68개의 구체적인 (repo, file, severity) 클래스입니다. 가장 지속적인 단일 지문은 7번 나타났습니다. 동일한 고심각도(high-severity) 클래스가 동일한 파일에서 1년 동안 7번 별도로 나타난 것입니다.
그림 1. 분포의 상단에서 선택된 반복되는 지문(recurring fingerprints): 동일한 익명화된 (저장소(repo), 파일, 심각도(severity)) 지문이 하나 이상의 리뷰에서 나타남. 68개의 클래스가 반복됨; 186/842개의 발견 사항 = 반복되는 클래스 내 22%; 반복 전용 비율(repeat-only rate) 118/842 = 14%.
저의 첫 번째 본능은 여러분이 예상할 법한 문장을 쓰는 것이었습니다: 데이터는 내 에이전트들이 학습하지 않는다는 것을 보여준다. 저는 그 문장을 지웠습니다. 그것은 데이터가 보여주는 바가 아니며, 그 차이는 이 글에서 그 무엇보다 중요합니다.
제가 가진 것은 기준점(baseline)입니다: 새로 제작된 측정 도구로부터 얻은 첫 번째 판독값, 그리고 그 이후의 단 한 번의 반복 확인입니다. 제가 가진 수치는 22%이며, 두 번의 판독 모두 동일했습니다. 하지만 수치(level)는 추세(trend)가 아닙니다. 내 에이전트들이 학습하지 않는다고 주장하려면, 많은 지점에서 추적된 비율과 하락하지 않는 선(line)이 필요합니다. 두 개의 지점으로는 추세를 나타낼 수 없습니다. 두 번의 관찰로 추세를 주장하는 것은 제가 다른 사람의 분석에서 거부할 바로 그 과잉 해석입니다. 결론이 제가 절반 정도 예상했던 것과 같다는 사실은, 그 결론을 덜 위험하게 만드는 것이 아니라 오히려 더 위험하게 만듭니다.
따라서 저는 주장의 범위를 정확하게 제한하겠습니다. 22%가 입증하는 것: 내 에이전트 군단(fleet)이 발견한 사항 중 의미 있는 비율이 반복되는 동일한 클래스이며, 제가 측정한 유일한 기간 동안 그 비율이 눈에 띄게 줄어들지 않았다는 것입니다. 22%가 입증하지 않는 것: 에이전트들이 학습할 능력이 없다거나, 내가 다음에 무엇을 하든 이 수치를 변화시킬 수 없다는 것입니다. 이것은 기준점(baseline)입니다. 이 수치의 모든 가치는 그것이 기준점이라는 데 있습니다. 즉, 내가 계속 믿고 싶어 하는 '느낌' 대신, 내가 변화를 지켜볼 수 있는 '실제 숫자'라는 점입니다.
수치 자체에 대해 두 가지 더 솔직하게 말씀드리겠습니다. 회의적인 독자라면 이 섹션을 가장 강력하게 파고들어야 하기 때문입니다. 첫째, "22%"가 무엇을 의미하는가 하는 점입니다. 이는 한 번 이상 나타난 클래스(class)에 속하는 발견 사항의 비율을 의미합니다. 842개 중 186개가 재발한 68개의 지문(fingerprints) 중 하나에 해당합니다. 만약 클래스의 첫 번째 출현 이후의 모든 출현만을 의미하는 '반복(repeats)'만을 계산하고 싶다면, 그 수치는 118개, 즉 14%가 됩니다. 제가 22%를 앞세운 이유는 그것이 이전에 명백히 다시 나타난 클래스에 배치된 제 리뷰 결과물의 비율이기 때문입니다. 하지만 머릿속으로 186 - 68을 계산하는 독자에게는 14% 또한 보여줄 가치가 있습니다.
둘째, 이 측정 도구의 편향(bias)은 제가 나중에 다시 언급하겠다고 약속했던 그 투박함(bluntness)의 대가입니다. 파일과 심각도(severity)를 공유하는 두 개의 진정으로 다른 이슈를 하나의 지문으로 통합(collapsing)하면 수치가 부풀려집니다. 반대로 파일 이름 변경(rename)은 클래스를 분리하여 마치 단일 항목(singletons)처럼 보이게 함으로써 수치를 낮출 수 있습니다. 제 추측으로는 통합(collapse)이 더 지배적입니다. 파일 및 심각도 충돌(shared file-and-severity collisions)이 이름 변경 분리(rename-splits)보다 더 흔하기 때문에, 만약 22%가 틀렸다면 아마도 너무 높게 측정되었을 가능성이 큽니다. 저는 이를 측정하지 않았으므로, 정확한 수치나 증명된 경계값이 아닌, 상향 편향된 추정치(upper-biased estimate)로 취급하십시오. 오류가 있다면, 실제 비율은 22%보다 높기보다는 낮을 가능성이 큽니다. 제가 이 방향성을 짚어내는 이유는 제가 가지고 들어왔던 의구심, 즉 '내 에이전트들이 정체되어 있다'는 의구심에 반하기 때문입니다. 당신의 사전 믿음(prior)을 치켜세워주는 숫자야말로 바로 무시해야 할 숫자입니다.
증거가 인정하는 것과 제가 그것들이 의미하기를 바라는 것 사이의 그 차이가 바로 학문의 핵심입니다. 이 수치 자체만으로도 충분히 불편합니다. 제가 이것을 확정적인 판결로 굳힐 필요는 없습니다.
가설: 지시사항(instructions)은 제어 흐름(control flow)이 아니다
설명을 내놓기 전에, 이 수치에 대해서는 어느 정도 회의적인 시각을 가질 필요가 있습니다. 재발(recurrence)이 학습을 측정하는 깔끔한 지표는 아니기 때문입니다. 이는 여러 가지 가능한 원인을 가진 운영상의 신호(operational signal)입니다. 지문(fingerprint)이 재발하는 이유는 해당 파일이 계속해서 문제를 끌어들이는 실제 핫스팟(hotspot)이기 때문일 수도 있고, 리뷰어와 무관하게 사람이나 다른 에이전트가 무언가를 다시 도입했기 때문일 수도 있습니다. 혹은 일련의 과정 중에 모델, 프롬프트(prompt), 또는 리뷰 정책(review policy)이 변경되었거나, 심각도 라벨(severity labels)이 완벽하게 안정적이지 않기 때문일 수도 있습니다. 이 중 어떤 것이든 리뷰어가 "학습에 실패"하지 않았음에도 재발을 일으킬 수 있습니다.
따라서 다음에 이어지는 내용은 여러 가설 중 하나일 뿐입니다. 데이터가 허용하는 유일한 가설이 아니라, 제가 가장 실행 가능하다고 판단한 가설입니다. 이는 별도의 실험을 통해 구체화되었습니다.
저는 유능한 에이전트에게 지시 사항(directives)에 다섯 가지의 핵심적인 지시사항(load-bearing instructions)이 포함된 작업을 부여했습니다. 이는 프로젝트의 지시 파일(instruction file)에 넣어두고 항상 적용된다고 가정하는 종류의 상시 규칙들입니다. 테스트 우선 원칙(test-first discipline) 준수, 비밀 스캔 게이트(secret-scan gate) 실행, 전체 보안 체크리스트(security checklist) 사용, 증거로서 완료 결과물(completion artifact) 생성, 리뷰어에게 디프(diff) 전달. 평이하고 명시적이며, 타협 불가능한 어조로 작성되었습니다.
에이전트는 이 다섯 가지 중 단 하나도 따르지 않았습니다. 반항해서가 아닙니다. 코드를 작성한 후에 테스트를 작성했고, 비밀 스캔을 건너뛰었으며, 체크리스트의 임의적인 일부만 사용했고, 증거 결과물 없이 작업을 완료했다고 선언했으며, 디프(diff)를 계산하지 않았습니다. 각각의 지름길(shortcut)은 국소적으로는 합리적이었습니다. 하지만 전체적으로는 제가 요구했다고 생각한 모든 게이트(gate)를 명확히 통과하지 못했습니다.
이것은 하나의 작업에 대해, 하나의 에이전트로부터 얻은 하나의 관찰 결과입니다. 이것이 얼마나 많은 의미를 가질지에 대해서는 신중하고 싶습니다. 이것은 일화(anecdote)이지 연구(study)가 아니며, 제가 "지시사항은 절대 작동하지 않는다"라고 주장하는 것도 아닙니다. 하지만 이것은 제가 가진 그 어떤 것보다 재발을 더 잘 설명해 주는 가설을 결정화(crystallize)해 주었습니다.
지시사항(Instructions)은 제어 흐름(control flow)이 아닙니다. 프롬프트 내의 지시(directive)는 모델이 컨텍스트 내의 다른 모든 요소와 함께 가중치를 두어 검토하는 제안 형태의 텍스트일 뿐이며, 실행되는 게이트(gate)가 아닙니다. "X를 하지 말라고 기억하세요"라는 말이 위반할 수 없는 제약 조건(constraint)이 되는 메커니즘은 존재하지 않습니다. 따라서 어떤 발견 사항이 수정되더라도, "이 클래스는 이제 여기서 금지됨"이라고 기록하는 구조적인 장치는 없습니다. 다음 검토는 다시 새롭게 시작되며, 동일한 컨텍스트를 가중치 있게 검토하고, 다시 동일한 결론에 도달할 자유를 가집니다. 외부에서 보기에 재발(Recurrence)이란 바로 이런 모습입니다. 에이전트가 학습에 실패하는 것이 아니라, 학습된 내용을 결합(bind)할 수 있는 장소가 없는 시스템인 것입니다.
저는 이것을 법칙이 아닌 가설로 간주합니다. 재발 수치들은 이 가설과 일치하며, 5번 중 0번의 관찰 결과가 이를 설명해 주지만, 어느 것도 이를 증명하지는 않습니다. 하지만 이 가설은 유용한 속성을 가지고 있습니다. 바로 실행 가능하다는 점입니다. 만약 문제가 "모델이 학습하기에 너무 약하다"는 것이라면, 해결책은 더 나은 모델을 기다리는 것일 겁니다. 하지만 문제가 "학습된 내용을 저장할 강제된 장소가 없다"는 것이라면, 그것은 모델의 문제가 전혀 아닙니다. 그것은 엔지니어링(engineering) 문제이며, 엔지니어링 문제는 제가 해결할 수 있습니다.
이를 굴절시키기 위해 내가 구축한 루프
지시사항이 스스로를 강제할 수 없다면, 강제력은 모델 내부의 프롬프트가 아니라 모델 주변에 존재해야 합니다. 그래서 저는 프롬프트가 담을 수 없는 교훈들을 위한 구조적 거처로서, 각각이 구조적 역할을 하는 세 가지 부분으로 구성된 루프를 구축했습니다.
캡처(Capture). 실질적인 작업의 한 조각이 완료되면, 훅(hook)이 실행되어 곧 폐기될 대화 속에 남겨두는 대신, 학습된 교훈을 디스크 상의 내구성이 있는 구조화된 노트(structured note)로 기록합니다. 트리거는 기계적(특정 형태의 작업이 종료됨)이며, 모델이 무시할 수 있는 정중한 상기(reminder)가 아닙니다. 핵심은 "방금 우리가 배운 것"을 기억(memory)이 아닌 파일(file)로 만드는 것입니다.
Recall (회상). 각 세션이 시작될 때, 축적된 관련 교훈들이 컨텍스트 (context)에 주입됩니다. 또한 별도의 레일(rail), 즉 실질적인 행동 앞에 위치하여 강제되는 게이트 (gate)가 존재하며, 에이전트가 진행하기 전에 반드시 회상 (recall) 단계를 거치도록 요구합니다. 이것은 재발 (recurrence)을 직접적으로 겨냥한 절반의 해결책입니다. 즉, '7번의 파일'에서 얻은 교훈은 더 이상 지난달의 트랜스크립트 (transcript) 안에 갇혀 있지 않습니다. 설계상, 에이전트가 해당 파일에 다시 접근하기 전에 그 교훈이 에이전트의 앞에 놓이게 됩니다. 이것이 실제로 (오류) 횟수를 낮추는지에 대해서는 아직 확언할 수 없습니다. 아래 내용을 참조하십시오.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기
