LangChain Blog출처 게시일

Eval 기반 개발이란 무엇인가? AI 에이전트를 개선하는 방법

대부분의 에이전트 개발은 같은 방식으로 시작합니다. 프롬프트를 작성하고, 몇 가지 질문을 직접 시도해 보고, 조정한 뒤 다시 시도합니다.

핵심 요약

  • Eval 기반 개발(EDD)은 일관된 지표 집합을 기준으로 성능을 측정하면서 에이전트를 구축하고, eval을 향해 hill climbing을 수행하는 방식입니다.
  • EDD의 첫 번째 단계는 원하는 동작이 좋다는 것이 무엇을 의미하는지에 대한 짧은 명세(spec)를 만드는 것입니다. 에이전트가 해서는 안 되는 일과 계속 동작해야 하는 부분도 포함하세요.
  • 반복 작업을 할 때는 실험을 비교함으로써 에이전트에 가한 변경을 평가하세요. 한 사례를 고치는 변경이 다른 사례를 망가뜨릴 수 있습니다.
  • CI와 프로덕션에서 eval을 계속 실행하고, 발견한 실패를 새로운 데이터셋 예시로 전환하세요.

대부분의 에이전트 개발은 같은 방식으로 시작합니다. 프롬프트를 작성하고, 몇 가지 질문을 직접 시도해 보고, 조정한 뒤 다시 시도합니다. 이는 초기에는 잘 작동합니다. 에이전트 오류가 명확하고 개선 사항을 쉽게 확인할 수 있기 때문입니다. 하지만 시간이 지나면 최근의 변경이 에이전트를 더 좋게 만들었는지 더 나쁘게 만들었는지 파악하는 것이 점점 더 어려워집니다.

Eval 기반 개발(EDD)은 에이전트의 성능을 측정하고 의사 결정을 안내하는 일관된 지표 집합을 제공함으로써 이 문제를 해결합니다. 여기 LangChain에서는 가장 진보된 에이전트를 구축할 때 EDD를 사용했습니다(관련 블로그 글은 IssueBench참고하세요). 이를 세 단계 과정으로 정리했습니다:

  1. 에이전트에게 좋다는 것이 무엇인지 정의합니다.
  2. 구축하기 전에 eval을 작성합니다.
  3. 변경을 수행하고 비교합니다.

이 블로그에서는 이 과정을 단계별로 살펴보며, 여러분의 팀이 자체 에이전트 개발 과정에 적용할 수 있도록 안내합니다.

Eval 기반 개발이란 무엇인가?

Eval 기반 개발이라는 이름과 개념은 테스트 기반 개발(TDD)에서 차용한 것으로, TDD에서는 통과할 코드를 작성하기 전에 실패하는 테스트를 먼저 작성합니다. 에이전트는 비결정적(non-deterministic)이기 때문에 전통적인 코드와 다릅니다:

  • 출력이 달라집니다. 같은 질문이 실행할 때마다 다른 답변을 받을 수 있습니다.
  • 하나 이상의 답변이 정답일 수 있습니다. 서로 다른 표현을 사용하더라도 두 개의 자연어 결과가 모두 옳다고 간주될 수 있습니다.
  • 에이전트가 자신의 단계를 스스로 선택합니다. 필요하지 않은 도구를 호출하거나 사용해야 할 도구를 건너뛰면서도 정답에 도달할 수 있습니다.

그 결과, 에이전트에는 다른 종류의 테스트가 필요합니다. Eval 은(는) 일련의 예시에 걸쳐 에이전트의 실행에 점수를 매기는 방식으로 이를 처리합니다. Eval은 전통적인 테스트보다 유연합니다. 에이전트 실행의 어떤 측면이든 점수를 매길 수 있고, 다른 LLM을 사용해 점수를 매길 수도 있습니다(LLM-as-a-judge).

EDD에서는 TDD와 마찬가지로 이러한 eval이 성공의 정의가 되며, 여러분은 그에 맞춰 에이전트를 구축하게 됩니다.

1단계: 에이전트에게 좋다는 것이 무엇인지 정의하기

EDD의 첫 번째 단계는 에이전트가 무엇을 해야 하는지 정의하는 것입니다. 그런 다음, 그 목표에 도달하기 위해 처리해야 하는 동작들을 나열합니다. 여기에는 지식 베이스에서 질문에 답변하기, 사용자를 대신해 조치를 취하기, 후속 질문을 해야 할 때를 아는 것과 같은 작업이 포함될 수 있습니다. 각 동작에 대한 요구 사항을 적어 두세요. 이것들이 모여 에이전트의 제품 요구 사항 문서(PRD)를 구성합니다.

EDD는 한 번에 하나의 행동에 대해 작업합니다. 이는 하나의 변경이 다른 변경의 효과를 흐리지 않으면서 hill climb를 수행할 수 있는 좁은 목표를 제공합니다. 선택하는 행동은 보통 곧 만들려는 기능이나 에이전트의 과거 실행에서 발견한 실패에서 비롯됩니다. 코드를 작성하기 전에 다음을 다루는 짧은 스펙을 정의해 두면 도움이 됩니다:

  • 행동이 언제 발생해야 하는지
  • 에이전트가 수행해야 할 작업
  • 에이전트가 해서는 안 되는 일
  • PRD의 어떤 동작들이 계속 작동해야 하는가

명세는 통과 또는 실패로 채점할 수 있을 만큼 충분히 명확해야 한다.

직원들이 회사 정보를 조회하는 내부 문서 에이전트가 있다고 가정해 보겠습니다. 이 에이전트는 두 가지 도구를 가지고 있습니다: search_docs 내부 문서 및 web_search 그 외 모든 용도를 위한 것입니다. 우리는 a를 추가할 계획입니다. create_ticket IT 티켓을 접수할 수 있는 도구입니다. 우리 스펙은 다음과 같습니다:

  • 언제: 사용자가 "내 노트북이 VPN에 연결되지 않아요"처럼 무언가 고장 난 것을 보고할 때.
  • 해야 할 일: 전화하기 create_ticket.
  • 하지 말 것: “VPN에 어떻게 연결하나요?” 같은 사용 방법 질문으로 티켓을 등록하지 마세요.
  • 유지해야 할 것: search_docs 그리고 web_search 지금 처리하는 질문들을 여전히 처리하는 것

에이전트가 아직 그 기능을 갖추지 못했더라도, 우리는 이 가이드라인 기준으로 평가할 것입니다.

현재의 docs agent 예제 구현과, 추가할 계획인 ticketing 도구입니다. 각 도구에는 이를 호출하게 될 예제 입력이 있습니다.

Step 2: 빌드하기 전에 eval 작성하기

데이터셋을 구축합니다. 데이터셋은 입력과, 선택적으로 참조용 'golden' 출력을 가진 테스트 케이스('example'이라고 함)들의 모음입니다. 입력을 얻는 가장 좋은 소스 중 하나는 실제 에이전트 실행 기록입니다. 사용자들은 예상치 못한 방식으로 표현할 수 있으며, 그들의 요청에는 스스로 작성하려고 하지 않을 수 있는 엣지 케이스들이 포함됩니다. 만약 여러분의 예제가 실제 트래픽처럼 보인다면, eval에서 좋은 점수를 받는 것이 프로덕션에서의 좋은 동작을 의미할 가능성이 더 높습니다. LangSmith에서는 실제 에이전트 실행 기록을 데이터셋에 직접 추가할 수 있습니다. 아직 실행 기록이 없다면, 일반적인 대안은 예제를 처음부터 직접 만드는 것입니다.

우리의 docs agent의 경우, 몇 가지 예제면 시작하기에 충분합니다. 데이터셋에는 티켓 요청과 함께, 기존 동작이 반영되도록 search_docs 및 web_search 으로 가야 할 질문들도 포함시킬 것입니다.

각 example은 입력 질문과 참조 출력, 즉 에이전트가 호출해야 할 도구를 짝지어 놓습니다.

또한 데이터셋을 확장하여 아직 다루지 않는 케이스들을 포함시킬 수 있습니다. 예를 들어 불만이 많은 사용자의 예제가 부족하다고 해봅시다. 기존 예제들을 LLM에 주고 더 화난 메시지로 다시 쓰도록 요청한 뒤, 에이전트가 여전히 올바른 도구를 호출하는지 확인할 수 있습니다.

평가기(evaluator)를 작성합니다. 데이터셋을 갖추었다면, PRD에서 정의한 '좋음'의 기준을 가져다가 예제들에 대한 에이전트 성능을 채점하는 테스트 또는 eval로 만들 수 있습니다. 평가기를 작성할 때는 테스트에 가장 적합한 채점 방식을 선택하세요. 검사가 결정적(deterministic)이라면 code eval 을 사용하고, 그렇지 않다면 LLM-as-a-judge 를 사용하세요. 에이전트의 최종 답변을 볼 것인지, 답에 도달하기 위해 취한 행동을 볼 것인지, 아니면 완전히 다른 무엇인가를 볼 것인지 결정해야 합니다. 우리의 docs agent의 경우, 각 케이스에서 올바른 도구를 사용하고 있는지 검증하기 위해 에이전트가 호출하는 도구들을 살펴보려고 합니다. 도구 선택은 코드로 쉽게 검사할 수 있으므로, code eval을 사용해 각 example이 참조 출력에 명시된 도구를 호출했는지 확인할 수 있습니다.

에이전트가 참조 출력의 도구를 호출하면 해당 example은 통과합니다.

우리의 docs agent는 몇 가지 특정 기능을 갖춘 간단한 챗봇입니다. 에이전트가 점점 더 복잡해지면, eval 스위트도 조금 다른 모습이 필요할 것입니다. 샌드박스의 코딩 에이전트처럼 에이전트가 환경에 변경을 가한다면, 몇 번의 도구 호출과 최종 응답을 검사하는 것만으로는 충분한 정보를 얻지 못합니다. 에이전트가 시스템에 남겨둔 상태를 검사해야 하고, 한 번의 실행이 다음 실행에 영향을 주지 않도록 각 실행마다 깨끗한 환경이 필요합니다. Harbor 는 이러한 작업들에 대해 에이전트를 실행하기 위한 오픈 소스 프레임워크이며, Terminal-Bench같은 업계 벤치마크의 기반이 되는 하네스입니다. 각 작업은 자체 샌드박스에서 실행되며, 최종 상태를 채점하는 테스트 스크립트가 함께 제공됩니다.

Terminal-Bench 같은 벤치마크에 맞춰 최적화하는 것도 EDD와 동일한 루프를 따릅니다. 먼저 작업과 테스트를 작성하고, 베이스라인을 실행한 뒤, 에이전트를 변경하면서 실험들을 비교합니다. 우리가 LangSmith Engine을 만들 때는 실제 및 합성 에이전트 실행 기록들로 자체 벤치마크를 만들고, 이를 Harbor eval로 실행했습니다. 또한 Harbor를 사용해 Deep Agents를 벤치마크합니다. 이를 통해 todo-list 미들웨어나 시스템 프롬프트의 일부 같은 하네스의 일부를 제거해도 에이전트가 나빠지지 않는지 확인할 수 있습니다.

기준선을 실행하세요. 데이터셋이나 평가자를 어떤 방식으로 구축하든, 모든 예제에 대해 에이전트를 실행하고 그 결과를 LangSmith에 실험으로 기록할 수 있습니다. 실험이란 에이전트를 데이터셋 전체에 대해 한 번 실행한 것으로, 각 예제의 입력, 출력, 평가 점수가 하나의 레코드에 함께 저장됩니다. 중앙화된 시스템을 갖추면 서로 다른 에이전트 버전의 결과를 비교할 수 있습니다. 에이전트를 변경하기 전에 비교 지표로 삼을 기준선 실험을 실행하는 것이 중요합니다.

저희 docs 에이전트의 경우, 해당 도구가 아직 존재하지 않기 때문에 데이터셋의 티켓 예제들은 실패 점수를 받습니다. 다른 예제들은 이미 작동하는 기능을 기록해 두는 것이므로, 나중에 새 도구를 추가했을 때 다른 부분이 망가졌는지 알 수 있습니다.

3단계: 변경 사항을 적용하고 비교하기

이제 create_ticket 도구를 만들고 동일한 평가를 실행합니다.

EDD는 평가를 향해 “힐 클라이밍(hill-climbing)”한다는 점을 기억하세요. 힐 클라이밍이란 에이전트를 개선하는 과정(평가, 비교, 조정)을 반복하여 객관적인 개선 증거와 함께 정의된 루프를 확립하는 것을 의미합니다. 에이전트에 대한 이후의 각 변경 사항은 자체적인 실험을 갖게 되며, 각 실험은 진전을 검증하기 위해 이전 실험과 비교됩니다. LangSmith에서는 두 실험을 선택하면 비교 보기를 열 수 있습니다. 이 보기는 각 예제의 점수를 나란히 보여주므로 어떤 예제가 개선되고 어떤 예제가 후퇴했는지 확인할 수 있습니다.

실험을 비교할 때는 평균 점수의 변화뿐만 아니라 성능 저하나 정상 동작의 덮어쓰기 여부도 파악하는 것이 중요합니다. 우리의 docs 에이전트에서 이제 티켓 예제들은 통과합니다. 하지만 "How do I connect to the VPN?" 질문이 이제 문서를 검색하는 대신 티켓을 생성합니다. 평균 점수는 올랐지만 한 사례가 깨졌습니다.

티켓팅 도구를 추가하면 평균 점수가 올라가지만, "How do I connect to the VPN?" 질문은 이제 실패합니다.

트레이스를 검토하는 것이 eval이 실패한 이유를 이해하는 가장 좋은 방법입니다. 트레이스는 에이전트의 한 번의 실행 기록으로, 모든 모델 호출과 도구 호출을 포함합니다. LangSmith에서는 어떤 프레임워크로 빌드된 에이전트든 트레이싱이 가능합니다. 자세한 내용은 다음을 확인하세요. tracing quickstart.

최신 실험의 실패한 트레이스를 열어보면 도구 설명에 "VPN and laptop issues"에 대해 create_ticket 를 사용하라고 되어 있어, VPN을 언급하는 모든 질문이 일치합니다. 이것이 기준선의 올바른 동작을 덮어씁니다.

트레이스를 통해 도구 설명이 너무 광범위하여 문서가 답할 수 있는 질문에도 에이전트가 티켓을 생성한다는 것을 알 수 있습니다.

해결책은 도구 설명을 IT가 조치해야 하는 요청으로 좁히는 것입니다. 이 변경을 구현한 후 eval을 다시 실행합니다. 이제 모든 예제가 통과합니다.

더 좁은 도구 설명으로 모든 예제가 통과됩니다.

작은 데이터셋에서의 완벽한 점수는 좋은 신호지만, 100%가 항상 올바른 목표는 아닙니다. 우리는 이 정확한 예제들을 보면서 도구 설명을 조정했습니다. 모든 예제가 통과할 때까지 에이전트를 계속 조정하면, 관심 있는 동작 대신 데이터셋에 과적합(overfitting)되기 시작할 수 있습니다. eval은 통과하지만 예제에서 다루지 않는 방식으로 표현된 요청은 여전히 놓치게 됩니다. 이를 확인하려면 반복 작업 중에는 보지 않는 보류(held-out) 예제 세트를 유지하세요. 조정 대상 예제에서는 점수가 올라가지만 보류 세트에서는 평평하게 유지된다면 과적합일 가능성이 높습니다.

다단계 에이전트는 어느 단계에서든 실패할 수 있으므로, LangSmith는 최종 답변 이상을 평가할 수 있게 해줍니다. 단일 단계, 도구 호출의 전체 시퀀스, 또는 스레드로 그룹화된 다중 턴 대화를 점수화할 수 있습니다.

출시하면서 EDD 유지하기

eval 자동화

변경 사항을 더 빠르게 배포하기 시작하면 eval 실행을 건너뛰거나 오래된 예제를 놓치기 쉽습니다. 워크플로우에 자동화된 평가를 추가하면 테스트되지 않은 변경 사항이 사용자에게 도달하는 것을 방지하고 프로덕션 이전에 성능 저하를 잡아낼 수 있습니다.

eval 스위트를 만드는 최선의 전략은 개별 설정에 따라 다릅니다. 빠른 코드 검사는 잘못된 병합을 차단할 수 있고, LLM 판정자를 사용하는 더 느린 eval은 야간 또는 릴리스 전에 실행할 수 있습니다. 반복 작업 중에는 데이터셋 분할을 사용하여 작업 중인 동작에 대한 예제만 실행하고, 출시 전에는 전체 세트를 실행하세요.

LangSmith는 pytest 및 Vitest와 통합되므로 eval이 코드 옆에 위치하여 모든 풀 리퀘스트에서 실행될 수 있습니다. 각 실행은 실험으로 기록되어 다른 모든 것과 같은 곳에서 결과를 볼 수 있습니다.

프로덕션에서 평가하기

에이전트를 배포하기 전에는 데이터셋이 개발 중에 테스트할 생각을 했던 사례만 다룰 가능성이 높습니다. 프로덕션에서는 다음 평가 방법을 사용하여 나머지를 표시할 수 있습니다:

  • 온라인 평가자(Online evaluators)는 들어오는 라이브 트레이스에 점수를 매깁니다. 트레이싱 프로젝트에 code checks 와 LLM judges 를 연결하고 트래픽의 일부를 샘플링하여 비용을 관리할 수 있습니다.
  • 주석 큐(Annotation queues)를 사용하면 팀이 표시된 실행을 수동으로 검토할 수 있습니다. 또한 LLM 판정자에 의존하기 전에 사람들과 판단이 일치하는지 확인하는 방법이기도 합니다.
  • 대시보드(Dashboards)는 시간에 따른 eval 점수, 피드백, 비용 및 지연 시간을 추적할 수 있어 릴리스가 상황을 더 좋게 만들었는지 나쁘게 만들었는지 확인할 수 있습니다.
  • 인사이트(Insights) 는 production 트레이스를 클러스터로 묶어주어 수천 번의 실행에서 새로운 패턴을 발견할 수 있게 해줍니다.
  • LangSmith Engine 은 한 단계 더 나아가, 문제 클러스터를 검토할 수 있는 어서션(assertions)이 포함된 데이터셋 예제로 변환해줍니다.

또한 우리는 Deep Agents에 사용하는 evals를 해당 repo에 공개 하여 실제 프로덕션 eval 스위트를 직접 볼 수 있도록 했습니다.

흔한 실수

  • 성공 기준을 너무 느슨하게 정의하는 것. eval이 쉽게 통과 여부를 판정할 수 있도록 성공을 명확히 정의하기 위한 힘든 작업을 미리 해두세요. “응답이 유용하다”는 것은 잘 정의된 메트릭이 아닙니다.
  • 수정 후에 eval을 작성하는 것. 새로운 출력을 본 후에는 설계상 통과하도록 eval을 작성하기 쉽습니다. 먼저 작성하고 현재의 깨진 버전에서 실패하는지 확인하세요.
  • 평균 점수만 확인하는 것. 평균 점수의 향상은 퇴보한 예제나 좋은 동작을 덮어쓴 변경 사항을 숨길 수 있습니다. 변경 사항을 유지하기로 결정하기 전에 각 예제를 검토하세요.
  • 필요 없는 eval을 추가하는 것. 각 eval은 에이전트를 어떤 방향으로 이끕니다. 각 eval을 수정 중인 실패나 곧 만들 기능과 같은 특정 변경 사항과 연결하세요.
  • 검증되지 않은 판정 모델을 맹신하는 것. 먼저 LLM 판정 모델을 인간 점수와 비교하세요. 판정 모델에게는 좁은 질문을 던지고, 모호한 1에서 10까지의 척도 대신 통과 또는 실패 방식을 사용하세요.

에이전트 평가 구축에 관한 자세한 내용은 이 웨비나를 확인하세요: Agent Evals 101 그리고 무료인 LangSmith 관련 LangChain Academy 강좌!

추가 읽을거리:

원문 출처

LangChain Blog

내용 안내

원문 발행 및 권리는 출처에 있습니다.

기계 번역 · 원문을 참고하세요