Son yazıda, AI yanıtlarını SSE (Server-Sent Events) üzerinden aktardık. Şimdi, her chatbotun karşılaştığı ilk haftadaki sorunu çözelim: modeliniz verilerinizi tanımıyor. İade politikası veya API belgeleri hakkında sorun, model ya hayal eder ya da kayıtsız kalır.
<p>RAG — retrieval-augmented generation — bu sorunu çözüyor. Modelin içeriğinizi bilmesini beklemek yerine, belgelerinizi embeddingler olarak depoluyorsunuz, her soruyla ilgili birkaç parçayı alıyorsunuz ve sadece bunları modele veriyorsunuz. İşte Laravel 11 ile PostgreSQL ve pgvector kullanarak bu sürecin tamamı — ekstra bir vektör veritabanı SaaS gerekmiyor.</p>
<h2>
<a name="first-an-honest-gate-do-you-even-need-rag" href="#first-an-honest-gate-do-you-even-need-rag">
</a>
Öncelikle, gerçekten RAG'e ihtiyacınız var mı?
</h2>
<p>Yakın zamanda kendi portföy sitem için bir chatbot yayınladım. Toplam bilgi tabanı: yaklaşık 2,000 token bilgi ve SSS. Bunun için RAG yapmadım — <em>tüm metni sistem istemine koydum</em> ve istem önbelleklemesi sayesinde maliyetleri düşürdüm. Daha basit bir kod, sıfır alım hatası ve model her soru için her şeyi görüyor.</p>
<p>Müşterilerle kullandığım kural şu şekildedir:</p>
<ul>
<li>
<strong>Corpus ~20k token altında</strong> → tüm corpus önbelleğe alınmış sistem isteminde. Tamam.</li>
<li>
<strong>Corpus daha büyükse veya sürekli güncelleniyorsa</strong> → RAG.</li>
</ul>
<p>Eğer birincil gruptaysanız, bu sekmeyi kapatın ve gönderin. Hala buradaysanız, haydi yapalım.</p>
<h2>
<a name="the-stack" href="#the-stack">
</a>
Teknolojik Yığın
</h2>
<ul>
<li>Laravel 11, PostgreSQL 15+ ile <code>pgvector</code> eklentisi.</li>
<li>
<code>openai-php/laravel</code> embedding ve sohbet için.</li>
<li>
<code>pgvector/pgvector-php</code> için Eloquent dönüşümü.</li>
</ul>
<div class="highlight js-code-highlight">
<pre class="highlight shell"><code>composer require openai-php/laravel pgvector/pgvectorphp artisan vendor:publish –provider=“OpenAI\Laravel\ServiceProvider”
<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>Çoğu yönetilen Postgres (RDS, Supabase, Neon, Laravel Forge kutuları) için pgvector yalnızca bir ifade uzaklıktadır:<br/></p>
<div class="highlight js-code-highlight">
<pre class="highlight sql"><code><span class="k">CREATE</span> <span class="n">EXTENSION</span> <span class="n">IF</span> <span class="k">NOT</span> <span class="k">EXISTS</span> <span class="n">vector</span><span class="p">;</span> <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>
<h2>
<a name="the-schema" href="#the-schema">
</a>
Şema
</h2>
<p>Bir tablo, belgelerinizin parçalarını ve bunların embedding vektörlerini saklar. <code>text-embedding-3-small</code> 1536 boyut üretir — iyi kalitede, ucuz (<strong>$0.02</strong> milyon token için).<br/></p>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kn">use</span> <span class="nc">Illuminate\Database\Migrations\Migration</span><span class="p">;</span>use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
DB::statement(‘CREATE EXTENSION IF NOT EXISTS vector’);
<span class="nc">Schema</span><span class="o">::</span><span class="nf">create</span><span class="p">(</span><span class="s1">'document_chunks'</span><span class="p">,</span> <span class="k">function</span> <span class="p">(</span><span class="nv">$table</span><span class="p">)</span> <span class="p">{</span>
<span class="nv">$table</span><span class="o">-></span><span class="nf">id</span><span class="p">();</span>
<span class="nv">$table</span><span class="o">-></span><span class="nf">string</span><span class="p">(</span><span class="s1">'source'</span><span class="p">);</span> <span class="c1">// örneğin "refund-policy.md"</span>
<span class="nv">$table</span><span class="o">-></span><span class="nf">unsignedInteger</span><span class="p">(</span><span class="s1">'position'</span><span class="p">);</span> <span class="c1">// kaynak içindeki parça sırası</span>
<span class="nv">$table</span><span class="o">-></span><span class="nf">text</span><span class="p">(</span><span class="s1">'content'</span><span class="p">);</span>
<span class="nv">$table</span><span class="o">-></span><span class="nf">timestamps</span><span class="p">();</span>
<span class="p">});</span>
<span class="no">DB</span><span class="o">::</span><span class="nf">statement</span><span class="p">(</span><span class="s1">'ALTER TABLE document_chunks ADD COLUMN embedding vector(1536)'</span><span class="p">);</span>
<span class="c1">// HNSW indeksi, benzerlik aramasını hızlı hale getirir, ~10k satırdan itibaren</span>
<span class="no">DB</span><span class="o">::</span><span class="nf">statement</span><span class="p">(</span><span class="s1">'CREATE INDEX ON document_chunks USING hnsw (embedding vector_cosine_ops)'</span><span class="p">);</span>
<span class="p">}</span>};
<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>Model:<br/></p>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kn">namespace</span> <span class="nn">App\Models</span><span class="p">;</span>use Illuminate\Database\Eloquent\Model;
use Pgvector\Laravel\Vector;
class DocumentChunk extends Model
{
protected $fillable = [‘source’, ‘position’, ‘content’, ’embedding’];
<span class="k">protected</span> <span class="nv">$casts</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'embedding'</span> <span class="o">=></span> <span class="nc">Vector</span><span class="o">::</span><span class="n">class</span><span class="p">];</span>}
<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>
<h2>
<a name="ingestion-chunk-embed-store" href="#ingestion-chunk-embed-store">
</a>
Giriş: parça, gömme, sakla
</h2>
<p>Parçalama stratejisi, insanların kabul ettiğinden daha fazla önemlidir. Benim varsayılanım: başlıklar/paragraflar üzerinde bölmek, her parçada ~500 token hedeflemek ve asla cümle ortasında bölmemek. Gelişmiş örtüşme penceresini, bunlara ihtiyacınız olduğu kanıtlanana kadar bekletebilirsiniz.<br/></p>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kn">namespace</span> <span class="nn">App\Console\Commands</span><span class="p">;</span>use App\Models\DocumentChunk;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
use OpenAI\Laravel\Facades\OpenAI;
class IngestDocs extends Command
{
protected $signature = ‘rag:ingest {path : Markdown dosyalarının dizini}’;
<span class="k">public</span> <span class="k">function</span> <span class="n">handle</span><span class="p">():</span> <span class="kt">int</span>
<span class="p">{</span>
<span class="k">foreach</span> <span class="p">(</span><span class="nc">File</span><span class="o">::</span><span class="nf">files</span><span class="p">(</span><span class="nv">$this</span><span class="o">-></span><span class="nf">argument</span><span class="p">(</span><span class="s1">'path'</span><span class="p">))</span> <span class="k">as</span> <span class="nv">$file</span><span class="p">)</span> <span class="p">{</span>
<span class="nv">$chunks</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-></span><span class="nf">chunk</span><span class="p">(</span><span class="nv">$file</span><span class="o">-></span><span class="nf">getContents</span><span class="p">());</span>
<span class="c1">// Dosya başına bir API çağrısı, parça başına değil — toplu girdi destekleniyor</span>
<span class="nv">$response</span> <span class="o">=</span> <span class="nc">OpenAI</span><span class="o">::</span><span class="nf">embeddings</span><span class="p">()</span><span class="o">-></span><span class="nf">create</span><span class="p">([</span>
<span class="s1">'model'</span> <span class="o">=></span> <span class="s1">'text-embedding-3-small'</span><span class="p">,</span>
<span class="s1">'input'</span> <span class="o">=></span> <span class="nv">$chunks</span><span class="p">,</span>
<span class="p">]);</span>
<span class="nc">DocumentChunk</span><span class="o">::</span><span class="nf">where</span><span class="p">(</span><span class="s1">'source'</span><span class="p">,</span> <span class="nv">$file</span><span class="o">-></span><span class="nf">getFilename</span><span class="p">())</span><span class="o">-></span><span class="nb">delete</span><span class="p">();</span>
<span class="k">foreach</span> <span class="p">(</span><span class="nv">$response</span><span class="o">-></span><span class="n">embeddings</span> <span class="k">as</span> <span class="nv">$i</span> <span class="o">=></span> <span class="nv">$embedding</span><span class="p">)</span> <span class="p">{</span>
<span class="nc">DocumentChunk</span><span class="o">::</span><span class="nf">create</span><span class="p">([</span>
<span class="s1>'source'</span> <span class="o">=></span> <span class="nv">$file</span><span class="o">-></span><span class="nf'>getFilename</span><span class="p">(),</span>
<span class="s1>'position'</span> <span class="o">=></span> <span class="nv">$i</span><span class="p">,</span>
<span class="s1>'content'</span> <span class="o">=></span> <span class="nv">$chunks</span><span class="p">[</span><span class="nv">$i</span><span class="p">],</span>
<span class="s1>'embedding'</span> <span class="o">=></span> <span class="nv">$embedding</span><span class="o">-></span><span class="n">embedding</span><span class="p">,</span>
<span class="p">]);</span>
<span class="p">}</span>
<span class="nv">$this</span><span class="o">-></span><span class="nf">info</span><span class="p">(</span><span class="s2">"</span><span class="si">{</span><span class="nv">$file</span><span class="o">-></span><span class="nf'>getFilename</span><span class="p">()</span><span class="si">}</span><span class="s2">: "</span> <span class="mf">.</span> <span class="nb">count</span><span class="p">(</span><span class="nv">$chunks</span><span class="p">)</span> <span class="mf">.</span> <span class="s1>'_chunks'</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="k">self</span><span class="o">::</span><span class="no">SUCCESS</span><span class="p">;</span>
<span class="p">}</span>
<span class="cd">/ @return string[] */</span>
<span class="k">private</span> <span class="k">function</span> <span class="n">chunk</span><span class="p">(</span><span class="kt">string</span> <span class="nv">$text</span><span class="p">,</span> <span class="kt">int</span> <span class="nv">$targetChars</span> <span class="o">=</span> <span class="mi">2000</span><span class="p">):</span> <span class="kt">array</span>
<span class="p">{</span>
<span class="nv">$paragraphs</span> <span class="o">=</span> <span class="nb">preg_split</span><span class="p">(</span><span class="s1">'/\n{2,}/'</span><span class="p">,</span><span class="nv">$text</span><span class="p">);</span>
<span class="nv">$chunks</span> <span class="o">=</span> <span class="p">[</span><span class="s1'>''</span><span class="p">];</span>
<span class="k">foreach</span> <span class="p">(</span><span class="nv">$paragraphs</span> <span class="k">as</span> <span class="nv">$p</span><span class="p">)</span> <span class="p">{</span>
<span class="nv">$current</span> <span class="o">=</span> <span class="nb">array_key_last</span><span class="p">(</span><span class="nv">$chunks</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$chunks</span><span class="p">[</span><span class="nv">$current</span><span class="p">])</span> <span class="o">+</span> <span class="nb">strlen</span><span class="p">(</span><span class="nv">$p</span><span class="p">)</span> <span class="o">></span> <span class="nv">$targetChars</span> <span class="o">&&</span> <span class="nv">$chunks</span><span class="p">[</span><span class="nv">$current</span><span class="p">]</span> <span class="o">!==</span> <span class="s1'>''</span><span class="p">)</span> <span class="p">{</span>
<span class="nv">$chunks</span><span class="p">[]</span> <span class="o">=</span> <span class="nv">$p</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nv">$chunks</span><span class="p">[</span><span class="nv">$current</span><span class="p">]</span><span class="mf">.</span><span class="o">=</span> <span class="s2">"</span><span class="se">\n\n</span><span class="s2">"</span> <span class="mf">.</span><span class="nv">$p</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nb">array_map</span><span class="p">(</span><span class="s1>'trim'</span><span class="p">,</span><span class="nv">$chunks</span><span class="p">);</span>
<span class="p">}</span>}
<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>Bunu çalıştırın: <code>php artisan rag:ingest storage/docs</code>. Yeniden çalıştırmak bir dosyanın parçalarını değiştirdiğinden, giriş idempotenttir - bunu dağıtımınıza veya planlı bir işe bağlayarak içeriklerinizi güncel tutabilirsiniz.</p>
<h2>
<a name="retrieval-the-fiveline-heart-of-rag" href="#retrieval-the-fiveline-heart-of-rag">
</a>
Alma: RAG'in beş satırlık kalbi
</h2>
<p>pgvector’ın <code/> operatörü kosinüs mesafesidir. Daha düşük = daha benzer. Kullanıcının sorusunu gömün, mesafeye göre sıralayın, en üstteki birkaçını alın:<br/></p>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kn">namespace</span> <span class="nn">App\Services</span><span class="p">;</span>use App\Models\DocumentChunk;
use OpenAI\Laravel\Facades\OpenAI;
class Retriever
{
/* @return array{content: string, source: string}[] /
public function search(string $question, int $limit = 5): array
{
$embedding = OpenAI::embeddings()->create([
<span class=”s1>’model’ => <span class=”s1>’text-embedding-3-small’,
<span class=”s1>’input’ => $question,
])->embeddings[0]->embedding;
<span class="k">return</span> <span class="nc">DocumentChunk</span><span class="o">::</span><span class="nf">query</span><span class="p">()</span>
<span class="o">-></span><span class="nf">selectRaw</span><span class="p">(</span><span class="s1>'content, source, embedding ? AS distance'</span><span class="p">,</span> <span class="p">[</span><span class="nb">json_encode</span><span class="p">(</span><span class="nv">$embedding</span><span class="p">)])</span>
<span class="o">-></span><span class="nf">orderBy</span><span class="p">(</span><span class="s1>'distance'</span><span class="p">)</span>
<span class="o">-></span><span class="nf">limit</span><span class="p">(</span><span class="nv">$limit</span><span class="p">)</span>
<span class="o">-></span><span class="nf">get</span><span class="p">()</span>
<span class="o">-></span><span class="nf">filter</span><span class="p">(</span><span class="k">fn</span> <span class="p">(</span><span class="nv">$c</span><span class="p">)</span> <span class="o">=></span> <span class="nv">$c</span><span class="o">-></span><span class="n">distance</span> <span class="o"> <span class="mf">0.55</span><span class="p">)</span> <span class="c1">// alaka katmanı — gerçek sorgular üzerinde ayarlayın</span>
<span class="o">-></span><span class="nf">map</span><span class="p">(</span><span class="k">fn</span> <span class="p">(</span><span class="nv">$c</span><span class="p">)</span> <span class="o">=></span> <span class="p">[</span><span class="s1>'content'</span> <span class="o">=></span> <span class="nv">$c</span><span class="o">-></span><span class="n">content</span><span class="p">,</span> <span class="s1>'source'</span> <span class="o">=></span> <span class="nv">$c</span><span class="o">-></span><span class="n">source</span><span class="p">])</span>
<span class="o">-></span><span class="nf">all</span><span class="p">();</span>
<span class="p">}</span>}
<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>Bu mesafe eşiği, hayal gücünüzü korumanızdır. Eğer hiçbir sonuç eşik değerinin altında puan almazsa, dürüst cevap "Bilmiyorum" olmalıdır — ve bunun yerine modele kalitesiz bağlam vermemelisiniz.</p>
<h2>
<a name="answering-with-context" href="#answering-with-context">
</a>
Bağlamla Yanıtlama
</h2>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kn">namespace</span> <span class="nn">App\Services</span><span class="p">;</span>use OpenAI\Laravel\Facades\OpenAI;
class KnowledgeBot
{
public function __construct(private Retriever $retriever) {}
<span class="k">public</span> <span class="k">function</span> <span class="n">answer</span><span class="p">(</span><span class="kt">string</span> <span class="nv">$question</span><span class="p">):</span> <span class="kt">string</span>
<span class="p">{</span>
<span class="nv">$chunks</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-></span><span class="n">retriever</span><span class="o">-></span><span class="nf">search</span><span class="p">(</span><span class="nv">$question</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$chunks</span> <span class="o">===</span> <span class="p">[])</span> <span class="p">{</span>
<span class="k">return</span> <span class="s2">"Belgelerimizde bunu bulamadım — ifadeyi değiştirip tekrar deneyin ya da destekle irtibata geçin."</span><span class="p">;</span>
<span class="p">}</span>
<span class="nv">$context</span> <span class="o">=</span> <span class="nf">collect</span><span class="p">(</span><span class="nv">$chunks</span><span class="p">)</span>
<span class="o">-></span><span class="nf">map</span><span class="p">(</span><span class="k">fn</span> <span class="p">(</span><span class="nv">$c</span><span class="p">)</span> <span class="o">=></span> <span class="s2">"[</span><span class="si">{</span><span class="nv">$c</span><span class="p">[</span><span class="s1>'source'</span><span class="p">]</span><span class="si">}</span><span class="s2">]</span><span class="se">\n</span><span class="si">{</span><span class="nv">$c</span><span class="p">[</span><span class="s1>'content'</span><span class="p">]</span><span class="si">}</span><span class="s2}>";</span>
<span class="o">-></span><span class="nb">implode</span><span class="p">(</span><span class="s2">"</span><span class="se">\n\n</span><span class="s2">---</span><span class="se">\n\n</span><span class="s2">"</span><span class="p">);</span>
<span class="nv">$response</span> <span class="o">=</span> <span class="nc">OpenAI</span><span class="o">::</span><span class="nf">chat</span><span class="p">()</span><span class="o">-></span><span class="nf">create</span><span class="p">([</span>
<span class="s1>'model'</span> <span class="o">=></span> <span class="s1>'gpt-4o-mini'</span><span class="p">,</span>
<span class="s1>'max_tokens'</span> <span class="o">=></span> <span class="mi">500</span><span class="p">,</span>
<span class="s1>'messages'</span> <span class="o">=></span> <span class="p">[</span>
<span class="p">[</span><span class="s1>'role'</span> <span class="o">=></span> <span class="s1>'system'</span><span class="p">,</span> <span class="s1>'content'</span> <span class="o">=></span> <span class="sh"><span class="p">],</span>
<span class="p">[</span><span class="s1>'role'</span> <span class="o">=></span> <span class="s1>'user'</span><span class="p">,</span> <span class="s1>'content'</span> <span class="o">=></span> <span class="nv">$question</span><span class="p">],</span>
<span class="p">],</span>
<span class="p">]);</span>
<span class="k">return</span> <span class="nv">$response</span><span class="o">-></span><span class="n">choices</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">-></span><span class="n">message</span><span class="o">-></span><span class="n">content</span><span class="p">;</span>
<span class="p">}</span>}
<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>KnowledgeBot::answer()</code> fonksiyonunu bu serinin ikinci bölümünde akış denetleyicisine bağlayın, böylece temelli yanıtlar üreten bir bilgi botuna sahip olacaksınız.</p>
<h2>
<a name="production-checklist" href="#production-checklist">
</a>
Üretim Kontrol Listesi
</h2>
<ul>
<li>
<strong>Alaka derecesi eşiği</strong>: alınan parçaları mesafe eşiğine göre filtreleyin; bunun altında bir "bulunamadı" yanıtı verin. Gerçek kullanıcı sorguları ile sayıyı ayarlayın, hissiyatlar üzerinden değil.</li>
<li>
<strong>İdempotent giriş</strong>: her kaynak dosyası için sil-me-değiştir işlemi yapın, dağıtım sırasında çalıştırın. Eskimiş embeddingler, geçmiş sorulara yanıt verir.</li>
<li>
<strong>HNSW indeksi</strong>: bunun olmaması durumunda her sorgu tam tablo taraması olur. Bunun için, alt-10ms hızda yüzbinlerce satırda tarama yapılabilir.</li>
<li>
<strong>Toplu embeddingler</strong>: her doküman için bir API çağrısı, her parça için değil — %10 daha az istek ve aynı fiyat.</li>
<li>
<strong>Maliyet sınırları ve oran limitleri</strong>: birinci bölümde belirtilen her şey geçerlidir — her soru bir embedding çağrısı ve bir sohbet çağrısı maliyetindedir.</li>
<li>
<strong>Soru + alınan kaynakları kaydet</strong> (tam içerik değil): Yanlış bir yanıt aldığınızda, alımın mı yoksa üretimin mi başarısız olduğunu bilmeniz gerekir. Bu ayrım düzeltmenizi belirler.</li>
<li>
<strong>Alımın ayrı olarak değerlendirilmesi</strong>: 20 bilinen soru → kaynak eşleşmelerini tutun ve doğru parçanın ilk 5 içinde belirdiğini doğrulayın. Bu, parçalama geri dönüşlerini kullanıcılarınızdan önce yakalar.</li>
</ul>
<h2>
<a name="whats-next" href="#whats-next">
</a>
Sonrası Neler?
</h2>
<p>Retrieval, modeli <em>bilgili</em> hale getiriyor. Bir sonraki adım, modeli <em>yetkin</em> hale getirecek: dördüncü bölümde, PHP'de AI ajanları oluşturacağız — modele çağırabileceği araçlar (arama siparişleri, bilet oluşturma, veritabanınızı sorgulama) verdiğimizde ve bu aracın çağrılma döngüsünü Laravel'de güvenli bir şekilde yönettiğimizde, işte chatbotlar ürün haline dönüşüyor.</p>
<hr/>
<p><em>Ben Aditya Kumar (<a href="https://github.com/adityakdevin" target="_blank" rel="noopener noreferrer">adityakdevin</a>) — AI destekli web ürünleri geliştiren bir Teknik Liderim. Beni <a href="https://adityadev.in" target="_blank" rel="noopener noreferrer">adityadev.in</a>'de bulabilirsiniz.</em></p>Kaynak: Orijinal Makale


