İçeriğe geç
edumintsBlog
LLM3 dk okuma

Değerlendirme (Eval) Süitinizin API Anahtarı ve Ağ Olmadan Çalışması İçin Deterministik Bir Mock LLM Sağlayıcısı Oluşturun

Kaynak: dev.to

Paylaş
İçindekiler 4 başlık

Her LLM projesi er ya da geç aynı engelle karşılaşır: Değerlendirme (eval) süitiniz ve birim testleriniz gerçek bir modeli çağırmak ister. Ancak bunu yaptıkları anda CI/CD süreçleri yavaşlar, maliyet artar, gizli API anahtarlarına ihtiyaç duyulur ve sağlayıcı modelde bir güncelleme yaptığında testler kararsızlaşır. LLM çıktıları doğası gereği deterministik değildir; bu yüzden sadece "veri hattı (pipeline) çalıştı mı?" sorusunu ölçen bir test bile kodunuzla ilgisi olmayan nedenlerle başarısız olabilir.

Bu sorunu çözmenin en etkili yolu deterministik bir mock (sahte) sağlayıcı kullanmaktır. Gerçek sağlayıcılarınızla birebir aynı arayüzü uygular, aynı yanıt yapısını döner ve tamamen çevrimdışı çalışır. Puanlama, veri toplama ve raporlama mantığınızı denetleyen testler hiçbir zaman ağa çıkmaz. evalgate projesini temel alan bu yaklaşım, kullandığınız her teknoloji yığınına kolayca uyarlanabilir ve AI Test Stratejileri açısından kritik bir pratik sunar.

1. Her İki Tarafın Paylaştığı Ortak Bir Arayüzle Başlayın#

Tüm sistemin temeli tek bir kurala dayanır: Gerçek sağlayıcınız ve mock sağlayıcınız birbiriyle tamamen değiştirilebilir olmalıdır. Bu nedenle önce dar ve net bir arayüz (Provider, ProviderRequest, ProviderResponse) tanımlamalı ve her adaptörün buna uymasını sağlamalısınız.

export interface ProviderRequest {
  model: string;
  messages?: { role: string; content: string }[];
  prompt?: string;
  temperature?: number;
  maxTokens?: number;
}

export interface ProviderResponse {
  output: string;
  latencyMs: number;
  usage?: { promptTokens: number; completionTokens: number; totalTokens: number };
  costUsd?: number;
  model: string;
  raw?: unknown;
}

export interface Provider {
  readonly name: string;
  complete(request: ProviderRequest): Promise<ProviderResponse>;
  embed?(text: string): Promise<number[]>;
}
  • Pratik Çıkarım: Yanıt nesnesi yalnızca metin (output) değil; gecikme süresi (latencyMs), token kullanımı (usage) ve maliyet (costUsd) bilgilerini de taşır. Eğer mock sağlayıcınız yalnızca düz bir metin dönerse, token kullanımını veya maliyeti hesaplayan kod yollarınız test edilmemiş olur. Her zaman yanıtın tam şeklini modelleyin.

2. İsteği Tek Bir Prompt Metnine İndirgeyin#

İstekler sisteme tek bir prompt dizgesi olarak veya bir sohbet mesajları listesi (messages) halinde gelebilir. Mock sağlayıcının üzerinde mantık yürütebilmesi için tek bir standart (canonical) metne ihtiyacı vardır; bu yüzden ilk adım olarak girdiyi normalize edin.

export function resolvePrompt(request: ProviderRequest): string {
  if (request.prompt !== undefined) return request.prompt;
  if (request.messages && request.messages.length > 0) {
    return request.messages.map((m) => `${m.role}: ${m.content}`).join("\n");
  }
  return "";
}
  • Pratik Çıkarım: Farklı girdi formatlarını (prompt ve messages) tek bir standart metinde birleştirmek, test altyapınızın karmaşıklığını azaltır ve sonraki adımlarda deterministik hesaplama yapmayı kolaylaştırır.

3. Tohumlanmış (Seeded) Hash ile Deterministik Hale Getirin#

Mock sağlayıcının temel vaadi, aynı girdinin her zaman aynı çıktıyı üretmesidir. Bunun için prompt metninin bir hash değerini hesaplayıp bu değeri küçük bir sözde-rastgele sayı üretecine (PRNG) tohum (seed) olarak besleyebilirsiniz. FNV-1a ve mulberry32 algoritmaları sadece birkaç satır koddan oluşur ve sıfır dış bağımlılık gerektirir.

const seed = fnv1a(prompt);
const rand = mulberry32(seed);
const latencyMs = Math.round(5 + rand() * 50); // 5-55ms arasında sabit "gecikme"
  • Pratik Çıkarım: Tohum değeri doğrudan prompt'tan türetildiği için, üretilen sahte gecikme süresi (latencyMs) bile tamamen tekrarlanabilirdir. Test süitini bin kez çalıştırsanız dahi birebir aynı sayıları alırsınız; bu da snapshot (anlık görüntü) tarzı doğrulamaları (assertions) mümkün kılar.

4. Çıktıyı Kontrol Etmenin İki Yolu: Fixture'lar ve Direktifler#

Kullanışlı bir mock sağlayıcı rastgele değil, yönlendirilebilir (steerable) olmalıdır. Çıktıyı kontrol etmek için iki temel mekanizma kullanılır:

  • Fixture'lar (Hazır Yanıtlar): Prompt içerisindeki metinle büyük/küçük harf duyarsız alt dizge (substring) olarak eşleşen önceden hazırlanmış yanıtlardır ve ilk eşleşen kural kazanır. Bu yaklaşım, belirli bir birim testin mock sağlayıcının iç çalışma mantığıyla ilgilenmeden tam ve sabit bir çıktıyı sabitlemesine (pinlemesine) olanak tanır.

Kaynak ve atıf

Bu yazı, dev.to üzerinde yayımlanan içerikten yararlanılarak Edumints tarafından yapay zekâ desteğiyle Türkçe hazırlandı. Ayrıntılar ve yazarların kendi anlatımı için orijinaline bakabilirsin:

  • dev.to/royalpinto007/build-a-deterministic-mock-llm-provider-so-your-eval-suite-runs-with-no-api-keys-and-no-network-1415