Salvar prompts em arquivos

Concluído

Nas unidades anteriores, você aprendeu como criar prompts reutilizáveis chamando kernel.InvokePromptAsync. Por exemplo:

Console.WriteLine(
    await kernel.InvokePromptAsync(generateNamesOfPrompt, new() {{ "input", "fantasy characters" }})
);

Criar prompts embutidos é útil, mas para projetos maiores, você pode querer organizar seus prompts em arquivos separados e importá-los para o kernel. Isto é semelhante à forma como os plugins incorporados são usados. Para criar seus próprios plug-ins de prompt, uma prática recomendada é criar pastas separadas para seus prompts.''

Como criar plugins semânticos

O SDK do Kernel Semântico suporta uma linguagem de modelagem de prompt com algumas regras de sintaxe simples. Você não precisa escrever código ou importar bibliotecas externas, basta usar as chaves {{...}} para incorporar expressões em seus prompts.

Para criar um plug-in semântico, você precisa de uma pasta contendo dois arquivos: um skprompt.txt arquivo e um config.json arquivo. O skprompt.txt arquivo contém o prompt para o modelo de linguagem grande (LLM), semelhante a todos os prompts que você escreveu até agora. O config.json arquivo contém os detalhes de configuração para o prompt.

O config.json ficheiro suporta os seguintes parâmetros:

  • type: O tipo de prompt. Normalmente, você usa o tipo de prompt de conclusão do chat.
  • description: Uma descrição do que o prompt faz. Esta descrição pode ser usada pelo kernel para invocar automaticamente o prompt.
  • input_variables: Define as variáveis que são usadas dentro do prompt.
  • execution_settings: As configurações para modelos de conclusão. Para modelos OpenAI, essas configurações incluem as max_tokens propriedades e temperature .

Por exemplo, suponha que você queira criar um agente de tutor de música. Você pode querer oferecer suporte a um recurso que sugere acordes para adicionar a uma possível progressão de acordes. Neste caso, o usuário fornece acordes iniciais e o plugin recomenda acordes que seriam um bom ajuste.

Para criar este plugin, você primeiro criaria uma pasta 'Prompts' em seu projeto, depois uma subpasta chamada 'SuggestChords'. Depois, você adiciona os arquivos 'skprompt.txt' e 'config.json' à sua pasta 'SuggestChords'.

Exemplo de ficheiro '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 é um parâmetro que controla temperature o quanto aleatorizar o texto gerado. Os valores devem estar entre 0 e 2. Uma temperatura mais baixa resulta numa saída mais focada e precisa, e uma temperatura mais elevada resulta numa produção mais diversificada e criativa.

No modelo atual, as solicitações podem usar até 4.097 tokens compartilhados entre prompt e conclusão. Isso significa que, se o prompt for de 4.000 tokens, a conclusão do bate-papo pode 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 seu plug-in semântico personalizado, importe o diretório 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 KernelPlugin objeto. Este objeto representa uma coleção de funções. CreatePluginFromPromptDirectory aceita o caminho do diretório de plug-in designado e o nome de cada subpasta é usado como um nome de função.

Por exemplo, se você aninhar '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 seus prompts 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 seus prompts para uma experiência de usuário mais previsível.