From cae2aaab4d33d3d020c3a7d13313a20c4f6f231f Mon Sep 17 00:00:00 2001 From: bilalgursen Date: Mon, 21 Sep 2026 04:48:42 +0300 Subject: [PATCH] =?UTF-8?q?fix(ai):=20tad=C4=B1ml=C4=B1k=20risk=20notu=20d?= =?UTF-8?q?eterministik=20+=20prompt=20dili?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Girişsiz /sonuc tadımlığının riskNotu'su LLM üretimiydi ve DB'den olduğu gibi servis ediliyordu; prompt'u da açıkça "yüksek/orta/düşük ihtimal dili kullan" diyordu. Rozet ise aynı satırda canlı hesaplanıyor → metinle rozet çelişebiliyordu. - tadimlikSec(): riskNotu okuma anında riskNotuMetni(riskHesapla(...) ?? dilimdenRisk(...)) ile üretilir (rozetle aynı formül). DB satırları ve şema değişmez; prod'da havuzu yeniden üretmek gerekmez, /api/tadimlik de kapsanır - tadimlik-uret prompt'u + mock metinleri: ihtimal dili yasaklandı, "son 4 yıl" → "son 5 yıl" (çıktı şeması aynı; script koşulmadı) - danışman sohbeti sistem prompt'u: "ihtimal dili kullan" → olasılık/yüzde/ ihtimal yasak, risk etiketleri + taban sıralarıyla konuş Co-Authored-By: Claude Fable 5.1 --- scripts/tadimlik-uret.ts | 11 ++++++----- src/app/api/soru/route.ts | 3 ++- src/lib/tadimlik-havuzu.ts | 12 ++++++++++-- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/scripts/tadimlik-uret.ts b/scripts/tadimlik-uret.ts index a869324..4e2c351 100644 --- a/scripts/tadimlik-uret.ts +++ b/scripts/tadimlik-uret.ts @@ -67,9 +67,10 @@ KURALLAR (kesin): - METİN DİYETİ: her alan TEK kısa cümle, dolgu söz yok. - gerekce: bu programın bu aday için neden mantıklı olduğu (TEK cümle, en fazla ~15 kelime, Türkçe). -- riskNotu: yerleşme ihtimali değerlendirmesi (TEK kısa cümle). ASLA "garanti", - "kesin", "yüzde yüz" deme; "yüksek/orta/düşük ihtimal" dili kullan. -- trendOzeti: son 4 yılın taban sıralaması hareketi, TEK cümle (ör. "2022'den +- riskNotu: geçmiş taban verisine dayalı risk değerlendirmesi (TEK kısa cümle). + ASLA garanti/kesin/yüzde/olasılık/ihtimal deme; "güvenli / az riskli / + riskli" etiketleriyle konuş. +- trendOzeti: son 5 yılın taban sıralaması hareketi, TEK cümle (ör. "2022'den beri taban 45B'den 38B'ye indi, bölüm zorlaşıyor"). - Adayın sıralaması yaklaşıktır; kesin sıra telaffuz etme, banda göre konuş.`; @@ -82,9 +83,9 @@ function mockMetin(p: Program, temsiliSira: number, kategori: string | null) { return { gerekce: `(Dev mock) ${p.isim}, ${kategori ? `${kategori} ilgisiyle ve ` : ""}~${temsiliSira.toLocaleString("tr-TR")} bandındaki sıralamanla uyumlu bir aday.`, riskNotu: - "(Dev mock) Taban sıralaması senin civarında; orta-yüksek ihtimalle yerleşilebilir.", + "(Dev mock) Son taban sıralaması sırana yakın; küçük bir kayma sonucu değiştirebilir.", trendOzeti: - "(Dev mock) Son 4 yılda taban sıralaması görece stabil seyretti.", + "(Dev mock) Son 5 yılda taban sıralaması görece stabil seyretti.", }; } diff --git a/src/app/api/soru/route.ts b/src/app/api/soru/route.ts index 305f284..01c0cfc 100644 --- a/src/app/api/soru/route.ts +++ b/src/app/api/soru/route.ts @@ -45,7 +45,8 @@ KURALLAR: sıralaması adayın belirgin altında, Az riskli (sarı) = adayın sıralaması civarında, Riskli (kırmızı) = geçen yıl adayın sıralamasının üzerinde kapandı. Risk sorularında bu etiketleri ve taban sıralarını kullan. -- ASLA yerleşme garantisi verme; "yüksek/orta/düşük ihtimal" dili kullan. +- ASLA yerleşme garantisi verme; olasılık, yüzde ya da "ihtimal" dili kullanma — + güvenli / az riskli / riskli etiketleri ve taban sıralarıyla konuş. - Bilmediğin güncel veriyi uydurma; emin değilsen YÖK Atlas'a bakmasını söyle. - Taban sıralamalarının her yıl değiştiğini gerektiğinde hatırlat. - Cevapları kısa ve öz tut (genelde 3-6 cümle); istenirse detaylandır. diff --git a/src/lib/tadimlik-havuzu.ts b/src/lib/tadimlik-havuzu.ts index 62dd85b..e1df7ae 100644 --- a/src/lib/tadimlik-havuzu.ts +++ b/src/lib/tadimlik-havuzu.ts @@ -8,6 +8,7 @@ import { turkishSlugify } from "./slug"; import type { PuanTuruKey } from "@/types/yokatlas"; import type { Dilim } from "./rapor-havuzu"; import type { RaporSonuc } from "@/features/rapor/types/rapor"; +import { dilimdenRisk, riskHesapla, riskNotuMetni } from "./risk"; /** Sihirbaz kategorisi seçilmemiş kullanıcı için kova×tür başına fallback satır. */ export const GENEL_KATEGORI = "genel"; @@ -76,13 +77,20 @@ export async function tadimlikSec( ), }); if (satir) { + const program = satir.program as RaporSonuc["programlar"][string]; return { programId: satir.programId, dilim: satir.dilim, gerekce: satir.gerekce, - riskNotu: satir.riskNotu, + // DB'deki riskNotu batch'te LLM'in temsili sıraya göre yazdığı + // cümledir; servis EDİLMEZ. Not, rozetle (tadimlik-satiri.tsx) aynı + // formülden adayın gerçek sırasına göre okuma anında üretilir — metin + // ile rozet çelişemez, olasılık dili sızamaz. + riskNotu: riskNotuMetni( + riskHesapla(program.efektifSira, sira) ?? dilimdenRisk(satir.dilim), + ), trendOzeti: satir.trendOzeti, - program: satir.program as RaporSonuc["programlar"][string], + program, }; } }