Günlük Kaydı ve Belgeleme Stratejileri
Yeniden üretilebilir hata ayıklama için istem sürümlerini, girdileri ve çıktıları kaydetme.
Günlük Kaydı ve Belgeleme Stratejileri, CoddyKit'te ücretsiz bir AI Prompt Engineering dersidir. Bu, 4 dersinin 4. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, AI Prompt Engineering öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. AI Prompt Engineering kursu toplamda 4 dersten oluşur.
İstemleri Günlüğe Kaydetmek Neden Önemlidir
Günlükleme olmadan istem hataları, bir kullanıcı bildirene kadar görünmez kalır. Günlükleme sayesinde şunları yapabilirsiniz:
- Gerilemeleri ortaya çıktıkları anda saptamak
- Geçmişteki herhangi bir hatayı tam olarak gerçekleştiği biçimde yeniden oluşturmak
- İstemler geliştikçe zaman içindeki iyileşmeyi ölçmek
- Uyumluluk veya güvenlik açısından model davranışını denetlemek
Günlükleme, üretim istem sistemleri için isteğe bağlı değildir — güvenilir LLM uygulamalarının temelidir.
Asgari Kullanılabilir Günlük Girdisi
Her istem etkileşimi, en azından şu alanları günlüğe kaydetmelidir:
timestamp: ISO 8601 UTCprompt_id: hangi istem şablonunun kullanıldığımodel: modelin tam adı ve sürümütemperature: örnekleme parametresiinput: kullanıcı mesajı (veya PII varsa bir karma değeri)output: model yanıtılatency_ms: yanıt süresitokens_used: girdi + çıktı belirteçleri
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 outputYapılandırılmış Günlük Biçimi
Günlük dosyaları için satır sonlarıyla ayrılmış JSON (JSONL) kullanın. Her satır eksiksiz ve geçerli bir JSON nesnesidir. Bu biçim:
- Kilit kullanmadan eklemeyi kolaylaştırır
- jq, pandas ve tüm günlük toplama araçları tarafından okunabilir
- Akış işlemeye uygundur — her satır geldiği anda işlenebilir
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)}')İstem Sürümleme
İstemler zaman içinde değişir. Sürümleme olmadan geçmiş davranışı yeniden oluşturamaz veya istem sürümleri arasındaki model çıktılarını karşılaştıramazsınız. Her günlük girdisinde bir sürüm tanımlayıcısı kullanın.
Basit sürümleme: anlamsal bir sürüm dizesi (ör. v1.2.3) veya bir git işleme karması. İstem sürümlerini özel bir dosyada saklayın; böylece yeniden oynatma için herhangi bir sürüm alınabilir.
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'] = versionGünlüklerde PII İşleme
Kullanıcı girdileri kişisel olarak tanımlanabilir bilgiler (PII) içerebilir. Ham girdileri günlüğe kaydetmek GDPR veya CCPA'yı ihlal edebilir. Seçenekler:
- Karma: girdinin SHA-256 değerini saklayın — tekilleştirme için yeniden üretilebilir, ancak yeniden oynatma için değildir
- Maskeleme: günlüğe kaydetmeden önce PII'yi değiştirmek üzere bir düzenli ifade veya NER modeli kullanın
- Ayrı depolama: PII'yi erişim denetimleri olan şifreli bir depoda günlüğe kaydedin; ana günlükte yalnızca bir başvuru ID'si kaydedin
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)Gecikme ve Maliyet Takibi
Günlükler maliyet ve gecikme panolarını mümkün kılar. Bir istem değişikliğinden sonra performans veya maliyet gerilemelerini saptamak için istem sürümü başına ölçümleri izleyin:
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}')Çıktı Değerlendirmesini Günlüğe Kaydetme
Ham günlüklerin ötesinde, her günlük girdisinin yanında değerlendirme puanlarını saklayın. Bu, eğilim analizini mümkün kılar: İstem sürümleri arasında çıktı kalitesi iyileşiyor mu?
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İstem Belgeleri
Her istem şablonunun yanında şu konuları kapsayan bir belge girdisi bulunmalıdır:
- Amaç: bu istemin gerçekleştirdiği görev
- Değişkenler: hangi yer tutucuların bulunduğu ve bunların ne beklediği
- Bilinen sınırlamalar: başarısız olduğu bilinen girdiler
- Sürüm geçmişi: her sürümde neyin ve neden değiştiği
- Sınama durumları: bu istemin sınama paketine bağlantı
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'
}
}Merkezi Günlükleme Hizmetlerini Kullanma
Üretim sistemlerinde günlükleri yerel dosyalar yerine merkezi bir hizmete yazın:
- LangSmith: LangChain'in yerel izleme ve değerlendirme platformu
- Weights and Biases Prompts: istemler için deney takibi
- Datadog / Grafana: özel ölçümlere sahip standart operasyon panoları
- Supabase / PostgreSQL: geçici analiz için günlükleri SQL ile sorgulama
Şema aynıdır; yalnızca hedef değişir.
# 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;Hata Artışlarında Uyarı
Hata oranları bir eşik değerin üzerine çıktığında uyarı verecek şekilde yapılandırın. Örneğin: 5 dakikalık bir zaman aralığında bir isteme yapılan çağrıların %10'undan fazlası geçersiz JSON döndürürse bir uyarı gönderin.
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')Saklama ve Arşivleme
Bir günlük saklama politikası tanımlayın:
- Ham çağrı günlükleri: 30 gün (kayan) — yüksek hacimlidir ve son sorunlarda hata ayıklamak için gereklidir
- Toplulaştırılmış ölçümler: 1 yıl — eğilim analizi ve maliyet tahmini için gereklidir
- Hata günlükleri: süresiz — temel neden örüntülerini belirlemek için gereklidir
30 günden sonra ham günlükleri sıkıştırıp arşivleyin. Hata günlüklerini asla silmeyin — istem mühendisliği için kurumsal hafızanızdır.
Bilgi Kontrolü
İstem günlüklerinde satır sonlarıyla ayrılmış JSON (JSONL) biçimini kullanmanın tek ve büyük bir JSON dizisine kıyasla temel avantajı nedir?
Özet: Günlük Kaydı ve Belgeleme
İstem günlük kaydı ve belgeleme için temel uygulamalar:
- Her çağrıyı günlüğe kaydedin: zaman damgası, istem_kimliği, sürüm, model, sıcaklık, girdi, çıktı, gecikme, belirteçler
- JSONL biçimini kullanın: append için uygundur ve standart araçlarla sorgulanabilir
- İstemleri sürümlendirin: her değişiklik yeni bir sürüm alır; günlükler sürüme başvurur
- PII verilerini yönetin: hassas girdileri günlüğe kaydetmeden önce maskeleyin veya özetleyin
- Maliyeti ve gecikmeyi izleyin: istem güncellemelerinden sonra gerilemeleri tespit edin
- Hata artışlarında uyarı verin: kayan pencereyle hata oranı izleme
Bu, İstem Hatalarını Ayıklama konulu 17. Dersin sonudur. Sıradaki: İstem Enjeksiyonu ve Savunma.
Sıkça Sorulan Sorular
“Günlük Kaydı ve Belgeleme Stratejileri” dersi ücretsiz mi?
Evet — “Günlük Kaydı ve Belgeleme Stratejileri” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve AI Prompt Engineering kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. AI Prompt Engineering kursu toplamda 4 dersten oluşur.
“Günlük Kaydı ve Belgeleme Stratejileri” dersinde ne öğreneceğim?
Yeniden üretilebilir hata ayıklama için istem sürümlerini, girdileri ve çıktıları kaydetme. AI Prompt Engineering ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
AI Prompt Engineering öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te AI Prompt Engineering, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 4. dersidir.
“Günlük Kaydı ve Belgeleme Stratejileri” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu AI Prompt Engineering dersinde kod yazıp çalıştırabilir miyim?
Evet. Her AI Prompt Engineering dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- Beklenmeyen Çıktıları Tanılama
- İstemler için Kök Neden Analizi
- Sistematik Hata Ayıklama Yaklaşımı
- Günlük Kaydı ve Belgeleme Stratejileri