czyli jak nauczyć SI robić to, czego potrzebujemy - na nasze polecenie, z naszą logiką
W ostatnim wpisie opowiadałem o tym, skąd w ogóle Semantic Kernel się wziął i czemu warto się nim zainteresować. Dziś schodzimy poziom głębiej i odpowiemy sobie na pytanie: jak nauczyć naszą sztuczną inteligencję czynić dobro - czyli jak tworzyć i wykorzystywać pluginy.
Zanim przejdziemy do kodu - trochę kontekstu.
W największym skrócie - pluginy to funkcje, które możesz zarejestrować w Semantic Kernel i potem wywoływać w kontekście. Nie różnią się wiele od zwykłych funkcji programistycznych… poza tym, że potrafią korzystać z mocy LLM (czyli dużych modeli językowych).
To funkcje oparte na promptach, czyli tekstach z "inputami" do wypełnienia. Przykład:
Zadanie: Podsumuj tekst.
Tekst: {{$input}}
Podsumowanie:
Taką funkcję tworzymy za pomocą kernel.CreateSemanticFunction(...). Idealnie nadaje się do pisania streszczeń, generowania treści, tłumaczeń itp.
Czyli nasze własne, klasyczne funkcje w C#:
[KernelFunction] public static string UpperCase(string input) => input.ToUpperInvariant();
Możemy ich używać do obliczeń, formatowania danych, walidacji i dowolnej logiki, której LLM nie musi się uczyć - bo przecież my to wiemy!
To nie tyle osobny rodzaj funkcji, co sposób na ich wielokrotne użycie. Prompt templates zapisujemy np. w plikach .txt albo .skprompt.txt, które potem łatwo podpinamy pod Semantic Kernel.
Pliki mogą mieć parametr {{$input}}, ale również dodatkowe zmienne - np. {{$language}}, {{$tone}} itd. Potem wystarczy je załadować:
kernel.ImportSemanticPluginFromDirectory("Plugins", "MyPlugin")
I gotowe!
Stwórzmy prosty plugin, który tłumaczy teksty na inne języki.
Struktura katalogów:
Plugins/
└── TranslatorPlugin/
└── Translate.skprompt.txt
Zawartość Translate.skprompt.txt:
Przetłumacz tekst na {{$language}}:
{{$input}}
Tłumaczenie:
W kodzie:
var plugin = kernel.ImportSemanticPluginFromDirectory("Plugins", "TranslatorPlugin");
var result = await kernel.InvokeAsync(plugin["Translate"], new() { ["input"] = "Cześć, jak się masz?", ["language"] = "angielski" });
Console.WriteLine(result);
W praktyce nie zatrzymujemy się na jednej funkcji. Często robimy coś takiego:
[1] Użytkownik zadaje pytanie → [2] Funkcja A buduje prompt → [3] Funkcja B przetwarza prompt → [4] Funkcja C analizuje wynik → [5] Funkcja D formatuje odpowiedź
Czyli tzw. chaining - funkcje wywoływane są jedna po drugiej, często korzystając z tego samego SKContext.
Możesz to zrobić manualnie:
var context = kernel.CreateNewContext(); context["input"] = "Jak działa Semantic Kernel?"; await kernel.InvokeAsync(plugin["AnalyzeQuestion"], context); await kernel.InvokeAsync(plugin["GeneratePrompt"], context); await kernel.InvokeAsync(plugin["GetAnswer"], context);
Albo - zautomatyzować to, używając planera (ale o tym innym razem 👀).
| Potrzebuję... | Typ funkcji |
|---|---|
| Logiki biznesowej | 🛠 Native function |
| Generowania/interpretowania tekstu | ✨ Prompt function |
| Łatwej reużywalności promptów | 🧩 Prompt template |
| Skomplikowanego przepływu danych | 🔁 Chaining (manualnie lub planer) |
Automatyczne tłumaczenia
Spersonalizowane odpowiedzi na pytania użytkowników
Tworzenie raportów lub streszczeń
Łączenie klasycznego C# z mocą LLM
W następnym wpisie przyjrzymy się wbudowanym pluginom, które Semantic Kernel udostępnia od ręki. Dzięki nim możesz od razu korzystać np. z wysyłania maili, zarządzania plikami czy konwersji dat - bez pisania ani linijki promptu!
Do przeczytania!
👉Masz pytania albo chcesz przykład w Twoim kontekście? Daj znać przez formularz kontaktowy!