로깅 및 문서화 전략
재현 가능한 디버깅을 위해 프롬프트 버전, 입력, 출력을 기록합니다.
로깅 및 문서화 전략은(는) CoddyKit의 무료 AI Prompt Engineering 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 AI Prompt Engineering 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. AI Prompt Engineering 강의에는 총 4개의 강의가 포함되어 있습니다.
프롬프트 기록이 중요한 이유
기록이 없으면 사용자가 보고할 때까지 프롬프트 실패를 알 수 없습니다. 기록을 사용하면 다음을 수행할 수 있습니다:
- 회귀가 발생하는 즉시 감지
- 과거의 모든 실패를 발생 당시와 정확히 동일하게 재현
- 프롬프트가 발전하면서 시간에 따른 개선 정도 측정
- 규정 준수 또는 안전성을 위해 모델 동작 감사
운영 프롬프트 시스템에서 기록은 선택 사항이 아닙니다. 신뢰할 수 있는 LLM 애플리케이션의 기반입니다.
최소 필수 기록 항목
모든 프롬프트 상호작용은 최소한 다음 필드를 기록해야 합니다:
timestamp: ISO 8601 UTCprompt_id: 사용된 프롬프트 템플릿model: 정확한 모델 이름 및 버전temperature: 샘플링 매개변수input: 사용자 메시지(PII가 포함된 경우 해시)output: 모델 응답latency_ms: 응답 시간tokens_used: 입력 + 출력 토큰
import time, json
from datetime import datetime, timezone
def logged_call(prompt_id, system_prompt, user_message, model='gpt-4o', temperature=0.7):
start = time.time()
resp = client.chat.completions.create(
model=model,
messages=[
{'role': 'system', 'content': system_prompt},
{'role': 'user', 'content': user_message}
],
temperature=temperature
)
latency = int((time.time() - start) * 1000)
output = resp.choices[0].message.content
log_entry = {
'timestamp': datetime.now(timezone.utc).isoformat(),
'prompt_id': prompt_id,
'model': model,
'temperature': temperature,
'input': user_message,
'output': output,
'latency_ms': latency,
'input_tokens': resp.usage.prompt_tokens,
'output_tokens': resp.usage.completion_tokens
}
append_log(log_entry)
return output구조화된 기록 형식
기록 파일에는 줄바꿈으로 구분된 JSON(JSONL)을 사용하십시오. 각 줄은 완전하고 유효한 JSON 객체입니다. 이 형식은 다음과 같은 장점이 있습니다:
- 잠금 없이 쉽게 추가할 수 있음
- jq, 판다스 및 모든 기록 집계 도구에서 읽을 수 있음
- 실시간 처리에 적합함 — 각 줄을 도착하는 즉시 처리할 수 있음
import json
LOG_FILE = 'prompt_logs.jsonl'
def append_log(entry):
with open(LOG_FILE, 'a') as f:
f.write(json.dumps(entry) + '\n')
def read_logs():
with open(LOG_FILE) as f:
return [json.loads(line) for line in f if line.strip()]
# Query: all entries for prompt_id 'summarize_v3'
logs = read_logs()
summarize_logs = [e for e in logs if e['prompt_id'] == 'summarize_v3']
print(f'Total calls to summarize_v3: {len(summarize_logs)}')프롬프트 버전 관리
프롬프트는 시간이 지나면서 변경됩니다. 버전 관리가 없으면 과거 동작을 재현하거나 프롬프트 버전 간 모델 출력을 비교할 수 없습니다. 모든 기록 항목에 버전 식별자를 사용하십시오.
간단한 버전 관리 방법은 의미론적 버전 문자열(예: v1.2.3) 또는 깃 커밋 해시를 사용하는 것입니다. 프롬프트 버전은 전용 파일에 저장하여 어떤 버전이든 재실행에 사용할 수 있도록 검색 가능하게 하십시오.
PROMPTS = {
'summarize': {
'v1': 'Summarize the following text.',
'v2': 'Summarize the following text in 3 sentences.',
'v3': 'Summarize the following text in exactly 3 sentences. '
'Start each sentence on a new line. No bullet points.'
}
}
CURRENT_VERSIONS = {'summarize': 'v3'}
def get_prompt(prompt_id):
version = CURRENT_VERSIONS[prompt_id]
return version, PROMPTS[prompt_id][version]
version, prompt = get_prompt('summarize')
log_entry['prompt_version'] = version기록에서 PII 처리
사용자 입력에는 개인 식별 정보(PII)가 포함될 수 있습니다. 원시 입력을 기록하면 GDPR 또는 CCPA를 위반할 수 있습니다. 선택지는 다음과 같습니다:
- 해시: 입력의 SHA-256을 저장합니다. 중복 제거에는 재현 가능하지만 재실행에는 사용할 수 없습니다
- 가리기: 정규식 또는 NER 모델을 사용하여 기록하기 전에 PII를 대체합니다
- 별도 저장: 접근 제어가 적용된 암호화 저장소에 PII를 기록하고, 주 기록에는 참조 ID만 기록합니다
import hashlib, re
def redact_pii(text):
# Redact email addresses
text = re.sub(r'[\w.-]+@[\w.-]+\.\w+', '[EMAIL]', text)
# Redact phone numbers (US format)
text = re.sub(r'\b\d{3}[-.]\d{3}[-.]\d{4}\b', '[PHONE]', text)
return text
def hash_input(text):
return hashlib.sha256(text.encode()).hexdigest()[:16]
log_entry['input'] = redact_pii(user_message)
log_entry['input_hash'] = hash_input(user_message)지연 시간 및 비용 추적
기록을 통해 비용 및 지연 시간 현황판을 만들 수 있습니다. 프롬프트 변경 후 성능이나 비용의 회귀를 감지할 수 있도록 프롬프트 버전별 지표를 추적하십시오:
def compute_cost(entry, price_per_1m_input=5.0, price_per_1m_output=15.0):
input_cost = entry['input_tokens'] / 1_000_000 * price_per_1m_input
output_cost = entry['output_tokens'] / 1_000_000 * price_per_1m_output
return input_cost + output_cost
def prompt_stats(prompt_id, version):
logs = [e for e in read_logs()
if e['prompt_id'] == prompt_id and e.get('prompt_version') == version]
if not logs:
return
avg_latency = sum(e['latency_ms'] for e in logs) / len(logs)
total_cost = sum(compute_cost(e) for e in logs)
print(f'{prompt_id} {version}: {len(logs)} calls, avg {avg_latency:.0f}ms, total ${total_cost:.4f}')출력 평가 기록
원시 기록을 넘어 각 기록 항목에 평가 점수도 함께 저장하십시오. 이를 통해 추세를 분석할 수 있습니다. 프롬프트 버전이 바뀌면서 출력 품질이 향상되고 있습니까?
def evaluated_call(prompt_id, system_prompt, user_message, evaluator_fn):
output = logged_call(prompt_id, system_prompt, user_message)
score = evaluator_fn(user_message, output)
# Update the last log entry with the evaluation score
logs = read_logs()
last = logs[-1]
last['eval_score'] = score
last['eval_pass'] = score >= 0.8
# Rewrite the last line
with open(LOG_FILE, 'a') as f:
# In practice, use a DB or separate eval log
pass
return output, score프롬프트 문서화
각 프롬프트 템플릿에는 다음 내용을 다루는 문서 항목이 함께 있어야 합니다:
- 목적: 이 프롬프트가 수행하는 작업
- 변수: 어떤 자리표시자가 있으며 각 자리표시자에 어떤 값이 필요한지
- 알려진 제한 사항: 실패하는 것으로 알려진 입력
- 버전 기록: 각 버전에서 무엇이 변경되었으며 그 이유
- 시험 사례: 이 프롬프트의 시험 모음 링크
PROMPT_DOCS = {
'summarize': {
'purpose': 'Summarize a single text passage into 3 sentences.',
'variables': {'text': 'The passage to summarize (max 2000 tokens)'},
'known_limitations': [
'Fails to preserve numbers accurately for texts with many statistics',
'May not summarize correctly for non-English text'
],
'versions': {
'v1': 'Initial version — vague length instruction',
'v2': 'Added 3-sentence limit',
'v3': 'Added line-break and no-bullet formatting fix'
},
'test_suite': 'tests/test_summarize.py'
}
}중앙 집중식 기록 서비스 사용
운영 시스템에서는 로컬 파일 대신 중앙 집중식 서비스에 기록을 작성하십시오:
- LangSmith: LangChain의 기본 추적 및 평가 플랫폼
- 웨이츠 앤 바이어스 프롬프트: 프롬프트 실험 추적
- 데이터독 / 그라파나: 사용자 지정 지표를 지원하는 표준 운영 현황판
- 수파베이스 / PostgreSQL: 에스큐엘로 기록을 조회하여 임시 분석 수행
구조는 동일하고 대상만 변경됩니다.
# Example: writing to Supabase
from supabase import create_client
supabase = create_client('https://xxx.supabase.co', 'your-anon-key')
def log_to_supabase(entry):
supabase.table('prompt_logs').insert(entry).execute()
# Now query with SQL:
# SELECT prompt_id, prompt_version, AVG(latency_ms), COUNT(*)
# FROM prompt_logs
# WHERE timestamp > NOW() - INTERVAL '7 days'
# GROUP BY prompt_id, prompt_version
# ORDER BY COUNT(*) DESC;실패 급증 알림
실패율이 임계값을 초과해 급증하면 알림을 설정하십시오. 예를 들어 5분 구간에서 프롬프트 호출의 10% 초과가 유효하지 않은 JSON을 반환하면 알림을 보내십시오.
from collections import deque
from datetime import datetime, timezone, timedelta
recent_results = deque(maxlen=100) # sliding window
def track_and_alert(prompt_id, success, alert_fn, threshold=0.10):
recent_results.append({'success': success, 'time': datetime.now(timezone.utc)})
window = [
r for r in recent_results
if r['time'] > datetime.now(timezone.utc) - timedelta(minutes=5)
]
if not window:
return
fail_rate = sum(1 for r in window if not r['success']) / len(window)
if fail_rate > threshold:
alert_fn(f'ALERT: {prompt_id} failure rate {fail_rate:.0%} in last 5 min')보존 및 보관
로그 보존 정책을 정의하십시오:
- 원시 호출 로그: 30일(순환 방식) — 양이 많고 최근 문제를 디버깅하는 데 필요합니다
- 집계 지표: 1년 — 추세 분석과 비용 예측에 필요합니다
- 실패 로그: 무기한 — 근본 원인 패턴을 파악하는 데 필요합니다
30일이 지난 원시 로그는 압축하여 보관하십시오. 실패 로그는 절대 삭제하지 마십시오. 실패 로그는 프롬프트 엔지니어링을 위한 조직의 축적된 기억입니다.
지식 확인
하나의 큰 JSON 배열과 비교할 때 프롬프트 로그에 줄바꿈으로 구분된 JSON(JSONL) 형식을 사용하는 주요 장점은 무엇입니까?
복습: 로그 기록과 문서화
프롬프트 로그 기록과 문서화를 위한 주요 관행:
- 모든 호출 기록: 시간 기록, 프롬프트 ID, 버전, 모델, 온도, 입력, 출력, 지연 시간, 토큰 수
- JSONL 형식 사용: 추가에 적합하며 표준 도구로 조회할 수 있음
- 프롬프트 버전 관리: 모든 변경 사항에 새 버전을 부여하고 로그에서 해당 버전을 참조함
- PII 처리: 기록하기 전에 민감한 입력을 마스킹하거나 해시 처리함
- 비용과 지연 시간 추적: 프롬프트 업데이트 후 회귀를 감지함
- 실패 급증 시 알림: 이동 구간별 실패율 모니터링
이것으로 프롬프트 실패 디버깅에 관한 17번 과정을 마칩니다. 다음: 프롬프트 주입과 방어.
자주 묻는 질문
“로깅 및 문서화 전략” 강의는 무료인가요?
네 — “로깅 및 문서화 전략” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 AI Prompt Engineering 강의 전체를 잠금 해제할 수 있습니다. AI Prompt Engineering 강의에는 총 4개의 강의가 포함되어 있습니다.
“로깅 및 문서화 전략”에서 뭘 배우나요?
재현 가능한 디버깅을 위해 프롬프트 버전, 입력, 출력을 기록합니다. 브라우저에서 직접 실행하는 실습 코드로 AI Prompt Engineering을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
AI Prompt Engineering을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 AI Prompt Engineering은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.
“로깅 및 문서화 전략” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 AI Prompt Engineering 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 AI Prompt Engineering 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 예상치 못한 출력 진단
- 프롬프트의 근본 원인 분석
- 체계적인 디버깅 접근법
- 로깅 및 문서화 전략