Derinlemesine yazılım eğitimleri için kanalımı takip edebilirsiniz...

Semantic Kernel Nedir? (DeepSeek R1 Eşliğinde .NET Açısından Derinlemesine Değerlendirelim)

Semantic Kernel Nedir (DeepSeek R1 Eşliğinde .NET Açısından Derinlemesine Değerlendirelim)
Merhaba,

Bu içeriğimizde Microsoft tarafından .NET ekosisteminde Yapay Zekâ (AI) uygulamalarını geliştirmemizi kolaylaştırmak amacıyla sunulan Semantic Kernel kütüphanesini hem teorik hem de pratik bir şekilde derinlemesine inceliyor olacağız. O halde buyurun hiç vakit kaybetmeksizin başlayalım…

Semantic Kernel Nedir?

Semantic Kernel, yukarıdaki satırlarda da bahsedildiği üzere Microsoft tarafından sunulan ve özellikle .NET ekosisteminde Yapay Zeka (AI) uygulamaları geliştirmeyi kolaylaştırmayı hedefleyen açık kaynaklı bir kütüphanedir. Büyük Dil Modelleri (Large Language Models – LLM) ve yapay zekâ tabanlı yetenekleri ile yazılım dünyasının geleneksel iş akışlarını birleştirmeye yönelik çeşitli araçlar ve soyutlamalar sağlamaktadır. Bu minvalde, .NET uygulamalarında OpenAI, Azure OpenAI, DeepSeek vs. gibi büyük dil modeli servislerini entegre edebilecek bir ‘çerçeve’ veya ‘iskelet’ rolü görmektedir diyebiliriz.

Semantic Kernel, .NET çalışmalarında AI destekli uygulamalar geliştirmek için özelleştirilebilir ve genişletilebilir bir yapı sunmaktadır. LLM’lerin çıktılarıyla geleneksel iş akışlarını birleştirebilir, iş mantıklarındaki kararları LLM destekli verebilir, geçmiş verileri hatırlayarak uygulamanın öğrenmesini ve konu bağlamının hatırlanmasını sağlayabilir, mevcut AI sistemlerini .NET yetenekleriyle genişletebilir ve kendimize uygun özelleştirerek ihtiyaçlarımıza AI destekli tam bir altyapı sağlayabiliriz.

Şimdi gelin, Semantic Kernel’ın yeteneklerini alt başlıklar altında tek tek değerlendirmeye ve böylece yapısal zenginliğini ortaya çıkarmaya çalışalım.

Büyük Dil Modelleriyle Entegrasyon

Semantic Kernel, OpenAI veya Azure OpenAI gibi servislerdeki büyük dil modelleri ile etkileşimi standart bir arayüz üzerinden sunmakta ve özellikle .NET uygulamalarında istemci çağrıları, kimlik doğrulama ve istemci yapılandırmaları gibi ayrıntıları kolaylıkla yöneterek LLM’lerden faydalanılmasını sağlamaktadır.

‘Plugins’ (Eklenti) ve ‘Functions’ (Fonksiyonlar)

Semantic Kernel, ‘Plugins’ (eklenti) ve ‘Function’ (fonksiyon) gibi yapıları tanımlayarak yeniden kullanılabilir yapay zeka işlevsellikleri yaratmamıza olanak tanımaktadır. Bu yaklaşım özellikle .NET uygulamaları içinde katmanlı ve modüler bir mimari kurmayı kolaylaştırmaktadır.

Plugins Function
Semantic Kernel’da belirli bir görevi yerine getiren modüler bileşene ‘Plugins’ denmektedir. Başka bir deyişle, LLM’lere çeşitli görevleri yaptırmak ve uygulamaya belirli yetenekler kazandırmak için tanımlanmış modüler yeteneklerdir.

Teknik olarak birbiriyle ilişkili ‘fonksiyonlar’ grubudur.

Örnek olarak;

  • Matematik Plugin’i : İçinde toplama, çıkarma, çarpma vs. gibi fonksiyonları barındırır.
  • Metin Analizi Plugin’i : İçinde duygu analizi, özetleme gibi işlemler yapan fonksiyonlar bulunur.
  • Çeviri Plugin’i : Metinleri bir dilden diğerine çevirmek için fonksiyonlar içerir. “Türkçe’den İngilizce’ye çevir” ya da “İngilizce’den Türkçe’ye çevir” gibi farklı fonksiyonlar barındırabilir.
Function ise tek bir amacı ve belirli bir görevi gerçekleştirmeye odaklı olan bağımsız bir işlemdir. Genelde bir LLM çağrısı veya belirli bir iş mantığını yürütmekten sorumlu fonksiyondur.

Bir plugin içerisinde bir veya birden fazla function bulunabilir. Yapısal olarak da function’lar; genellikle bir girdi almakta, iş mantığı doğrultusunda operatif işlem yapmakta ve bu işlem neticesinde bir çıktı üretmektedir.

Örnek olarak;

  • SummarizeText() : Bir metni özetleyen fonksiyondur.
  • ExtractKeywords() : Metinden anahtar kelimeleri ayıklayan fonksiyondur.
  • TranslateText() : Metni farklı bir dile çeviren fonksiyondur.
Plugin, bir dizi fonksiyonu içeren daha büyük bir yapıyken, function ise tek başına çalışan belirli bir göreve odaklı operatif çalışma sergileyen bir işlemdir.
Prompt Şablonlama ve Düzgün Prompt Yönetimi

Büyük dil modellerine gönderilen prompt’ların tutarlı ve sürdürülebilir olması için Semantic Kernel prompt şablonlama özelliği sunmaktadır. Bu özellik sayesinde modelin nasıl cevap vermesi, hangi bilgilerin dikkate alınması veya nasıl bir üslup kullanılması gerektiğini belirleyen şablonlar oluşturulabilmekte ve yönetilebilmektedir. Tabi bunu yaparken bir yandan da uygulamanın farklı sürümleri veya ortamlarına göre prompt’ları ayırabilir ve kullanıcılardan yahut başka sistemlerden gelen verileri de şablona kolayca entegre edebilirsiniz.

Bağlam (Context) ve Memory (Bellek)

Semantic Kernel, uygulamalarınızda diyaloğa veya senaryoya dayalı bir bellek/memory kavramı getirmektedir. Bir LLM ile konuşma halindeyken veya ardışık sorgular yaparken önceki adımlardan elde edilen bilgilerin saklanması ve bu bilgilerin gelecekteki sorgularda kullanılması oldukça kritik öneme sahiptir diyebiliriz. Haliyle Semantic Kernel ile ister o anki istek veya konuşma akışına göre gerekli bilgilerin saklandığı geçici belleği(Kısa Vadeli Hafıza / Short-Term Memory), isterseniz de kullanıcının geçmiş etkileşimleri, veritabanı bilgileri veya önceki sorgulardan türetilmiş sonuçlar gibi kalıcı verilerin bulunduğu uzun vadeli hafızayı(Uzun Vadeli Hafıza / Long-Term Memory) kullanabilirsiniz.

Yüksek Seviyeli Senaryo Desteği

Semantic Kernel sadece temel fonksiyon çağrılarını değil, daha karmaşık senaryoların da ele alınabilmesi için çeşitli yüksek seviyeli soyutlamalar da sunmaktadır. Misal olarak; bir fonksiyonun çıktısını bir başka fonksiyonun girdisi olarak alıp işlemek (zincirleme prompt’lar – chaining), model cevabına göre farklı iş akışı adımlarını tetiklemek veya sonlandırmak gibi koşullu iş akışları ve domain’e özel senaryolarda LLM’in yanıtlarını ek mantıkla birleştirerek karar mekanizmaları oluşturmak örnek verilebilir.

Semantic Kernel İle Hangi Uygulamalar Yapılabilir?

Semantic Kernel sayesinde .NET uygulamalarında aşağıdaki gibi yapay zeka tabanlı pek çok senaryoyu hayata geçirmek mümkündür.

Sohbet Uygulamaları (Chatbot’lar) Müşteri hizmetleri, teknik destek veya iç kaynak danışmanlığı gibi özel alanlarda sohbet robotları gibi özel amaçlı Chatbot’lar ve kullanıcılarla farklı dillerde etkileşim kurabilen, soruları anlayıp cevaplayabilen çoklu dil destekli sohbet uygulamaları geliştirilebilir. Tüm bunları yaparken kullanıcıların önceki mesajlarından veya uygulama içinde yapılan aksiyonlardan gelen bilgileri Semantic Kernal’ın sağladığı memory/bellek mekanizmasıyla saklayıp ileri adımlarda kullanarak daha insansı etkileşimler sağlanabilir.
İçerik Oluşturma (Content Generation) Özgün blog yazıları, makaleler, sosyal medya gönderileri, ürün tanıtımları veya reklam kampanyaları için yaratıcı pazarlama ve reklam metinleri, mevcut bir içeriği özetlemek ya da detaylandırmak için metin genişletme yahut kısaltma işlemleri yapılabilir.
Soru – Cevap (Q & A) ve Bilgi Yönetimi Kurumsal dokümantasyon, veri tabanlarından veya belge depoları içinden cevap bulabilen sistemler ya da kullanıcıların sorularına göre ilgili belgeler üzerinden arama yapabilen ve önerilerde bulunabilen sistemler geliştirilebilir.
Metin Dönüşümleri ve Dil İşleme Farklı dillere çeviri, uzun metinleri özetleme, raporlama veya konuşma transkriptlerini kısaltıp özetleme yazılımları oluşturulabilir. Bunların dışında metinde ifade edilen duygu, ton veya niyet gibi öğeleri tespit ederek duygu analizinin de yapılabilmesi muhtemeldir.
Vee daha fazlasını…

Bunların dışında genel anlamda AI agent dediğimiz ve önceden belirlenmiş hedeflere ulaşabilen programlar da geliştirebilirsiniz. Ne gibi mi? Kod yazan, e-posta oluşturup gönderen, toplantıları özetleyen, önerilerde bulunan vs. gibi…

Semantic Kernel İle ML.NET Arasındaki Fark Nedir?

ML.NET, genel makine öğrenimi için tasarlanmışken, Semantic Kernel ise büyük dil modellerini ve yaratıcı AI görevlerini kullanabilmek için bir orkestrasyon sağlaması maksadıyla tasarlanmıştır.

Özellik / Kriter ML.NET Semantic Kernel
Kullanım Alanı Makine öğrenmesi (ML) modellerini .NET içinde eğitmek ve çalıştırmak için geliştirilmiştir.

Modeli kendiniz eğitirsiniz.
 

Tahmin, sınıflandırma, regresyon, zaman serisi, anormallik tespiti vs. kullanım alanlarıdır.

Büyük dil modelleri (LLM) ile çalışabilmek ve AI destekli uygulamalar geliştirebilmek için tasarlanmıştır.

Var olan LLM’leri kullanır, eğitim yapmazsınız.

Chatbot, içerik oluşturma, Q & A, metin özetleme, çeviri vs. kullanım alanlarıdır.

Amaç Geleneksel makine öğrenmesi modellerini eğitmeyi ve tahmin yapmayı amaçlar. LLM’leri ve geleneksel programlamayı birleştirmek ve Chatbox, metin işleme, planlama vb. işlemleri yapmayı amaçlar.
Model Eğitimi Özel ML modellerini eğitmek mümkündür. Sınıflandırma, regresyon, tahminleme vs. yapılabilir. Kendi modelini eğitmemektedir. OpenAI, Azure OpenAI, DeepSeek vs. gibi büyük AI modellerini kullanır.
Bağımlılıklar Tamamen lokal çalışabilir, dış API bağımlılığı yoktur. Dış AI API’lerine bağımlıdır. OpenAI, Azure OpenAI, Hugging Face, DeepSeek vs.

Evet, artık Semantic Kernel’ı yeterince tanıdığımıza göre .NET platformunda pratiksel olarak deneyimlemeye geçebiliriz.

.NET Projesinde Semantic Kernel Kullanımı

Semantic Kernel’ı minimum kurulumla kullanabilmek için SDK paketine ve kullanılacak LLM servisinden bir endpoint’e ihtiyacımız vardır diyebiliriz. Misal olarak aşağıdaki süreçte DeepSeek R1 eşliğinde çalışan bir Semantic Kernel örneklendirmesini inceleyebilirsiniz;

  • Adım 1
    Uygulamaya Install-Package Microsoft.SemanticKernel paketini yükleyiniz.
  • Adım 2
    DeepSeek R1, LLaMA, Phi vs. gibi open source olan LLM’lerle yerel olarak etkileşim kurabilmemize olanak tanıyan Ollama platformunu şuradan indirip bilgisayarınıza kurunuz.
  • Adım 3
    Herhangi bir terminal’dan ollama run deepseek-r1 talimatıyla DeepSeek R1 modelini yükleyiniz.

    DeepSeek, OpenAI-o1 ile karşılaştırılabilir performansa sahip birinci nesil bir modeldir.

    Semantic Kernel Nedir (.NET Açısından Derinlemesine Değerlendirelim)İşlem tamamlandıktan sonra ollama list talimatıyla modelin kullanılabilir olduğunu doğrulayabilirsiniz.

  • Adım 4
    Semantic Kernel’i aşağıdaki gibi yapılandırınız;

    Console Application;

    using Microsoft.SemanticKernel;
    
    var builder = Kernel.CreateBuilder();
    
    var kernel = builder.Build();
    

    Asp.NET Core Application;

    var builder = WebApplication.CreateBuilder(args);
    builder.Services.AddKernel();
    
    var app = builder.Build();
    

    Ve ardından DeepSeek R1’i Semantic Kernel’a entegre edebilmek için
    Install-Package Codeblaze.SemanticKernel.Connectors.Ollama kütüphanesini yüklemeli ve aşağıdaki gibi entegrasyon işlemlerini gerçekleştirmelisiniz;

    Console Application;

    using Codeblaze.SemanticKernel.Connectors.Ollama;
    using Microsoft.SemanticKernel;
    using Microsoft.Extensions.DependencyInjection;
    
    var builder = Kernel.CreateBuilder()
                        .AddOllamaChatCompletion("deepseek-r1:latest", "http://localhost:11434");
    
    builder.Services.AddScoped<HttpClient>();
    
    var kernel = builder.Build();
    
    while (true)
    {
        Console.WriteLine("Soru sor :");
        string input = Console.ReadLine();
        var response = await kernel.InvokePromptAsync(input);
        Console.WriteLine($"Cevap :\n------------------------\n{response}\n------------------------");
    }
    

    Asp.NET Core Application;

    using Codeblaze.SemanticKernel.Connectors.Ollama;
    using Level1.Essentials.ViewModels;
    using Microsoft.SemanticKernel.ChatCompletion;
    
    var builder = WebApplication.CreateBuilder(args);
    builder.Services.AddKernel()
                    .AddOllamaChatCompletion("deepseek-r1", "http://localhost:11434");
    
    builder.Services.AddRequestTimeouts();
    builder.Services.AddHttpClient();
    
    var app = builder.Build();
    
    app.UseRequestTimeouts();
    
    app.MapPost("/chat", async (IChatCompletionService chatCompletionService, ChatModel chatModel) =>
    {
        var response = await chatCompletionService.GetChatMessageContentAsync(chatModel.Input);
        return response.ToString();
    }).WithRequestTimeout(TimeSpan.FromMinutes(10));
    
    app.Run();
    
  • Adım 5
    Ve son olarak yapılan çalışmaları derleyip, çalıştırınız ve test ediniz.
    Semantic Kernel Nedir? (DeepSeek R1 Eşliğinde .NET Açısından Derinlemesine Değerlendirelim)

    İyi kötü sorulan soruya bişeyler anlatarak cevap vermiş 🙂

Evet, görüldüğü üzere .NET platformunda Semantic Kernel’ı kullanmak bu kadar basit… Şimdi gelin .NET açısından olaya biraz daha hakimiyet sağlayabilmek için teknik detaylara dalmaya başlayalım…

Prompt Şablonlarının(Templates) Kullanımı

Semantic Kernel’daki promt şablonları, Doğal Dil İşleme (NLP) ile yapay zeka modellerini kullanarak dinamik prompt’lar oluşturmak için kullanılan bir yapıdır. Bunlar, belirli bir bağlam veya girdiye göre özelleştirilebilen şablonlardır. Yapısal olarak yer tutucular(placeholders) ve parametreler eşliğinde çalışmaktadırlar.

Misal olarak aşağıda basit bir şablon yapısını inceleyebilirsiniz;

Yandaki işlemi hesapla:: {{$input}}

Burada {{$input}} ifadesi placeholder’a karşılık gelirken, parametre ise kullanıcı ya da sistem tarafından sağlanan gerçek değere karşılık gelmektedir.

Eğer bu şablonu Semantic Kernal’da kullanmak isterseniz aşağıdaki gibi bir çalışma yapabilirsiniz;

var builder = Kernel.CreateBuilder()
                    .AddOllamaChatCompletion("deepseek-r1:latest", "http://localhost:11434");

builder.Services.AddScoped<HttpClient>();

var kernel = builder.Build();

var promptTemplate = "Yandaki işlemi hesapla: {{$input}}";
var function = kernel.CreateFunctionFromPrompt(promptTemplate);
var arguments = new KernelArguments { ["input"] = "1 + 2 + 5 * 3" };
var result = await function.InvokeAsync(kernel, arguments);
Console.WriteLine(result);

Prompt şablonları, daha akıllı ve daha uyarlanabilir uygulamalar oluşturmanın basit ve güçlü bir yoludur.

History Objesi İle Geçmiş Bağlamın Hatırlanması

Semantic Kernel’da History objesi, bir konuşmanın geçmişini saklamak ve modelin önceki mesajlara göre daha bağlamsal yanıtlar vermesini sağlamak için kullanılmaktadır. Bu yetenek, özellikle chat-based AI uygulamalarında geçmiş konuşmaları takip etmek için önemlidir. Yapısal olarak memory mekanizmasıyla birlikte çalışmakta ve kullanıcının önceki mesajlarını saklamaktadır. Bunun için SemanticKernal.Chat veya SemanticKernel.Memory gibi bileşenlerden yararlanmaktadır.

Kullanım mantığı oldukça basittir. History nesnesi oluşturulmalı ve önceki mesajlar bu nesnede depolanmalıdır. Ve kullanıcılardan yeni mesajlar geldikçe bu nesne güncellenmeli ve bir yandan da model kullanılırken de bu obje bağlamsal veri olarak değerlendirilmelidir. Bunu daha iyi anlayabilmek için aşağıdaki örnek kullanımı inceleyebilirsiniz;

using Codeblaze.SemanticKernel.Connectors.Ollama;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;

var builder = Kernel.CreateBuilder()
                    .AddOllamaChatCompletion("deepseek-r1:latest", "http://localhost:11434");

builder.Services.AddScoped<HttpClient>();

var kernel = builder.Build();

var history = new ChatHistory();
//İlk mesaj eklenmektedir.
history.AddUserMessage("Merhaba! Bu gün hava nasıl?");

//Model çağrısı yapılmaktadır.
var chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();
var response = await chatCompletionService.GetChatMessageContentAsync(history);

//Response history'e eklenmektedir.
history.AddAssistantMessage(response.ToString());

//Aynı şekilde yeni mesajda history'e eklenerek devam edilir.
history.AddUserMessage("Peki, hafta sonu için hava tahmini nedir?");
var response2 = await chatCompletionService.GetChatMessageContentAsync(history);
history.AddAssistantMessage(response2.ToString());

Console.WriteLine(response2.ToString());

Console.Read();

Burada dikkat ederseniz farklı mesaj türlerini tutabilecek bir özelliğe sahip olan ChatHistory nesnesinden istifade edilmektedir. Bu mesaj türlerini ele alırsak eğer;

  • System Messages
    Modelin davranışını yönlendirmek için kullanılan mesajlardır. Yani modelin bir rol oynamasını ve belirli kurallar çerçevesinde çalışmasını sağlamak için kullanılırlar. Haliyle bu mesajlar genellikle kullanıcılardan alınmaz ya da gösterilmezler!
  • User Messages
    Kullanıcıların yazdığı mesajlardır. Model, bu mesajlara karşın yanıt üretmekten sorumludur.
  • Assistant Messages
    Yapay zeka modelinin verdiği yanıtlardır.

History nesnesi, sohbet tabanlı uygulamalarda yahut konuşma geçmişine dayalı akıllı yanıt sistemlerinde büyük kolaylık sağlamaktadır…

Ayrıca ChatMessage nesnesinde sohbet geçmişine dair daha fazla ayrıntıyı aşağıdaki gibi ekleyebilirsiniz;

history.Add(new ChatMessageContent()
{
    Role = AuthorRole.User,
    AuthorName = "Gençay Yıldız",
    Items = [
        new TextContent{ Text = "Metin Işığın en çok hangi şarkısı sevilmektedir?" },
        new ImageContent { Uri = new Uri("https://i.ytimg.com/vi/xx_FwxOGBa8/maxresdefault.jpg") }
        ]
});

Görüldüğü üzere kullanıcı adları, resim içeriği gibi ek bilgilerle sohbet geçmişi daha da derinleştirilebilmektedir…

Eklenti (Plugin) Yapılanması

Semantic Kernel’da, eklentiler ile uygulamalara özel işlevleri içeren, Semantic Kernel’a entegre edilebilen ve doğal dil komutlarıyla çağrılabilen modüler kod parçacıkları oluşturulabilmektedir. Misal olarak, eğer uygulamanızda belirli bir hesaplama yapmak, veritabanı işlemleri gerçekleştirmek veya başka özel iş mantıklarını uygulamak isterseniz, bu işlevleri bir plugin içinde toplayarak Semantic Kernel’a ekleyebilirsiniz.

Böylece uygulamanızın gereksinimlerine göre özel işlemleri modüler bir şekilde organize edebilir; okunabilirliği, test edilebilirliği ve bakımı oldukça kolay bir kod inşasında bulunabilirsiniz. Ayrıca, ihtiyaç duyulan yeni işlevleri mevcut Semantic Kernel yeteneklerine entegre ederek uygulamanızı daha esnek ve genişletilebilir hale getirebilirsiniz.

Aşağıda, basit bir örnek üzerinden eklenti oluşturma, kernel’a ekleme ve kullanma adımlarını inceleyebilirsiniz;

    public class CalculatorPlugin
    {
        [KernelFunction("add")]
        [Description("İki sayısal değer üzerinde toplama işlemi gerçekleştirir.")]
        [return: Description("Toplam değeri döndürür.")]
        public int Add(int number1, int number2)
            => number1 + number2;
    }

Yukarıda görüldüğü üzere, uygulamaya özgü fonksiyonları içeren bir sınıf oluşturulmuştur. İşte bu sınıf bizler için bir plugin niteliği taşımaktadır. Sınıf içerisindeki Add metodu bu eklentinin niteliklerinden birisidir ve görüldüğü üzere bazı attribute’lar tarafından işaretlenmiştir. Bu attribute’lardan KernelFunction, işaretlediği metodu Semantic Kernel’ın tanıyabileceği bir kernel fonksiyon olarak nitelendirmemizi sağlar. Böylece SK, bu fonksiyonu, parantez içerisinde belirtilen benzersiz isimle eşleyerek çalıştırır. Description ve return: Description attribute’larının ise ne oldukları zahiren aşikardır. Biri metodun işlevini tanıtırken, diğeri ise geri dönüş değerini tanıtmaktadır.

Velhasıl, oluşturulan bu plugin’i SK’ya aşağıdaki gibi import edebilirsiniz;

Console Application;

var builder = Kernel.CreateBuilder()
                    .AddOllamaChatCompletion("deepseek-r1:latest", "http://localhost:11434");

builder.Services.AddScoped<HttpClient>();

var kernel = builder.Build();

kernel.Plugins.AddFromType<CalculatorPlugin>();
.
.
.

Asp.NET Core Application;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddKernel()
                .AddOllamaChatCompletion("deepseek-r1", "http://localhost:11434")
                .Plugins.AddFromType<CalculatorPlugin>();
.
.
.

Ve ekledikten sonra da aşağıdaki gibi plugin’i kullanabilirsiniz;

Console Application;

.
.
.
var arguments = new KernelArguments
{
    ["number1"] = 3,
    ["number2"] = 5
};

var addResult = await kernel.InvokeAsync("CalculatorPlugin", "add", arguments);
Console.WriteLine($"Sonuç : {addResult}");

Asp.NET Core Application;

.
.
.
app.MapGet("/add/{number1}/{number2}", async (Kernel kernel, int number1, int number2) =>
{
    var arguments = new KernelArguments
    {
        ["number1"] = number1,
        ["number2"] = number2
    };
    var addResult = await kernel.InvokeAsync("CalculatorPlugin", "add", arguments);
    return addResult.GetValue<int>();
}).WithRequestTimeout(TimeSpan.FromMinutes(10));
Prompt İçeriğine Göre Eklentinin AI Tarafından Otomatik Çağrılması

Tabi isterseniz, bu eklenti fonksiyonlarını otomatik olarak da çağırtabilir ve uygulamanın kullanıcı girdilerine daha akıllıca yanıtlar vermesini sağlayabilirsiniz. Yani, belirli eylemlere karşın açık komutları tetiklemekten ziyade, kullanıcının isteğine göre AI tarafından çağrılacak uygun eklentiler devreye sokulabilir ve böylece daha doğal bir etkileşim durumu söz konusu olabilir. Ve bir yandan da irademizce yapılan fonksiyon çağrımlarının azaltılmasını sağlayarak, sanki kesin talimat verircesine yapılan davranışlar yerine, kullanıcı deneyimlerinin daha organik bir şekilde geliştirilebilmesini sağlayabilirsiniz.

.
.
.
var chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();
var result = await chatCompletionService.GetChatMessageContentAsync(
    "üç ve beş'in toplamını hesapla",
    executionSettings: new PromptExecutionSettings
    {
        FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
    },
    kernel: kernel
    );


Console.WriteLine(result.ToString());

Tabi burada dikkat edilmesi gereken husus şudur ki; Semantic Kernel’da prompt içeriğine göre fonksiyon çağırabilmek için kullanılan dil modelinin (LLM) dahili olarak Function Calling özelliğini desteklemesi gerekmektedir. Eğer ki sizler de bu içerikte olduğu gibi Ollama üzerinden çalışma gerçekleştiriyorsanız bu özelliğin desteklenmediğini göreceksiniz. Bu davranışın şu anda ancak OpenAI yahut Azure OpenAI tarafından desteklenmekte olduğunu söylemekte fayda görmekteyim.

Fonksiyonların Yapılandırma Seçenekleri

Kullanılan AI modelinin çalışması sırasında tarafımızca oluşturulan plugin’lere nasıl erişeceğini ve bunların sürecin hangi aşamasında devreye gireceğini yapılandırabilir ve ince dokunuşlarla kontrolde bulunabilirsiniz. Özellikle gerçek zamanlı verilere ihtiyaç olduğunda dış bir API’ye istek gönderilmesi gerektiğinde plugin’leri kullanabilir veya gizlilik ya da güvenlik için işlevselliği kısıtlama gibi belirli durumlarda AI’ın yanıtlarını kendinize göre uyarlayabilirsiniz. Böylece davranışları stratejik olarak yönetebilir, uygulamanızın performansını optimize edebilirsiniz.

Uygulamada oluşturup dahil ettiğiniz tüm eklentiler, varsayılan olarak kullanılabilir vaziyettedirler. Sizler, istediğinizin kullanımını sınırlayabilir ya da komple devre dışı bırakabilirsiniz.

Aşağıdaki gibi bir çalışma neticesinde sürece eklenmiş fonksiyonlardan herhangi biri veya birileri, AI modeline gelen prompt neticesinde otomatik olarak devreye sokularak, cevabı şekillendirebilirler;

var builder = Kernel.CreateBuilder()
                    .AddOllamaChatCompletion("deepseek-r1:latest", "http://localhost:11434");

builder.Services.AddScoped<HttpClient>();

var kernel = builder.Build();

kernel.Plugins.AddFromType<APlugin>();
kernel.Plugins.AddFromType<BPlugin>();
kernel.Plugins.AddFromType<CPlugin>();

PromptExecutionSettings promptExecutionSettings = new()
{
    FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
};

await kernel.InvokePromptAsync("...", new(promptExecutionSettings));

Ya da eklenmiş fonksiyonlardan sürece otomatik olarak dahil olacak olanları aşağıdaki gibi seçebilirsiniz ve böylece modelin kullanacağı eklentileri sınırlandırabilirsiniz;

.
.
.
PromptExecutionSettings promptExecutionSettings = new()
{
    FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(functions: [
        kernel.Plugins.GetFunction(nameof(APlugin), "a"),
        kernel.Plugins.GetFunction(nameof(CPlugin), "c")
        ])
};

Veya modelin plugin tabanlı davranışını aşağıdaki gibi komple engelleyebilirsiniz;

.
.
.
PromptExecutionSettings promptExecutionSettings = new()
{
    FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(functions: [])
};

Bunların dışında aşağıdaki gibi kullanılan AI modeli en az bir plugin’i seçmeye de zorlanabilir;

.
.
.
PromptExecutionSettings promptExecutionSettings = new()
{
    FunctionChoiceBehavior = FunctionChoiceBehavior.Required()
};

Ya da aşağıdaki gibi tüm plugin’ler iptalde edilebilir;

.
.
.
PromptExecutionSettings promptExecutionSettings = new()
{
    FunctionChoiceBehavior = FunctionChoiceBehavior.None()
};
Filtre (Filters) Yapılandırması

Semantic Kernel’da filtreler, AI modeline gönderilen prompt’ların çözümlenmesi sürecinde kullanıcı izinlerinden tutun loglamaya kadar birçok eylemin sıralı bir şekilde gerçekleştirilmesini sağlayan yapılardır.

Bu minvalde Semantic Kernel, kontrolü ve özelleştirmeyi geliştirmek için aşağıdaki gibi üç tür filtre yapısı sunmaktadır;

  • Function Invocation Filters
    Bir fonksiyonun her yürütülme/işlenme sürecinde tetiklenecek olan filter’dır. Böylece ilgili fonksiyonla ilgili meta verilere erişim şansı doğacak hem de ilgili fonksiyon yürütülmeden önce ve sonra log atma imkanı söz konusu olacaktır.

        public sealed class LoggingFilter : IFunctionInvocationFilter
        {
            public async Task OnFunctionInvocationAsync(FunctionInvocationContext context, Func<FunctionInvocationContext, Task> next)
            {
                Console.WriteLine($"Çalıştırılıyor = Eklenti Adı : {context.Function.PluginName} | Fonksiyon Adı : {context.Function.Name}");
                await next(context);
                Console.WriteLine($"Çalıştırıldı = Eklenti Adı : {context.Function.PluginName} | Fonksiyon Adı : {context.Function.Name}");
            }
        }
    
  • Prompt Render Filters
    Prompt oluşturma sırasında tetiklenen ve prompt’ların nasıl biçimlendirileceği ve AI’ya nasıl gönderileceği üzerinde kontrol fırsatı sağlayan filter’dır. Özellikle hassas bilgiler için prompt’u değiştirme/düzenleme veya semantic caching’i etkinleştirme gibi görevler için oldukça ideal fırsatlar sağlamaktadır.

    Misal olarak aşağıdaki gibi bir prompt render filter oluşturabilir;

        public sealed class SafePromptFilter : IPromptRenderFilter
        {
            public async Task OnPromptRenderAsync(PromptRenderContext context, Func<PromptRenderContext, Task> next)
            {
                await next(context);
                context.RenderedPrompt = "3 + 5 sonucu kaçtır?";
            }
        }
    

    ve bu filter’ı kullanarak aşağıdaki gibi gelen prompt’ları manipüle edebilirsiniz;

    .
    .
    .
    var result = await kernel.InvokePromptAsync("dokuz'un ikiye bölümünden kalan kaçtır?");
    Console.WriteLine(result.ToString());
    

    Semantic Kernel Nedir (.NET Açısından Derinlemesine Değerlendirelim)

  • Auto Function Invocation Filters
    Bu filter’da yalnızca otomatik fonksiyon çağırma işlemi sırasında tetiklenmektedir. Genellikle ara sonuçlara göre iş akışlarını ayarlamak ya da mevcut süreci sonlandırmak için kullanılmaktadır;

        public sealed class EarlyTerminationFilter : IAutoFunctionInvocationFilter
        {
            public async Task OnAutoFunctionInvocationAsync(AutoFunctionInvocationContext context, Func<AutoFunctionInvocationContext, Task> next)
            {
                await next(context);
    
                var result = context.Result.GetValue<string>();
                if (result == "desired result")
                {
                    context.Terminate = true;
                }
            }
        }
    

Evet, filter’lar bunlardan ibarettir. Tabi hangi filter’ı kullanıyorsanız kullanın uygulamaya implemente etmeniz gerekmektedir. Bunun için aşağıdaki iki yöntemden birini kullanabilirsiniz;
Dependency Injection;

builder.Services.AddSingleton<IFunctionInvocationFilter, LoggingFilter>();
builder.Services.AddSingleton<IPromptRenderFilter, SafePromptFilter>();
builder.Services.AddSingleton<IAutoFunctionInvocationFilter, EarlyTerminationFilter>();

Kernel Properties;

kernel.FunctionInvocationFilters.Add(new LoggingFilter());
kernel.PromptRenderFilters.Add(new SafePromptFilter());
kernel.AutoFunctionInvocationFilters.Add(new EarlyTerminationFilter());

İşte bu kadar…
Tabi daha fazla detayla Semantic Kernel’ın kılcal damarlarına temas edebilirdik. Ancak bundan gayrısı içeriği haddinden fazla şişirmeye ve siz değerli okuyucuların şirazesine kaydırmak için kasıta girecektir. Ben içeriği burada nihayetlendirip bundan sonrasını sizlerin ihtiyaç ve meramına bırakmayı uygun görmekteyim…

Bir kaç kelam eşliğinde nihai dokunuş yaparsak eğer;
Anlayacağınız Semantic Kernel, .NET dünyasında yapay zeka fonksiyonları geliştirmeyi ve büyük dil modellerini uzman sistemlerde, soru-cevap süreçlerinde yahut içerik oluşturma gibi senaryolarda verimli bir şekilde kullanmayı kolaylaştıran kaliteli ve oldukça yetenekli bir kütüphanedir. SK sayesinde uygulama geliştiricileri, LLM çağrılarını karmaşık hale getiren pek çok detayı soyutlayarak daha temiz ve modüler kod yazabilmekte ve prompt yönetiminden bellek işleyişine, eklenti konseptinden API entegrasyonuna kadar geniş bir yelpazede SK’nın özelliklerinden istifade edebilmektedir.

İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Not : Örnek çalışmaya aşağıdaki github adresinden erişebilirsiniz.
https://github.com/gncyyldz/Semantic.Kernel.Example

Bunlar da hoşunuza gidebilir...

10 Cevaplar

  1. Eyüp dedi ki:

    Emeğinize sağlık. Bu serinin devam etmesi hatta belki youtube üzerinde AI ve .Net adı altında bir seriye dönüşmesini çok isterim. Özellikle yazıda belirtilen ama anlatılmayan AI Agent işlemlerini de bu video serisinde işleyebiliriz. Yapay zekanın gelişimine ayak uydurmak çok faydalı olacaktır. Tekrardan emeğinize sağlık 🙂

    • Gençay dedi ki:

      Evet, bir seri tadında olacaktır ve bu akşamdan itibaren youtube üzerinden de bu içerikler desteklenmeye başlanacaktır.
      Bol faydalar olsun 🌹

  2. Berkay dedi ki:

    Merhaba hocam, daha detaylı incelemeden yorum bölümüne geldim 🙂 AI tarafıyla ilgili sizlerden kapsamlı eğitimler veya içerikler bekliyoruz 🙂

    Emeğinize sağlık tekrardan.

  3. Hasan dedi ki:

    Teşekkürler hocam. gayet anlaşılır güzel bir makale olmuş. Emeğinize sağlık

  4. Gençay dedi ki:

    Değerli arkadaşlar;

    Ollama’yı docker ortamında yapılandırıp DeepSeek-R1 modelini bir container üzerinden ayağa kaldırabilmek için aşağıdaki talimatlardan istifade edebilirsiniz;

    docker run -d -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama
    docker exec -it ollama /bin/bash
    ollama run deepseek-r1
    
  5. Enes dedi ki:

    Hocam docker exec -it ollama /bin/bash bu komutu çalıstırınca root@8dd75fec484b:/# geliyor burda ne yapılmalı anlamadım. Yardımınızı rica ediyorum.

  6. Ahmet Kandil İş dedi ki:

    Hocam selam,
    Custom Plugin ile işlem yapmak istediğimde ;
    ClientResultException: Service request failed.
    Status: 404 (Not Found)
    hatası alıyorum.
    model olarak google/gemma-3-4b-it:free , google/gemini-2.0-flash-exp:free dahil bir çoğunu denedim.
    Model yazdığım plugini çağıramadığı için mi bu hatayı alıyorumdur.
    Teşekkürler.

    • Ahmet Kandil dedi ki:

      Hocam problem kullandığım modelden kaynaklanıyormus. GPT-4o-mini modeli ile çözdüm. Fakat mcp client server ugyulamalarında .csv dosya okuyup özetlemesini istediğimde 300-400 satırlık dosyada problem olmuyor fakat yaklaşık 3000 satır olduğunda aşağıdaki hatayı aldım.

      ClientResultException: Service request failed.
      Status: 400 (Bad Request)

      ya context’e fazla geliyor ya da daha kabiliyetli model tercih etmem gerek.
      Emeğinize sağlık.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir