Запросы на сохранение в файлы
В предыдущих уроках вы узнали, как создавать повторно используемые запросы путем вызова kernel.InvokePromptAsync
. Например:
Console.WriteLine(
await kernel.InvokePromptAsync(generateNamesOfPrompt, new() {{ "input", "fantasy characters" }})
);
Создание встроенных запросов полезно, но для больших проектов может потребоваться упорядочить запросы в отдельные файлы и импортировать их в ядро. Это аналогично тому, как используются встроенные подключаемые модули. Чтобы создать собственные подключаемые модули запросов, рекомендуется создать отдельные папки для запросов.
Создание семантических подключаемых модулей
Пакет SDK для семантического ядра поддерживает язык шаблонов запроса с некоторыми простыми правилами синтаксиса. Вам не нужно писать код или импортировать внешние библиотеки, просто используйте фигурные скобки {{...}} для внедрения выражений в запросы.
Чтобы создать семантический подключаемый модуль, вам потребуется папка, содержащая два файла: skprompt.txt
файл и config.json
файл. Файл skprompt.txt
содержит запрос на большую языковую модель (LLM), как и все запросы, которые вы написали до сих пор. Файл config.json
содержит сведения о конфигурации запроса.
Файл config.json
поддерживает следующие параметры:
type
: тип запроса. Обычно используется тип запроса завершения чата.description
: описание того, что делает запрос. Это описание может использоваться ядром для автоматического вызова запроса.input_variables
: определяет переменные, используемые внутри запроса.execution_settings
: параметры для моделей завершения. Для моделей OpenAI эти параметры включаютmax_tokens
иtemperature
свойства.
Например, предположим, что вы хотите создать агент музыкального преподавателя. Вы можете поддержать функцию, которая предлагает аккорды, чтобы добавить к потенциальной прогрессии аккордов. В этом случае пользователь предоставляет начальные аккорды и подключаемый модуль рекомендует аккорды, которые будут хорошими.
Чтобы создать этот подключаемый модуль, сначала создайте папку "Запросы" в проекте, а затем вложенную папку "SuggestChords". Затем вы добавите файлы "skprompt.txt" и "config.json" в папку "SuggestChords".
Пример файла 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>
Пример файла 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
},
]
}
В этом примере используется параметр, temperature
который определяет, сколько нужно случайным образом сгенерировать созданный текст. Значения должны быть от 0 до 2. Более низкая температура приводит к более сосредоточенным и точным выходным данным, а более высокая температура приводит к более разнообразным и творческим выходным данным.
В текущей модели запросы могут использовать до 4097 маркеров, общих между запросом и завершением. Это означает, что если запрос составляет 4000 маркеров, завершение чата может быть не более 97 маркеров. Дополнительные сведения о параметрах тонкой настройки см. в документации по LLM.
Чтобы использовать настраиваемый семантический подключаемый модуль, необходимо импортировать каталог запроса в ядро и вызвать подключаемый модуль по имени папки. Например:
var plugins = kernel.CreatePluginFromPromptDirectory("Prompts");
string input = "G, C";
var result = await kernel.InvokeAsync(
plugins["SuggestChords"],
new() {{ "startingChords", input }});
Console.WriteLine(result);
В этом примере CreatePluginFromPromptDirectory
возвращается KernelPlugin
объект. Этот объект представляет коллекцию функций. CreatePluginFromPromptDirectory
принимает путь к указанному каталогу подключаемого модуля, а имя каждой вложенной папки используется в качестве имени функции.
Например, если вы вложены "SuggestChords" в папку с именем "ChordProgressions", используйте каталог запроса "Prompts/ChordProgressions", а имя функции останется неизменным. Кроме того, в качестве имени функции можно использовать каталог "Запрос" и ссылаться на "ChordProgressions/SuggestChordss".
// 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);
При выполнении этого кода должен быть получен ответ, аналогичный следующим выходным данным:
D major, A minor, E minor, B minor, F major, G7
Сохранение запросов на файлы — отличный способ упорядочить код и сделать его более поддерживаемым. Файлы конфигурации также позволяют дополнительно настроить запросы на более прогнозируемое взаимодействие с пользователем.