Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Prompt Templates in Semantic Kernel
An agent's role is primarily shaped by the instructions it receives, which dictate its behavior and actions. Similar to invoking a Kernel
prompt, an agent's instructions can include templated parameters—both values and functions—that are dynamically substituted during execution. This enables flexible, context-aware responses, allowing the agent to adjust its output based on real-time input.
Additionally, an agent can be configured directly using a Prompt Template Configuration, providing developers with a structured and reusable way to define its behavior. This approach offers a powerful tool for standardizing and customizing agent instructions, ensuring consistency across various use cases while still maintaining dynamic adaptability.
Feature currently unavailable in Java.
Agent Instructions as a Template
Creating an agent with template parameters provides greater flexibility by allowing its instructions to be easily customized based on different scenarios or requirements. This approach enables the agent's behavior to be tailored by substituting specific values or functions into the template, making it adaptable to a variety of tasks or contexts. By leveraging template parameters, developers can design more versatile agents that can be configured to meet diverse use cases without needing to modify the core logic.
Chat Completion Agent
// Initialize a Kernel with a chat-completion service
Kernel kernel = ...;
ChatCompletionAgent agent =
new()
{
Kernel = kernel,
Name = "StoryTeller",
Instructions = "Tell a story about {{$topic}} that is {{$length}} sentences long.",
Arguments = new KernelArguments()
{
{ "topic", "Dog" },
{ "length", "3" },
}
};
agent = ChatCompletionAgent(
service=AzureChatCompletion(), # or other supported AI Services
name="StoryTeller",
instructions="Tell a story about {{$topic}} that is {{$length}} sentences long.",
arguments=KernelArguments(topic="Dog", length="2"),
)
Feature currently unavailable in Java.
OpenAI Assistant Agent
Templated instructions are especially powerful when working with an OpenAIAssistantAgent
. With this approach, a single assistant definition can be created and reused multiple times, each time with different parameter values tailored to specific tasks or contexts. This enables a more efficient setup, allowing the same assistant framework to handle a wide range of scenarios while maintaining consistency in its core behavior.
// Retrieve an existing assistant definition by identifier
AzureOpenAIClient client = OpenAIAssistantAgent.CreateAzureOpenAIClient(new AzureCliCredential(), new Uri("<your endpoint>"));
AssistantClient assistantClient = client.GetAssistantClient();
Assistant assistant = await client.GetAssistantAsync();
OpenAIAssistantAgent agent = new(assistant, assistantClient, new KernelPromptTemplateFactory(), PromptTemplateConfig.SemanticKernelTemplateFormat)
{
Arguments = new KernelArguments()
{
{ "topic", "Dog" },
{ "length", "3" },
}
}
# Create the client using Azure OpenAI resources and configuration
client, model = AzureAssistantAgent.setup_resources()
# Retrieve the assistant definition from the server based on the assistant ID
definition = await client.beta.assistants.retrieve(
assistant_id="your-assistant-id",
)
# Create the AzureAssistantAgent instance using the client and the assistant definition
agent = AzureAssistantAgent(
client=client,
definition=definition,
arguments=KernelArguments(topic="Dog", length="3"),
)
Feature currently unavailable in Java.
Agent Definition from a Prompt Template
The same Prompt Template Config used to create a Kernel Prompt Function can also be leveraged to define an agent. This allows for a unified approach in managing both prompts and agents, promoting consistency and reuse across different components. By externalizing agent definitions from the codebase, this method simplifies the management of multiple agents, making them easier to update and maintain without requiring changes to the underlying logic. This separation also enhances flexibility, enabling developers to modify agent behavior or introduce new agents by simply updating the configuration, rather than adjusting the code itself.
YAML Template
name: GenerateStory
template: |
Tell a story about {{$topic}} that is {{$length}} sentences long.
template_format: semantic-kernel
description: A function that generates a story about a topic.
input_variables:
- name: topic
description: The topic of the story.
is_required: true
- name: length
description: The number of sentences in the story.
is_required: true
Agent Initialization
// Read YAML resource
string generateStoryYaml = File.ReadAllText("./GenerateStory.yaml");
// Convert to a prompt template config
PromptTemplateConfig templateConfig = KernelFunctionYaml.ToPromptTemplateConfig(generateStoryYaml);
// Create agent with Instructions, Name and Description
// provided by the template config.
ChatCompletionAgent agent =
new(templateConfig)
{
Kernel = this.CreateKernelWithChatCompletion(),
// Provide default values for template parameters
Arguments = new KernelArguments()
{
{ "topic", "Dog" },
{ "length", "3" },
}
};
import yaml
from semantic_kernel.prompt_template import PromptTemplateConfig
# Read the YAML file
with open("./GenerateStory.yaml", "r", encoding="utf-8") as file:
generate_story_yaml = file.read()
# Parse the YAML content
data = yaml.safe_load(generate_story_yaml)
# Use the parsed data to create a PromptTemplateConfig object
prompt_template_config = PromptTemplateConfig(**data)
agent = ChatCompletionAgent(
service=AzureChatCompletion(), # or other supported AI services
prompt_template_config=prompt_template_config,
arguments=KernelArguments(topic="Dog", length="3"),
)
Feature currently unavailable in Java.
Overriding Template Values for Direct Invocation
When invoking an agent directly, the agent's parameters can be overridden as needed. This allows for greater control and customization of the agent's behavior during specific tasks, enabling you to modify its instructions or settings on the fly to suit particular requirements.
// Initialize a Kernel with a chat-completion service
Kernel kernel = ...;
ChatCompletionAgent agent =
new()
{
Kernel = kernel,
Name = "StoryTeller",
Instructions = "Tell a story about {{$topic}} that is {{$length}} sentences long.",
Arguments = new KernelArguments()
{
{ "topic", "Dog" },
{ "length", "3" },
}
};
KernelArguments overrideArguments =
new()
{
{ "topic", "Cat" },
{ "length", "3" },
});
// Generate the agent response(s)
await foreach (ChatMessageContent response in agent.InvokeAsync([], options: new() { KernelArguments = overrideArguments }))
{
// Process agent response(s)...
}
agent = ChatCompletionAgent(
service=AzureChatCompletion(),
name="StoryTeller",
instructions="Tell a story about {{$topic}} that is {{$length}} sentences long.",
arguments=KernelArguments(topic="Dog", length="2"),
)
# Create a thread to maintain the conversation state
# If no threaded is created, a thread will be returned
# with the initial response
thread = None
override_arguments = KernelArguments(topic="Cat", length="3")
# Two ways to get a response from the agent
# Get the response which returns a ChatMessageContent directly
response = await agent.get_response(messages="user input", arguments=override_arguments)
thread = response.thread
# or use the invoke method to return an AsyncIterable of ChatMessageContent
async for response in agent.invoke(messages="user input", arguments=override_arguments):
# process agent response(s)...
thread = response.thread
Feature currently unavailable in Java.
How-To
For an end-to-end example for creating an agent from a prompt-template, see: