Evaluation 및 Operation Type
WhatAP LLM Observability는 운영 중인 LLM 애플리케이션의 응답 품질과 안정성을 자동으로 측정하는 Evaluation 기능과, LLM 호출을 시스템 프롬프트 단위로 그룹화·필터링하는 Operation Type 라벨링을 제공합니다. 두 기능 모두 사용자 트랜잭션의 응답 시간에 영향을 주지 않도록 설계되어 있으며, 코드에 데코레이터 한 줄을 추가하는 것만으로 적용할 수 있습니다.
현재(2026년 6월 기준) Evaluation , Operation Type 라벨링 기능은 Python만 지원합니다.
Evaluation
Evaluation은 LLM 응답에 대해 할루시네이션, 답변 관련성, 유해성(toxicity), 프롬프트 인젝션, 사실성(factuality), PII 누출, 의심 URL 등의 평가를 자동으로 적용하는 기능입니다. 평가 결과는 점수(0.0~1.0)로 산출되어 메트릭과 로그싱크에 함께 수집되므로, 응답 품질을 시계열로 추적하고 임계치 기반 알림을 구성할 수 있습니다.
judge LLM 호출에는 사용자 호출에서 사용하던 client 인스턴스를 그대로 재사용합니다. 따라서 평가 파이프라인을 활성화하면 사용자 응답을 위한 LLM 호출과 별개로 judge 호출만큼의 LLM 리소스(토큰·비용)가 추가로 발생합니다.
설정 옵션
| 키 | 기본값 | 설명 |
|---|---|---|
llm_eval_enabled | false | 평가 파이프라인 마스터 토글. false면 큐 적재 및 워커가 동작하지 않습니다. |
llm_eval_sample_rate | 1.0 | 평가의 샘플링 비율 ( 1.0 == 100% 비율 입니다.) |
llm_eval_buffer_limit | 1000 | 평가 큐의 최대 크기. 초과 시 평가가 드롭되며 LLM030 경고가 발생합니다. |
llm_eval_workers | 4 | 평가자를 실행하는 ThreadPoolExecutor의 워커 수. |
llm_eval_judge_timeout_sec | 30 | judge LLM 1회 호출의 최대 대기 시간(초). 초과 시 judge_error로 처리됩니다. 0 또는 음수면 무제한. |
사용 방법
Evaluation 는 특정 함수에만 적용하는 데코레이터 방식과, 애플리케이션 전역에 적용하는 방식 중 선택할 수 있습니다.
방식 A — 데코레이터 (특정 함수의 LLM 호출만 평가)
from whatap.llm.evaluators import evaluate_with
from whatap.llm.evaluators.builtins import CombinedJudgeEvaluator
@evaluate_with(CombinedJudgeEvaluator())
def chat(q):
...
방식 B — 앱 전역 등록 (모든 LLM 호출에 always-on 적용)
from whatap.llm.evaluators import register_evaluator
from whatap.llm.evaluators.builtins import CombinedJudgeEvaluator
register_evaluator(CombinedJudgeEvaluator()) # 앱 시작 시 한 번만 호출
등록 가능한 평가자 클래스
from whatap.llm.evaluators.builtins import (
# LLM judge 기반 — judge 호출 비용 발생
CombinedJudgeEvaluator,
HallucinationEvaluator,
AnswerRelevanceEvaluator,
ToxicityEvaluator,
PromptInjectionEvaluator,
FactualityEvaluator,
# 규칙 기반 — LLM 호출 없음, 비용 0
PIILeakEvaluator,
URLScanEvaluator,
)
Evaluation 클래스 설명
| Evaluator | LABEL | 종류 | 점수 방향 | 비용 |
|---|---|---|---|---|
CombinedJudgeEvaluator | combined_judge | LLM judge | 종합 위험도 — 낮을수록 좋음 | judge 1회로 5개 aspect |
HallucinationEvaluator | hallucination | LLM judge | 낮을수록 좋음 | judge 1회 |
AnswerRelevanceEvaluator | answer_relevance | LLM judge | 높을수록 좋음 | judge 1회 |
ToxicityEvaluator | toxicity | LLM judge | 낮을수록 좋음 | judge 1회 |
PromptInjectionEvaluator | prompt_injection | LLM judge | 낮을수록 좋음 | judge 1회 |
FactualityEvaluator | factuality | LLM judge | 높을수록 좋음 | judge 1회 |
각 Evaluation 이 측정하는 항목은 다음과 같습니다.
-
answer_relevance: 답변 관련성(높을수록 좋음)응답이 사용자 질문에 얼마나 충실하게 답하는지를 측정합니다. 질문에 완전히 답하면
1.0, 부분적·지엽적으로만 답하면0.5, 질문과 무관하거나 회피·이탈한 경우0.0으로 채점됩니다. -
hallucination: 할루시네이션(낮을수록 좋음)응답에 근거 없는 주장이 포함되어 있는지를 측정합니다. 컨텍스트(ground truth)가 주어진 경우에는 컨텍스트에 대한 충실도(faithfulness)를, 컨텍스트가 없는 경우에는 응답 자체의 자기 일관성(self-consistency)을 기준으로 평가합니다.
0.0은 컨텍스트에 완전히 충실한 상태,1.0은 전적으로 날조된 상태입니다. -
toxicity: 유해성(낮을수록 좋음)응답에 유해 콘텐츠가 포함되어 있는지를 hate / harassment / violence / sexual / self_harm / profanity 6개 카테고리 기준으로 판정하며, 탐지된 카테고리 목록을 함께 반환합니다.
0.0은 완전히 안전,1.0은 심각한 유해 상태입니다. -
prompt_injection: 프롬프트 인젝션(낮을수록 좋음)사용자 입력에 포함된 "ignore previous instructions" 류의 오버라이드 시도가 성공했는지, 혹은 응답이 시스템 프롬프트·숨겨진 지시·기밀 정보를 누출했는지를 판정합니다.
0.0은 원래 작업을 그대로 수행하고 어떤 보호 정보도 노출하지 않은 상태,1.0은 인젝션에 완전히 탈취된 상태입니다. -
factuality: 사실성(높을수록 좋음)응답의 사실적 정확도를 측정합니다. 역사·과학·지리·수학적 사실과 날짜·이름·숫자 등 검증 가능한 객관적 주장을 기준으로 하며, 의견이나 완곡한 표현은 평가 대상에서 제외합니다.
1.0은 모든 사실 주장이 정확한 상태,0.0은 명백히 거짓인 주장이 다수 포함된 상태입니다. 컨텍스트 충실도를 보는hallucination과 달리, factuality는 컨텍스트와 무관하게 응답 자체의 사실 정확도를 봅니다.
Combined Judge
어떤 평가자를 등록하느냐에 따라 judge LLM 호출 횟수가 크게 달라집니다.
개별 평가자 등록 (5회 호출)hallucination / answer_relevance / toxicity / prompt_injection / factuality를 각각 등록하면, 평가마다 별도의 judge LLM 호출이 발생하여 응답 1건당 5회 호출됩니다.
combined_judge 등록 (1회 호출, 기본 권장)CombinedJudgeEvaluator는 5개 aspect를 하나의 통합 평가 요청으로 묶어 judge LLM을 단 1회만 호출하고, 그 결과로 5개 aspect 점수를 모두 받아옵니다. 개별 평가자 5개를 등록한 것 대비 judge 호출 비용을 약 80% 절감할 수 있어 기본 사용을 권장합니다.
종합 위험도 점수 (combined_judge)
combined_judge는 5개 aspect 점수를 하나의 종합 위험도(risk)로 합산합니다. 이때 점수 방향이 다른 두 그룹을 위험도 기준으로 통일합니다.
- 위험 방향 aspect (
hallucination,toxicity,prompt_injection) — 점수가 높을수록 위험하므로 점수를 그대로 위험도로 사용합니다. - 품질 방향 aspect (
answer_relevance,factuality) — 점수가 높을수록 좋으므로1 − score를 위험도로 사용합니다.
각 aspect를 독립적인 위험으로 가정하고, "모든 aspect가 안전할 확률"의 보수(complement)로 종합 위험도를 계산합니다. 통계학의 Probabilistic OR 공식입니다.

계산 예시
위험도 [0.7, 0.3, 0.1, 0.1, 0.2]인 경우: 1 − (0.3 × 0.7 × 0.9 × 0.9 × 0.8) = 0.864
위험도 합산 특성 (시뮬레이션)
| 개별 위험 도 | 최댓값(max) | 종합(compound) |
|---|---|---|
[0.5, 0, 0, 0, 0] | 0.50 | 0.50 |
[0.5, 0.5, 0, 0, 0] | 0.50 | 0.75 |
[0.3, 0.3, 0.3, 0.3, 0.3] | 0.30 | 0.83 |
[1.0, 0, 0, 0, 0] | 1.00 | 1.00 |
종합 위험도는 단순 최댓값보다 항상 크거나 같습니다. 낮은 위험이라도 여러 aspect에 걸쳐 누적되면 종합 위험도는 그만큼 높아지며, 어느 한 aspect가 1.0이면 나머지와 무관하게 종합 위험도도 1.0이 됩니다. 이를 통해 단일 지표로는 놓치기 쉬운 "여러 영역에서 동시에 조금씩 나쁜 응답"을 효과적으로 포착할 수 있습니다.
Operation Type
Operation Type은 LLM 호출을 prompt / chain / agent 단위로 그룹화·필터링하기 위한 사용자 정의 라벨입니다. 지정한 라벨은 메트릭 dimension의 일부가 되므로, prompt 단위로 latency·cost·평가 점수를 분리해 분석할 수 있습니다.
설정 키
| 키 | 의미 | 기본값 |
|---|---|---|
operation_type | prompt / chain / agent 이름 | 'default' |
prompt_version | 프 롬프트 버전 | 'v1' |
사용 방법
from whatap.llm import prompt_meta
@prompt_meta(operation_type='checkout_chain', prompt_version='v3')
def checkout(question):
return client.chat.completions.create(...)
from whatap.llm import prompt_meta_scope
def handler(req):
with prompt_meta_scope(operation_type='greeting', prompt_version='v2'):
return client.chat.completions.create(...)
from whatap.llm import get_prompt_meta
op_type, version = get_prompt_meta() # 스코프가 없으면 ('default', 'v1') 반환