사용자 이메일을 더 친근한 어조로 다시 작성하는 AI 에이전트를 만드는 데 사흘을 썼습니다. 화요일에는 완벽하게 작동합니다. 수요일에는 동일한 입력에 대해 이상하리만치 격식 있는 것을 생성합니다. 목요일에는 이유 없이 사과하며 '따뜻한 마음을 담아, 당신의 AI'라는 서명을 합니다.
테스트 스위트를 바라봅니다. 모든 단언(assertion)이 빨간색입니다. 하지만 에이전트가 고장 난 것은 아닙니다. 그저... 오늘 다릅니다.
에이전트형 AI에서 가장 정신 나갈 만한 문제, 즉 매번 질문할 때마다 다른 답변을 내는 것을 어떻게 테스트하느냐에 오신 것을 환영합니다.
전통적인 테스트가 즉시 실패하는 이유
만약 이전에 단위 테스트(unit tests)를 작성해 본 적이 있다면, 그 과정을 알고 있을 겁니다. 입력 X가 주어지면 출력 Y를 기대한다. 깔끔하고 결정론적이며 아름답죠.
AI 에이전트는 이것을 비웃습니다.
LLM에 기반한 에이전트는 동일한 문장을 열 가지 다른 방식으로 재구성할 수 있습니다. 모두 정확하고, 분위기 점검(vibe check)을 통과하며, 하드코딩된 예상 문자열과 일치하는 것은 없습니다. `assertEqual(output,
이 테스트는 에이전트가 "Hey there!"를 쓰든 "Hi friend!"를 쓰든 통과합니다. 왜냐하면 당신은 _단어_가 아니라 _계약(contract)_을 테스트하고 있기 때문입니다.
레이어 2: 가드레일 단언(Guardrail Assertions)
이것들은 "절대 이렇게 하지 마라"와 "항상 이렇게 하라"는 규칙들입니다. 실제 중요한 것, 즉 다음 사항들을 포착합니다:
def test_email_guardrails(agent, sample_email):
result = agent.rewrite(sample_email)
...
주목할 점은 단 하나의 하드코딩된 구문도 없다는 것입니다. 모든 단언은 LLM이 어떤 방식으로 문구를 구성하든 관계없이 출력물이 갖춰야 할 _속성(property)_에 관한 것입니다.
레이어 3: 평가자로서의 LLM (LLM-as-Judge) (네, 정말로)
"이게 실제로 친근한가?"와 같은 주관적인 부분은 두 번째 LLM 호출을 평가자(grader)로 사용하세요. 순환적이라고 들릴 수 있지만, 평가자에게 루브릭(rubric)을 제공하면 놀라울 정도로 잘 작동합니다:
def test_tone_quality(agent, judge_llm, sample_email):
result = agent.rewrite(sample_email)
...
이것을 5번 실행해 보세요. 5번 중 4번만 통과해도 당신의 에이전트는 견고합니다. 만약 2와 5 사이를 오간다면, 프롬프트에 문제가 있다는 뜻입니다. 그리고 이제 직감(gut feeling) 대신 _측정값(measurement)_을 갖게 된 것입니다.
에이전트를 위한 테스트 피라미드 (The Test Pyramid for Agents)
만드는 모든 에이전트에 이 구조를 적용하세요:
- 기반(Base) (커밋마다 실행): 구조적 스키마 검증. 빠르고 결정론적이며, 출력 형식의 회귀(regressions)를 포착합니다.
- 중간(Middle) (매일 밤 실행): 20개 이상의 다양한 입력에 걸친 가드레일 단언. 안전성/정책 위반 및 드리프트(drift)를 포착합니다.
- 최상단(Top) (매주 실행): 선별된 벤치마크 세트를 사용한 LLM-as-judge 평가. 미묘한 품질 저하를 포착합니다.
기반 레이어는 밀리초 단위로 실행됩니다. 최상단 레이어는 API 호출 비용으로 몇 센트가 들 뿐입니다. 둘 다 "플레이그라운드에서 한 번 시도해 보니 괜찮아 보였어"라는 것보다 훨씬 낫습니다.
아무도 말해주지 않는 단 하나의 것
에이전트 테스트는 에이전트가 올바르다는 것을 증명하는 것이 아닙니다. 그것은 배포하기에 안전하다는 것을 증명하는 것입니다. 이것이 더 낮은 기준점이며, 훨씬 더 유용한 기준점입니다.
당신의 에이전트는 당신을 놀라게 할 것입니다. 예상치 못한 방식으로 내용을 재구성할 것이고, 때로는 당신이 직접 작성한 것보다 더 나을 수도 있습니다. 테스트 스위트의 역할은 '놀라움을 방지'하는 것이 아니라, '재앙(disasters)'을 방지하는 것입니다.
자, 그럼 제가 과제를 하나 드리겠습니다. 지금 만들고 있는 어떤 에이전트를 가져와서 그에 대한 가드레일 어설션(guardrail assertions) 세 가지를 작성해 보세요. 출력 일치 여부 같은 것이 아닙니다. 느낌(vibes)도 아닙니다. 에이전트가 항상 만족해야 하는 세 가지 구체적인 속성이어야 합니다.
당신이라면 어떤 가드레일을 먼저 만들겠습니까? 댓글로 남겨주세요. 제가 충분히 엄격한지 알려드리겠습니다.