5.10.3 DeepEval을 이용한 CI/CD 환경 내 자동화된 회귀 테스트(Regression Test) 연동
프롬프트를 조금 수정했더니 예전에 잘 대답하던 골든 데이터(Golden Data) 질문에 갑자기 오답을 뱉기 시작하는 현상. 이를 AI 공학에서는 ’인지적 퇴행(Cognitive Regression)’이라고 부른다. 이를 막기 위한 회귀 테스트(Regression Test)는 개발자가 수동으로 돌리는 것이 아니라 시스템이 자동으로, 매 커밋(Commit)마다 가혹하게 수행해야 한다.
파이썬 환경에서 DeepEval은 Pytest 생태계와 완전히 동화되어 작동하기 때문에, 별도의 무거운 외부 실행기 없이 기존의 CI/CD 워크플로우(GitHub Actions 등)에 가장 매끄럽게 연동되는 평가 프레임워크다.
1. 평가 데이터셋(Evaluation Dataset) 기반의 테스트 코드 작성
DeepEval은 결정론적 오라클뿐만 아니라 LLM-as-a-Judge 기반의 확률론적 지표 평가까지 하나의 단위 테스트(Unit Test) 함수 안에 묶어낼 수 있다. 수십 개의 골든 샘플을 순회하며 ’최소 합격선(Threshold)’을 넘는지 결정론적으로 단언(Assert)하는 코드를 작성해 보자.
import pytest
from deepeval import assert_test
from deepeval.metrics import AnswerRelevancyMetric
from deepeval.test_case import LLMTestCase
# CI 파이프라인에서 실행될 MFD 픽스처 데이터
dataset = [
{"input": "비밀번호는 어떻게 초기화하나요?", "expected": "로그인 화면의 '비밀번호 찾기'를 누르세요."},
{"input": "환불 기한이 언제인가요?", "expected": "결제 후 7일 이내에만 가능합니다."}
]
# Pytest의 파라미터라이징을 통해 데이터셋 자동 순회
@pytest.mark.parametrize("data", dataset)
def test_rag_pipeline_regression(data):
# 실제 백엔드 AI 라우터 가동
actual_output = my_rag_agent.invoke(data["input"])
# 평가 지표 객체 생성 (정답 관련성, 최소 통과 기준 0.8점 설정)
relevancy_metric = AnswerRelevancyMetric(threshold=0.8)
# 평가 케이스 생성
test_case = LLMTestCase(
input=data["input"],
actual_output=actual_output,
expected_output=data["expected"]
)
# 오라클 단언: 0.8점을 넘지 못하면 Pytest는 즉시 AssertionError를 던짐
assert_test(test_case, [relevancy_metric])
위 코드는 겉보기에는 평범한 Pytest 함수지만, 내부적으로는 모델의 응답을 평가하고 점수를 매기는 거대한 평가 엔진이 구동되고 있다. threshold=0.8 이라는 숫자는 곧 이 파이프라인의 **‘결정론적 품질 통제선(Quality Gate)’**이 된다.
2. CI/CD 워크플로우(Workflow)의 배포 차단(Block) 매커니즘
작성된 코드는 GitHub Actions나 GitLab CI 파이프라인에 그대로 이식된다.
# .github/workflows/ai_regression_test.yml
name: AI Regression Test
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: 파이썬 및 라이브러리 설치
run: pip install pytest deepeval my_ai_app
- name: DeepEval 회귀 테스트 실행
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} # 평가용 LLM(Judge) 구동을 위한 키
run: deepeval test run tests/test_rag_pipeline.py
이 워크플로우의 핵심은 run: deepeval test run 명령어다. 만약 단 한 개의 엣지 케이스라도 0.8점의 임계점을 넘지 못하거나 문법(Syntax) 오라클을 통과하지 못하면, 이 프로세스는 Exit Code 1을 반환하여 즉시 붉은 X표를 띄우고(Fail) 메인 브랜치로의 병합(Merge)을 물리적으로 차단한다.
3. 회귀 테스트의 지속적 진화
한 가지 주의할 점은, LLM 모델이나 프롬프트가 업데이트되면 과거의 100점짜리 정답이 오늘 기준으로는 60점짜리 오답이 될 수도 있다는 것이다. 따라서 CI/CD 파이프라인에 묶여 있는 골든 데이터셋은 한 번 만들어두고 방치하는 ’화석’이 되어서는 안 된다.
시스템 관리자는 정기적으로 운영 로그에서 새로운 엣지 케이스를 건져 올리고, 낡은 픽스처는 폐기(Retire)하며 이 평가 코퍼스(Corpus)를 끊임없이 물갈이해야 한다. DeepEval과 통합된 CI/CD 시스템은 이 물갈이된 데이터셋을 땔감 삼아, 인간의 눈을 피해 몰래 스며드는 인지적 퇴행의 싹을 매 커밋마다 무자비하게 짓밟아버릴 것이다.