LLM 테스트 자동화 프레임워크 vitals를 통해 AI 애플리케이션 성능 평가 및 모델 비교가 쉬워집니다. R 환경에서 LLM 평가 체계를 구축하고 자동화하는 방법을 알아봅니다.
생성형 AI 애플리케이션이 기대한 답변을 내놓고 있는지 확인하는 것은 쉽지 않습니다. 더 저렴한 LLM이나 로컬에서 무료로 실행할 수 있는 모델로도 일부 작업을 충분히 처리할 수 있을지 판단하기 어렵습니다. 모델 성능은 매달 달라지는 듯 보이며, 기존 소프트웨어 코드와 달리 LLM은 같은 질문에도 매번 동일한 답을 내놓지 않습니다. 테스트를 반복 실행하는 과정은 번거롭고 시간도 많이 소요됩니다.
다행히 LLM 테스트를 자동화하는 프레임워크가 있습니다. 이런 LLM 평가 체계는 전통적인 코드의 유닛 테스트와 비슷한 개념이지만, LLM은 같은 질문에 여러 방식으로 답할 수 있고, 정답이 하나가 아닐 수 있으므로 훨씬 더 유연한 기준으로 응답을 분석해야 합니다.
파이썬의 인스펙트(Inspect) 프레임워크를 기반으로 한 R 패키지 ‘바이탈(vitals)’은 이러한 자동화된 LLM 평가 체계를 R 환경에 제공합니다. vitals은 R 패키지 엘머(ellmer)와 연동하도록 설계되었으며, 두 패키지를 함께 사용하면 프롬프트와 AI 애플리케이션을 평가하고, 서로 다른 LLM이 성능과 비용에 어떤 영향을 미치는지 비교할 수 있습니다.
패키지 저자인 포짓(Posit)의 수석 소프트웨어 엔지니어 사이먼 카우치는 vitals 평가 세트인 ‘블러프벤치(bluffbench)’를 활용한 실험에서 AI 에이전트가 기대와 어긋나는 정보가 그래프에 포함될 경우 이를 무시하는 경향이 있다는 점을 발견했습니다. 카우치는 현재 vitals을 활용해 어떤 LLM이 R 코드를 얼마나 잘 작성하는지도 측정하고 있습니다.
vitals 설정
vitals 패키지는 CRAN에서 설치할 수 있으며, 개발 버전을 사용하려면 깃허브에서 pak::pak("tidyverse/vitals")로 설치하면 됩니다. vitals은 Task 객체를 사용해 LLM 평가를 생성하고 실행하며, 각 Task에는 데이터셋(dataset), 솔버(solver), 스코어러(scorer) 세 가지 요소가 필요합니다.
데이터셋
dataset은 테스트하려는 내용을 담은 데이터 프레임입니다. 이 데이터 프레임에는 최소 두 개의 열이 필요합니다. input은 LLM에 보낼 요청, target은 LLM이 응답하기를 기대하는 내용입니다. vitals 패키지에는 are라는 예제 데이터셋이 포함되어 있습니다. 자신만의 input-target 쌍을 만드는 가장 쉬운 방법 중 하나는 스프레드시트를 활용하는 것입니다. 스프레드시트에 input과 target 열을 만든 뒤 원하는 내용을 입력하고, googlesheets4나 rio 같은 패키지를 이용해 해당 파일을 R로 불러오면 됩니다.
솔버
Task의 두 번째 구성 요소는 solver입니다. solver는 질의를 LLM에 전달하는 R 코드입니다. 단순한 질의라면 보통 ellmer의 채팅 객체를 vitals의 generate() 함수로 감싸는 방식으로 충분합니다. 반면 도구 호출이 필요하거나 입력 구조가 복잡하다면 사용자 정의 solver를 작성해야 할 수 있습니다. 이번 데모에서는 기본 generate() 기반 solver를 사용합니다.
vitals을 사용할 때는 R 패키지 ellmer에 대한 이해가 도움이 됩니다. ellmer 채팅 객체를 generate() 함수로 감싸면 vitals용 solver로 사용할 수 있습니다. Task 객체는 데이터셋의 input 열을 LLM에 전달할 질문으로 자동 인식합니다. 데이터셋에 질의가 여러 개 포함되어 있다면 generate()가 이를 순차적으로 처리합니다.
스코어러
마지막으로 필요한 요소는 scorer입니다. 이름 그대로 결과를 채점하는 역할을 합니다. vitals에는 여러 유형의 scorer가 포함되어 있으며, LLM을 활용해 결과를 평가하는 방식도 제공됩니다. vitals의 LLM 기반 scorer 중 하나인 model_graded_qa()는 solver가 질문에 얼마나 적절히 답했는지를 평가합니다. 또 다른 함수인 model_graded_fact()는 solver의 응답에 특정 사실이 포함되어 있는지 판단합니다.
vitals은 기본적으로 테스트 중인 동일한 LLM을 scorer로 사용하지만, 별도의 LLM을 심판으로 지정할 수 있습니다. 채점 기준이 단순하지 않다면, 상위권 프런티어 LLM을 심판 역할로 사용하는 편이 안전합니다.