Teknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor HaberleriTeknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor HaberleriTeknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor Haberleri
Yazı Tipi BoyutlandırıcıAa
  • Anasayfa
  • Teknoloji
    • Siber Güvenlik
    • Yapay Zeka
    • Donanım
    • Bilim
  • Yazılım
  • Savunma & İstihbarat
  • Oyun
  • Yaşam
    • Finans
    • Sinema
    • Dünyadan Haberler
  • İş Birliği
Okuma: Laravel AI Akışı Kullanıcı Deneyimi: Yazma Göstergeleri, Düşünce Durumları ve Akış İptali
Paylaş
Yazı Tipi BoyutlandırıcıAa
Teknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor HaberleriTeknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor Haberleri
Ara
Bizi Takip Et
  • Hakkımızda
  • Gizlilik politikası
  • Tanıtım Yazısı ve Backlink Hizmeti
© 2026 Teknomers. All Rights Reserved.

Anasayfa » Laravel AI Akışı Kullanıcı Deneyimi: Yazma Göstergeleri, Düşünce Durumları ve Akış İptali

Yazılım

Laravel AI Akışı Kullanıcı Deneyimi: Yazma Göstergeleri, Düşünce Durumları ve Akış İptali

teknomers
Son güncelleme: 6 Haziran 2026 12:48
teknomers
Paylaş
Paylaş



“Çalışıyor” ile “İyi” Arasındaki Fark

<p>Laravel'de son zamanlarda bir AI özelliği yayına almışsanız, bu farkı biliyorsunuzdur. Backend, token'ları doğru bir şekilde akıtsa da, testler geçse de, teknik bilgiye sahip olmayan bir paydaş arayüzü açıp hiçbir şey görünmeden önce neden donduğunu soruyor. 
</p>

<p><strong>Laravel AI akış kullanıcı deneyimi</strong> bir backend problemi değildir. Taşıma seçeneği zaten belirlenmiştir. <a href="https://origin-main.com/laravel-real-time-ai-ux/" target="_blank" rel="noopener noreferrer">Gerçek zamanlı AI teslimat kalıpları üzerine modülümüz</a> mevcut seçenekleri anlatmaktadır. <a href="https://origin-main.com/ai-foundations/laravel-ai-streaming-livewire-sse-websockets/" target="_blank" rel="noopener noreferrer">Mimarinize uygun doğru akış taşımasını seçmek</a> ilk adımdır. Bu makale ikinci adımı ele alıyor: taşıma işlevsel hale geldikten sonra kullanıcıların gerçekten deneyimlediği.
</p>

<p>Bir AI akış arayüzünün tüm kullanıcı deneyimini yönlendiren üç durum vardır.</p>

<ul>
    <li><strong>Ön akış (düşünme):</strong> kullanıcı gönderimi ile ilk token arasındaki sessizlik</li>
    <li><strong>Orta akış (üretme):</strong> görsel bozulma olmadan ilerleyen token render'ı</li>
    <li><strong>Son akış (tamamlandı veya iptal edildi):</strong> doğru nihai durumla temiz çözüm</li>
</ul>

<p>Kullanıcılar taşıma katmanınızı deneyimlemezler. İlk token gönderilene kadar geçen sessizlik, belirsiz bir metin duvarı ve kaçan bir üretimi durdurma yollarının tamamen yokluğu ile karşılaşırlar. Bu, Alpine.js ve Prism PHP yığını üzerinde belirli uygulama yöntemleri ile çözülebilen sorunlardır. Her birine değineceğiz.</p>

<p>Bu sorunların hiçbiri egzotik değildir. Bilinçli UX çalışması yapılmadan yayımlanan her AI arayüzünde ortaya çıkar. İyi haber şu ki, her birinin arka planda mimaride değişiklik yapılmadan uygulanabilir bir çözümü vardır.</p>

<h2>
    <a name="prestream-handling-the-silence-before-the-first-token" href="#prestream-handling-the-silence-before-the-first-token">
    </a>
    Ön Akış: İlk Token Öncesindeki Sessizliği Yönetmek
</h2>

<p>Kullanıcının bir isteği gönderdiği ile ilk token’ın geldiği zaman aralığı, çoğu AI arayüzünün kullanıcı kaybettiği yerdir. Hızlı, düşük karmaşıklıkta tamamlamalarda bu farkedilemez. Ancak karmaşık akıl yürütme görevlerinde, soğuk API başlatmalarda veya ağır yüklenmiş uç noktalarda bu iki ila beş saniye sürebilir. O sessizlik, backend tam olarak çalışsa bile bozuk gibi algılanır.</p>

<p>Çözüm basit: istek geldiğinde hemen adlandırılmış bir SSE olayı yaymalısınız, Prism çağrısından önce. Ön akış sessizliği, bir token çıktığında değil, o olayı aldığında “düşünme” durumuna geçmesi sağlanarak örtülmüş olur.</p>

<h3>
    <a name="ui-state-%E2%86%94-sse-stream-lifecycle" href="#ui-state-%E2%86%94-sse-stream-lifecycle">
    </a>
    UI Durumu ↔ SSE Akış Yaşam Döngüsü
</h3>

<p><a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foy6j9ljx5f0ircomrz2s.PNG" class="article-body-image-wrapper"><img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foy6j9ljx5f0ircomrz2s.PNG" alt="UI State - SSE Stream Lifecycle" loading="lazy"/></a></p>

<h3>
    <a name="pattern-a-animated-typing-indicator-with-alpinejs" href="#pattern-a-animated-typing-indicator-with-alpinejs">
    </a>
    Desen A: Alpine.js ile Animasyonlu Yazım Göstergesi
</h3>

<p>SSE rotası <code>event: thinking</code> olayını hemen, Prism çağrısı başlamadan önce yayar. Her iki işlem de aynı <code>response()->stream()</code> geri arama içinde çalıştığı için ikinci bir talep gerekmemektedir:<br/></p>

<div class="highlight js-code-highlight">
    <pre class="highlight php"><code><span class="kn">use</span> <span class="nc">Illuminate\Http\Request</span><span class="p">;</span>

use Prism\Prism\Facades\Prism;

Route::get(‘/chat/stream’, function (Request $request) {
return response()->stream(function () use ($request) {
echo “event: thinking\n“;
echo “data: {}\n\n“;
ob_flush();
flush();

    <span class="nv">$stream</span> <span class="o">=</span> <span class="nc">Prism</span><span class="o">::</span><span class="nf">text</span><span class="p">()</span>
        <span class="o">-&gt;</span><span class="nf">using</span><span class="p">(</span><span class="s1">'anthropic'</span><span class="p">,</span> <span class="s1">'claude-sonnet-4-6'</span><span class="p">)</span>
        <span class="o">-&gt;</span><span class="nf">withMaxTokens</span><span class="p">(</span><span class="mi">2048</span><span class="p">)</span>
        <span class="o">-&gt;</span><span class="nf">withPrompt</span><span class="p">(</span><span class="nv">$request</span><span class="o">-&gt;</span><span class="nf">string</span><span class="p">(</span><span class="s1>'message'</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">limit</span><span class="p">(</span><span class="mi">2000</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">value</span><span class="p">())</span>
        <span class="o">-&gt;</span><span class="nf">stream</span><span class="p">();</span>

    <span class="k">foreach</span> <span class="p">(</span><span class="nv">$stream</span> <span class="k">as</span> <span class="nv">$chunk</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="nb">connection_aborted</span><span class="p">())</span> <span class="p">{</span>
            <span class="k">break</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="k">echo</span> <span class="s2">"data: "</span> <span class="mf">.</span> <span class="nb">json_encode</span><span class="p">([</span><span class="s1>'text'</span> <span class="o">=&gt;</span> <span class="nv">$chunk</span><span class="o">-&gt;</span><span class="n">text</span><span class="p">])</span> <span class="mf">.</span> <span class="s2">"</span><span class="se">\n\n</span><span class="s2">"</span><span class="p">;</span>
        <span class="nb">ob_flush</span><span class="p">();</span>
        <span class="nb">flush</span><span class="p">();</span>
    <span class="p">}</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nb">connection_aborted</span><span class="p">())</span> <span class="p">{</span>
        <span class="k">echo</span> <span class="s2">"data: [DONE]</span><span class="se">\n\n</span><span class="s2">"</span><span class="p">;</span>
        <span class="nb">ob_flush</span><span class="p">();</span>
        <span class="nb">flush</span><span class="p">();</span>
    <span class="p">}</span>
<span class="p">},</span> <span class="mi">200</span><span class="p">,</span> <span class="p">[</span>
    <span class="s1">'Content-Type'</span>      <span class="o">=&gt;</span> <span class="s1>'text/event-stream'</span><span class="p">,</span>
    <span class="s1>'Cache-Control'</span>     <span class="o">=&gt;</span> <span class="s1>'no-cache'</span><span class="p">,</span>
    <span class="s1>'X-Accel-Buffering'</span> <span class="o">=&gt;</span> <span class="s1>'no'</span><span class="p">,</span>
<span class="p">]);</span>

})->middleware(<span class=”s1>’auth:sanctum’);

Enter fullscreen mode

        <svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewbox="0 0 24 24" class="highlight-action crayons-icon highlight-action--fullscreen-off"><title>Exit fullscreen mode</title>
        <path d="M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z"/>
        </svg>
    </div>
</div>

<p>Alpine.js bileşeni durumu bir boole bayrağı yerine açık bir string enum olarak yönetir. Bu, iptal eklediğinizde önemlidir. Bir EventSource kapandığında, <code>onerror</code> koşuldan bağımsız olarak ateşlenir. String durumu <code>onerror</code>’ın kapanmanın kullanıcı iptali mi yoksa bir ağ hatası mı olduğunu kontrol etmesine olanak tanır. Boole <code>isLoading</code> bu ayrımı yapamaz. Tüm reaktif özellikler, Alpine'nin onları başlangıçta takip edebilmesi için data nesnesinde tanımlanmıştır:<br/></p>

<div class="highlight js-code-highlight">
    <pre class="highlight javascript"><code><span class="kd">function</span> <span class="nf">chatStream</span><span class="p">()</span> <span class="p">{</span>
        <span class="k">return</span> <span class="p">{</span>
            <span class="na">output</span><span class="p">:</span>   <span class="dl">''</span><span class="p">,</span>
            <span class="na">message</span><span class="p">:</span>  <span class="dl">''</span><span class="p">,</span>
            <span class="na">state</span><span class="p">:</span>    <span class="dl">'</span><span class="s1">idle</span><span class="dl">'</span><span class="p">,</span> <span class="c1">// idle | thinking | streaming | complete | cancelled</span>
            <span class="na">thoughts</span><span class="p">:</span> <span class="p">[],</span>
            <span class="na">buffer</span><span class="p">:</span>   <span class="dl">''</span><span class="p">,</span>
            <span class="na">rafId</span><span class="p">:</span>    <span class="kc">null</span><span class="p">,</span>
            <span class="na">source</span><span class="p">:</span>   <span class="kc">null</span><span class="p">,</span>

            <span class="nf">startStream</span><span class="p">()</span> <span class="p">{</span>
                <span class="k">this</span><span class="p">.</span><span class="nx">state</span>    <span class="o">=</span> <span class="dl">'</span><span class="s1">thinking</span><span class="dl">'</span><span class="p">;</span>
                <span class="k">this</span><span class="p">.</span><span class="nx">output</span>   <span class="o">=</span> <span class="dl">''</span><span class="p">;</span>
                <span class="k">this</span><span class="p">.</span><span class="nx">thoughts</span> <span class="o">=</span> <span class="p">[];</span>
                <span class="k">this</span><span class="p">.</span><span class="nx">buffer</span>   <span class="o">=</span> <span class="dl">''</span><span class="p">;</span>

                <span class="k">if </span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">rafId</span><span class="p">)</span> <span class="p">{</span>
                    <span class="nf">cancelAnimationFrame</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">rafId</span><span class="p">);</span>
                    <span class="k">this</span><span class="p">.</span><span class="nx">rafId</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
                <span class="p">}</span>
                <span class="k">if </span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">source</span><span class="p">)</span> <span class="k">this</span><span class="p">.</span><span class="nx">source</span><span class="p">.</span><span class="nf">close</span><span class="p">();</span>

                <span class="k">this</span><span class="p">.</span><span class="nx">source</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">EventSource</span><span class="p">(</span>
                    <span class="s2">`/chat/stream?message=</span><span class="p">${</span><span class="nf">encodeURIComponent</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">message</span><span class="p">)}</span><span class="s2">`</span>
                <span class="p">);</span>

                <span class="k">this</span><span class="p">.</span><span class="nx">source</span><span class="p">.</span><span class="nf">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">thinking</span><span class="dl">'</span><span class="p">,</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
                    <span class="k">this</span><span class="p">.</span><span class="nx">state</span> <span class="o">=</span> <span class="dl>'</span><span class="s1">thinking</span><span class="dl>'</span><span class="p">;</span>
                <span class="p">});</span>

                <span class="k">this</span><span class="p">.</span><span class="nx">source</span><span class="p">.</span><span class="nf">addEventListener</span><span class="p">(</span><span class="dl>'</span><span class="s1">tool_call</span><span class="dl>'</span><span class="p">,</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
                    <span class="kd">const</span> <span class="nx">data</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nf">parse</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">data</span><span class="p">);</span>
                    <span class="k">this</span><span class="p">.</span><span class="nx">thoughts</span><span class="p">.</span><span class="nf">push</span><span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">status</span><span class="p">);</span>
                <span class="p">});</span>

                <span class="kd">const</span> <span class="nx">flush</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
                    <span class="k">if </span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">buffer</span><span class="p">)</span> <span class="p">{</span>
                        <span class="k">this</span><span class="p">.</span><span class="nx">output</span> <span class="o">+=</span> <span class="k">this</span><span class="p">.</span><span class="nx">buffer</span><span class="p">;</span>
                        <span class="k">this</span><span class="p">.</span><span class="nx">buffer</span>  <span class="o">=</span> <span class="dl">''</span><span class="p">;</span>
                    <span class="p">}</span>
                    <span class="k">if </span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span> <span class="o">===</span> <span class="dl>'</span><span class="s1">streaming</span><span class="dl>'</span><span class="p">)</span> <span class="p">{</span>
                        <span class="k">this</span><span class="p">.</span><span class="nx">rafId</span> <span class="o">=</span> <span class="nf">requestAnimationFrame</span><span class="p">(</span><span class="nx">flush</span><span class="p">);</span>
                    <span class="p">}</span>
                <span class="p">};</span>

                <span class="k">this</span><span class="p">.</span><span class="nx">source</span><span class="p">.</span><span class="nx">onmessage</span> <span class="o">=</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
                    <span class="k">if </span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">data</span> <span class="o">===</span> <span class="dl>'</span><span class="s1">[DONE]</span><span class="dl>'</span><span class="p">)</span> <span class="p">{</span>
                        <span class="k">this</span><span class="p">.</span><span class="nx">state</span> <span class="o">=</span> <span class="dl>'</span><span class="s1">complete</span><span class="dl>'</span><span class="p">;</span>
                        <span class="k">if </span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">rafId</span><span class="p">)</span> <span class="p">{</span>
                            <span class="nf">cancelAnimationFrame</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">rafId</span><span class="p">);</span>
                            <span class="k">this</span><span class="p">.</span><span class="nx">output</span> <span class="o">+=</span> <span class="k">this</span><span class="p">.</span><span class="nx">buffer</span><span class="p">;</span>
                            <span class="k">this</span><span class="p">.</span><span class="nx">buffer</span>  <span class="o">=</span> <span class="dl'>''</span><span class="p">;</span>
                            <span class="k">this</span><span class="p">.</span><span class="nx">rafId</span>   <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
                        <span class="p">}</span>
                        <span class="k">this</span><span class="p">.</span><span class="nx">source</span><span class="p">.</span><span class="nf">close</span><span class="p">();</span>
                        <span class="k">return</span><span class="p">;</span>
                    <span class="p">}</span>
                    <span class="k">try</span> <span class="p">{</span>
                        <span class="kd">const</span> <span class="nx">parsed</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nf">parse</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">data</span><span class="p">);</span>
                        <span class="k">if </span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span> <span class="o">!==</span> <span class="dl>'</span><span class="s1">cancelled</span><span class="dl>'</span><span class="p">)</span> <span class="p">{</span>
                            <span class="k">this</span><span class="p">.</span><span class="nx">state</span>   <span class="o">=</span> <span class="dl>'</span><span class="s1">streaming</span><span class="dl>'</span><span class="p">;</span>
                            <span class="k">this</span><span class="p">.</span><span class="nx">buffer</span> <span class="o">+=</span> <span class="nx">parsed</span><span class="p">.</span><span class="nx">text</span> <span class="o">??</span> <span class="dl'>''</span><span class="p">;</span>
                            <span class="k">if </span><span class="p">(</span><span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">rafId</span><span class="p">)</span> <span class="p">{</span>
                                <span class="k">this</span><span class="p">.</span><span class="nx">rafId</span> <span class="o">=</span> <span class="nf">requestAnimationFrame</span><span class="p">(</span><span class="nx">flush</span><span class="p">);</span>
                            <span class="p">}</span>
                        <span class="p">}</span>
                    <span class="p">}</span> <span class="k">catch </span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
                        <span class="nx">console</span><span class="p">.</span><span class="nf">error</span><span class="p">(</span><span class="dl>'</span><span class="s1">SSE parse error:</span><span class="dl>'</span><span class="p">,</span> <span class="nx">e</span><span class="p">);</span>
                    <span class="p">}</span>
                <span class="p">};</span>

                <span class="k">this</span><span class="p">.</span><span class="nx">source</span><span class="p">.</span><span class="nx">onerror</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
                    <span class="k">if </span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span> <span class="o">!==</span> <span class="dl>'</span><span class="s1">cancelled</span><span class="dl>'</span><span class="p">)</span> <span class="p">{</span>
                        <span class="k">this</span><span class="p">.</span><span class="nx">state</span> <span class="o">=</span> <span class="dl>'</span><span class="s1">idle</span><span class="dl>'</span><span class="p">;</span>
                    <span class="p">}</span>
                    <span class="k">this</span><span class="p">.</span><span class="nx">source</span><span class="p">.</span><span class="nf">close</span><span class="p">();</span>
                <span class="p">};</span>
            <span class="p">},</span>

            <span class="nf">cancel</span><span class="p">()</span> <span class="p">{</span>
                <span class="k">if </span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">source</span><span class="p">)</span> <span class="k">this</span><span class="p">.</span><span class="nx">source</span><span class="p">.</span><span class="nf">close</span><span class="p">();</span>
                <span class="k">this</span><span class="p">.</span><span class="nx">state</span> <span class="o">=</span> <span class="dl>'</span><span class="s1">cancelled</span><span class="dl>'</span><span class="p">;</span>
                <span class="k">if </span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">rafId</span><span class="p">)</span> <span class="p">{</span>
                    <span class="nf">cancelAnimationFrame</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">rafId</span><span class="p">);</span>
                    <span class="k">this</span><span class="p">.</span><span class="nx">output</span> <span class="o">+=</span> <span class="k">this</span><span class="p">.</span><span class="nx">buffer</span><span class="p">;</span>
                    <span class="k">this</span><span class="p">.</span><span class="nx">buffer</span>  <span class="o">=</span> <span class="dl'>''</span><span class="p">;</span>
                    <span class="k">this</span><span class="p">.</span><span class="nx">rafId</span>   <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
                <span class="p">}</span>
            <span class="p">}</span>
        <span class="p">};</span>
    <span class="p">}</span>
    </code></pre>
    <div class="highlight__panel js-actions-panel">
        <div class="highlight__panel-action js-fullscreen-code-action">
            <svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewbox="0 0 24 24" class="highlight-action crayons-icon highlight-action--fullscreen-on"><title>Enter fullscreen mode</title>
            <path d="M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z"/>
            </svg>

            <svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewbox="0 0 24 24" class="highlight-action crayons-icon highlight-action--fullscreen-off"><title>Exit fullscreen mode</title>
            <path d="M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z"/>
            </svg>
        </div>
    </div>
</div>

<p>Durum odaklı şablon doğrudan bileşene bağlanır:<br/></p>

<div class="highlight js-code-highlight">
    <pre class="highlight html"><code><span class="nt"><div> <span class="na">x-data=</span><span class="s">"chatStream()"</span><span class="nt">&gt;</span>
<span class="nt"><p> <span class="na">x-show=</span><span class="s">"state === 'idle' || state === 'complete' || state === 'cancelled'"</span><span class="nt">&gt;</span>
    <span class="nt"><input/> <span class="na">x-model=</span><span class="s">"message"</span> <span class="na">type=</span><span class="s">"text"</span> <span class="na">placeholder=</span><span class="s">"Bir şey sor…" </span><span class="nt">&gt;</span>
    <span class="nt"><button> <span class="err">@</span><span class="na">click=</span><span class="s">"startStream()"</span><span class="nt">&gt;</span>Gönder<span class="nt"/></button></span>
<span class="nt"/></span></p></span>

<span class="nt"><p> <span class="na">x-show=</span><span class="s">"state === 'thinking'"</span> <span class="na">class=</span><span class="s">"typing-indicator"</span><span class="nt">&gt;</span>
    <span class="nt"><span/><span/><span/></span>
<span class="nt"/></p></span>

<span class="nt"><div> <span class="na">x-show=</span><span class="s">"thoughts.length &gt; 0"</span> <span class="na">class=</span><span class="s">"thought-states"</span><span class="nt">&gt;</span>
    <span class="nt"><template> <span class="na">x-for=</span><span class="s">"(thought, index) in thoughts"</span> <span class="na">:key=</span><span class="s">"index"</span><span class="nt">&gt;</span>
        <span class="nt"><p> <span class="na">x-text=</span><span class="s">"thought"</span> <span class="na">class=</span><span class="s">"thought-item"</span><span class="nt">&gt;</span></p></span>
    <span class="nt"/></template></span>
<span class="nt"/></div></span>

<span class="nt"><p>
    <span class="na">x-show=</span><span class="s">"state === 'streaming' || state === 'complete' || state === 'cancelled'"</span>
    <span class="na">x-text=</span><span class="s">"output"</span>
    <span class="na">class=</span><span class="s">"output-area"</span><span class="nt">&gt;</span>
<span class="nt"/></p></span>

<span class="nt"><button> <span class="na">x-show=</span><span class="s">"state === 'streaming'"</span> <span class="err">@</span><span class="na">click=</span><span class="s">"cancel()"</span><span class="nt">&gt;</span>Durdur<span class="nt"/></button></span>


Enter fullscreen mode

            <svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewbox="0 0 24 24" class="highlight-action crayons-icon highlight-action--fullscreen-off"><title>Exit fullscreen mode</title>
            <path d="M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z"/>
            </svg>
        </div>
    </div>
</div>

<blockquote>
    <p>[Mimari Notu] Bu örnekler, <code>laravel/ai</code> SDK'sını değil, Prism PHP'yi kullanır. Prism’in akış API'sı bu yazının yazıldığı sırada ajans iş akışları için daha olgun ve daha geniş sağlayıcı kapsamı sunmaktadır. <code>laravel/ai</code> SDK’sı, Laravel ekiplerinin uzun vadeli üretim yönüdür. Yeni projeler için öncelikle değerlendirin; özellikle sağlayıcı kümeniz OpenAI veya Anthropic ile sınırlıysa varsayılan olarak Prism'den kaçının.</p>
</blockquote>

<h3>
    <a name="pattern-b-skeleton-loader-with-livewire" href="#pattern-b-skeleton-loader-with-livewire">
    </a>
    Desen B: Livewire ile Skeleton Yükleyici
</h3>

<p>AI yanıtı, bir kart, veri tablosu veya üretilmiş form önizlemesi gibi yapılandırılmış bir düzen içinde görüntülendiğinde, yazım göstergesi yerine bir iskelet yer tutucu daha uygundur. Bir yazım göstergesi, yanıtın metinsel ve konuşmalıklı olduğunu ima eder. Bir iskelet yapısal bir şeyin geldiğini ima eder. Livewire’ın <code>wire:loading</code> talimatı, bu ek JavaScript olmadan bunu yönetir:<br/></p>

<div class="highlight js-code-highlight">
    <pre class="highlight html"><code><span class="nt"><div> <span class="na">wire:loading</span> <span class="na">wire:target=</span><span class="s">"generate"</span><span class="nt">&gt;</span>
<span class="nt"><div> <span class="na">class=</span><span class="s">"skeleton-card"</span><span class="nt">&gt;</span>
    <span class="nt"><p> <span class="na">class=</span><span class="s">"skeleton-line w-3/4"</span><span class="nt">&gt;</span></p></span>
    <span class="nt"><p> <span class="na">class=</span><span class="s">"skeleton-line w-full"</span><span class="nt">&gt;</span></p></span>
    <span class="nt"><p> <span class="na">class=</span><span class="s">"skeleton-line w-5/6"</span><span class="nt">&gt;</span></p></span>
<span class="nt"/></div></span>

<span class="nt"><p> <span class="na">wire:loading.remove</span> <span class="na">wire:target=</span><span class="s">"generate"</span><span class="nt">&gt;</span>
{{ $response }}


Enter fullscreen mode

            <svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewbox="0 0 24 24" class="highlight-action crayons-icon highlight-action--fullscreen-off"><title>Exit fullscreen mode</title>
            <path d="M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z"/>
            </svg>
        </div>
    </div>
</div>

<p><a href="https://origin-main.com/coding-tutorials/laravel-livewire-claude-api-real-time-chat/" target="_blank" rel="noopener noreferrer">Livewire ve Claude API gerçek zamanlı sohbet kılavuzu</a>, akış yanıtları için tam Livewire bileşen yaşam döngüsünü kapsamaktadır; <code>wire:poll</code> yedekleri, sürekli SSE bağlantılarının desteklenmediği ortamlar için.</p>

<h2>
    <a name="midstream-rendering-tokens-without-browser-lag" href="#midstream-rendering-tokens-without-browser-lag">
    </a>
    Orta Akış: Tarayıcı Gecikmesi Olmadan Token'ları Render Etmek
</h2>

<p>Naif token ekleme (her SSE mesajında çıktıya doğrudan ekleme yapmak), uzun yanıtlar üzerinde yerleşik bir yüklemeye neden olur. Tarayıcı her değişiklikte DOM'u yeniden akıtır. Karmaşık bir yanıtta 500. token' da, arayüz görünür bir şekilde yavaşlar ve yanıt büyüdükçe bu yavaşlama daha da kötüleşir.</p>

<p>Akış çerçevelerinin kullanıldığı batched DOM güncelleme yaklaşımı, yukarıda <code>chatStream()</code> bileşenine entegre edilmiştir. <code>flush</code> işlevi gelen token'ları <code>this.buffer</code> içinde toplar ve bu tamponu <code>this.output</code>'a, her animasyon karesi üzerinde boşaltır; bu sayede her SSE olayında DOM değişiklikleri 60fps'de sınırlandırılmış olur.</p>

<blockquote>
    <p>[Üretim Tehlikesi] Yüksek token yanıtları (2,000'den fazla token) alan ekipler, mobil donanımda masaüstü kullanıcılarından önce kötüleşmeyi gözlemlerler. Hızlı bir ağda ve yeterli bir modelle, ham token ekleme işlemi, saniyede yüzlerce DOM değişikliği yapmaya çalışabilir. Çerçeve hızı sınırı, bir yanıt 30 token/sn veya 300 token/sn geldiğinde de aynı şekilde uygulanır; çıktı alanı, tarayıcının doğal boya döngüsünde güncellenir.</p>
</blockquote>

<p>İkinci bir optimizasyon, bağımlılık maliyetine değer: AI çıktınız markdown ise, akış sırasında artan render, ham markdown söz dizimleri görünürken bir okuma deneyimini büyük ölçüde iyileştirir. <code>marked.js</code> gibi hafif bir istemci tarafı ayırıcısı kullanın. Ancak, yarı render edilmiş kod bloklarının kullanıcıya ulaşmasına engel olmak için, render işlemi her token’da değil, debounced bir aralıkta gerçekleştirilmelidir. 150ms'lik bir debounced, yarı-render edilmiş kod bloklarının kullanıcıya ulaşmasını engellerken, çıktıyı görsel olarak ilerleyen bir şekilde tutar. Her debounced tıkında, tam bir biriktirilmiş dizeye göre değil, her bir token'a göre parse yapılmalıdır.</p>

<h2>
    <a name="agentic-thought-states" href="#agentic-thought-states">
    </a>
    Ajans Düşünce Durumları
</h2>

<p>Çok aşamalı ajans iş akışları, tek dönüş akışlarının yaşamadığı belirli bir UX problemi taşır. Model, görünür bir yanıt üretmeden önce iki veya üç araç çağrısı yapabilir. Kullanıcının perspektifinden bu, alışılmadık derecede uzun bir ön akış sessizliğinden ayırt edilemez. İşlem gizlidir. Kullanıcıların hiçbir şeyin olup olmadığını, sistemin ne yaptığını veya beklemeye mi yoksa iptal etmeye mi karar vereceklerine dair bir sinyal yoktur.</p>

<p>Doğru yaklaşım, her bir araç çağrısını olduğu gibi yüzeye çıkarır. Her Prism araç geri çağrısı, yürütmesine başladığında adlandırılmış bir SSE olayı yayar. Ön uç, <code>tool_call</code> olaylarını dinler ve bunları, ana yanıt alanının üzerinde ve görsel olarak daha düşük olan geçici bir düşünce durumu kaydı olarak render eder:<br/></p>

<div class="highlight js-code-highlight">
    <pre class="highlight php"><code><span class="kn">use</span> <span class="nc">Prism\Prism\Tool</span><span class="p">;</span>

$tools = [
Tool::as‘search_knowledge_base’)
->for‘Kapsamlı makaleler bulmak için iç bilgi birimini ara’)
->withStringParameter‘query’, <span class=”s1>’Arama sorgusu’)
->using<span class=”p>(function (string $query): string {
echo “event: tool_call\n“;
echo “data: “ . json_encode([<span class=”s1>’status’ => <span class=”s2>”Arama yapılıyor: {$query}<span class=”s2>””]) . “\n\n“;
ob_flush();
flush();

        <span class="k">return</span> <span class="nc">KnowledgeBase</span><span class="o">::</span><span class="nf">search</span><span class="p">(</span><span class="nv">$query</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">take</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">toJson</span><span class="p">();</span>
    <span class="p">}),</span>

];

Enter fullscreen mode

            <svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewbox="0 0 24 24" class="highlight-action crayons-icon highlight-action--fullscreen-off"><title>Exit fullscreen mode</title>
            <path d="M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z"/>
            </svg>
        </div>
    </div>
</div>

<p><code>tool_call</code> olay dinleyicisi ve <code>thoughts</code> dizisi zaten <code>chatStream()</code> bileşeninin bir parçasıdır. Şablon bölümünün üzerine düşünce durumları kaydını render eder. Düşünce durumu öğelerini küçük bir yazı boyutunda, soluk bir renkte tutun ve ana çıktı alanından görsel ağırlık ile ayrılmış olarak yerleştirin. Bunlar içerik değil, işlem göstergeleridir. Kullanıcılar ana cevabı okumaya devam etmelidir.</p>

<blockquote>
    <p>[Üretim Tehlikesi] Düşünce durumu verilerinin SSE ile yayılması sadece araç geri çağrısı akış yanıtı ile aynı PHP çıktı tamponunda çalıştığında geçerlidir. Bu, tek bir HTTP isteği ile senkronize SSE akışları için geçerlidir. Laravel Horizon'a sıraya alınan işler olarak devredilen ajanslar için, araç geri çağrısı bir işçi işleminde çalışır ve herhangi bir HTTP çıktı tamponu yoktur. Bu mimaride, düşünce durumlarını WebSockets üzerinden Reverb ile yayın yaparak iletin. <a href="https://origin-main.com/laravel-architecture/laravel-reverb-ai-streaming-websocket-token-delivery/" target="_blank" rel="noopener noreferrer">Token başına gönderim kılavuzu</a> uzun süreli sıra süreçleri için yayın kanalı yaklaşımını ele alır.</p>
</blockquote>

<p>Tüm Prism araç kayıt ve geri çağrı şemalarını çalıştıran bu olaylar için, <a href="https://origin-main.com/ai-agents/laravel-prism-php-agentic-apps/" target="_blank" rel="noopener noreferrer">Ajansik Laravel Uygulamaları Oluşturma Kılavuzu</a> referans uygulamasıdır.</p>

<h2>
    <a name="stream-cancellation-the-backend-half-nobody-implements" href="#stream-cancellation-the-backend-half-nobody-implements">
    </a>
    Akış İptali: Kimsenin Uygulamadığı Backend Yarı
</h2>

<p>İptal işleminin iki yarısı vardır. Ön uç yarısı beş satır JavaScript ve çoğu uygulamalar bunu içerir. Backend yarısı ise uygulamaların birer birer dağılmasıdır ve ölçek açısından sonuçları teorik değildir.</p>

<h3>
    <a name="frontend-cancellation" href="#frontend-cancellation">
    </a>
    Ön uç İptali
</h3>

<p>EventSource'u kapat ve durumu güncelle. <code>cancel()</code> yöntemi zaten <code>chatStream()</code> bileşeninde tanımlanmıştır. Kritik detay ise durum makinesi: <code>onerror</code> her EventSource kapandığında ateşlenir, kapanmanın kasıtlı olup olmadığına bakılmaksızın. Durumunu <code>cancelled</code> olarak ayarlamak, <code>source.close()</code> ile çağrılmadan önce, <code>onerror</code> dinleyicisinin <code>cancelled</code> durumunu görmesini sağlıyor. Bunu yapmazsanız, kullanıcı iptal eder ve hemen yeni bir istek başlatırsa, UI'nın beklenmedik bir şekilde <code>idle</code> durumuna sıçraması söz konusu olabilir.</p>

<h3>
    <a name="backend-cancellation-for-direct-streams" href="#backend-cancellation-for-direct-streams">
    </a>
    Direk Akışlar için Backend İptali
</h3>

<p>Bir SSE bağlantısı kapandığında, PHP otomatik olarak çalışmakta olan süreci sonlandırmaz. Prism çağrısı, istemcinin çıkışı almadığı halde sunucuda yürütülmeye devam eder ve token'ları ve sağlayıcı kotasını tüketir. Kısa tamamlamalarda bu israf edici olur. Birkaç araç çağrısı olan ajans döngülerinde, bu gerçekten masraflı hale gelebilir.</p>

<blockquote>
    <p>[Üretim Tehlikesi] Orantısız bir miktar yük altında olan bir çok kiracılı uygulamada, korumasız akışlar birikir. Her bir yetim süreç, LLM sağlayıcısına açık bir HTTP bağlantısını tutar. Sağlayıcı oran sınırları, sadece istekleri değil, etkin bağlantıları sayar. İlk görünür belirti, yük altında 429 hatalarının ortaya çıkmasıdır; bu hatalar, trafik düştüğünde ortadan kaybolur, bu da nedeninin çözülmesini zorlaştırır.</p>
</blockquote>

<p>Önceki bölümde verilen <code>connection_aborted()</code> koruması, doğru bir örnek olarak gösterilmektedir. Her yinelemede kontrol edin ve istemcinin bağlantısını kestiğinde <code>break</code> yapın. Temiz tamamlamalarda <code>[DONE]</code> belirtecini yaymayı unutmayın: frontend, bağlantı kapandığında <code>onerror</code> olayının ateşlenmesini beklemeden <code>complete</code> durumuna geçmek için gerekli olanı gerektirir. Uzun süreli SSE bağlantıları için yeniden bağlantı ve zaman aşımını ele alan <a href="https://origin-main.com/laravel-architecture/laravel-sse-production-reconnects-timeouts-multi-tenant/" target="_blank" rel="noopener noreferrer">üretim SSE kılavuzu</a>, canlı tutma aralıklarını ve çok kiracılı akış izolasyonunu ele alır.</p>

<blockquote>
    <p>[Kenar Durum Uyarısı] <code>connection_aborted()</code> PHP’nin istemcinin TCP bağlantısını kapattığını fark etmesine bağlıdır. Bazı Nginx yapılandırmalarında, tarayıcı bağlantısı kesildiğinde PHP-FPM ile yukarı akış bağlantısı açık kalır, bu durumda <code>connection_aborted()</code> asla <code>true</code> döndürmez. Nginx direktifinin <code>fastcgi_ignore_client_abort</code> 'un kapalı (varsayılan) olarak ayarlanması gerekir, böylece PHP bağlantıları doğru bir şekilde kesintileri algılayabilir. <code>connection_aborted()</code>'i iptal mekanizması olarak kullanmadan önce, yığınınızda bunu doğrulayın. Hızlı bir test: bir SSE akışını açın, tarayıcı sekmesini kapatın ve PHP işleminin birkaç saniye içinde sona erip ermediğini kontrol edin.</p>
</blockquote>

<h3>
    <a name="backend-cancellation-for-queued-agentic-jobs" href="#backend-cancellation-for-queued-agentic-jobs">
    </a>
    Sıralı Ajans İşleri için Backend İptali
</h3>

<p>Laravel Horizon'a devredilen uzun süreli ajans işlerinde, <code>connection_aborted()</code> geçerli değildir. Kuva işçi süreci, HTTP bağlantısından bağımsız olarak çalışılır. İptal etmek için, her adımda kontrol edilen bir Redis bayrağı gerekir.</p>

<p>İptal son noktası, hem kullanıcı kimliği hem de iş kimliği için bayrağı ayarlamaktadır:<br/></p>

<div class="highlight js-code-highlight">
    <pre class="highlight php"><code><span class="kn">use</span> <span class="nc">Illuminate\Http\Request</span><span class="p">;</span>

use Illuminate\Support\Facades\Cache;

Route::post(<span class=”s1>’/chat/{jobId}/cancel’, function (string $jobId, Request $request) {
$userId = $request->user()->id;
$cacheKey = “stream_cancel:{$userId}:{$jobId}“;

<span class="nc">Cache</span><span class="o">::</span><span class="nf">put</span><span class="p">(</span><span class="nv">$cacheKey</span><span class="p">,</span> <span class="kc">true</span><span class="p">,</span> <span class="nf">now</span><span class="p">()</span><span class="o">-&gt;</span><span class="nf">addMinutes</span><span class="p">(</span><span class="mi">5</span><span class="p">));</span>

<span class="k">return</span> <span class="nf">response</span><span class="p">()</span><span class="o">-&gt;</span><span class="nf">json</span><span class="p">([</span><span class="s1>'cancelled'</span> <span class="o">=&gt;</span> <span class="kc">true</span><span class="p">]);</span>

})->middleware(<span class=”s1>’auth:sanctum’);

Enter fullscreen mode

            <svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewbox="0 0 24 24" class="highlight-action crayons-icon highlight-action--fullscreen-off"><title>Exit fullscreen mode</title>
            <path d="M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z"/>
            </svg>
        </div>
    </div>
</div>

<p>İş, her adımda bayrağı kontrol eder ve çıkarken temizler:<br/></p>

<div class="highlight js-code-highlight">
    <pre class="highlight php"><code><span class="cp"><?php </span?>

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Cache;

class AgentStreamJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable;

<span class="k">public</span> <span class="k">function</span> <span class="n">__construct</span><span class="p">(</span>
    <span class="k">private</span> <span class="k">readonly</span> <span class="kt">string</span> <span class="nv">$jobId</span><span class="p">,</span>
    <span class="k">private</span> <span class="k">readonly</span> <span class="kt">int</span>    <span class="nv">$userId</span><span class="p">,</span>
    <span class="k">private</span> <span class="k">readonly</span> <span class="kt">array</span>  <span class="nv">$agentSteps</span><span class="p">,</span>
<span class="p">)</span> <span class="p">{}</span>

<span class="k">public</span> <span class="k">function</span> <span class="n">handle</span><span class="p">():</span> <span class="kt">void</span>
<span class="p">{</span>
    <span class="nv">$cacheKey</span> <span class="o">=</span> <span class="s2">"stream_cancel:</span><span class="si">{</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">userId</span><span class="si">}</span><span class="s2">:</span><span class="si">{</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">jobId</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>

    <span class="k">foreach</span> <span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">agentSteps</span> <span class="k">as</span> <span class="nv">$step</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="nc">Cache</span><span class="o">::</span><span class="nf">get</span><span class="p">(</span><span class="nv">$cacheKey</span><span class="p">))</span> <span class="p">{</span>
            <span class="nc">Cache</span><span class="o">::</span><span class="nf">forget</span><span class="p">(</span><span class="nv">$cacheKey</span><span class="p">);</span>
            <span class="k">return</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">executeStep</span><span class="p">(</span><span class="nv">$step</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="k">private</span> <span class="k">function</span> <span class="n">executeStep</span><span class="p">(</span><span class="kt">mixed</span> <span class="nv">$step</span><span class="p">):</span> <span class="kt">void</span>
<span class="p">{</span>
    <span class="c1">// adım yürütme mantığı</span>
<span class="p">}</span>

}

Enter fullscreen mode Orijinal Makale

Laravel Yerelleştirme: Çok Dilli Web Sitesi – DEV Community
Z.AI LARAVEL 12 SDK – Geliştirici Topluluğu
Laravel Geliştiricileri için WebSockets 101: Kavramdan Üretime Deploynix Üzerinde
Laravel 12 ile Vite Kullanarak Bootstrap 5 Nasıl Kurulur
Django, Rails ve Laravel Başlangıç Şablonlarının Karşılaştırması
Bu Makaleyi Paylaş
Facebook Bağlantıyı Kopyala Yazdır
Paylaş
Önceki Makale Uranüs’ün Uyduları, Kaybolan Gezegenlerin İzini Sürdürüyor!
Sonraki Makale Stellar Blade’den Heyecan Verici Kan Yağmuru Duyuruldu!

Sanal Medya

FacebookBeğen
452Takip Et
PinterestSabitle
237Takip Et

Son Eklenenler

Bireysel Geliştiricinin Takım Gibi İnşa Etme Yöntemi: Planı Dondurma, Kesişen Noktaları Dondurma
Yazılım
Kritik Uyarı: UNC3753’ün Vishing ve Fiziksel İhlalleriyle Veri Hırsızlığı
Siber Güvenlik
Yeni Bir Macera: Spyro Ejderha, 20 Yıl Sonra Geri Dönüyor
Oyun
Kritik: VS Code, Tedarik Zinciri Saldırılarını Önlemek İçin Gecikme Getirdi
Siber Güvenlik
XRP Fiyatında Stabilizasyon: Dört Aylık Düşüklerin Üzerinde $1.10
Finans
5 Dakikada Üretime Hazır Bir Restoran POS Sistemi Oluşturma (Claude AI + Laravel)
Yazılım
//

Siber güvenlik, yapay zeka ve savunma sanayiinden; finans ve sinema dünyasına uzanan geniş bir yelpaze. Teknomers; teknoloji, strateji ve yazılım dünyasını sade bir dille sizlerle buluşturuyor.

Kurumsal

  • Hakkımızda
  • Gizlilik politikası
  • Tanıtım Yazısı ve Backlink Hizmeti

Kategoriler

  • Teknoloji
  • Oyun
  • Sinema
  • Siber Güvenlik
  • Bilim
  • Finans
  • Dünyadan Güncel Haberler

Populer

  • TV'de Ücretsiz İzlenebilen Şifresiz Erotik Kanallar (2025 Güncel Frekans Listesi)

  • The Last of Us PC Kontrolleri: Hızlı Silah Değiştirme ve Tüm Tuşlar (2025)

  • Hogwarts Legacy'de Odaklanma İksiri Nasıl Yapılır?

Teknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor HaberleriTeknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor Haberleri
Bizi Takip Et
© 2026 Teknomers. All Rights Reserved.
Welcome Back!

Sign in to your account

Kullanıcı Adı veya E-posta Adresi
Şifre

Şifrenizi mi unuttunuz?