Zapisywanie monitów o pliki
W poprzednich lekcjach przedstawiono sposób tworzenia monitów wielokrotnego użytku przez wywołanie metody kernel.InvokePromptAsync
. Na przykład:
Console.WriteLine(
await kernel.InvokePromptAsync(generateNamesOfPrompt, new() {{ "input", "fantasy characters" }})
);
Tworzenie wbudowanych monitów jest przydatne, ale w przypadku większych projektów możesz zorganizować monity w oddzielne pliki i zaimportować je do jądra. Jest to podobne do sposobu użycia wbudowanych wtyczek. Aby utworzyć własne wtyczki monitów, najlepszym rozwiązaniem jest utworzenie oddzielnych folderów dla monitów.
Jak tworzyć wtyczki semantyczne
Zestaw SDK jądra semantycznego obsługuje język tworzenia szablonów monitów z kilkoma prostymi regułami składni. Nie musisz pisać kodu ani importować żadnych bibliotek zewnętrznych, wystarczy użyć nawiasów klamrowych {{...}} aby osadzić wyrażenia w monitach.
Aby utworzyć wtyczkę semantyczną, potrzebny jest folder zawierający dwa pliki: skprompt.txt
plik i config.json
plik. Plik skprompt.txt
zawiera monit o podanie dużego modelu językowego (LLM), podobnie jak wszystkie monity napisane do tej pory. Plik config.json
zawiera szczegóły konfiguracji monitu.
Plik config.json
obsługuje następujące parametry:
type
: typ monitu. Zazwyczaj używasz typu monitu o ukończenie czatu.description
: opis tego, co robi monit. Ten opis może służyć przez jądro do automatycznego wywoływania monitu.input_variables
: definiuje zmienne, które są używane wewnątrz monitu.execution_settings
: ustawienia modeli uzupełniania. W przypadku modeli OpenAI te ustawienia obejmująmax_tokens
właściwości itemperature
.
Załóżmy na przykład, że chcesz utworzyć agenta nauczyciela muzyki. Możesz chcieć obsługiwać funkcję, która sugeruje akordy, aby dodać do potencjalnego progresji akordu. W takim przypadku użytkownik udostępnia akordy początkowe, a wtyczka zaleca akordy, które byłyby dobrym rozwiązaniem.
Aby utworzyć tę wtyczkę, należy najpierw utworzyć folder "Monity" w projekcie, a następnie podfolder o nazwie "SuggestChords". Następnie należy dodać pliki "skprompt.txt" i "config.json" do folderu "SuggestChords".
Przykład pliku "skprompt.txt":
<message role="system">Instructions: You are a helpful music theory assistant.
Provide the user with several chords that they could add to a chord progression
based on some starting chords they provide</message>
<message role="user">Am Em</message>
<message role="assistant">
C major, F major, G major, D major, E major, B minor
</message>
<message role="user"> {{$startingChords}}</message>
Przykład pliku "config.json":
{
"schema": 1,
"type": "completion",
"description": "Recommends chords to the user based on starting chords",
"execution_settings": {
"default": {
"max_tokens": 1000,
"temperature": 0
}
},
"input_variables": [
{
"name": "startingChords",
"description": "The starting chords provided by the user",
"required": true
},
]
}
W tym przykładzie temperature
parametrem jest parametr, który kontroluje, ile ma być losowane wygenerowanego tekstu. Wartości muszą należeć do zakresu od 0 do 2. Niższa temperatura skutkuje bardziej skoncentrowanym i precyzyjnym wyjściem, a wyższa temperatura skutkuje bardziej zróżnicowanymi i kreatywnymi danymi wyjściowymi.
W bieżącym modelu żądania mogą używać maksymalnie 4097 tokenów współużytkowanych między monitem a ukończeniem. Oznacza to, że jeśli monit zawiera 4000 tokenów, ukończenie czatu może wynosić co najwyżej 97 tokenów. Więcej informacji na temat dostrajania parametrów można znaleźć w dokumentacji modułu LLM.
Aby użyć niestandardowej wtyczki semantycznej, zaimportuj katalog monitu do jądra i wywołaj wtyczkę według jego nazwy folderu. Na przykład:
var plugins = kernel.CreatePluginFromPromptDirectory("Prompts");
string input = "G, C";
var result = await kernel.InvokeAsync(
plugins["SuggestChords"],
new() {{ "startingChords", input }});
Console.WriteLine(result);
W tym przykładzie CreatePluginFromPromptDirectory
zwraca KernelPlugin
obiekt. Ten obiekt reprezentuje kolekcję funkcji. CreatePluginFromPromptDirectory
akceptuje ścieżkę wyznaczonego katalogu wtyczek, a nazwa każdego podfolderu jest używana jako nazwa funkcji.
Jeśli na przykład zagnieżdżono element "SuggestChords" w folderze o nazwie "ChordProgressions", użyjesz katalogu monitu "Prompts/ChordProgressions", a nazwa funkcji pozostanie taka sama. Alternatywnie można użyć katalogu "Prompt" i odwołania "ChordProgressions/SuggestChords" jako nazwy funkcji.
// Example of nested prompt folders
var chordProgressionPlugin = kernel.CreatePluginFromPromptDirectory("Prompts/ChordProgressions");
string input = "G, C";
var result = await kernel.InvokeAsync(
chordProgressionPlugin["SuggestChords"],
new() {{ "startingChords", input }});
Console.WriteLine(result);
Uruchomienie tego kodu powinno spowodować wygenerowanie odpowiedzi podobnej do następujących danych wyjściowych:
D major, A minor, E minor, B minor, F major, G7
Zapisywanie monitów do plików to doskonały sposób organizowania kodu i zwiększenia jego obsługi. Pliki konfiguracji umożliwiają również dalsze dostrajanie monitów o bardziej przewidywalne środowisko użytkownika.