Salvar solicitações em arquivos
Nas unidades anteriores, você aprendeu a criar prompts reutilizáveis chamando kernel.InvokePromptAsync
. Por exemplo:
Console.WriteLine(
await kernel.InvokePromptAsync(generateNamesOfPrompt, new() {{ "input", "fantasy characters" }})
);
Criar solicitações embutidas é útil, mas para projetos maiores, talvez você queira organizá-las em arquivos separados e importá-las para o kernel. Isso se assemelha à maneira como os plug-ins internos são usados. Para criar seus próprios plug-ins de solicitação, uma das melhores práticas é criar pastas separadas para as solicitações.
Como criar plug-ins semânticos
O SDK do Kernel Semântico dá suporte a uma linguagem de modelagem de solicitação com algumas regras de sintaxe simples. Você não precisa escrever código ou importar bibliotecas externas, basta usar chaves {{...}} para inserir expressões em suas solicitações.
Para criar um plug-in semântico, você precisa de uma pasta contendo dois arquivos: um arquivo skprompt.txt
e um arquivo config.json
. O arquivo skprompt.txt
contém o prompt para o LLM (modelo de linguagem grande), semelhante a todos os prompts que você escreveu até agora. O arquivo config.json
contém os detalhes de configuração do prompt.
O arquivo config.json
dá suporte aos seguintes parâmetros:
type
: O tipo da solicitação. Normalmente, você usa o tipo de prompt de conclusão de chat.description
: Uma descrição do que a solicitação faz. Essa descrição pode ser usada pelo kernel para invocar automaticamente a solicitação.input_variables
: Define as variáveis que são usadas dentro da solicitação.execution_settings
: As configurações dos modelos de conclusão. Para modelos do OpenAI, essas configurações incluem as propriedadesmax_tokens
etemperature
.
Por exemplo, suponha que você queira criar um agente tutor de música. Você pode querer oferecer suporte a uma funcionalidade que sugira acordes a serem adicionados a uma progressão de acordes potencial. Nesse caso, o usuário fornece os acordes iniciais e o plug-in recomenda os acordes que seriam adequados.
Para criar esse plug-in, primeiro você criaria uma pasta “Prompts” em seu projeto e, em seguida, uma subpasta chamada “SuggestChords”. Posteriormente, você adiciona os arquivos “skprompt.txt” e “config.json” à pasta “SuggestChords”.
Exemplo de arquivo “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>
Exemplo de arquivo “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
},
]
}
Neste exemplo, o parâmetro temperature
é um parâmetro que controla o quanto randomizar o texto gerado. Os valores devem estar entre 0 e 2. Uma temperatura mais baixa resulta em uma saída mais focada e precisa, enquanto uma temperatura mais alta resulta em uma saída mais diversa e criativa.
No modelo atual, as solicitações podem usar até 4.097 tokens compartilhados entre o envio da solicitação e a conclusão. Isso significa que se a solicitação for de 4.000 tokens, a conclusão do chat poderá ser de no máximo 97 tokens. Você pode encontrar mais informações sobre parâmetros de ajuste fino na documentação do seu LLM.
Para usar o plug-in semântico personalizado, importe o diretório de prompt para o kernel e chame o plug-in pelo nome da pasta. Por exemplo:
var plugins = kernel.CreatePluginFromPromptDirectory("Prompts");
string input = "G, C";
var result = await kernel.InvokeAsync(
plugins["SuggestChords"],
new() {{ "startingChords", input }});
Console.WriteLine(result);
Neste exemplo, CreatePluginFromPromptDirectory
retorna um objeto KernelPlugin
. Este objeto representa uma coleção de funções. CreatePluginFromPromptDirectory
aceita o caminho do diretório do plug-in designado e o nome de cada subpasta é usado como um nome de função.
Por exemplo, se você aninhasse "SuggestChords" dentro de uma pasta chamada "ChordProgressions", você usaria o diretório de prompt "Prompts/ChordProgressions" e o nome da função permaneceria o mesmo. Como alternativa, você pode usar o diretório “Prompt” e fazer referência a “ChordProgressions/SuggestChords” como o nome da função.
// 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);
A execução desse código deve produzir uma resposta semelhante à seguinte saída:
D major, A minor, E minor, B minor, F major, G7
Salvar suas solicitações em arquivos é uma ótima maneira de organizar seu código e torná-lo mais fácil de manter. Os arquivos de configuração também permitem que você ajuste ainda mais suas solicitações para ter uma experiência de usuário mais previsível.