{"id":7673,"date":"2026-02-11T22:57:47","date_gmt":"2026-02-11T19:57:47","guid":{"rendered":"https:\/\/sitecenneti.com\/wordpress\/?p=7673"},"modified":"2026-02-14T23:28:10","modified_gmt":"2026-02-14T20:28:10","slug":"wordpress-icin-uctan-uca-rag-ai-asistani-gelistirici-el-kitabi","status":"publish","type":"post","link":"https:\/\/sitecenneti.com\/wordpress\/wordpress-eklentisi-yazma\/wordpress-icin-uctan-uca-rag-ai-asistani-gelistirici-el-kitabi\/","title":{"rendered":"WordPress \u0130\u00e7in U\u00e7tan Uca RAG AI Asistan\u0131: Geli\u015ftirici El Kitab\u0131"},"content":{"rendered":"<div id=\"toc_container\" class=\"toc_transparent no_bullets\"><p class=\"toc_title\">BU DERS\u0130N BA\u015eLIKLARI<\/p><ul class=\"toc_list\"><li><a href=\"#1_Proje_Kurulumu_ve_Dosya_Yapisi\"><span class=\"toc_number toc_depth_1\">1<\/span> 1. Proje Kurulumu ve Dosya Yap\u0131s\u0131<\/a><\/li><li><a href=\"#2_Veritabani_Katmani_Supabase_pgvector\"><span class=\"toc_number toc_depth_1\">2<\/span> 2. Veritaban\u0131 Katman\u0131: Supabase &amp; pgvector<\/a><\/li><li><a href=\"#3_Verileri_Vektorlestirip_Yukleme_scriptsingest-datats\"><span class=\"toc_number toc_depth_1\">3<\/span> 3. Verileri Vekt\u00f6rle\u015ftirip Y\u00fckleme: scripts\/ingest-data.ts<\/a><\/li><li><a href=\"#4_WordPress_Eklentisi_webasistant-ai-chatphp\"><span class=\"toc_number toc_depth_1\">4<\/span> 4. WordPress Eklentisi: webasistant-ai-chat.php<\/a><\/li><li><a href=\"#Sonuc\"><span class=\"toc_number toc_depth_1\">5<\/span> Sonu\u00e7<\/a><\/li><\/ul><\/div>\n\n<p>Bu rehber, Google Gemini 2.5 Flash ve Supabase kullanarak kendi verilerini bilen bir asistan\u0131 s\u0131f\u0131rdan in\u015fa etmek isteyenler i\u00e7in haz\u0131rlanm\u0131\u015ft\u0131r.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span id=\"1_Proje_Kurulumu_ve_Dosya_Yapisi\">1. Proje Kurulumu ve Dosya Yap\u0131s\u0131<\/span><\/h2>\n\n\n\n<p>\u0130lk olarak bilgisayar\u0131m\u0131zda projemiz i\u00e7in bir \u00e7al\u0131\u015fma alan\u0131 olu\u015fturuyoruz.<\/p>\n\n\n\n<p>Terminal (Bash) Komutlar\u0131:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Proje klas\u00f6r\u00fcn\u00fc olu\u015ftur\nmkdir webasistant-master &amp;&amp; cd webasistant-master\n\n# Node.js projesini initialize et\nnpm init -y\n\n# Gerekli ba\u011f\u0131ml\u0131l\u0131klar\u0131 y\u00fckle\nnpm install @google\/generative-ai @supabase\/supabase-js dotenv tsx typescript @types\/node\n\n# TypeScript ayarlar\u0131n\u0131 yap\nnpx tsc --init\n\n# Klas\u00f6r ve dosya yap\u0131s\u0131n\u0131 kurgula\nmkdir scripts\ntouch .env\ntouch scripts\/ingest-data.ts<\/code><\/pre>\n\n\n\n<p><strong>Olu\u015fmas\u0131 gereken nihai dosya yap\u0131s\u0131:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>node_modules\/<\/code><\/li>\n\n\n\n<li><code>scripts\/ingest-data.ts<\/code> (Veri y\u00fckleme)<\/li>\n\n\n\n<li><code>.env<\/code> (Anahtarlar)<\/li>\n\n\n\n<li><code>package.json<\/code><\/li>\n\n\n\n<li><code>webasistant-ai-chat.php<\/code> (WordPress Eklentisi)<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><span id=\"2_Veritabani_Katmani_Supabase_pgvector\">2. Veritaban\u0131 Katman\u0131: Supabase &amp; pgvector<\/span><\/h2>\n\n\n\n<p>Yapay zekan\u0131n haf\u0131zas\u0131 (RAG) i\u00e7in Supabase \u00fczerinde vekt\u00f6r deste\u011fini kuruyoruz. Supabase panelindeki <strong>SQL Editor<\/strong> k\u0131sm\u0131na bu blo\u011fu yap\u0131\u015ft\u0131r\u0131n ve <strong>Run<\/strong> deyin:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>-- 1. Vekt\u00f6r eklentisini etkinle\u015ftir\ncreate extension if not exists vector;\n\n-- 2. D\u00f6k\u00fcmanlar\u0131 saklayaca\u011f\u0131m\u0131z tablo\ncreate table documents (\n  id bigserial primary key,\n  content text,\n  embedding vector(768) -- Gemini'nin vekt\u00f6r boyutu 768'dir\n);\n\n-- 3. Semantik Arama Fonksiyonu (RPC)\n-- Bu fonksiyon, sorulan sorunun vekt\u00f6r\u00fc ile tablodaki en yak\u0131n 3 d\u00f6k\u00fcman\u0131 getirir.\ncreate or replace function match_documents (\n  query_embedding vector(768),\n  match_threshold float,\n  match_count int\n) returns table (id bigint, content text, similarity float)\nlanguage plpgsql as $$\nbegin\n  return query\n  select documents.id, documents.content, 1 - (documents.embedding &lt;=> query_embedding) as similarity\n  from documents\n  where 1 - (documents.embedding &lt;=> query_embedding) > match_threshold\n  order by similarity desc\n  limit match_count;\nend;\n$$;<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><span id=\"3_Verileri_Vektorlestirip_Yukleme_scriptsingest-datats\">3. Verileri Vekt\u00f6rle\u015ftirip Y\u00fckleme: <code>scripts\/ingest-data.ts<\/code><\/span><\/h2>\n\n\n\n<p>VS Code i\u00e7erisinde <code>scripts\/ingest-data.ts<\/code> dosyas\u0131n\u0131 a\u00e7\u0131n ve \u015fu kodlar\u0131 yap\u0131\u015ft\u0131r\u0131n. Bu kod, metni al\u0131r, Gemini API ile vekt\u00f6re \u00e7evirir ve Supabase&#8217;e yazar.<\/p>\n\n\n\n<p>typescript kodu:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { GoogleGenerativeAI } from \"@google\/generative-ai\";\nimport { createClient } from '@supabase\/supabase-js';\n\n\/\/ Yap\u0131land\u0131rma Bilgileri\nconst GOOGLE_KEY = \"BURAYA_GOOGLE_API_KEY_GELECEK\";\nconst SUPABASE_URL = \"BURAYA_SUPABASE_URL_GELECEK\";\nconst SUPABASE_KEY = \"BURAYA_SUPABASE_ANON_KEY_GELECEK\";\n\nconst genAI = new GoogleGenerativeAI(GOOGLE_KEY);\nconst supabase = createClient(SUPABASE_URL, SUPABASE_KEY);\n\nasync function addDataToMemory(text: string) {\n  try {\n    console.log(\"\ud83d\udd04 Metin analiz ediliyor...\");\n    \n    \/\/ Gemini Embedding Modelini \u00c7a\u011f\u0131r\u0131yoruz\n    const model = genAI.getGenerativeModel({ model: \"models\/gemini-embedding-001\" }, { apiVersion: 'v1beta' });\n    \n    \/\/ Metni vekt\u00f6re d\u00f6n\u00fc\u015ft\u00fcr\n    const result = await model.embedContent(text);\n    const embedding = result.embedding.values;\n\n    console.log(\"\ud83d\udcbe Veritaban\u0131na yaz\u0131l\u0131yor...\");\n    const { error } = await supabase.from('documents').insert({\n      content: text,\n      embedding: embedding\n    });\n\n    if (error) throw error;\n    console.log(\"\u2705 Ba\u015far\u0131yla eklendi: \" + text.substring(0, 50) + \"...\");\n\n  } catch (err) {\n    console.error(\"\u274c Hata:\", err);\n  }\n}\n\n\/\/ \u00d6rnek kullan\u0131m:\naddDataToMemory(\"WebAsistantAI y\u0131ll\u0131k abonelik \u00fccreti 1500 TL'dir ve s\u0131n\u0131rs\u0131z destek i\u00e7erir.\");<\/code><\/pre>\n\n\n\n<p><strong>\u00c7al\u0131\u015ft\u0131rmak i\u00e7in terminale \u015funu yaz\u0131n:<\/strong> <code>npx tsx scripts\/ingest-data.ts<\/code><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span id=\"4_WordPress_Eklentisi_webasistant-ai-chatphp\">4. WordPress Eklentisi: <code>webasistant-ai-chat.php<\/code><\/span><\/h2>\n\n\n\n<p>\u0130\u015fte t\u00fcm yap\u0131y\u0131 bir araya getiren, y\u00f6netim panelli ve AJAX destekli WordPress eklentisi. Bu dosyay\u0131 <code>wp-content\/plugins\/webasistant-ai-chat\/<\/code> i\u00e7ine koyun.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\/*\nPlugin Name: WebAsistant AI Master Pro\nDescription: Gemini 2.5 Flash ve Supabase RAG tabanl\u0131, y\u00f6netim panelli tam te\u015fekk\u00fcll\u00fc AI asistan\u0131.\nVersion: 2.0\nAuthor: Senin Ad\u0131n\n*\/\n\nif (!defined('ABSPATH')) exit;\n\n\/\/ 1. ADIM: WordPress Admin Men\u00fcs\u00fc\nadd_action('admin_menu', function() {\n    add_menu_page('WebAsistant AI', 'WebAsistant AI', 'manage_options', 'wai-settings', 'wai_render_settings', 'dashicons-id-alt');\n});\n\nfunction wai_render_settings() {\n    if (isset($_POST&#91;'wai_save'])) {\n        update_option('wai_settings', $_POST&#91;'wai_settings']);\n        echo '&lt;div class=\"updated\">&lt;p>Ayarlar ba\u015far\u0131yla kaydedildi.&lt;\/p>&lt;\/div>';\n    }\n    $opt = get_option('wai_settings');\n    ?>\n    &lt;div class=\"wrap\">\n        &lt;h1>WebAsistant AI Yap\u0131land\u0131rmas\u0131&lt;\/h1>\n        &lt;form method=\"post\">\n            &lt;table class=\"form-table\">\n                &lt;tr>&lt;th>Google API Key&lt;\/th>&lt;td>&lt;input type=\"text\" name=\"wai_settings&#91;g_key]\" value=\"&lt;?php echo esc_attr($opt&#91;'g_key']); ?>\" class=\"regular-text\">&lt;\/td>&lt;\/tr>\n                &lt;tr>&lt;th>Supabase URL&lt;\/th>&lt;td>&lt;input type=\"text\" name=\"wai_settings&#91;s_url]\" value=\"&lt;?php echo esc_attr($opt&#91;'s_url']); ?>\" class=\"regular-text\">&lt;\/td>&lt;\/tr>\n                &lt;tr>&lt;th>Supabase Key&lt;\/th>&lt;td>&lt;input type=\"text\" name=\"wai_settings&#91;s_key]\" value=\"&lt;?php echo esc_attr($opt&#91;'s_key']); ?>\" class=\"regular-text\">&lt;\/td>&lt;\/tr>\n                &lt;tr>&lt;th>Bot Ad\u0131&lt;\/th>&lt;td>&lt;input type=\"text\" name=\"wai_settings&#91;name]\" value=\"&lt;?php echo esc_attr($opt&#91;'name']); ?>\" placeholder=\"\u00d6rn: WebAsistant Destek\">&lt;\/td>&lt;\/tr>\n                &lt;tr>&lt;th>Tema Rengi&lt;\/th>&lt;td>&lt;input type=\"color\" name=\"wai_settings&#91;color]\" value=\"&lt;?php echo esc_attr($opt&#91;'color']); ?>\">&lt;\/td>&lt;\/tr>\n            &lt;\/table>\n            &lt;?php submit_button('Kaydet', 'primary', 'wai_save'); ?>\n        &lt;\/form>\n    &lt;\/div>\n    &lt;?php\n}\n\n\/\/ 2. ADIM: Frontend Widget (Sohbet Penceresi)\nadd_action('wp_footer', function() {\n    $opt = get_option('wai_settings');\n    if (empty($opt&#91;'g_key'])) return;\n    $color = $opt&#91;'color'] ?: '#2271b1';\n    ?>\n    &lt;style>\n        #wai-chat-box { display: none; width: 350px; height: 500px; background: #fff; border-radius: 15px; position: fixed; bottom: 90px; right: 20px; flex-direction: column; box-shadow: 0 10px 25px rgba(0,0,0,0.2); overflow: hidden; border: 1px solid #eee; z-index: 999999; }\n        .wai-msg { padding: 10px 14px; border-radius: 15px; max-width: 80%; font-size: 14px; margin-bottom: 8px; line-height: 1.5; }\n        .wai-user { align-self: flex-end; background: &lt;?php echo $color; ?>; color: #fff; border-radius: 15px 15px 0 15px; }\n        .wai-bot { align-self: flex-start; background: #f1f1f1; color: #333; border-radius: 15px 15px 15px 0; }\n    &lt;\/style>\n\n    &lt;div id=\"wai-chat-container\" style=\"position: fixed; bottom: 20px; right: 20px; z-index: 999999; font-family: sans-serif;\">\n        &lt;div id=\"wai-chat-btn\" style=\"background:&lt;?php echo $color; ?>; width:60px; height:60px; border-radius:50%; cursor:pointer; display:flex; align-items:center; justify-content:center; color:#fff; font-size:30px; box-shadow:0 4px 15px rgba(0,0,0,0.3);\">\ud83d\udcac&lt;\/div>\n        \n        &lt;div id=\"wai-chat-box\">\n            &lt;div style=\"background:&lt;?php echo $color; ?>; color:#fff; padding:15px; font-weight:bold; display:flex; justify-content:space-between;\">\n                &lt;span>&lt;?php echo esc_html($opt&#91;'name']); ?>&lt;\/span>\n                &lt;span id=\"wai-close\" style=\"cursor:pointer\">\u2715&lt;\/span>\n            &lt;\/div>\n            &lt;div id=\"wai-messages\" style=\"flex:1; overflow-y:auto; padding:15px; background:#fff; display:flex; flex-direction:column;\">\n                &lt;div class=\"wai-msg wai-bot\">Merhaba, size nas\u0131l yard\u0131mc\u0131 olabilirim?&lt;\/div>\n            &lt;\/div>\n            &lt;div style=\"padding:10px; border-top:1px solid #eee; display:flex; gap:5px; background:#fff;\">\n                &lt;input type=\"text\" id=\"wai-input\" placeholder=\"Yaz\u0131n...\" style=\"flex:1; border:1px solid #ddd; padding:10px; border-radius:5px; outline:none;\">\n                &lt;button id=\"wai-send\" style=\"background:&lt;?php echo $color; ?>; color:#fff; border:none; padding:0 15px; border-radius:5px; cursor:pointer;\">>&lt;\/button>\n            &lt;\/div>\n        &lt;\/div>\n    &lt;\/div>\n\n    &lt;script>\n    jQuery(document).ready(function($) {\n        $('#wai-chat-btn').click(() => $('#wai-chat-box').fadeToggle(200).css('display', 'flex'));\n        $('#wai-close').click(() => $('#wai-chat-box').hide());\n\n        function send() {\n            let s = $('#wai-input').val().trim(); if(!s) return;\n            $('#wai-messages').append('&lt;div class=\"wai-msg wai-user\">'+s+'&lt;\/div>');\n            $('#wai-input').val('');\n            $('#wai-messages').scrollTop($('#wai-messages')&#91;0].scrollHeight);\n            let lid = 'l-'+Date.now();\n            $('#wai-messages').append('&lt;div id=\"'+lid+'\" style=\"font-size:11px; color:#999; margin: 5px 0;\">D\u00fc\u015f\u00fcn\u00fcyor...&lt;\/div>');\n\n            $.post('&lt;?php echo admin_url('admin-ajax.php'); ?>', { action: 'wai_ask_ai', question: s }, function(r) {\n                $('#'+lid).remove();\n                if(r.success) { $('#wai-messages').append('&lt;div class=\"wai-msg wai-bot\">'+r.data+'&lt;\/div>'); }\n                $('#wai-messages').scrollTop($('#wai-messages')&#91;0].scrollHeight);\n            });\n        }\n        $('#wai-send').click(send);\n        $('#wai-input').keypress(e => { if(e.which == 13) send(); });\n    });\n    &lt;\/script>\n    &lt;?php\n});\n\n\/\/ 3. ADIM: Arka Plan AJAX \u0130\u015fleyici (Gemini &amp; Supabase K\u00f6pr\u00fcs\u00fc)\nadd_action('wp_ajax_wai_ask_ai', 'wai_ajax_process');\nadd_action('wp_ajax_nopriv_wai_ask_ai', 'wai_ajax_process');\n\nfunction wai_ajax_process() {\n    $opt = get_option('wai_settings');\n    $q = sanitize_text_field($_POST&#91;'question']);\n\n    \/\/ A. Embedding (Soru Vekt\u00f6r\u00fc)\n    $e_res = wp_remote_post(\"https:\/\/generativelanguage.googleapis.com\/v1beta\/models\/gemini-embedding-001:embedContent?key=\".$opt&#91;'g_key'], &#91;\n        'headers' => &#91;'Content-Type' => 'application\/json'],\n        'body' => json_encode(&#91;\"content\" => &#91;\"parts\" => &#91;&#91;\"text\" => $q]]], \"outputDimensionality\" => 768])\n    ]);\n    $vec = json_decode(wp_remote_retrieve_body($e_res), true)&#91;'embedding']&#91;'values'];\n\n    \/\/ B. Supabase RAG (En Yak\u0131n Bilgiyi Bul)\n    $s_res = wp_remote_post($opt&#91;'s_url'].\"\/rest\/v1\/rpc\/match_documents\", &#91;\n        'headers' => &#91;'Content-Type' => 'application\/json', 'apikey' => $opt&#91;'s_key'], 'Authorization' => 'Bearer ' . $opt&#91;'s_key']],\n        'body' => json_encode(&#91;\"query_embedding\" => $vec, \"match_threshold\" => 0.1, \"match_count\" => 3])\n    ]);\n    $docs = json_decode(wp_remote_retrieve_body($s_res), true);\n    $ctx = \"\"; if(!empty($docs)) { foreach($docs as $d) { $ctx .= $d&#91;'content'] . \"\\n\"; } }\n\n    \/\/ C. Gemini 2.5 Flash ile Cevap \u00dcret\n    $c_res = wp_remote_post(\"https:\/\/generativelanguage.googleapis.com\/v1beta\/models\/gemini-2.5-flash:generateContent?key=\".$opt&#91;'g_key'], &#91;\n        'headers' => &#91;'Content-Type' => 'application\/json'],\n        'body' => json_encode(&#91;\"contents\" => &#91;&#91;\"parts\" => &#91;&#91;\"text\" => \"Sen {$opt&#91;'name']} dan\u0131\u015fman\u0131s\u0131n. Bilgiler:\\n$ctx\\nSoru: $q\"]]]]])\n    ]);\n    $ans = json_decode(wp_remote_retrieve_body($c_res), true)&#91;'candidates']&#91;0]&#91;'content']&#91;'parts']&#91;0]&#91;'text'];\n\n    wp_send_json_success($ans);\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><span id=\"Sonuc\">Sonu\u00e7<\/span><\/h2>\n\n\n\n<p>Bu rehberle, modern bir AI asistan\u0131n\u0131n t\u00fcm katmanlar\u0131n\u0131 ge\u00e7tik:<\/p>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li><strong>Vekt\u00f6r Haf\u0131zas\u0131:<\/strong> Supabase ile semantik arama kurduk.<\/li>\n\n\n\n<li><strong>Veri \u0130\u015fleme:<\/strong> Node.js ile verileri &#8220;beyne&#8221; enjekte ettik.<\/li>\n\n\n\n<li><strong>WordPress:<\/strong> T\u00fcm yap\u0131y\u0131 g\u00fcvenli ve y\u00f6netilebilir bir eklentiye d\u00f6n\u00fc\u015ft\u00fcrd\u00fck.<\/li>\n<\/ol>\n\n\n\n<p>Art\u0131k elinizde saniyeler i\u00e7inde cevap veren, sitenizin her k\u00f6\u015fesinde \u00e7al\u0131\u015fan ve tamamen sizin verilerinizle beslenen devasa bir yapay zeka asistan\u0131 var.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>BU DERS\u0130N BA\u015eLIKLARI1 1. Proje Kurulumu ve Dosya Yap\u0131s\u01312 2. Veritaban\u0131 Katman\u0131: Supabase &amp; pgvector3 3. Verileri Vekt\u00f6rle\u015ftirip Y\u00fckleme: scripts\/ingest-data.ts4 4. WordPress Eklentisi: webasistant-ai-chat.php5 Sonu\u00e7 Bu rehber, Google Gemini 2.5 Flash ve Supabase kullanarak kendi verilerini bilen bir asistan\u0131 s\u0131f\u0131rdan in\u015fa etmek isteyenler i\u00e7in haz\u0131rlanm\u0131\u015ft\u0131r. 1. Proje Kurulumu ve Dosya Yap\u0131s\u0131 \u0130lk olarak bilgisayar\u0131m\u0131zda projemiz [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10],"tags":[],"class_list":["post-7673","post","type-post","status-publish","format-standard","hentry","category-wordpress-eklentisi-yazma"],"_links":{"self":[{"href":"https:\/\/sitecenneti.com\/wordpress\/wp-json\/wp\/v2\/posts\/7673","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sitecenneti.com\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sitecenneti.com\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sitecenneti.com\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sitecenneti.com\/wordpress\/wp-json\/wp\/v2\/comments?post=7673"}],"version-history":[{"count":2,"href":"https:\/\/sitecenneti.com\/wordpress\/wp-json\/wp\/v2\/posts\/7673\/revisions"}],"predecessor-version":[{"id":7679,"href":"https:\/\/sitecenneti.com\/wordpress\/wp-json\/wp\/v2\/posts\/7673\/revisions\/7679"}],"wp:attachment":[{"href":"https:\/\/sitecenneti.com\/wordpress\/wp-json\/wp\/v2\/media?parent=7673"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sitecenneti.com\/wordpress\/wp-json\/wp\/v2\/categories?post=7673"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sitecenneti.com\/wordpress\/wp-json\/wp\/v2\/tags?post=7673"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}