/** * Danışman çıktı denetimi — Jev (TypeSafe "System One" modeli). * * Danışman cevabı bittikten sonra tek soru sorulur: cevap yerleşme garantisi * veriyor ya da yerleşmeyi olasılık/yüzde/ihtimal diliyle tahmin ediyor mu * (sistem prompt'undaki yasak; api/soru/route.ts). Jev metin üretmez, 0-1 * arası bir olasılık döner. Yalnız danışmanın CEVABI gider; kullanıcının * mesajı, adı ya da e-postası gitmez. Sağlayıcı ABD'de — /gizlilik "Hizmet * sağlayıcılar" bölümünde yazılı; değişirse aynı commit'te güncellenir. * * Güvenli tarafa düşer: anahtar yoksa, zaman aşımında ya da hata olursa * denetim atlanır (null), cevap olduğu gibi kalır. Saf modül: Next dışından * (scripts/kesif-jev.ts) da import edilir. */ const UC = "https://api.typesafe.ai/v1/systemone"; const MODEL = "jev-latest"; /** 5 Eki 2026 keşfi: temiz cevaplar ≤0,37, ihlaller ≥0,74 (36 örnek). */ export const JEV_IHLAL_ESIGI = 0.5; /** Akış sonunda bekletir; ölçülen p95 ~335 ms. */ const ZAMAN_ASIMI_MS = 2000; export const JEV_IHLAL_SORUSU = { type: "noul", instructions: "Bu metin bir üniversite tercih danışmanının öğrenciye verdiği Türkçe cevaptır. Cevap, öğrenciye bir programa yerleşeceğine dair garanti/söz/kesinlik veriyor mu YA DA yerleşmeyi olasılık, yüzde, ihtimal ya da şans diliyle tahmin ediyor mu? " + "Şunlar ihlal DEĞİLDİR: 'Güvenli / Az riskli / Riskli' etiketleri; 'garanti verilemez' gibi reddeden cümleler; burs indirimi, doluluk, öğrenci oranı ya da mezunların istihdam oranı gibi yerleşme tahmini olmayan yüzdeler; geçmiş taban sırası ve kontenjan sayıları.", } as const; type JevYanit = { answers?: Record; usage?: { input_tokens?: number }; }; export function jevAnahtari(): string | undefined { return process.env.TYPESAFE_API_KEY?.trim() || undefined; } /** Ham çağrı: ihlal olasılığı + girdi token'ı. Hata fırlatır (keşif betiği görsün). */ export async function jevIhlalSor( anahtar: string, cevap: string, zamanAsimiMs = 30_000, ): Promise<{ p: number; girdiToken: number }> { const r = await fetch(UC, { method: "POST", headers: { Authorization: `Bearer ${anahtar}`, "Content-Type": "application/json" }, body: JSON.stringify({ state: cevap, model: MODEL, questions: { ihlal: JEV_IHLAL_SORUSU } }), signal: AbortSignal.timeout(zamanAsimiMs), }); if (!r.ok) throw new Error(`Jev ${r.status}: ${(await r.text()).slice(0, 300)}`); const y = (await r.json()) as JevYanit; const p = y.answers?.ihlal?.noul; if (typeof p !== "number") throw new Error(`Jev beklenmeyen yanıt: ${JSON.stringify(y).slice(0, 300)}`); return { p, girdiToken: y.usage?.input_tokens ?? 0 }; } /** * Danışman cevabının ihlal olasılığı; denetim yapılamadıysa null. Asla * fırlatmaz — denetim cevabı düşürmemeli. */ export async function cevapIhlalOlasiligi(cevap: string): Promise { const anahtar = jevAnahtari(); if (!anahtar || !cevap.trim()) return null; try { return (await jevIhlalSor(anahtar, cevap, ZAMAN_ASIMI_MS)).p; } catch (hata) { console.warn("[jev] denetim atlandı:", hata instanceof Error ? hata.message : hata); return null; } } /** İhlal yakalanınca cevabın sonuna eklenen düzeltme notu. */ export const JEV_DUZELTME_NOTU = "Not: Yukarıdaki cevap bir yerleşme garantisi ya da olasılık tahmini değildir. Taban sıraları her yıl değişir; karar verirken Güvenli / Az riskli / Riskli etiketlerine ve geçmiş taban sıralarına bak.";