
Tue Sep 01 2026

Model seçmek kolay, zor kısmı üretime almak 🎯.
Geçen yıl bir hackathon’da harika bir demo hazırladık; model %98 doğrulukla çalışıyordu, herkes alkışladı. Ama canlıya aldığımızda maliyet patladı 💸 ve gecikme 5‑10 kat arttı ⏱. O an anladım ki: AI Mühendisliği sadece model eğitmek değil, Üretim Ortamı'na uygun hale getirmek demek.
Bu yüzden bu yazının odak noktası “AI Üretim Hazırlığı Kontrol Listesi” olacak. Liste maddeleri üzerinden gidip, her birinin neden kritiğini ve nasıl çözeceğimizi konuşacağız. Hazırsan başlayalım 🚀.
Her maddeyi tek tek inceleyeceğiz, pratik ipuçları vereceğim ve “Ne oluyor burada?” diye sorarak mantığı kavrayacağız. Hadi başlayalım! 🎉
Modeli eğittiğimizde her şey mükemmel görünüyordu — metrikler yeşildi, test seti de memnun ediciydi. Ama canlıya aldığımızda hikaye tamamen değişti. İşte benim de başıma gelen, ve muhtemelen sizin de başınıza gelebilecek beş yaygın tuzak 🎯:
🔇 Sessiz hatalar (silent failures)
Ben şunu yaşadım: model bir girdi için boş ya da anlamsız bir cevap döndürdü, ama hata kodu 200 OK döndü. İzleme (monitoring) yokmuş gibi göründü, kullanıcı şikayet etene kadar fark etmedik.
Mühendislik eksikliği: Çıktı doğrulama (output validation) ve LLM Evalüasyonu pipeline’ı koymamıştık.
💸 Beklenmedik maliyet patlamaları
Ben şunu yaşadım: birden fazla büyük model (ör. 70B parametre) aynı anda çağrılıyordu, token maliyeti geceleri 3‑4 kat arttı. Faturalar geldikten sonra anladık ki batch‑processing ya da model distillation düşünmemişiz.
Mühendislik eksikliği: maliyet modellemesi ve rate‑limit / quota guardrail’leri eksikti.
⏱ Gecikme (latency) sorunları
Ben şunu yaşadım: gerçek‑zamanlı sohbet botunda 3‑5 sn cevap süresi, kullanıcı deneyimini bozdu. Asenkron akış ya da caching stratejisi yoktu.
Mühendislik eksikliği: SLA tanımlaması ve performance guardrails (max latency, timeout) konulmamıştı.
📉 Veri sapması (data drift)
Ben şunu yaşadım: eğitim verisinde nadir görülen bir argo/terim üretimde sıkça geçti, model halüsine girdi. Drift algılama (data drift detection) modülü yoktu, model aylarca yanlış tahmin üretti.
Mühendislik eksikliği: Sürekli veri izleme ve re‑training trigger mekanizması koymamıştık.
🔓 Güvenlik ihlalleri (prompt injection, PII leakage)
Ben şunu yaşadım: bir kullanıcı “ignore previous instructions” payload’ı gönderdi, model hassas veri (API key, e‑posta) sızdırdı. Guardrails (input/output filter, PII maskeler) yoktu.
Mühendislik eksikliği: Güvenlik katmanı (input sanitization, output redaction) ilk günden entegre edilmemişti.
Bu tuzakların hepsi “model iyi, mühendislik kötü” demekten ibaret. Modeli canlıya almak bir yazılım dağıtımıdır — aynı disiplin, aynı gözlem, aynı güvenlik gerektirir. ✅
Hazırsan bu kontrol listesiyle prod'a çıkmadan önce mutlaka kontrol etmemiz gereken 5 katmanı tek tek inceleyelim 👇
| Katman | Ne? | Neden? | Nasıl? |
|---|---|---|---|
| Evals 🧪 | Model çıktılarını sistematik test etme | "İyi görünüyor" demek yetmez, kanıt lazım | Otomatik test seti + LLM-as-judge pipeline |
| Gözlemlenebilirlik 🔍 | Log, trace, metrik toplama | Sürpriz olmasın, hata anında görünsün | Structured logging + distributed tracing + dashboards |
| Maliyet/Gecikme ⚡ | Token, latency, $/request takibi | Bütçe patlamasın, kullanıcı beklemesin | Caching, routing, model seçim stratejisi |
| Veri Sapması 📊 | Input/output dağılım değişiklikleri | Model sessizce bozulmasın | Drift detection + periyodik yeniden değerlendirme |
| Guardrails 🛡 | Güvenlik, PII, policy ihlali engelleme | Riskli çıktı prod'a gitmesin | Input/output filter + rule engine + fallback |
- [ ] **LLM Evalüasyonu**: Otomatik testler ve LLM-as-judge pipeline'ı kuruldu
- [ ] **Gözlemlenebilirlik**: Loglama, tracing ve metrikler entegre edildi
- [ ] **Maliyet & Gecikme**: Token kullanımı, latency ve $/request SLA'sı tanımlandı
- [ ] **Veri Sapması**: Drift detection ve periyodik yeniden değerlendirme planı hazır
- [ ] **Guardrails**: Input/output filtreleri, PII koruması ve policy engine aktif
Bu 5 madde sadece birer checkbox değil — her biri gece uyumanı sağlayan bir sigorta poliçesi 🛡️
Hepsini tiklediğinde: "Modelim prod'da nasıl davranıyor?" sorusuna veriyle, loglarla, metriklerle cevap verebilirsin.
Hadi bir sonraki katmandan başlayalım — Evals'e dalıyoruz! 🚀
Hazırsan başlayalım. Çoğumuz "model çalışıyor, yeter" derken aslında sürekli değişen bir hedefi vuruyoruz 🎯. Evalüasyon bir kez yazıp unuttuğumuz test dosyası değil, kodunuzla aynı repo'da yaşayan, CI/CD'den geçen, her deploy'da size "bu değişim kötü mü iyi mi?" diye çenen sürekli bir süreç.
Bu yüzden üç katmanlı bir yaklaşım benimsiyorum:
| Katman | Ne İşe Yarar? | Hız | Maliyet | Güvenilirlik |
|---|---|---|---|---|
| Unit / Otomatik | Format, yasaklı kelime, schema, latency | ⚡ Çok hızlı | 💰 Düşük | ✅ Yüksek (deterministik) |
| LLM-as-Judge | Semantik benzerlik, tutarlılık, ton | 🚀 Orta | 💰💰 Orta | ⚠️ Judge de yanılabilir |
| Human Eval | Nuans, güvenlik, ürün hissiyatı | 🐢 Yavaş | 💰💰💰 Yüksek | ✅ En güvenilir |
Pratik kural: Her PR'da unit + LLM-as-judge koşar, haftada bir human eval oturumu yaparız. Böylece "gece deploy ettim, sabah kahve içip bakıyorum" derdi bitmiş olur ☕.
GitHub Actions örneğiyle adım adım:
# .github/workflows/llm-eval.yml
name: LLM Evaluation Pipeline
on:
pull_request:
branches: [main, develop]
push:
branches: [main]
jobs:
eval:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install deps
run: |
pip install -r requirements.txt
pip install pytest pytest-asyncio
- name: Run unit evals (fast, deterministic)
run: pytest tests/eval_unit.py -v --tb=short
- name: Run LLM-as-Judge evals (semantic)
if: github.event_name == 'pull_request'
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: pytest tests/eval_llm_judge.py -v --tb=short
- name: Upload eval report
if: always()
uses: actions/upload-artifact@v4
with:
name: eval-report
path: eval_results/
Ne oluyor burada?
eval_results/ klasörüne yazılır, artifact olarak yüklenir 📊main branch'ine merge olmadan kırmızı badge görürsünüz ⛔| Metrik | Neden Önemli? | Hedef |
|---|---|---|
| Accuracy (doğruluk) | Ground truth'a ne kadar yakın? | > 0.85 |
| Latency (p95) | Kullanıcı deneyimi | < 2.5s |
| Token Usage | Maliyet kontrolü | Trend izle |
| Hallucination Rate | Güvenilirlik | < 2% |
| Format Compliance | Downstream parser'ın patlamaması | 100% |
Bu metrikleri Prometheus/Grafana'a push edip, "son 7 günde hallucination rate %1.2 → %3.4 çıktı" diye alarm kuruyorum 🚨.
Hadi pratik bir örnek üzerinden anlayalım. Aşağıdaki test üç kriteri doğrular:
# tests/eval_unit.py
import json
import pytest
from sentence_transformers import SentenceTransformer, util
# --- Test verileri ---
TEST_CASES = [
{
"name": "valid_json_no_banned_high_similarity",
"llm_response": '{"answer": "İstanbul Türkiye'nin en kalabalık şehridir.", "confidence": 0.95}',
"ground_truth": "İstanbul Türkiye'nin en nüfuslu şehridir.",
"banned_words": ["hack", "bypass", "exploit", "ignore"],
"min_similarity": 0.8,
},
{
"name": "invalid_json_format",
"llm_response': 'Bu bir JSON değil, düz metin.',
"ground_truth": "İstanbul Türkiye'nin en nüfuslu şehridir.",
"banned_words": ["hack", "bypass"],
"min_similarity": 0.8,
},
{
"name": "contains_banned_word",
"llm_response": '{"answer": "Bu sistemi hack etmek için şu yolu izleyin.", "confidence": 0.9}',
"ground_truth": "İstanbul Türkiye'nin en nüfuslu şehridir.",
"banned_words": ["hack", "bypass"],
"min_similarity": 0.8,
},
]
# --- Embedding modeli (hafif, hızlı) ---
@pytest.fixture(scope="session")
def embedder():
# all-MiniLM-L6-v2: 384 dim, ~80MB, CPU'da hızlı
return SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
# --- Yardımcı fonksiyonlar ---
def is_valid_json(text: str) -> bool:
"""Cevap geçerli JSON mı?"""
try:
json.loads(text)
return True
except json.JSONDecodeError:
return False
def contains_banned(text: str, banned: list[str]) -> bool:
"""Yasaklı kelime var mı? (case-insensitive)"""
lower = text.lower()
return any(word.lower() in lower for word in banned)
def semantic_similarity(text1: str, text2: str, model) -> float:
"""Cosine similarity (0-1 arası)"""
emb1 = model.encode(text1, convert_to_tensor=True)
emb2 = model.encode(text2, convert_to_tensor=True)
return float(util.cos_sim(emb1, emb2).item())
# --- Ana test fonksiyonu ---
@pytest.mark.parametrize("case", TEST_CASES, ids=lambda c: c["name"])
def test_llm_response_quality(case, embedder):
"""
LLM cevabı 3 kritere göre değerlendirilir:
1. JSON formatında olmalı
2. Yasaklı kelime içermemeli
3. Ground truth ile semantik benzerlik > threshold
"""
response = case["llm_response"]
ground_truth = case["ground_truth"]
banned = case["banned_words"]
threshold = case["min_similarity"]
# 1️⃣ JSON format kontrolü
assert is_valid_json(response), f"❌ Geçersiz JSON: {response[:100]}..."
# JSON parse edip 'answer' alanını alıyoruz (semantik karşılaştırma için)
parsed = json.loads(response)
answer_text = parsed.get("answer", "")
# 2️⃣ Yasaklı kelime kontrolü
assert not contains_banned(answer_text, banned), \
f"❌ Yasaklı kelime tespit edildi: {answer_text}"
# 3️⃣ Semantik benzerlik kontrolü
sim = semantic_similarity(answer_text, ground_truth, embedder)
assert sim >= threshold, \
f"❌ Benzerlik düşük: {sim:.3f} < {threshold} (cevap: '{answer_text}')"
# ✅ Hepsi geçti
print(f"✅ [{case['name']}] similarity={sim:.3f} | JSON=OK | Banned=OK")
Bu dosyayı şu komutla çalıştırırsınız:
pytest tests/eval_unit.py -v
Çıktı örneği:
tests/eval_unit.py::test_llm_response_quality[valid_json_no_banned_high_similarity] PASSED
tests/eval_unit.py::test_llm_response_quality[invalid_json_format] FAILED
tests/eval_unit.py::test_llm_response_quality[contains_banned_word] FAILED
Sonuç olarak: Evalüasyon "test yazmak" değil, güvenle deploy etmeyi sağlayan canlı bir sistemdir. Küçük başlayın (unit testler), sonra LLM-as-judge ekleyin, CI/CD'ye bağlayın. Geleceğiniz siz size minnettar olacak 😉.
Hazırsan başlayalım 🎯. Bir LLM tabanlı uygulamayı canlıya aldığında, model “kara kutu” gibi davranır: girdi veriyorsun, çıktı alıyorsun ama arada ne olduğunu bilmezsin. İşte gözlemlenebilirlik (observability) devreye giriyor — üç bacak ile bu kutuyu aydınlatıyorsun:
LLM bağlamında tracing vazgeçilmez çünkü:
Geçen hafta prod’da bir “JSON parse hatası” aldık. Kullanıcı “Ürün fiyatını ver” dedi, model ise geçersiz JSON döndürdü. Langfuse trace’ini açtım:
gpt‑4o 1.200 token çıktı.json.loads başarısız oldu.5 dakika sonra prompt’a “Sadece geçerli JSON döndür” kuralı ekledim, yeniden deploy ettim ve hata ortadan kalktı. Trace olmasaydı günlerce loglarda boğulurdum 😅.
Aşağıdaki snippet, herhangi bir LLM çağrısını (OpenAI, Anthropic, yerel model…) input, output, token sayısı, hata durumu olarak trace eder. Kendi projenizde @trace_llm ekleyip unutursunuz.
# tracing_decorator.py
import functools
import time
from opentelemetry import trace
from opentelemetry.trace import Status, StatusCode
tracer = trace.get_tracer(__name__)
def trace_llm(func):
"""LLM çağrısını OpenTelemetry span'ı içine alır."""
@functools.wraps(func)
def wrapper(*args, **kwargs):
# Span başlat
with tracer.start_as_current_span(f"llm.{func.__name__}") as span:
start = time.perf_counter()
try:
# ---- Girdi logla ----
span.set_attribute("llm.input.args", str(args))
span.set_attribute("llm.input.kwargs", str(kwargs))
# Fonksiyonu çalıştır
result = func(*args, **kwargs)
# ---- Çıktı ve token sayısı logla ----
# Varsayım: result dict içerisinde 'text' ve 'usage' anahtarları var
output_text = result.get("text", "")
usage = result.get("usage", {})
span.set_attribute("llm.output.text", output_text[:500]) # ilk 500 char
span.set_attribute("llm.usage.prompt_tokens", usage.get("prompt_tokens", 0))
span.set_attribute("llm.usage.completion_tokens", usage.get("completion_tokens", 0))
span.set_attribute("llm.usage.total_tokens", usage.get("total_tokens", 0))
span.set_status(Status(StatusCode.OK))
return result
except Exception as exc:
# Hata durumunu span'a işle
span.record_exception(exc)
span.set_status(Status(StatusCode.ERROR, str(exc)))
raise
finally:
duration_ms = (time.perf_counter() - start) * 1000
span.set_attribute("llm.duration_ms", round(duration_ms, 2))
return wrapper
Nasıl çalışıyor?
llm.<fonksiyon_adı> adıyla.args, kwargs) attribute olarak eklenir.result beklenir.record_exception ile trace’e hata stack’i düşer, span ERROR statüsüne geçer.Kullanım örneği
@trace_llm
def call_openai(prompt: str, model: str = "gpt-4o"):
# OpenAI SDK çağrısı (basitleştirilmiş)
response = openai_client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt}],
)
return {
"text": response.choices[0].message.content,
"usage": {
"prompt_tokens": response.usage.prompt_tokens,
"completion_tokens": response.usage.completion_tokens,
"total_tokens": response.usage.total_tokens,
},
}
Artık her call_openai çağrısı tam bir trace bırakıyor. Langfuse, LangSmith ya da kendi OpenTelemetry backend’inde “Model ne düşündü?” sorusuna tek tıkla cevap bulursunuz 🚀.
@trace_llm dekoratörünü kopyala, projene ekle, her LLM çağrını sar. Gerisi otomatik 🎉.Bir sonraki bölümde metrikleri nasıl dashboard’a dökeceğimiz ve alarmları nasıl kuracağımız konuşacağız. Görüşmek üzere! 👋
Maliyet ve gecikme sadece technical metric değil, ticari kısıtlayıcı 🎯.
Bir ürün sahibi olarak “Bu ay bütçeyi aştık” veya “Kullanıcı 10 sn bekledi” duymak istemezsiniz.
Bu yüzden her istekte para ve süreyi birden kontrol etmemiz lazım.
| Strateji | Ne işe yarar? | ✅ Avantaj | ❌ Dezavantaj |
|---|---|---|---|
| Semantic Caching (GPTCache) | Aynı anlama gelen sorguları vektör uzayında eşleştirip cevabı tekrar üretir. | Maliyeti %40–%60 düşürebilir, gecikme ms seviyesine iner. | Cache boyutu büyürse bellek/yönetim maliyeti artar; stale cevap riski var. |
| Model Routing | Basit sorular → gpt‑3.5‑turbo, karmaşık → gpt‑4. | Pahalı modeli sadece gerekli yerde çalıştırır. | Routing mantığı yanlışsa kalite kaybı yaşanabilir. |
| Token Optimizasyonu (Prompt Compression) | Prompt’u özetleyip/kırparak token sayısını azaltır. | Her istekte %20–%30 token tasarrufu. | Over‑compression bağlam kaybına yol açabilir. |
| Streaming Yanıtlar | Cevabı parça parça döner, kullanıcı hemen görmeye başlar. | Algılanan gecikme büyük ölçüde azalır. | Sunucu tarafında biraz daha karmaşık hata yönetimi gerektirir. |
Kısa bir başarı hikayesi:
Ben GPTCache entegre ettikten sonra aylık LLM maliyetim %40 düştü ve ortalama yanıt süresi 2.3 sn → 0.7 sn oldu 🚀.
# model_router.py
import tiktoken
from openai import OpenAI
client = OpenAI() # API key env'den alınır
ENC = tiktoken.encoding_for_model("gpt-3.5-turbo")
# -------------------------------------------------
# Karmaşıklık skorunu token sayısına + anahtar kelimeye göre hesaplıyoruz
# -------------------------------------------------
def complexity_score(prompt: str) -> int:
tokens = len(ENC.encode(prompt))
# Basit bir kural: 300 token altı + "özet", "çevir" gibi kelimeler → düşük
low_keywords = {"özet", "çevir", "listele", "kısa"}
has_low_kw = any(kw in prompt.lower() for kw in low_keywords)
return tokens if not has_low_kw else tokens // 2 # düşükse puanı yarıya indir
# -------------------------------------------------
# Router: skor 500 altı → gpt-3.5-turbo, aksi → gpt-4
# -------------------------------------------------
def route_and_call(prompt: str) -> str:
score = complexity_score(prompt)
model = "gpt-3.5-turbo" if score < 500 else "gpt-4"
print(f"🔎 Skor: {score} → Model: {model}")
resp = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt}],
temperature=0.2,
)
return resp.choices[0].message.content
# -------------------------------------------------
# Hızlı test
# -------------------------------------------------
if __name__ == "__main__":
sorular = [
"Python'da liste nasıl sıralanır?", # basit
"Yapay zeka etiği üzerine 2000 kelimelik bir makale yaz.", # karmaşık
]
for s in sorular:
print(route_and_call(s)[:200] + "…\n")
Nasıl çalışıyor?
complexity_score → prompt’un token sayısını ve bazı low‑complexity anahtar kelimelerine bakar.route_and_call → skor 500 altındaysa gpt‑3.5‑turbo, aksi gpt‑4 çağrılır.Hazırsan bir sonraki bölümde monitoring & alerting ile bu metrikleri nasıl izleyeceğimize bakalım 🚦.
Hazırsan başlayalım 🚀
Modelin eğitim ve doğrulama setlerinde mükemmel performans gösterdiğini varsayalım. Üç ay sorunsuz çalışıyor, aniden accuracy düşüyor, müşteriler şikayet ediyor. Ne oldu? 🤔
| Terim | Ne Demek? | Neden Önemli? |
|---|---|---|
| Data Drift 📊 | Girdi özelliklerinin dağılımı (ör. yaş, gelir, tıklama sayısı) zamanla değişir. Modelin gördüğü x dağılımı eğitimdeki x’ten sapar. | Model aynı f(x)’i kullanıyor ama x artık farklı → tahminler yanlışlaşır. |
| Concept Drift 🎯 | Etiket (y) ile girdi (x) arasındaki ilişki değişir. Örn: önce "yüksek harcama = sadık müşteri", şimdi "yüksek harcama = kampanya avcısı". | Modelin öğrendiği f(x) artık geçerli değil; yeniden eğitim zorunlu. |
Kısaca: Data drift = girdi dağılımı değişir. Concept drift = hedef fonksiyonu değişir. İkisi de modelin sessizce çökmesine yol açar 😱
Sonuç: Model "iyi" görünüyor ama aslında eski dünyaya uygun. Biz bunu sessizce fark etmemiz lazım.
Bu metrikler günlük/haftalık izlenmeli ve bir eşik aşıldığında otomatik uyarı (alert) tetiklenmeli ⚠️.
| Metrik | Yöntem | Eşik Örneği | Aksiyon |
|---|---|---|---|
| Feature drift | KS Testi / PSI | p‑value < 0.01 veya PSI > 0.2 | Slack/Email → "Feature X drift tespit edildi" |
| Prediction drift | KL Divergence | KL > 0.05 | Model yeniden eğitim pipeline’ını tetikle |
| Label drift (varsa) | Chi‑square | p‑value < 0.01 | Veri mühendisliği ekibine bildir |
İpucu: Alert’ları sessiz modda başlatın, gürültüyü azaltmak için burn-in periyodu (ör. 7 gün) uygulayın.
Aşağıdaki script, referans (eğitim) ve mevcut (production) veri setleri arasında Data Drift Report üretir. Raporu HTML olarak kaydedip CI/CD’nize ekleyebilirsiniz.
# drift_report.py
import pandas as pd
from evidently.report import Report
from evidently.metric_preset import DataDriftPreset
# 1️⃣ Verileri yükle (CSV, Parquet, DB …)
reference_df = pd.read_parquet("data/reference.parquet") # eğitim/doğrulama seti
current_df = pd.read_parquet("data/current.parquet") # üretim verisi (son 1 hafta)
# 2️⃣ Rapor nesnesi oluştur
drift_report = Report(metrics=[DataDriftPreset()])
# 3️⃣ Çalıştır
drift_report.run(reference_data=reference_df, current_data=current_df)
# 4️⃣ HTML çıktısı al
drift_report.save_html("reports/data_drift_report.html")
print("✅ Data Drift raporu oluşturuldu: reports/data_drift_report.html")
DataDriftPreset() hem istatistiksel testleri (KS, Chi‑square, PSI) hem de görselleştirmeleri (histogram, ECDF) içeren hazır bir preset’tir.Bu sayede ne oluyor?
- Günlük bir cron/job ile bu scripti çalıştırırsınız.
- Rapor HTML’i Grafana/Slack/Confluence’a gönderilir.
- Otomatik alert kuralınız (ör.
any(p_value < 0.01)) tetiklendiğinde ekip anında haberdar olur.
Eğer Evidently kurmak istemiyorsanız, embedding vektörleri üzerinde basit bir KS testi de işinizi görür:
from scipy.stats import ks_2samp
import numpy as np
# reference_emb, current_emb → (n_samples, dim) boyutunda numpy array
def embedding_drift_score(ref_emb: np.ndarray, cur_emb: np.ndarray, alpha: float = 0.01) -> dict:
drift_flags = {}
for dim in range(ref_emb.shape[1]):
stat, p = ks_2samp(ref_emb[:, dim], cur_emb[:, dim])
drift_flags[dim] = p < alpha
return drift_flags
# Kullanım
flags = embedding_drift_score(reference_embeddings, current_embeddings)
print(f"Drift olan boyut sayısı: {sum(flags.values())}")
Hadi bu altyapıyı kurup modelinizin "sessiz çöküşünü" önleyelim! 🚀
Guardrails, sadece güvenlik değil; format, tutarlılık ve kalite de sağlayan koruma şeritleridir 🎯.
Modelin ürettiği her şeyi “güvenli bir kutu” içine alırsınız; dışarıda kalacak şeyler engellenir veya düzeltilir.
Kısa bir deneyim: Ben output guardrail sayesinde modelin JSON’u bozmasını engelledim. Daha önce “virgül eksik” hatalarıyla saatler kaybediyordum; artık şema uyumsuzluğu anında yakalanıyor ve model kendini düzeltiyor 🚀.
<rail version="0.1">
<!-- Çıktı JSON şeması -->
<output>
<object name="answer" required="true">
<string name="summary" required="true" description="Kısa özet"/>
<array name="sources" required="true">
<string description="Kaynak URL veya başlık"/>
</array>
</object>
</output>
<!-- Yasaklı kelime kontrolü -->
<validators>
<validator name="banned-words" on="answer.summary">
<param name="words">["hack", "exploit", "şifre"]</param>
<on-fail>reask</on-fail>
</validator>
<!-- Kaynak zorunluluğu -->
<validator name="required-field" on="answer.sources">
<param name="min-length">1</param>
<on-fail>reask</on-fail>
</validator>
</validators>
</rail>
Ne oluyor burada?
<output> bloğu, modelin dönmesi gereken JSON yapısını tanımlar.banned-words validator, summary alanında “hack” gibi kelimeleri yakalayıp modeli tekrar sormaya (reask) zorlar.required-field validator, sources dizisinin en az bir öğe içermesini garanti altına alır.Bu şemayı projenize eklediğinizde, model her seferinde istenen formatta, güvenli ve kaynaklı bir cevap üretir. 🎉
Model seçmek eğlenceli kısım 🎉
Mühendislik ise onu sürdürülebilir kılan kısım 🛠
Üretime çıkmadan önce bu kontrol listesini bir kez daha gözden geçir:
Bu adımları atlamak "hızlı çıkış" gibi görünse de, uzun vadede felaket yaratıyor ❗️
Kendi üretim felaket hikayelerinizi yorumlarda paylaşın 👇
Başka takımların aynı hataları yaşamaması için deneyimleriniz altın değerinde.
Bir sonraki yazımda bu kontrollerden birini derinlemesine kodlayacağız – birlikte pratik bir guardrail veya drift detection pipeline'ı yazalım.
Hazırsanız başlayalım, mühendislik disipliniyle AI'yi güvenle üretime taşıyalım! 💪✨
Bu içerik tamamen yapay zeka destekli otomasyon sistemi ile üretilmiştir.
All rights reserved