Files
kolaytercih/docs/ekip-raporlari/2026-10-09/yapay-zeka-revizyon-koda-bagli.md
bilalgursen da0e9dff7a docs(ekip): 7–10 Ekim raporları, eval sonuçları, seslendirme betiği
- docs/ekip-raporlari/2026-10-07, 2026-10-09, 2026-10-10 raporları ve ekran görüntüleri
  (ses/ altındaki mp3 dosyaları depoya alınmadı, 38 MB)
- BACKLOG #38: rehber yazılarına "Dinle" düğmesi adayı
- scripts/seslendir.py (Türkçe TTS) ve .gitignore'a .venv-tts/
- scripts/eval/sonuc: 8–10 Ekim revizyon eval çıktıları

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-11 00:33:39 +03:00

86 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Yapay zekâ — liste revizyonu koda bağlandı (QA B1 kökten çözüm)
Dal `v2`, taban `128c175`, commit'ler `cee4bf3` (kod), `bad5856` (meraklısına şeması), `e9dfa35` (eval) — push yok. Gerçek modelle ölçüm: `deepseek/deepseek-v4-flash @ openrouter.ai`, 9 Eki 2026 gecesi, **56 model çağrısı** (sınır 60), ≈0,0063 $. Başkalarının dirty dosyalarına (`.claude/settings.json`, `AGENTS.md`, `data/app.db`, `BACKLOG.md`, `layout.tsx`, `site-footer.tsx`, `2026-10-07/`, `21-19-51` json, `seslendir.py`) dokunulmadı. Tarayıcı açılmadı.
## Özet (5 madde)
1. **Revizyon artık sohbet modelinin kararına bağlı değil.** `liste_revize` aracı modelin listesinden çıktı. Adayın mesajı regex kapısından geçip aday paketliyse `src/lib/ai/revizyon-niyeti.ts` tek küçük yapılandırılmış çağrıyla (`yapilandirilmisUret`, json_schema, araçsız; eski aracın parametre şeması `LISTE_REVIZE_PARAMETRELERI` ve `revizyonKuraliKur` aynen kullanılır) `{niyet, kural | form}` çıkarır; route kural geçerliyse listeyi **koddan** kurar (`listeRevizeKoddan` → `listeRevizeCekirdek`, paket/kilit/kredi kapıları aynı), kural eksikse **formu koddan** açar, niyet "soru/diger" ise normal sohbete düşer (regex yanlış pozitifi zararsız).
2. **Cevap da koddan:** revizyon ve form turunda sohbet modeli **hiç çağrılmaz**; sayılar ve ilk 5 program adı sunucu sonucundan şablonla basılır (`sabitCevap`). Gerekçe ölçümden: sonuç önünde dururken model dağılım sayısını 8 cevabın 2'sinde yanlış yazdı (11/7/6 ↔ gerçek 7/12/5; 0/11/13 ↔ 4/12/8), adları eksik/sıra dışı aktardı; formda da "ne istediğini yaz" diye formu baltaladı. İlke 1 (deterministik olan LLM'e bırakılmaz).
3. **Ölçüm hedefi tuttu:** gerçek modelde koddan revizyon **8/8**, kural beklenen alanı taşıyor **8/8**, sahte beyan **0**, r09 form, r10 araçsız (10/10). Önce: 5/8, 3 sahte beyan. Revizyon turu artık 1 niyet çağrısı (ort. 1-3 sn, ≈0,00007 $) + liste üretimi; sohbet çağrısı yok (önce 1-4 çağrı, 3-32 sn).
4. **Güvenlik ağı güçlendi:** beyan regex'i kaldı; beyan var + revizyon yok → düzeltme notu **ve mesajın sohbet kredisi iade** (`grantCredits refund`, refId=mesajId, idempotent), not bunu söyler. Niyet çıkarımı başarısızsa (zaman aşımı/sağlayıcı) normal sohbete düşülmez — koddan "isteğini okuyamadım, tekrar yaz" + iade; çünkü ölçümde bu durumda model uydurma adlarla "kurdum" yazdı (r04, 23-07 koşusu; ağ yakaladı). Ayrıca `liste-revizyon.ts` iade refId'si `<mesajId>:revizyon` oldu: `(reason, refId)` tekilliği sohbet iadesiyle çakışıyordu (eski gizli hata).
5. **Sapmalar:** şartnamedeki "sonucu sohbet modeline araç sonucu olarak ver, model anlatsın" adımı denendi (iki koşu) ve **geri alındı** — nedeni 2. madde. Niyet çağrısında `OpenInference` üst sağlayıcısı yalnız bu çağrı için atlanıyor (3/3 ölçümde 11-12,5 sn; diğerleri 1-3 sn) — sağlayıcı ayarı sayılabilir, `[BİLAL]` görürse tek satır. Mekanik: `akis-denetim` 13/13 (9 eski + 4 yeni), `revizyon-denetim` 5/5; `typegen + tsc + lint` temiz.
## Tasarım (uygulanan)
```
mesaj ─► revizyonNiyetiVar (regex, sohbet-gecmisi.ts) ─ hayır ─► normal sohbet (model; liste_revize yok)
│ evet + paketli
▼
revizyonNiyetiCikar (revizyon-niyeti.ts; 1 json_schema çağrısı, 20 sn, OpenInference hariç)
├─ niyet soru/diger ──────────────► normal sohbet
├─ belirsiz (hata/zaman aşımı) ───► koddan "okuyamadım" cevabı + kredi iadesi
├─ revizyon + kural geçerli ──────► islem liste_revize: listeRevizeKoddan → sabitCevap (şablon)
└─ revizyon + kural eksik ────────► islem soru_sor: modelin formu (anketDogrula) ya da varsayilanForm → sabitCevap
"Form cevaplarım:" mesajı → aynı yol (önceki form dökümü çıkarıma verilir)
```
- `src/lib/ai/sohbet-akisi.ts:127` `sabitCevap`; `:205-247` koddan işlem: ekrana `tool-input-start/available` + `tool-output-available|error` (istemci `sohbet-client.tsx`/`arac-pilleri.tsx` değişmedi — liste yenileme, toast, form çizimi aynen), kayda `meta.revizyon`/`meta.anket` (route `onAracSonucu`). Başarısız revizyon artık ekranda **"Listeni yeniden kuramadım"** hapı (`output-error`; eskiden `{hata}` sonucu "kurdum" hapı gösteriyordu).
- `src/app/api/soru/route.ts:295-325` dallanma; `:349` `onRevizeBeyani` iadesi.
- `src/lib/ai/danisman-prompt.ts` revizyon bölümü: "listeyi sen değiştiremezsin; sunucu kurar ve cevabı yazar; çağrıldıysan liste değişmedi — kurdum deme, net istek iste ya da soru_sor".
- `src/lib/ai/sohbet-gecmisi.ts:37` pencere: `[Araç kaydı: …]` etiketi **geri alındı** (model etiketi kopyalayıp cevabı o biçimde yazdı, 22-59 koşusu r04-r07), yerine doğal tek cümle (`Listeni yeniden kurdum: 24 tercih (…). İlk 5: …`).
- `src/lib/ai/cagri.ts` `yapilandirilmisUret`: `wireJsonSema`, `model`, `zamanAsimiMs`, `dislanan` seçenekleri (varsayılanlar değişmedi). `src/lib/ai/client.ts` `niyetModeli()` = `OPENROUTER_NIYET_MODEL` yoksa rapor modeli.
- `/meraklisina` şeması: `huni-semasi.tsx:33` RV düğümü + aria-label + figcaption + 4. bölüm metni.
## Bulgular
- **B1 kök neden (koddan ve ölçümden):** `src/lib/ai/sohbet-akisi.ts` (eski, 128c175) araç seçimi modele aitti; örnek r03 ("İlk 5'i Bursa'ya göre güncelle.", 2 başarılı geçmiş) → araçsız "Liste yenilendi… Bursa Uludağ…" (uydurma). Şimdi aynı girdi → `{"ilkTercihler":{"adet":5,"iller":["BURSA"]}}` kural, koddan kurulum, şablon cevap (23-07 koşusu, 1,5 sn niyet).
- **Model sayı/ad güvenilmezliği (yeni, ölçüldü):** 23-02 koşusu r04: sunucu sonucu `7 hayal/12 dengeli/5 güvenli`, model "11 hayal / 7 dengeli / 6 güvenli" ve ilk 5'te sonuçta olmayan "İSTANBUL ÜNİVERSİTESİ-CERRAHPAŞA"; r07: sonuç 4/12/8, model "0 hayal / 11 dengeli / 13 güvenli". → şablon (`sabitCevap`).
- **Etiket taklidi (yeni):** 22-59 koşusu r04, r05, r06, r07 cevapları aynen `[Sunucu kaydı: bu cevapta liste sunucu tarafından yeniden kuruldu — …]` ile başladı. Asistan turuna konan her yapay işaret taklit ediliyor (7 Eki raporundaki gözlem doğrulandı). → doğal cümle.
- **Niyet çıkarımı başarısızken sohbete düşmek tehlikeli:** 23-07 r04 (form cevabı) niyet çağrısı 20 sn zaman aşımı → normal sohbet → model "Listeni yeniden kurdum: 24 tercih (9/12/3)… İSTANBUL AREL…" (uydurma; not + iade çalıştı). → `route.ts:310` koddan "okuyamadım" + iade (gerçek modelle koşulmadı; mekanik `koddan-revizyon-hata` senaryosu aynı yolu sınar).
- **Yavaş üst sağlayıcı:** niyet çağrısında OpenInference 11,1 / 12,5 sn (2 koşu), Wafer 10,2 sn (r09, 3 soruluk form çıktısı; sonraki koşuda 3,8 sn), diğerleri 1,1-3,3 sn. 23-07 koşusunda bir çağrı 20 sn'de kesildi (sağlayıcı bilinmiyor — abort).
- **r05 kural hatası (1 kez):** 22-59 koşusunda "ilk 3 tercih İzmir'de olsun" → `{"universiteTipi":"farketmez","iskelet":"standart"}`; prompt'a "yalnız istenen değişikliği yaz, farketmez/standart yalnız açıkça istenirse" eklendi, sonraki 2 koşuda doğru.
- **Kredi defteri çakışması (eski gizli hata):** `src/features/rapor/liste-revizyon.ts` iade satırı `refId=mesajId` yazıyordu; `ledger_reason_ref` tekilliği yüzünden aynı mesajın sohbet iadesi (yarım kalma) "tekrar" sayılıp düşmüyordu. Düzeltildi (`:51 iadeRefId`).
## Eval sonuçları (`pnpm eval:revizyon`, 10 senaryo, QA kaydından gerçek geçmişler)
| koşu | revizyon tetiklendi (8 beklenen) | kural doğru | sahte beyan | geçen | model çağrısı | maliyet | gecikme (niyet / cevap) |
|---|---|---|---|---|---|---|---|
| **önce** `128c175` (model araç seçer, 21-19-51) | 5/8 | — | **3** | 7/10 | 21 | 0,0032 $ | — / 3,3-32 sn |
| ara 1: koddan revizyon, model anlatıyor, `[Sunucu kaydı]` etiketi (22-59-20) | 8/8 | 7/8 | 0 | 9/10 | 20 | 0,0024 $ | 1,6-11,1 / 2,9-25 sn; 4 cevap etiketi kopyaladı |
| ara 2: doğal kayıt cümlesi, model anlatıyor (23-02-50) | 8/8 | 8/8 | 0 | 10/10 | 19 | 0,0025 $ | 1,1-12,5 / 2,6-7 sn; **2/8 cevapta sayı yanlış** |
| **son**: cevap şablondan, OpenInference hariç (23-07-25) | 7/8* | 7/8* | 1* | 9/10 | 12 | 0,0008 $ | 1,1-6,5 (+1 zaman aşımı 20 sn) / 0 sn (koddan) |
| son, r04 tekrar (23-08-21) | 1/1 | 1/1 | 0 | 1/1 | 1 | 0,0001 $ | 5,4 / 0 |
\* r04: niyet çağrısı zaman aşımı → normal sohbet → model uydurdu, güvenlik ağı yakaladı (not + iade). Bu yol sonradan koddan cevaba çevrildi (`route.ts:310`); tekrar koşuda r04 geçti. Son hâlin 8/8'i "ara 2 + şablon" ve "r04 tekrar" birleşiminden okunur; **tek koşuda 10/10 son kod ile koşulmadı** (bütçe: 56/60).
Mekanik: `akis-denetim` 13/13 (yeni: `koddan-revizyon` modelsiz şablon ve `tool-liste_revize` parçası; `niyet-diger-sahte-beyan` → not + iade; `koddan-form` model çağrısı 0; `koddan-revizyon-hata` → `output-error` + "kuramadım"), `revizyon-denetim` 5/5. Ham sonuçlar `scripts/eval/sonuc/2026-10-08T22-57-23 … 23-08-21-revizyon.json` (commit'te).
## Maliyet ve gecikme etkisi
- **Kullanıcı kredisi:** değişmedi — revizyon isteği 1 sohbet kredisi (form cevabı bedelsiz), liste üretimi paketliye 0. Yeni iade yolları: sahte beyan (model turunda) ve niyet çıkarımı başarısızlığı → 1 kredi iade, `refId=mesajId` (yarım kalma iadesiyle aynı anahtar, çift iade yok).
- **Bizim maliyet:** revizyon turu başına 1 niyet çağrısı ≈ 4,3 k girdi + 80 çıktı token ≈ **0,00007 $** (form üretiminde ≈0,0002 $); sohbet modeli o turda çağrılmıyor (önce 1-4 çağrı, 0,0002-0,001 $). Regex yanlış pozitifinde ("listeme not ekle") niyet çağrısı boşa gider (≈0,00007 $, 1-3 sn) ve sohbet normal sürer.
- **Gecikme:** cevap başlangıcı = niyet çağrısı (p50 ≈ 2 sn, en kötü 20 sn zaman aşımı) + liste üretimi (20-60 sn, değişmedi); şablon cevap anında. Önce: model 1-4 adım (3-32 sn) + üretim. "Listeni yeniden kuruyorum…" hapı niyet çağrısından sonra, üretim boyunca görünür.
- **Token:** sohbet sistem prompt'u ~120 token kısaldı (revizyon bölümü sadeleşti); pencerede revizyon turları ~1 cümle.
## Sapmalar / açık noktalar
- "Sonucu sohbet modeline araç sonucu olarak ver" **uygulanmadı** (iki koşuda ölçülüp geri alındı; sayı/ad hatası). Model artık revizyon turunda hiç konuşmuyor; yorum isteniyorsa şablona `kuralOzeti` ile tek cümle eklendi (`— ilk 5 tercih: il Bursa`).
- `OpenInference` yalnız niyet çağrısında atlanıyor (`revizyon-niyeti.ts:158`); rapor üretimi ve sohbet etkilenmez. Niyet zaman aşımı 20 sn; bir çağrı buna takıldı (sağlayıcı bilinmiyor).
- `OPENROUTER_NIYET_MODEL` yeni, **isteğe bağlı** env; tanımsızsa davranış değişmez (rapor modeli).
- Paketsiz adayda niyet çağrısı yapılmaz; model `/paket`'e yönlendirir (önceki davranış).
- Sürüm artırılmadı (`v2` dalı 2.0.0 geliştirmesi; önceki fix commit'leriyle tutarlı).
- UI'a bakılmadı (tarayıcı yasak): koddan `tool-*` parçaları istemcinin zaten tükettiği biçimde; `huni-semasi.tsx` düğümü mermaid'de yalnız metin ekledi, görsel kontrol Bilal'de.
## Önerilen değişiklikler
- `[KARAR]` uygulandı: koda bağlı revizyon, şablon cevap, iade ağı, refId düzeltmesi, eval güncellemesi, meraklısına şeması.
- `[BİLAL]` `OPENROUTER_NIYET_MODEL`: daha ucuz/hızlı küçük bir model (ör. `openai/gpt-4.1-nano` sınıfı) için ayrı ölçüm (~10 çağrı); mevcut maliyet zaten ≈0,00007 $/tur olduğu için acele değil.
- `[BİLAL]` Niyet çağrısında OpenInference'ın atlanması kalsın mı; istenirse `kaliciDislananSaglayicilar`'a (rapor+sohbet) taşımak ayrı ölçüm ister.
- `[KARAR]` sonraki tur: `pnpm eval:revizyon --tekrar 3` ile stokastik tutarlılık (≈33 çağrı, ≈0,003 $) ve regex yanlış pozitif seti ("listeme not ekle", "güncel takvim nedir") — niyet "diger" oranı.
## Bilal'den istenen
1. Son kodla izole tam koşu: `pnpm eval:revizyon` (≈11 çağrı, ≈0,001 $, ~1 dk); hedef 8/8 · sahte beyan 0 · 10/10 — 3 dk.
2. Lokalde paketli hesapla bir kez "ilk 5 Ankara olsun" + belirsiz "listemi değiştir" yazıp hap/form/toast'ın göründüğünü görmek (tarayıcı bende yasak) — 5 dk.
3. `OPENROUTER_NIYET_MODEL` ve OpenInference kararı (yukarıda) — 1 dk.