프롬프트는 코드다
많은 팀이 프롬프트를 하드코딩합니다. 누가 언제 왜 바꿨는지 추적이 안 되고, 성능이 나빠져도 원인을 찾기 어렵습니다.
Git 기반 프롬프트 레지스트리
CODE
prompts/
├── customer_service/
│ ├── refund_handler.v1.yaml
│ ├── refund_handler.v2.yaml ← 현재 프로덕션
│ └── refund_handler.v3.yaml ← 실험 중
└── content_generation/
└── blog_writer.v4.yamlYAML
# refund_handler.v2.yaml
version: "2.0.1"
model: "claude-sonnet-4-6"
temperature: 0.1
system: |
당신은 {{company_name}}의 CS 전문가입니다.
환불 정책: {{refund_policy}}
metadata:
author: "team-cx"
eval_score: 0.87
changelog: "공감 표현 강화, 거절 문구 부드럽게"Python
class PromptRegistry:
def __init__(self, dir: str = "prompts"):
self.dir = Path(dir)
def get(self, name: str, version: str = "latest") -> dict:
if version == "latest":
files = sorted(self.dir.glob(f"**/{name}.v*.yaml"))
return yaml.safe_load(files[-1].read_text())
return yaml.safe_load((self.dir / f"{name}.{version}.yaml").read_text())A/B 테스트: 트래픽 분할
Python
import hashlib
class PromptABTest:
def __init__(self, control: str, experiment: str, split: float = 0.1):
self.control = control
self.experiment = experiment
self.split = split
def get_version(self, user_id: str) -> str:
# 동일 user_id는 항상 같은 그룹 (일관된 UX)
h = int(hashlib.md5(user_id.encode()).hexdigest(), 16)
return self.experiment if (h % 100) < (self.split * 100) else self.controlLLM-as-Judge 자동 평가
Python
JUDGE = """
고객 문의: {msg}
에이전트 응답: {resp}
1~5점 채점 후 JSON만 반환:
- empathy: 고객 감정 공감도
- accuracy: 정보 정확도
- resolution: 문제 해결도
- overall: 종합
{"empathy": N, "accuracy": N, "resolution": N, "overall": N}
"""
async def llm_judge(msg: str, resp: str) -> dict:
result = await llm.generate(JUDGE.format(msg=msg, resp=resp), temperature=0)
return json.loads(result)통계적 유의성 검정
Python
from scipy import stats
def analyze_ab(ctrl_scores: list, exp_scores: list) -> dict:
_, p = stats.ttest_ind(ctrl_scores, exp_scores)
ctrl_m = sum(ctrl_scores) / len(ctrl_scores)
exp_m = sum(exp_scores) / len(exp_scores)
return {
"control_mean": ctrl_m,
"experiment_mean": exp_m,
"improvement": f"{(exp_m - ctrl_m) / ctrl_m * 100:+.1f}%",
"p_value": p,
"significant": p < 0.05,
"winner": "experiment" if exp_m > ctrl_m and p < 0.05 else "control"
}CI/CD 통합
YAML
# .github/workflows/prompt-eval.yml
on:
push:
paths: ["prompts/**/*.yaml"]
jobs:
eval:
steps:
- run: python scripts/validate_prompts.py
- run: python scripts/run_evals.py --dataset golden --threshold 0.82
- run: python scripts/register_ab_test.py --version ${{ github.sha }}이 3편 시리즈로 프롬프트 엔지니어링의 전 과정(기법 습득→고급 패턴→체계적 운영)이 완성됩니다.
버전 태그 규칙
TEXT
prompts/support_v3.md
changelog: 2026-09-01 tone 완화, tool schema 추가
owner: platform-ai| 환경 | 참조 |
|---|---|
| staging | main 또는 rc/* |
| production | 불변 태그 vX.Y |
A/B 최소 설계
- 트래픽 5–20%로 B 노출
- 1차 지표: 작업 성공률 / 재질문율
- 가드레일: 정책 위반율 동시 모니터링
- 승자만 prod 태그 승격
A/B 결과를 잘못 읽는 흔한 원인과 점검
프롬프트 A/B 테스트는 설계보다 결과 해석에서 더 자주 틀립니다.
원인
- 사용자 단위가 아니라 요청 단위로 무작위 배정해, 같은 사용자가 두 버전을 섞어 경험함
- 유의성이 나올 때까지 매일 결과를 들여다보다 멈추는 "중간 확인(peeking)"으로 거짓 양성이 늘어남
- LLM-as-Judge 평가 모델이 긴 답변이나 특정 위치(첫 번째 제시된 답)를 선호하는 편향
점검 방법
- 배정 로그에서 사용자별로 버전이 하나만 나오는지 확인합니다.
SQL
SELECT user_id, count(DISTINCT prompt_version) AS v
FROM llm_requests WHERE experiment = 'summary-v3'
GROUP BY user_id HAVING count(DISTINCT prompt_version) > 1;- 표본 크기와 종료 시점을 시작 전에 정하고, 그 전에는 결과를 의사결정에 쓰지 않습니다.
- Judge 편향 점검: 같은 두 답변을 순서만 바꿔 두 번 평가해 판정이 뒤집히는 비율을 측정합니다. 비율이 높으면 양쪽 순서 평가를 평균하거나 사람 평가 샘플로 보정합니다.
해결
- 사용자 ID 해시로 버전을 고정 배정합니다(예:
int(hashlib.sha256(user_id.encode()).hexdigest(), 16) % 100 < 50). 파이썬 내장hash()는 문자열 값이 프로세스마다 달라(PYTHONHASHSEED) 워커나 재시작에 따라 배정이 바뀌므로 쓰지 않습니다. - 품질 지표와 함께 비용(토큰 수)과 지연 지표를 같이 비교해, 품질 차이가 작으면 저렴한 쪽을 선택합니다.
재발 방지
- 실험 정의(가설, 지표, 표본 크기, 종료 조건)를 프롬프트와 같은 저장소에 문서로 남깁니다.
참고 자료
검증 환경·편집자 주
- 2026-09. 시크릿·PII는 프롬프트 파일에 넣지 마세요.
자주 묻는 질문 (FAQ)
Q. 온도(temperature)도 버전하나요?
네. 모델·온도·툴 스키마를 한 릴리스로 묶어야 재현이 됩니다.
✦ ✦ ✦
출처·검증 안내
글마다 출처와 확인 범위가 다릅니다. 아래에 확인일·확인 범위·출처가 기록된 글만 그 범위에서 확인된 것입니다. 기록이 없는 글은 적용 전 사용 중인 버전의 공식 문서로 직접 확인하고, 오류는 이메일로 알려주세요. 편집 정책 · 이메일로 제보
이 글에는 사람이 확인한 날짜·범위 기록이 아직 없습니다.
주제 관련 공식 문서(자동 연결 · 문장별 근거 아님)Git 공식 문서 ↗
이 글이 도움이 되었나요?
댓글
첫 번째 댓글을 남겨보세요.