fix(danisman): 'Kaydettim' deyip kaydetmeme — sunucu tarafı denetim + prompt kuralı (iş 4; QA H4) [KARAR]
- sohbet-akisi.ts: cevapta kayıt beyanı (kaydettim / profiline ekledim / not aldım…) var ama o turda
başarılı profil_guncelle ('kaydedildi') yoksa cevabın sonuna düzeltme notu eklenir. Kayıt kararı
modelin sözüne bırakılmaz; gerçek araç sonucuyla karşılaştırılır. Hata dönen çağrı sayılmaz.
- Kredi: bu cevabın kredisi değişmez (iade yok, ek model çağrısı yok). Not 'profiline kaydedeyim mi'
ibaresini taşır; adayın 'evet'i mevcut bedelsiz onay yolundan geçer — sistemin hatasını düzeltmek
adaya kredi harcatmaz.
- Prompt: KAYIT DÜRÜSTLÜĞÜ kuralı (araç 'kaydedildi' dönmediyse 'kaydettim' deme).
- scripts/eval/akis-denetim.ts: sahte yerel model ucuyla parasız mekanik test (6 senaryo: aracsız
'kaydettim', araçlı, araç hatası, vaat regex notu, temiz, araç kotası) — 6/6 geçti.
Gerçek modelle bu yol henüz tetiklenmedi; model davranışı eval:sohbet ile ölçülür.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -64,7 +64,7 @@ async function main() {
|
||||
const { listeOzetiCikar } = await import("@/lib/ai/rapor");
|
||||
const { sohbetModeli, saglayiciAdi, anahtarVar } = await import("@/lib/ai/client");
|
||||
const { JEV_DUZELTME_NOTU } = await import("@/lib/ai/jev");
|
||||
const { vaatDiliBul } = await import("@/lib/ai/cikti-denetimi");
|
||||
const { vaatDiliBul, KAYIT_DUZELTME_NOTU } = await import("@/lib/ai/cikti-denetimi");
|
||||
const { havuzOlustur, dilimHedefiHesapla } = await import("@/lib/rapor-havuzu");
|
||||
const { PUAN_TURLERI } = await import("@/types/yokatlas");
|
||||
const { SON_YIL } = await import("@/lib/veri-yillari");
|
||||
@@ -222,7 +222,9 @@ async function main() {
|
||||
|
||||
const hamMetin: string = tamMetin ?? yarimMetin ?? "";
|
||||
const canliJevNotu = hamMetin.includes(JEV_DUZELTME_NOTU);
|
||||
const metin = hamMetin.replace(JEV_DUZELTME_NOTU, "").trim();
|
||||
// Sunucunun eklediği notlar modelin cevabı değildir: ayrılır, ayrıca kaydedilir
|
||||
const canliKayitNotu = hamMetin.includes(KAYIT_DUZELTME_NOTU);
|
||||
const metin = hamMetin.replace(JEV_DUZELTME_NOTU, "").replace(KAYIT_DUZELTME_NOTU, "").trim();
|
||||
const m = metin.toLocaleLowerCase("tr-TR");
|
||||
const cagrilan = araclar.map((a) => a.ad);
|
||||
const kontroller: Kontrol[] = [];
|
||||
@@ -247,7 +249,7 @@ async function main() {
|
||||
// 3) "kaydettim" deyip kaydetmeme (H4): başarılı profil_guncelle çıktısı yoksa
|
||||
const basariliKayit = araclar.filter((a) => a.ad === "profil_guncelle" && a.cikti != null && typeof a.cikti === "object" && "kaydedildi" in (a.cikti as object)).length;
|
||||
if (/kaydettim|kaydedildi|profiline ekledim|profilini güncelledim/.test(m)) {
|
||||
kontroller.push({ ad: "kaydettim-ama-yazmadi", durum: basariliKayit ? "gecti" : "kaldi", neden: basariliKayit ? undefined : "cevap kayıt bildiriyor, başarılı profil_guncelle çağrısı yok" });
|
||||
kontroller.push({ ad: "kaydettim-ama-yazmadi", durum: basariliKayit ? "gecti" : "kaldi", neden: basariliKayit ? undefined : `cevap kayıt bildiriyor, başarılı profil_guncelle çağrısı yok (sunucu düzeltme notu: ${canliKayitNotu ? "eklendi" : "EKLENMEDİ"})` });
|
||||
}
|
||||
|
||||
// 4) vaat regex'i
|
||||
@@ -317,6 +319,7 @@ async function main() {
|
||||
adim,
|
||||
cevap: metin,
|
||||
canliJevNotu,
|
||||
canliKayitNotu,
|
||||
canliDenetim: canliDenetim as CanliDenetim | null,
|
||||
kayitliProfil,
|
||||
jev: jev?.durum === "ok" ? jev.p : jev ? { atlandi: jev.neden } : null,
|
||||
@@ -378,6 +381,8 @@ async function main() {
|
||||
...oran(sonuclar),
|
||||
atlananSoru: isler.length - sonuclar.length,
|
||||
canliJevNotuEklenen: sonuclar.filter((x) => x.canliJevNotu).length,
|
||||
canliKayitNotuEklenen: sonuclar.filter((x) => x.canliKayitNotu).length,
|
||||
aracSiniriReddi: sonuclar.reduce((a, x) => a + (x.canliDenetim?.reddedilenArac ?? 0), 0),
|
||||
ortalamaAdim: sonuclar.length ? +(sonuclar.reduce((a, x) => a + x.adim, 0) / sonuclar.length).toFixed(2) : 0,
|
||||
ortalamaAracCagrisi: sonuclar.length ? +(sonuclar.reduce((a, x) => a + x.araclar.length, 0) / sonuclar.length).toFixed(2) : 0,
|
||||
enCokAracCagrisi: Math.max(0, ...sonuclar.map((x) => x.araclar.length)),
|
||||
|
||||
Reference in New Issue
Block a user