코드 평가
코드 평가 (Code-Evals)
G-Eval이 자연어 기준으로 평가를 정의한다면, Code-Eval은 Confident AI 플랫폼에서 직접 Python 코드를 작성해 커스텀 메트릭을 만들고 실행하게 해줘요. JSON 구조 검증, 결정적 채점, 복잡한 계산처럼 자연어로 표현하기 어려운 평가 로직이 필요할 때 특히 유용해요. 이 글에서는 Code-Eval의 동작 방식과 작성 예시를 살펴볼게요.
출처: 문서
본문
개요
Code-Eval은 Confident AI 플랫폼에서 직접 Python 코드를 작성해 커스텀 메트릭을 만들고 실행하게 해줘요. 자연어 기준을 쓰는 G-Eval과 달리, deepeval 프레임워크를 사용해 평가 로직을 완전히 프로그램적으로 제어할 수 있어요.
Code-Eval도 Confident AI에서 실행돼요.
왜 Code-Eval인가요?
자연어로 표현할 수 없는 평가 로직이 필요할 때 Code-Eval이 안성맞춤이에요.
- 정확한 포맷 검증 — JSON 구조, 정규 표현식 패턴, 특정 출력 포맷을 검증해요.
- 결정적 채점 — LLM 변동성 없이 일관된 규칙 기반 로직을 적용해요.
- 복잡한 계산 — 다단계 연산, 통계 분석, 집계를 수행해요.
- 커스텀 비즈니스 규칙 — 내 사용 사례에 고유한 도메인별 검증 로직을 구현해요.
톤, 도움됨, 미묘한 품질 검사 같은 주관적 평가가 필요하다면 G-Eval을 쓰세요 — LLM-as-a-judge 추론을 처리하고 코드 없이도 만들기 쉬워요.
동작 방식
Code-Eval은 deepeval에서 커스텀 메트릭 만들기와 똑같이 동작해요. BaseMetric을 상속하는 Python 클래스를 작성하고 평가 로직을 구현하면 돼요.
다만 Confident AI에서는 다음 메서드만 편집할 수 있어요.
a_measure()— 평가 로직이 실행되는 async 메서드is_successful()— 테스트 케이스 통과 여부를 결정
메트릭의 다른 모든 부분(초기화, 프로퍼티 등)은 플랫폼이 처리해요.
사용 가능한 패키지
내 코드는 안전한 환경에서 실행되며 다음에 접근할 수 있어요.
deepeval라이브러리 — 항상 GitHub의 최신 버전.BaseMetric, 테스트 케이스 타입 등 모든 유틸리티를 포함해요.- 표준 Python 라이브러리 —
json,re,math,collections,datetime등 - 외부 네트워크 호출 없음 — 보안을 위해 외부 API 호출은 (현재는) 지원되지 않아요.
UI로 Code-Eval 만들기
Code-Eval 메트릭은 Project > Metrics > Library 아래에서 만들 수 있어요.
메트릭 세부 정보 입력
메트릭 이름, 그리고 선택적으로 설명을 입력해요. single-turn 또는 multi-turn 메트릭 중 무엇을 만들지도 토글할 수 있어요.
일반 메트릭 정보 (General Metric Info)
메트릭 이름은 프로젝트 내에서 고유해야 하며, 어떤 기본 메트릭 이름과도 충돌하면 안 돼요.
평가 코드 작성
G-Eval에서 criteria, evaluation steps, rubric을 정의하는 대신, 평가 **점수(score)**를 직접 계산하는 Python 코드를 작성해요.
내 코드는 적절한 base class를 상속하고 다음을 구현해야 해요.
a_measure(test_case)—self.score,self.reason,self.success를 설정하는 async 평가 로직is_successful()— threshold에 따라 메트릭 통과 여부를 반환(미리 채워져 있음, 변경 권장하지 않음)
a_measure() 메서드가 self.score를 반환할 필요는 없지만, 반환하길 권장해요.
Single-turn
single-turn 메트릭은 BaseMetric을 상속하고 LLMTestCase를 받아요.
from deepeval.metrics import BaseMetric
from deepeval.test_case import LLMTestCase
class CodeMetric(BaseMetric):
async def a_measure(self, test_case: LLMTestCase) -> float:
# Your evaluation logic here
if len(test_case.actual_output) > 5:
self.score = 1
else:
self.score = 0
self.success = self.score >= self.threshold
return self.score
def is_successful(self) -> bool:
if self.error is not None:
self.success = False
else:
try:
self.success = self.score >= self.threshold
except TypeError:
self.success = False
return self.success
LLMTestCase 객체는 input, actual_output, expected_output 등의 파라미터에 접근할 수 있게 해줘요.
Multi-turn
multi-turn 메트릭은 BaseConversationalMetric을 상속하고 ConversationalTestCase를 받아요.
from deepeval.metrics import BaseConversationalMetric
from deepeval.test_case import ConversationalTestCase
class CodeMetric(BaseConversationalMetric):
async def a_measure(self, test_case: ConversationalTestCase) -> float:
# Your evaluation logic here
if len(test_case.turns) > 5:
self.score = 1
else:
self.score = 0
self.success = self.score >= self.threshold
return self.score
def is_successful(self) -> bool:
if self.error is not None:
self.success = False
else:
try:
self.success = self.score >= self.threshold
except TypeError:
self.success = False
return self.success
ConversationalTestCase는 turns 목록에 접근할 수 있게 해주며, 각 turn은 role, content 등 다른 파라미터를 담고 있어요.
테스트 케이스 파라미터에 대한 자세한 내용은 Test Cases, Goldens, and Datasets 문서를 참고하세요.
검토 후 저장
코드를 작성했으면 최종 검토 페이지에서 모든 게 올바른지 확인하고 Save를 클릭해요.
이제 Code-Eval 메트릭을 metric collection에 추가해 원격 eval을 시작할 수 있어요.
고급 사용법 (Advanced Usage)
상세 로그 설정 (Set verbose logs)
self.verbose_logs로 평가 로직의 중간 단계와 결정 경로를 로그로 남길 수 있어요. 복잡한 메트릭을 디버깅하거나 점수가 어떻게 계산되는지 이해할 때 유용해요.
from deepeval.metrics import BaseMetric
from deepeval.test_case import LLMTestCase
class CodeMetric(BaseMetric):
async def a_measure(self, test_case: LLMTestCase) -> float:
# Log anything for debugging purposes
self.verbose_logs = "Wow I can't believe I can do this on Confident AI"
return self.score
def is_successful(self) -> bool:
if self.error is not None:
self.success = False
return self.success
상세 로그는 메트릭 결과와 함께 Confident AI 대시보드에 표시되어, 평가 결정 과정을 쉽게 추적할 수 있어요.
reasoning 기록 (Log reasoning)
self.reason로 점수에 대한 사람이 읽을 수 있는 설명을 남겨요. 특정 점수가 왜 부여됐는지 이해하는 데 도움이 되며 평가 결과에 표시돼요.
from deepeval.metrics import BaseMetric
from deepeval.test_case import LLMTestCase
class CodeMetric(BaseMetric):
async def a_measure(self, test_case: LLMTestCase) -> float:
# Set any reason you wish
self.reason = "Wow I can't believe I can do this on Confident AI"
return self.score
def is_successful(self) -> bool:
if self.error is not None:
self.success = False
return self.success
명확한
self.reason는 평가 결과를 이해하기 훨씬 쉽게 만들어요. 특히 실패한 테스트 케이스를 검토하거나 예상 밖의 점수를 디버깅할 때 그렇지요.
예외 발생 (Raise exceptions)
Python에서 평소처럼 에러를 던지고 self.error에 기록할 수도 있어요.
from deepeval.metrics import BaseMetric
from deepeval.test_case import LLMTestCase
class CodeMetric(BaseMetric):
async def a_measure(self, test_case: LLMTestCase) -> float:
try:
raise ValueError("Raising an error because I feel like it")
except Exception as e:
# Surface the error before re-raising
self.error = str(e)
raise
return self.score
def is_successful(self) -> bool:
if self.error is not None:
self.success = False
return self.success
더 알아보기
- G-Eval — 자연어 기준의 커스텀 메트릭
- Custom Metrics — 커스텀 메트릭 개요
- Metric Collections — 원격 평가를 위한 메트릭 묶기