---
title: "Laya ile Türkçe Metin Sınıflandırma: Talebi Yönlendirmek"
url: "https://cilginyazilim.com/blog/laya-ile-turkce-metin-siniflandirma"
description: "Türkçe metin sınıflandırma için EVREN'in Laya modeli: choice, score ve noul soruları, PHP ile istek, olasılık eşiği ve kesilen metni insana yönlendirme."
published: "2026-10-15T10:00:00+03:00"
modified: "2026-10-15T10:00:03+03:00"
author: "Çılgın Yazılım"
category: "Kurumsal Yazılım ve Entegrasyon"
tags: ["php", "api", "entegrasyon", "llm", "makine öğrenmesi"]
site: "Çılgın Yazılım"
language: "tr"
---

# Laya ile Türkçe Metin Sınıflandırma: Talebi Yönlendirmek

Laya bir destek talebine üç soruyu tek istekte, olasılıklarıyla cevaplar. Varsayılan pencere 1.024 token: uzun bir e-postanın sonu okunmasa da istek hata vermez.

[EVREN yapay zekâ platformundaki](https://cilginyazilim.com/blog/evren-yapay-zeka-platformu-nedir) `laya` modeli bir destek talebine sorduğunuz soruları tek istekte yanıtlar: hangi birime gitmeli, ne kadar acil, içinde hakaret var mı. Cevap serbest metin olarak gelmez. Her soru için bir değer ve olasılık döner. Böylece Türkçe metin sınıflandırmada iş, [sohbet modelinin çıktısını şemaya zorlamaktan](https://cilginyazilim.com/blog/llm-ciktisini-semaya-zorlamak) çıkar ve olasılığa eşik koymaya iner: eşiğin altında kalan talebi insan okur. Aşağıdaki adımlar bu akışı PHP 8.0 ve üstü, cURL ve mbstring ile kurar. Anahtarı almayı ve kullanım şartlarını onaylamayı [EVREN API'sine PHP ile ilk istek](https://cilginyazilim.com/blog/evren-api-php-ile-ilk-istek) yazısı anlatıyor.

![Laya systemone isteğinin soru türlerini, okuma penceresini ve eşik kuralını özetleyen kart](https://cilginyazilim.com/uploads/blog/2026/10/laya-ile-turkce-metin-siniflandirma-ozet.png)
*Model emin olmadığında ya da metni sonuna kadar okumadığında karar insanındır.*

## Adım 1: Soruları choice, score ve noul olarak yazın

İstek gövdesi üç alandan oluşur: `model` (burada `laya`), `state` (sınıflandırılacak metin) ve `questions`. Her sorunun anahtarını siz seçersiniz, yanıt aynı anahtarlarla döner. Soru `type`, `instructions` ve gerekiyorsa `criteria` taşır. EVREN'in [model kataloğu](https://evren.ssyz.org.tr/llm/models) (giriş yapınca açılır) üç türü şöyle tanımlar:

| Tür | Ne sorar | Yanıtta ne döner |
| --- | --- | --- |
| `choice` | Seçeneklerden biri (`criteria`: anahtar → açıklama) | `choice`, `probabilities`, `answer_confidence` |
| `score` | Sıralı düzeyler (`criteria`: liste) | `score` (düzeylerin beklenen değeri, üç düzeyde 0–2), `probabilities` |
| `noul` | Evet mi, hayır mı | `noul`: evet olasılığı (0–1) |

Bu ve sonraki dört bloğu `laya.php` adlı tek dosyaya sırayla ekleyin. Talebin üç sorusu bir sabitte durur:

```php
<?php
// Açıklamalar modelin okuduğu metindir: kısa ve birbirinden ayırt edici olsun.
const TALEP_SORULARI = [
    'birim' => [
        'type' => 'choice',
        'instructions' => 'Talebi hangi birim ele almalı?',
        'criteria' => [
            'fatura' => 'ödeme, iade, ücret, fatura',
            'teknik' => 'hata, kesinti, giriş sorunu',
            'kargo' => 'gönderim, teslimat, gecikme',
            'diger' => 'diğer',
        ],
    ],
    'aciliyet' => [
        'type' => 'score',
        'instructions' => 'Ne kadar acil?',
        'criteria' => ['acil değil', 'orta', 'kritik'],
    ],
    'hakaret' => [
        'type' => 'noul',
        'instructions' => 'Mesajda hakaret veya saldırgan ifade var mı?',
    ],
];
```

Seçenek sayısını küçük tutun. ConvAI'nin [çok dilli Laya model kartı](https://huggingface.co/convaiinnovations/laya-multilingual), 1.024 token'ın 256'sının soruya ve seçeneklerine ayrıldığını yazar ve `choice` sorularının yaklaşık 20 seçeneğin altında tutulmasını önerir. EVREN'in kataloğuna göre Türkçe metin EVREN'in Türkçe ince ayarlı checkpoint'ine, İngilizce metin ConvAI'nin `convaiinnovations/laya` checkpoint'ine gider. Hangisinin yanıtladığı `routing.model` alanındadır.

## Adım 2: İsteği tek PHP fonksiyonuyla gönderin

`laya_sor()` soruları `POST /v1/systemone` adresine gönderir ve 200 ile gelen, `answers` alanı olan yanıtı dizi olarak döndürür. Geri kalan her durumda istisna fırlatır, böylece çağıran kod tek bir `catch` ile talebi insana bırakır.

```php
// Anahtar kodda durmaz, sunucunun ortam değişkeninden okunur.
function laya_sor(string $metin, array $sorular, int $maxLen = 1024): array
{
    $ch = curl_init('https://evren-llmapi.ssyz.org.tr/v1/systemone');
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CONNECTTIMEOUT => 5,
        CURLOPT_TIMEOUT => 20,
        CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('EVREN_API_KEY'), 'Content-Type: application/json'],
        CURLOPT_POSTFIELDS => json_encode(
            ['model' => 'laya', 'state' => $metin, 'questions' => $sorular, 'max_len' => $maxLen],
            JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE | JSON_THROW_ON_ERROR
        ),
    ]);
    $ham = curl_exec($ch);
    $kod = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
    $yanit = is_string($ham) ? json_decode($ham, true) : null;
    if ($kod !== 200 || ! isset($yanit['answers'])) {
        // mb_strcut harfi ortadan bölmez: bölünen UTF-8, bu mesajı JSON'a ya da utf8mb4 sütuna yazdırmaz
        $neden = $ham === false ? curl_error($ch) : ($yanit['error']['message'] ?? mb_strcut($ham, 0, 200, 'UTF-8'));
        throw new RuntimeException("Laya HTTP $kod: $neden");
    }
    return $yanit;
}
```

Kimlik için hem `Authorization: Bearer` hem `X-API-Key` başlığı kabul edilir, hata gövdesi OpenAI biçimindedir. Belgeye göre 403 `terms_not_accepted` şartların onaylanmadığını, 429 hesap kotasını, 503 sunucunun o anki doluluğunu gösterir. Günlük token kotası Laya dahil bütün modellerin toplamıdır ve [EVREN'in çıkarım sayfasına](https://evren.ssyz.org.tr/llm-inference) göre her gün 03:00'te (TSİ) yenilenir.

`laya_sor()` 503'te de yeniden denemez, istisna fırlatır; talebi Adım 4'teki `talep_yonlendir()` insana bırakır. Yeniden denemek isterseniz bekleme süresi ve devre kesici kararlarını [üçüncü parti API'de dayanıklılık](https://cilginyazilim.com/blog/ucuncu-parti-api-entegrasyonunda-dayaniklilik) yazısı anlatıyor. Anahtar tanımlı değilse `getenv()` `false` döner ve istek boş bir `Bearer` başlığıyla gider. CodeIgniter 4'te `.env` dosyasına yazılan `EVREN_API_KEY` de `getenv()` ile okunur.

## Adım 3: Alıntılanan eski yazışmayı metinden atın

Alıntılanan eski yazışma, Laya'nın 1.024 token'lık varsayılan okuma penceresini boşuna doldurur. Pencereyi aşan kısım kesilir, istek hata vermez ve tek işaret `usage.truncated` alanının `true` olmasıdır. Yanıtla açılan bir talep altındaki eski yazışmayı da taşır. Bu fonksiyon yeni mesajın alıntının üstünde olduğunu varsayar: `>` ile başlayan satırları ve alıntı başlığının altını atar.

```php
// Karar en üstteki yeni mesajdan verilir, altındaki alıntı modele gitmez.
function talep_metni(string $govde): string
{
    $tut = [];
    foreach (preg_split('/\R/u', mb_scrub($govde, 'UTF-8')) as $satir) {
        $satir = trim($satir);
        if (preg_match('/^(-{2,}\s*Original Message\s*-*|.*\b(wrote|yazdı):)$/iu', $satir)) {
            break;   // alıntı başlığı: altındaki her şey eski yazışma
        }
        if ($satir !== '' && ! str_starts_with($satir, '>')) {
            $tut[] = $satir;
        }
    }
    return implode("\n", $tut);
}
```

Desenler örnektir. Kendi e-posta altyapınızın alıntı başlığını gerçek bir talep üzerinde görüp ekleyin. Yeni mesajın içinde `yazdı:` ile biten bir satır da alıntı başlığı sayılır; o satır ve altı atılır. Yanıt alıntı başlığının altına yazıldıysa o da atılır. Başlığın üstünde hiçbir satır kalmadıysa Adım 4 talebi konuya bakarak sınıflamaz, insana bırakır. Üstte bir selam satırı (`Merhaba,`) bile kalırsa talep konu ve o satırla sınıflanır.

`mb_scrub()` geçersiz UTF-8 baytlarını `?` yapar. O çağrı olmasa `preg_split()` geçersiz metinde `false` döndürür, `foreach` uyarı verip döngüyü atlar ve talep boş sayılır.

## Adım 4: Kesilen ya da belirsiz talebi insana bırakın

Kesilen ya da belirsiz talep üç fonksiyonla insan kuyruğuna gider. `talep_sinifla()` ilk yanıt kesildiyse aynı metni `max_len` 8.192 ile bir kez daha sorar, belgedeki en geniş pencere de budur. `talep_yonlendir()` gövdeden yeni mesaj kalmadıysa hiç istek atmaz, kaldıysa konuyu mesajın başına ekler.

```php
// Kesilen yanıtı Laya'nın en geniş penceresiyle bir kez daha sorar.
function talep_sinifla(string $metin): array
{
    $y = laya_sor($metin, TALEP_SORULARI);
    return ($y['usage']['truncated'] ?? false) ? laya_sor($metin, TALEP_SORULARI, 8192) : $y;
}

// Ağ hatası, kota ya da bulunamayan mesaj: hepsinde talep kaybolmaz, insan kuyruğuna düşer.
function talep_yonlendir(string $konu, string $govde): array
{
    $mesaj = talep_metni($govde);
    if ($mesaj === '') {
        return ['kuyruk' => 'insan', 'neden' => 'yeni mesaj bulunamadı', 'oncelik' => null];
    }
    try {
        $y = talep_sinifla(trim(talep_metni($konu) . "\n" . $mesaj));
    } catch (RuntimeException $e) {
        return ['kuyruk' => 'insan', 'neden' => $e->getMessage(), 'oncelik' => null];
    }
    return talep_karar($y);
}
```

Geniş pencere yalnız kesilen talepte açılır, çünkü EVREN belgesi `max_len`'i uzun belgeler için anar. ConvAI'nin model kartı kısa girdinin 8.192 ile de aynı cevabı aldığını yazar, ama EVREN'in Türkçe checkpoint'i için böyle bir ölçüm yayımlanmadı. Aynı kart, yaklaşık 4.000 token'ın üstünde doğruluğun dağıldığını da not eder.

`talep_karar()` yanıtı dört yola ayırır. Metin yine kesildiyse ya da hakaret olasılığı 0,2 ile 0,8 arasındaysa talep insana gider. Hakaret olasılığı 0,8 ve üstündeyse birimden bağımsız olarak moderasyona gider. Kalan talep birim eşiğinin (`answer_confidence` < 0,8) altında kaldıysa ya da seçeneklerde olmayan bir birim geldiyse insana, değilse seçilen birime gider.

```php
// Eşikler örnektir: birim eşiğini son adımdaki sayım verir.
function talep_karar(array $y): array
{
    $a = $y['answers'];
    $birim = $a['birim']['choice'] ?? '';
    $hakaret = $a['hakaret']['noul'] ?? 0.5;
    [$kuyruk, $neden] = match (true) {
        $y['usage']['truncated'] ?? false => ['insan', 'metin 8.192 tokenı aşıyor'],
        $hakaret > 0.2 && $hakaret < 0.8 => ['insan', 'hakaret belirsiz'],
        $hakaret >= 0.8 => ['moderasyon', null],   // birim belirsiz olsa da
        ($a['birim']['answer_confidence'] ?? 0) < 0.8,
        ! isset(TALEP_SORULARI['birim']['criteria'][$birim]) => ['insan', 'birim belirsiz'],
        default => [$birim, null],
    };
    return ['kuyruk' => $kuyruk, 'neden' => $neden, 'oncelik' => (int) round($a['aciliyet']['score'] ?? 2)];
}
```

Eşik için önerilen alan `answer_confidence`'tır, yani verilen yanıtın olasılığı; `confidence` dağılımın ne kadar sivri olduğunu ölçer. İsteğe `min_confidence` eklerseniz Laya eşiğin altındaki yanıtı `low_confidence` diye işaretler. Bu işaretin yanıttaki yeri katalog örneğinde görünmediği için kural burada kodda duruyor.

> Aynı isteği `"model": "clef"` ile gönderirseniz bu kesilme kontrolü hiçbir şey yakalamaz. Belgeye göre Clef'in penceresi 16.384 token'dır, aşan kısım hata vermeden kesilir ve `usage.truncated` dönmez: `input_tokens` 16.384 ise metin kesilmiştir. Clef `max_len`, `lang` ve `min_confidence` alanlarını yok sayar, yanıtında `answer_confidence` da yoktur.

## Hakaret tespitinde Laya, öteki üç Türkçe sette Clef önde

Platformun yayımladığı iç ölçüme göre Clef iki Türkçe karar setinde belirgin biçimde, niyet testinde az farkla önde. Hakaret tespitinde ise Laya önde. Katalogdaki karşılaştırma tablosu şöyle:

| Veri seti | Ölçüt | Laya | Clef |
| --- | --- | --- | --- |
| jevalt-bench TR (1.019 örnek) | seçim / evet-hayır | %59 / %76 | %91 / %98 |
| jev-TR çeviri seti (1.539 örnek) | seçim / evet-hayır | %54 / %77 | %88 / %96 |
| MASSIVE niyet testi (Türkçe) | seçim | %95 | %98 |
| OffensEval-TR testi | evet-hayır | %92 | %87 |

MASSIVE niyet testinde fark küçüktür: %95'e karşı %98. Rakamlar platformun kendi ölçümüdür ve sizin taleplerinizin dağılımını göstermez. Katalog hakaret ve saldırganlık akışlarında Laya'yı önerir. Birim sorusunu Clef'e taşımak isterseniz Adım 4'teki birim eşiğini `probabilities` üzerinden yeniden kurmanız ve kesilmeyi `input_tokens` ile yakalamanız gerekir.

## Eşiği insanın etiketlediği eski taleplerle doğrulayın

Doğru eşik, birimini bir insanın verdiği eski talepleri Laya'ya sorup her eşikte kaç talebin otomatik gittiğini ve bunların kaçının yanlış birime düştüğünü sayarak bulunur. Bu betik `laya.php` ile aynı klasörde çalışır:

```php
<?php
// gecmis.csv: başlıksız, UTF-8; her satır konu;govde;birim (birim TALEP_SORULARI anahtarıyla birebir: fatura, diger)
require __DIR__ . '/laya.php';
is_file(__DIR__ . '/gecmis.csv') || exit("gecmis.csv bulunamadı\n");
$f = fopen(__DIR__ . '/gecmis.csv', 'r');
$sonuc = [];
while (($s = fgetcsv($f, null, ';', '"', '')) !== false) {
    [$konu, $mesaj, $dogru] = [$s[0] ?? '', talep_metni($s[1] ?? ''), trim($s[2] ?? '')];
    if ($mesaj === '' || ! isset(TALEP_SORULARI['birim']['criteria'][$dogru])) {
        echo "atlandı: mesaj yok ya da birim tanımsız ($dogru)\n";
        continue;
    }
    try {
        $y = talep_sinifla(trim(talep_metni($konu) . "\n" . $mesaj));   // üretimdeki yol: gerekirse 8.192 ile
        $a = $y['answers']['birim'] ?? [];
        $kesik = $y['usage']['truncated'] ?? false;                      // üretimde insana gider, otomatik sayılmaz
        $sonuc[] = [$kesik ? 0 : ($a['answer_confidence'] ?? 0), ($a['choice'] ?? '') === $dogru];
    } catch (RuntimeException $e) {
        echo "atlandı: {$e->getMessage()}\n";
    }
}
foreach ([0.6, 0.7, 0.8, 0.9] as $esik) {
    $oto = array_filter($sonuc, fn ($r) => $r[0] >= $esik);
    $yanlis = count(array_filter($oto, fn ($r) => ! $r[1]));
    printf("eşik %.1f: %d/%d talep otomatik, %d yanlış birim\n", $esik, count($oto), count($sonuc), $yanlis);
}
```

PowerShell'de anahtarı `$env:EVREN_API_KEY = 'evren_llm_...'` ile verip `C:\xampp\php\php.exe dogrula.php` komutunu çalıştırabilirsiniz. Dosyayı UTF-8 kaydedin: başka kodlamadaki Türkçe harfleri `mb_scrub()` `?` yapar ve sayım bozulur. Birim sütunu `TALEP_SORULARI` anahtarlarıyla birebir yazılır (`fatura`, `diger`); `Fatura` ya da `Diğer` yazan satır atlanır ve ekranda görünür. Betik üretimdeki kesilme yolunu izler: kesilen talebi 8.192 ile yeniden sorar, yine kesilirse otomatik saymaz. Hakaret bandına ya da moderasyona düşen talepleri ayırmaz, onları da birim olasılığına göre sayar.

Otomatik giden talepler içinde yanlış sayısının kabul edebileceğiniz düzeye indiği en düşük eşik, Adım 4'teki birim eşiğinin yerine geçer. Hakaret bandını aynı yolla seçmek için CSV'ye bir hakaret sütunu gerekir. Platform, dolaylı ifade edilen iptal ve ayrılma tehditlerinde modelin hata yapabileceğini yazar ve kritik akışlarda eşiğin kendi verinizle doğrulanmasını ister. Laya'nın model kartı da taban checkpoint'lerin olasılıklarını kalibre edilmeden fazla iyimser bulur.

**Test ortamı:** Kod PHP 8.2.12 (cURL, mbstring) ve CodeIgniter 4.7.4 (yalnız `.env` denemesi) ile, katalogdaki istek ve yanıt biçimini taklit eden yerel bir sunucuya karşı çalıştırıldı: normal ve eşik altı talep, boş, alıntılı ve alttan yanıtlanmış metin, 8.192 token'ı aşan metin, 401, 403, 429, 503, JSON olmayan 502, bozuk JSON ve zaman aşımı. Gerçek uç noktaya istek atılmadı. Taklit olasılıkları kurallarla ürettiği için Laya'nın doğruluğu ölçülmedi; uç noktanın davranışı belgeye göre yazıldı.

---

Eşiğin üstünde kalan yanlış karar doğrudan yanlış birime gider: Laya bir fatura itirazını 0,95 olasılıkla kargo sayarsa talep kimseye görünmeden kargo kuyruğuna düşer. Temsilci talebi başka kuyruğa taşıdığında bu hata görünür olur. Taşınan her talebi Laya'nın verdiği birim ve `answer_confidence` değeriyle birlikte kaydederseniz yanlış kararların hangi olasılık aralığında toplandığı görünür. Son adımdaki sayımı da bu taleplerle yenileyip birim eşiğini oradan güncellersiniz.

## Sıkça Sorulan Sorular

### Laya bir LLM mi, sohbet modelinin yerine geçer mi?

Hayır. Laya metin üretmeyen bir karar modelidir; verilen metin hakkında choice, score ve noul sorularını tek geçişte olasılıklarıyla yanıtlar. EVREN kataloğu serbest metin yanıtı gereken işlerde sohbet modellerini önerir: cevap taslağı, özet ya da çeviri için sohbet ucu kullanılır.

### Jev için yazılmış bir istemci EVREN'de çalışır mı?

Evet, platform belgesine göre. EVREN'in /v1/systemone ucu Jev sözleşmesiyle uyumludur ve Jev istemcileri model alanına jev-1 yazıldığında değişiklik yapmadan çalışır; bu ad Laya'ya gider. Taban adres ve anahtar yine EVREN'inkiler olmalıdır.

### Laya'yı Hugging Face'ten indirip kendi sunucumda çalıştırabilir miyim?

Evet, ama EVREN'in Türkçe ince ayarı olmadan. ConvAI'nin laya-multilingual checkpoint'i Apache 2.0 lisanslıdır ve laya-serve aynı /v1/systemone biçimini sunar; LAYA_API_KEY tanımlanmazsa bütün ağ arayüzlerinde kimliksiz dinler. EVREN'in Türkçe checkpoint'i evren/laya-tr-v5 ise 11 Ekim 2026'da herkese açık değildi.

---

Kaynak: [Laya ile Türkçe Metin Sınıflandırma: Talebi Yönlendirmek](https://cilginyazilim.com/blog/laya-ile-turkce-metin-siniflandirma)
