perf(liste): satır biçimi "id|gerekçe" — çıktı token'ı ~%27 az, gecikme p50 22,5 → ~14 sn [KARAR]

Gecikme çıktı token'ıyla orantılı (üst sağlayıcıya göre 25–115 token/sn);
çıktının ~%20'si satır başına yinelenen JSON anahtarlarıydı.

- Tel şeması: liste elemanı nesne ({"id","gerekce"}) yerine tek dizgi
  "id|gerekçe"; satirCoz ayrıştırır, kimlik yine havuzda doğrulanır
  (havuz-dışı koruması aynı).
- maxTokens 4000 → 2000 (ölçüm: 38 sağlıklı çağrıda çıktı 746–1.099 token).
  reasoning'i kapatmayan üst sağlayıcıya düşen çağrı ~50 sn yerine ~25 sn'de
  kesilir; ikinci deneme o sağlayıcı atlanarak yapılır.

Ölçüm: aynı 3 profilde (p05, a07, p13) çıktı 3.724 → 2.710 token.
40 profil: çağrı başına ortalama çıktı ~1.277 → ~940 token; gecikme p50
22,5 → 14,8 sn, p95 61,6 → 30,1 sn (p95 kazancının çoğu ikinci çağrının
kalkmasından — 3128b01). Maliyet 40 liste için 0,0285 → 0,0300 $ (değişmedi).
İzlenecek: son koşuda ham çıktıda 2 havuz-dışı kimlik görüldü (taban ve önceki
iki koşuda 0); ikisi de korumada atıldı, nihai listede havuz dışı 0.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-10-05 08:49:57 +03:00
parent da8d303ea4
commit 9469c0bd89

View File

@@ -53,11 +53,20 @@ import { ILK_YIL } from "../veri-yillari";
// Modele giden adlar (5 Eki 2026): üçüncü liste telde `guvenli`dir, iç anahtar // Modele giden adlar (5 Eki 2026): üçüncü liste telde `guvenli`dir, iç anahtar
// `garanti` kalır. Prompt'ta "garanti" alan adı ve dilim değeri olarak 10+ kez // `garanti` kalır. Prompt'ta "garanti" alan adı ve dilim değeri olarak 10+ kez
// geçince model sözcüğü adaya dönük metne taşıyordu (ölçüm: 19/888 gerekçe, // geçince model sözcüğü adaya dönük metne taşıyordu (ölçüm: 19/888 gerekçe,
// 14/37 üst metin). Program kimliği alanı kısa (`id`): çıktı token'ı. // 14/37 üst metin).
const AiTercihSchema = z.object({ //
id: z.string(), // Satır biçimi: nesne ({"id": …, "gerekce": …}) değil TEK DİZGİ, "id|gerekçe".
gerekce: z.string(), // Çıktı token'ının ~%20'si satır başına yinelenen JSON anahtarlarıydı; gecikme
}); // çıktı token'ıyla doğru orantılı (ölçüm aşağıda, raporUretAyrintili).
const SATIR_AYRACI = "|";
type AiSatir = { id: string; gerekce: string };
/** "106510077|Gerekçe cümlesi." → { id, gerekce }; ayraç yoksa satırın tamamı kimlik sayılır. */
function satirCoz(ham: string): AiSatir {
const i = ham.indexOf(SATIR_AYRACI);
if (i < 0) return { id: ham.trim(), gerekce: "" };
return { id: ham.slice(0, i).trim(), gerekce: ham.slice(i + 1).trim() };
}
const AiTercihSchema = z.string();
type TelListe = "hayal" | "dengeli" | "guvenli"; type TelListe = "hayal" | "dengeli" | "guvenli";
const TEL_ADI: Record<Dilim, TelListe> = { const TEL_ADI: Record<Dilim, TelListe> = {
hayal: "hayal", hayal: "hayal",
@@ -95,6 +104,9 @@ KURALLAR (kesin):
- Havuz üç dizi hâlinde verilir: havuz.hayal, havuz.dengeli, havuz.guvenli. - Havuz üç dizi hâlinde verilir: havuz.hayal, havuz.dengeli, havuz.guvenli.
hayal listesine YALNIZCA havuz.hayal içindeki programları koy; dengeli ve hayal listesine YALNIZCA havuz.hayal içindeki programları koy; dengeli ve
guvenli için de aynısı. Bir programı başka dizinin listesine taşıma. guvenli için de aynısı. Bir programı başka dizinin listesine taşıma.
- Listelerin her elemanı TEK dizgidir, biçimi: "id|gerekce" (ör.
"123456789|Seçtiğin alanla eşleşen, kontenjanı geniş bir program."). id,
havuzdaki programın id'sidir; dik çizgiden sonra gerekce gelir.
- SADECE havuzdaki id'leri kullan; havuzda olmayan program ASLA önerme. - SADECE havuzdaki id'leri kullan; havuzda olmayan program ASLA önerme.
Aynı id'yi birden fazla kez kullanma. Aynı id'yi birden fazla kez kullanma.
- Seçerken adayın ilgi alanlarını ve illerini, kontenjan/yerleşen hareketini - Seçerken adayın ilgi alanlarını ve illerini, kontenjan/yerleşen hareketini
@@ -200,7 +212,8 @@ function secimiOnar(
const gorulen = new Set<string>(); const gorulen = new Set<string>();
if (parsed) { if (parsed) {
for (const d of DILIMLER) { for (const d of DILIMLER) {
for (const t of parsed[TEL_ADI[d]]) { for (const ham of parsed[TEL_ADI[d]]) {
const t = satirCoz(ham);
const p = havuzMap.get(t.id); const p = havuzMap.get(t.id);
if (!p) { if (!p) {
onarim.havuzDisi++; onarim.havuzDisi++;
@@ -577,9 +590,11 @@ export async function raporUretAyrintili(
: `${kullaniciMesaji}\n\nÖNCEKİ DENEMENDE HATA VARDI: ${sonHata} Kurallara tam uy.`, : `${kullaniciMesaji}\n\nÖNCEKİ DENEMENDE HATA VARDI: ${sonHata} Kurallara tam uy.`,
sema: AiRaporGevsek, sema: AiRaporGevsek,
wireSema: aiSemaWire(hedef), wireSema: aiSemaWire(hedef),
// Küçük şema (24 satır × gerekce + genel + uyarılar) ~1-1.5k token; // Ölçüm (5 Eki 2026, 38 sağlıklı çağrı): çıktı 746–1.099 token.
// reasoning kapalıyken 4000 rahat bir tavan, kaçak uzun üretimi de keser. // 2000 rahat bir tavan; reasoning'i kapatmayan üst sağlayıcıya düşen
maxTokens: 4000, // çağrı da ~50 sn yerine ~25 sn'de kesilir ve ikinci deneme o
// sağlayıcı atlanarak yapılır (bkz. cagri.ts).
maxTokens: 2000,
gozlem: (g) => cagrilar.push(g), gozlem: (g) => cagrilar.push(g),
}); });
} catch (err) { } catch (err) {