chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
# Chat Completion Agents
|
||||
|
||||
The following samples demonstrate how to get started with Chat Completion Agents using Semantic Kernel.
|
||||
|
||||
## Configuring a Chat Completion Agent
|
||||
|
||||
The `ChatCompletionAgent` relies on an underlying AI service connector. Depending on the AI service you choose, you may need to install additional packages. Refer to the [official SK documentation](https://learn.microsoft.com/en-us/semantic-kernel/concepts/ai-services/chat-completion/?tabs=csharp-AzureOpenAI%2Cpython-AzureOpenAI%2Cjava-AzureOpenAI&pivots=programming-language-python#installing-the-necessary-packages-1) for guidance on which extras are required.
|
||||
|
||||
Next, follow this [configuration guide](../../concepts/README.md#configuring-the-kernel) to set up your environment for running the sample code.
|
||||
|
||||
If you're developing outside the Semantic Kernel repository, it's recommended to place your `.env` file at the root of your project. When using VSCode, this allows the IDE to automatically load the `.env` file and make the environment variables available to your application.
|
||||
|
||||
This setup enables the following code to work without explicitly passing keyword arguments to the AI service constructor:
|
||||
|
||||
```python
|
||||
from semantic_kernel.agents import ChatCompletionAgent
|
||||
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
|
||||
|
||||
agent = ChatCompletionAgent(
|
||||
service=AzureChatCompletion(), # No explicit kwargs needed due to environment variable configuration
|
||||
name="Assistant",
|
||||
instructions="Answer questions about the world in one sentence.",
|
||||
)
|
||||
```
|
||||
|
||||
If you prefer to configure the service manually, you can do the following:
|
||||
|
||||
```python
|
||||
from semantic_kernel.agents import ChatCompletionAgent
|
||||
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
|
||||
|
||||
agent = ChatCompletionAgent(
|
||||
service=AzureChatCompletion(
|
||||
api_key="your-api-key",
|
||||
endpoint="your-aoai-endpoint",
|
||||
deployment_name="your-deployment-name",
|
||||
api_version="2025-03-01-preview" # Replace with your desired API version
|
||||
),
|
||||
name="Assistant",
|
||||
instructions="Answer questions about the world in one sentence.",
|
||||
)
|
||||
```
|
||||
|
||||
For more information about the `ChatCompletionAgent` see Semantic Kernel's official documentation [here](https://learn.microsoft.com/en-us/semantic-kernel/frameworks/agent/chat-completion-agent?pivots=programming-language-python).
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import ChatCompletionAgent
|
||||
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create a chat completion agent that
|
||||
answers user questions using the Azure Chat Completion service. The Chat Completion
|
||||
Service is passed directly via the ChatCompletionAgent constructor. This sample
|
||||
demonstrates the basic steps to create an agent and simulate a conversation
|
||||
with the agent.
|
||||
|
||||
The interaction with the agent is via the `get_response` method, which sends a
|
||||
user input to the agent and receives a response from the agent.
|
||||
"""
|
||||
|
||||
# Simulate a conversation with the agent
|
||||
USER_INPUTS = [
|
||||
"Why is the sky blue?",
|
||||
"What is the capital of France?",
|
||||
]
|
||||
|
||||
|
||||
async def main():
|
||||
# 1. Create the agent by specifying the service
|
||||
agent = ChatCompletionAgent(
|
||||
service=AzureChatCompletion(credential=AzureCliCredential()),
|
||||
name="Assistant",
|
||||
instructions="Answer questions about the world in one sentence.",
|
||||
)
|
||||
|
||||
for user_input in USER_INPUTS:
|
||||
print(f"# User: {user_input}")
|
||||
# 2. Invoke the agent for a response
|
||||
response = await agent.get_response(
|
||||
messages=user_input,
|
||||
)
|
||||
# 3. Print the response
|
||||
print(f"# {response.name}: {response}")
|
||||
|
||||
"""
|
||||
Sample output:
|
||||
# User: Why is the sky blue?
|
||||
# Assistant: The sky appears blue because molecules in the Earth's atmosphere scatter shorter wavelengths of
|
||||
sunlight, like blue, more than the longer wavelengths, causing the sky to look blue to our eyes.
|
||||
# User: What is the capital of France?
|
||||
# Assistant: The capital of France is Paris.
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import (
|
||||
ChatCompletionAgent,
|
||||
ChatHistoryAgentThread,
|
||||
)
|
||||
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create a chat completion agent that
|
||||
answers user questions using the Azure Chat Completion service. The Chat Completion
|
||||
Service is passed directly via the ChatCompletionAgent constructor. This sample
|
||||
demonstrates the basic steps to create an agent and simulate a conversation
|
||||
with the agent.
|
||||
|
||||
The interaction with the agent is via the `get_response` method, which sends a
|
||||
user input to the agent and receives a response from the agent. The conversation
|
||||
history needs to be maintained by the caller in the chat history object.
|
||||
"""
|
||||
|
||||
# Simulate a conversation with the agent
|
||||
USER_INPUTS = [
|
||||
"Hello, I am John Doe.",
|
||||
"What is your name?",
|
||||
"What is my name?",
|
||||
]
|
||||
|
||||
|
||||
async def main():
|
||||
# 1. Create the agent by specifying the service
|
||||
agent = ChatCompletionAgent(
|
||||
service=AzureChatCompletion(credential=AzureCliCredential()),
|
||||
name="Assistant",
|
||||
instructions="Answer the user's questions.",
|
||||
)
|
||||
|
||||
# 2. Create a thread to hold the conversation
|
||||
# If no thread is provided, a new thread will be
|
||||
# created and returned with the initial response
|
||||
thread: ChatHistoryAgentThread = None
|
||||
|
||||
for user_input in USER_INPUTS:
|
||||
print(f"# User: {user_input}")
|
||||
# 3. Invoke the agent for a response
|
||||
response = await agent.get_response(
|
||||
messages=user_input,
|
||||
thread=thread,
|
||||
)
|
||||
print(f"# {response.name}: {response}")
|
||||
# 4. Store the thread, which allows the agent to
|
||||
# maintain conversation history across multiple messages.
|
||||
thread = response.thread
|
||||
|
||||
# 5. Cleanup: Clear the thread
|
||||
await thread.delete() if thread else None
|
||||
|
||||
"""
|
||||
Sample output:
|
||||
# User: Hello, I am John Doe.
|
||||
# Assistant: Hello, John Doe! How can I assist you today?
|
||||
# User: What is your name?
|
||||
# Assistant: I don't have a personal name like a human does, but you can call me Assistant.?
|
||||
# User: What is my name?
|
||||
# Assistant: You mentioned that your name is John Doe. How can I assist you further, John?
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
from semantic_kernel import Kernel
|
||||
from semantic_kernel.agents import ChatCompletionAgent, ChatHistoryAgentThread
|
||||
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create a chat completion agent that
|
||||
answers user questions using the Azure Chat Completion service. The Chat Completion
|
||||
Service is first added to the kernel, and the kernel is passed in to the
|
||||
ChatCompletionAgent constructor. This sample demonstrates the basic steps to
|
||||
create an agent and simulate a conversation with the agent.
|
||||
|
||||
Note: if both a service and a kernel are provided, the service will be used.
|
||||
|
||||
The interaction with the agent is via the `get_response` method, which sends a
|
||||
user input to the agent and receives a response from the agent. The conversation
|
||||
history needs to be maintained by the caller in the chat history object.
|
||||
"""
|
||||
|
||||
# Simulate a conversation with the agent
|
||||
USER_INPUTS = [
|
||||
"Hello, I am John Doe.",
|
||||
"What is your name?",
|
||||
"What is my name?",
|
||||
]
|
||||
|
||||
|
||||
async def main():
|
||||
# 1. Create the instance of the Kernel to register an AI service
|
||||
kernel = Kernel()
|
||||
kernel.add_service(AzureChatCompletion(credential=AzureCliCredential()))
|
||||
|
||||
# 2. Create the agent
|
||||
agent = ChatCompletionAgent(
|
||||
kernel=kernel,
|
||||
name="Assistant",
|
||||
instructions="Answer the user's questions.",
|
||||
)
|
||||
|
||||
# 3. Create a thread to hold the conversation
|
||||
# If no thread is provided, a new thread will be
|
||||
# created and returned with the initial response
|
||||
thread: ChatHistoryAgentThread = None
|
||||
|
||||
for user_input in USER_INPUTS:
|
||||
print(f"# User: {user_input}")
|
||||
# 4. Invoke the agent for a response
|
||||
response = await agent.get_response(
|
||||
messages=user_input,
|
||||
thread=thread,
|
||||
)
|
||||
print(f"# {response.name}: {response}")
|
||||
thread = response.thread
|
||||
|
||||
# 4. Cleanup: Clear the thread
|
||||
await thread.delete() if thread else None
|
||||
|
||||
"""
|
||||
Sample output:
|
||||
# User: Hello, I am John Doe.
|
||||
# Assistant: Hello, John Doe! How can I assist you today?
|
||||
# User: What is your name?
|
||||
# Assistant: I don't have a personal name like a human does, but you can call me Assistant.?
|
||||
# User: What is my name?
|
||||
# Assistant: You mentioned that your name is John Doe. How can I assist you further, John?
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
from typing import Annotated
|
||||
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import ChatCompletionAgent, ChatHistoryAgentThread
|
||||
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
|
||||
from semantic_kernel.functions import kernel_function
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create a chat completion agent that
|
||||
answers questions about a sample menu using a Semantic Kernel Plugin. The Chat
|
||||
Completion Service is passed directly via the ChatCompletionAgent constructor.
|
||||
Additionally, the plugin is supplied via the constructor.
|
||||
"""
|
||||
|
||||
|
||||
# Define a sample plugin for the sample
|
||||
class MenuPlugin:
|
||||
"""A sample Menu Plugin used for the concept sample."""
|
||||
|
||||
@kernel_function(description="Provides a list of specials from the menu.")
|
||||
def get_specials(self) -> Annotated[str, "Returns the specials from the menu."]:
|
||||
return """
|
||||
Special Soup: Clam Chowder
|
||||
Special Salad: Cobb Salad
|
||||
Special Drink: Chai Tea
|
||||
"""
|
||||
|
||||
@kernel_function(description="Provides the price of the requested menu item.")
|
||||
def get_item_price(
|
||||
self, menu_item: Annotated[str, "The name of the menu item."]
|
||||
) -> Annotated[str, "Returns the price of the menu item."]:
|
||||
return "$9.99"
|
||||
|
||||
|
||||
# Simulate a conversation with the agent
|
||||
USER_INPUTS = [
|
||||
"Hello",
|
||||
"What is the special soup?",
|
||||
"What does that cost?",
|
||||
"Thank you",
|
||||
]
|
||||
|
||||
|
||||
async def main():
|
||||
# 1. Create the agent
|
||||
agent = ChatCompletionAgent(
|
||||
service=AzureChatCompletion(credential=AzureCliCredential()),
|
||||
name="Host",
|
||||
instructions="Answer questions about the menu.",
|
||||
plugins=[MenuPlugin()],
|
||||
)
|
||||
|
||||
# 2. Create a thread to hold the conversation
|
||||
# If no thread is provided, a new thread will be
|
||||
# created and returned with the initial response
|
||||
thread: ChatHistoryAgentThread = None
|
||||
|
||||
for user_input in USER_INPUTS:
|
||||
print(f"# User: {user_input}")
|
||||
# 4. Invoke the agent for a response
|
||||
response = await agent.get_response(messages=user_input, thread=thread)
|
||||
print(f"# {response.name}: {response} ")
|
||||
thread = response.thread
|
||||
|
||||
# 4. Cleanup: Clear the thread
|
||||
await thread.delete() if thread else None
|
||||
|
||||
"""
|
||||
Sample output:
|
||||
# User: Hello
|
||||
# Host: Hello! How can I assist you today?
|
||||
# User: What is the special soup?
|
||||
# Host: The special soup is Clam Chowder.
|
||||
# User: What does that cost?
|
||||
# Host: The special soup, Clam Chowder, costs $9.99.
|
||||
# User: Thank you
|
||||
# Host: You're welcome! If you have any more questions, feel free to ask. Enjoy your day!
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
from typing import Annotated
|
||||
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
from semantic_kernel import Kernel
|
||||
from semantic_kernel.agents import ChatCompletionAgent, ChatHistoryAgentThread
|
||||
from semantic_kernel.connectors.ai import FunctionChoiceBehavior
|
||||
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
|
||||
from semantic_kernel.functions import KernelArguments, kernel_function
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create a chat completion agent that
|
||||
answers questions about a sample menu using a Semantic Kernel Plugin. The Chat
|
||||
Completion Service is first added to the kernel, and the kernel is passed in to the
|
||||
ChatCompletionAgent constructor. Additionally, the plugin is supplied via the kernel.
|
||||
To enable auto-function calling, the prompt execution settings are retrieved from the kernel
|
||||
using the specified `service_id`. The function choice behavior is set to `Auto` to allow the
|
||||
agent to automatically execute the plugin's functions when needed.
|
||||
"""
|
||||
|
||||
|
||||
# Define a sample plugin for the sample
|
||||
class MenuPlugin:
|
||||
"""A sample Menu Plugin used for the concept sample."""
|
||||
|
||||
@kernel_function(description="Provides a list of specials from the menu.")
|
||||
def get_specials(self) -> Annotated[str, "Returns the specials from the menu."]:
|
||||
return """
|
||||
Special Soup: Clam Chowder
|
||||
Special Salad: Cobb Salad
|
||||
Special Drink: Chai Tea
|
||||
"""
|
||||
|
||||
@kernel_function(description="Provides the price of the requested menu item.")
|
||||
def get_item_price(
|
||||
self, menu_item: Annotated[str, "The name of the menu item."]
|
||||
) -> Annotated[str, "Returns the price of the menu item."]:
|
||||
return "$9.99"
|
||||
|
||||
|
||||
# Simulate a conversation with the agent
|
||||
USER_INPUTS = [
|
||||
"Hello",
|
||||
"What is the special soup?",
|
||||
"What does that cost?",
|
||||
"Thank you",
|
||||
]
|
||||
|
||||
|
||||
async def main():
|
||||
# 1. Create the instance of the Kernel to register the plugin and service
|
||||
service_id = "agent"
|
||||
kernel = Kernel()
|
||||
kernel.add_plugin(MenuPlugin(), plugin_name="menu")
|
||||
kernel.add_service(AzureChatCompletion(service_id=service_id, credential=AzureCliCredential()))
|
||||
|
||||
# 2. Configure the function choice behavior to auto invoke kernel functions
|
||||
# so that the agent can automatically execute the menu plugin functions when needed
|
||||
settings = kernel.get_prompt_execution_settings_from_service_id(service_id=service_id)
|
||||
settings.function_choice_behavior = FunctionChoiceBehavior.Auto()
|
||||
|
||||
# 3. Create the agent
|
||||
agent = ChatCompletionAgent(
|
||||
kernel=kernel,
|
||||
name="Host",
|
||||
instructions="Answer questions about the menu.",
|
||||
arguments=KernelArguments(settings=settings),
|
||||
)
|
||||
|
||||
# 4. Create a thread to hold the conversation
|
||||
# If no thread is provided, a new thread will be
|
||||
# created and returned with the initial response
|
||||
thread: ChatHistoryAgentThread = None
|
||||
|
||||
for user_input in USER_INPUTS:
|
||||
print(f"# User: {user_input}")
|
||||
# 5. Invoke the agent for a response
|
||||
async for response in agent.invoke(messages=user_input, thread=thread):
|
||||
print(f"# {response.name}: {response}")
|
||||
thread = response.thread
|
||||
|
||||
# 6. Cleanup: Clear the thread
|
||||
await thread.delete() if thread else None
|
||||
|
||||
"""
|
||||
Sample output:
|
||||
# User: Hello
|
||||
# Host: Hello! How can I assist you today?
|
||||
# User: What is the special soup?
|
||||
# Host: The special soup is Clam Chowder.
|
||||
# User: What does that cost?
|
||||
# Host: The special soup, Clam Chowder, costs $9.99.
|
||||
# User: Thank you
|
||||
# Host: You're welcome! If you have any more questions, feel free to ask. Enjoy your day!
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
from semantic_kernel import Kernel
|
||||
from semantic_kernel.agents import AgentGroupChat, ChatCompletionAgent
|
||||
from semantic_kernel.agents.strategies import TerminationStrategy
|
||||
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create a simple, agent group chat that
|
||||
utilizes An Art Director Chat Completion Agent along with a Copy Writer Chat
|
||||
Completion Agent to complete a task.
|
||||
|
||||
Note: This sample use the `AgentGroupChat` feature of Semantic Kernel, which is
|
||||
no longer maintained. For a replacement, consider using the `GroupChatOrchestration`.
|
||||
|
||||
Read more about the `GroupChatOrchestration` here:
|
||||
https://learn.microsoft.com/semantic-kernel/frameworks/agent/agent-orchestration/group-chat?pivots=programming-language-python
|
||||
|
||||
Here is a migration guide from `AgentGroupChat` to `GroupChatOrchestration`:
|
||||
https://learn.microsoft.com/semantic-kernel/support/migration/group-chat-orchestration-migration-guide?pivots=programming-language-python
|
||||
"""
|
||||
|
||||
|
||||
def _create_kernel_with_chat_completion(service_id: str) -> Kernel:
|
||||
kernel = Kernel()
|
||||
kernel.add_service(AzureChatCompletion(service_id=service_id, credential=AzureCliCredential()))
|
||||
return kernel
|
||||
|
||||
|
||||
class ApprovalTerminationStrategy(TerminationStrategy):
|
||||
"""A strategy for determining when an agent should terminate."""
|
||||
|
||||
async def should_agent_terminate(self, agent, history):
|
||||
"""Check if the agent should terminate."""
|
||||
last_message = history[-1].content.lower()
|
||||
return "approved" in last_message and "not approved" not in last_message
|
||||
|
||||
|
||||
REVIEWER_NAME = "ArtDirector"
|
||||
REVIEWER_INSTRUCTIONS = """
|
||||
You are an art director who has opinions about copywriting born of a love for David Ogilvy.
|
||||
The goal is to determine if the given copy is acceptable to print.
|
||||
If so, state that it is approved.
|
||||
If not, provide insight on how to refine suggested copy without example.
|
||||
"""
|
||||
|
||||
COPYWRITER_NAME = "CopyWriter"
|
||||
COPYWRITER_INSTRUCTIONS = """
|
||||
You are a copywriter with ten years of experience and are known for brevity and a dry humor.
|
||||
The goal is to refine and decide on the single best copy as an expert in the field.
|
||||
Only provide a single proposal per response.
|
||||
You're laser focused on the goal at hand.
|
||||
Don't waste time with chit chat.
|
||||
Consider suggestions when refining an idea.
|
||||
"""
|
||||
|
||||
TASK = "a slogan for a new line of electric cars."
|
||||
|
||||
|
||||
async def main():
|
||||
# 1. Create the reviewer agent based on the chat completion service
|
||||
agent_reviewer = ChatCompletionAgent(
|
||||
kernel=_create_kernel_with_chat_completion("artdirector"),
|
||||
name=REVIEWER_NAME,
|
||||
instructions=REVIEWER_INSTRUCTIONS,
|
||||
)
|
||||
|
||||
# 2. Create the copywriter agent based on the chat completion service
|
||||
agent_writer = ChatCompletionAgent(
|
||||
kernel=_create_kernel_with_chat_completion("copywriter"),
|
||||
name=COPYWRITER_NAME,
|
||||
instructions=COPYWRITER_INSTRUCTIONS,
|
||||
)
|
||||
|
||||
# 3. Place the agents in a group chat with a custom termination strategy
|
||||
group_chat = AgentGroupChat(
|
||||
agents=[
|
||||
agent_writer,
|
||||
agent_reviewer,
|
||||
],
|
||||
termination_strategy=ApprovalTerminationStrategy(
|
||||
agents=[agent_reviewer],
|
||||
maximum_iterations=10,
|
||||
),
|
||||
)
|
||||
|
||||
# 4. Add the task as a message to the group chat
|
||||
await group_chat.add_chat_message(message=TASK)
|
||||
print(f"# User: {TASK}")
|
||||
|
||||
# 5. Invoke the chat
|
||||
async for content in group_chat.invoke():
|
||||
print(f"# {content.name}: {content.content}")
|
||||
|
||||
"""
|
||||
Sample output:
|
||||
# User: a slogan for a new line of electric cars.
|
||||
# CopyWriter: "Drive the Future: Shockingly Efficient."
|
||||
# ArtDirector: This slogan has potential but could benefit from refinement to create a stronger ...
|
||||
# CopyWriter: "Electrify Your Drive."
|
||||
# ArtDirector: Approved. This slogan is concise, memorable, and effectively communicates the ...
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+145
@@ -0,0 +1,145 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
from semantic_kernel import Kernel
|
||||
from semantic_kernel.agents import AgentGroupChat, ChatCompletionAgent
|
||||
from semantic_kernel.agents.strategies import KernelFunctionSelectionStrategy, KernelFunctionTerminationStrategy
|
||||
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
|
||||
from semantic_kernel.functions import KernelFunctionFromPrompt
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create a simple, agent group chat that utilizes
|
||||
An Art Director Chat Completion Agent along with a Copy Writer Chat Completion Agent to
|
||||
complete a task. The sample also shows how to specify a Kernel Function termination and
|
||||
selection strategy to determine when to end the chat or how to select the next agent to
|
||||
take a turn in the conversation.
|
||||
|
||||
Note: This sample use the `AgentGroupChat` feature of Semantic Kernel, which is
|
||||
no longer maintained. For a replacement, consider using the `GroupChatOrchestration`.
|
||||
|
||||
Read more about the `GroupChatOrchestration` here:
|
||||
https://learn.microsoft.com/semantic-kernel/frameworks/agent/agent-orchestration/group-chat?pivots=programming-language-python
|
||||
|
||||
Here is a migration guide from `AgentGroupChat` to `GroupChatOrchestration`:
|
||||
https://learn.microsoft.com/semantic-kernel/support/migration/group-chat-orchestration-migration-guide?pivots=programming-language-python
|
||||
"""
|
||||
|
||||
|
||||
def _create_kernel_with_chat_completion(service_id: str) -> Kernel:
|
||||
kernel = Kernel()
|
||||
kernel.add_service(AzureChatCompletion(service_id=service_id, credential=AzureCliCredential()))
|
||||
return kernel
|
||||
|
||||
|
||||
REVIEWER_NAME = "ArtDirector"
|
||||
REVIEWER_INSTRUCTIONS = """
|
||||
You are an art director who has opinions about copywriting born of a love for David Ogilvy.
|
||||
The goal is to determine if the given copy is acceptable to print.
|
||||
If so, state that it is approved.
|
||||
If not, provide insight on how to refine suggested copy without example.
|
||||
"""
|
||||
|
||||
COPYWRITER_NAME = "CopyWriter"
|
||||
COPYWRITER_INSTRUCTIONS = """
|
||||
You are a copywriter with ten years of experience and are known for brevity and a dry humor.
|
||||
The goal is to refine and decide on the single best copy as an expert in the field.
|
||||
Only provide a single proposal per response.
|
||||
You're laser focused on the goal at hand.
|
||||
Don't waste time with chit chat.
|
||||
Consider suggestions when refining an idea.
|
||||
"""
|
||||
|
||||
TASK = "a slogan for a new line of electric cars."
|
||||
|
||||
|
||||
async def main():
|
||||
# 1. Create the reviewer agent based on the chat completion service
|
||||
agent_reviewer = ChatCompletionAgent(
|
||||
kernel=_create_kernel_with_chat_completion("artdirector"),
|
||||
name=REVIEWER_NAME,
|
||||
instructions=REVIEWER_INSTRUCTIONS,
|
||||
)
|
||||
|
||||
# 2. Create the copywriter agent based on the chat completion service
|
||||
agent_writer = ChatCompletionAgent(
|
||||
kernel=_create_kernel_with_chat_completion("copywriter"),
|
||||
name=COPYWRITER_NAME,
|
||||
instructions=COPYWRITER_INSTRUCTIONS,
|
||||
)
|
||||
|
||||
# 3. Create a Kernel Function to determine if the copy has been approved
|
||||
termination_function = KernelFunctionFromPrompt(
|
||||
function_name="termination",
|
||||
prompt="""
|
||||
Determine if the copy has been approved. If so, respond with a single word: yes
|
||||
|
||||
History:
|
||||
{{$history}}
|
||||
""",
|
||||
)
|
||||
|
||||
# 4. Create a Kernel Function to determine which agent should take the next turn
|
||||
selection_function = KernelFunctionFromPrompt(
|
||||
function_name="selection",
|
||||
prompt=f"""
|
||||
Determine which participant takes the next turn in a conversation based on the the most recent participant.
|
||||
State only the name of the participant to take the next turn.
|
||||
No participant should take more than one turn in a row.
|
||||
|
||||
Choose only from these participants:
|
||||
- {REVIEWER_NAME}
|
||||
- {COPYWRITER_NAME}
|
||||
|
||||
Always follow these rules when selecting the next participant:
|
||||
- After user input, it is {COPYWRITER_NAME}'s turn.
|
||||
- After {COPYWRITER_NAME} replies, it is {REVIEWER_NAME}'s turn.
|
||||
- After {REVIEWER_NAME} provides feedback, it is {COPYWRITER_NAME}'s turn.
|
||||
|
||||
History:
|
||||
{{{{$history}}}}
|
||||
""",
|
||||
)
|
||||
|
||||
# 5. Place the agents in a group chat with the custom termination and selection strategies
|
||||
chat = AgentGroupChat(
|
||||
agents=[agent_writer, agent_reviewer],
|
||||
termination_strategy=KernelFunctionTerminationStrategy(
|
||||
agents=[agent_reviewer],
|
||||
function=termination_function,
|
||||
kernel=_create_kernel_with_chat_completion("termination"),
|
||||
result_parser=lambda result: str(result.value[0]).lower() == "yes",
|
||||
history_variable_name="history",
|
||||
maximum_iterations=10,
|
||||
),
|
||||
selection_strategy=KernelFunctionSelectionStrategy(
|
||||
function=selection_function,
|
||||
kernel=_create_kernel_with_chat_completion("selection"),
|
||||
result_parser=lambda result: str(result.value[0]) if result.value is not None else COPYWRITER_NAME,
|
||||
agent_variable_name="agents",
|
||||
history_variable_name="history",
|
||||
),
|
||||
)
|
||||
|
||||
# 6. Add the task as a message to the group chat
|
||||
await chat.add_chat_message(message=TASK)
|
||||
print(f"# User: {TASK}")
|
||||
|
||||
# 7. Invoke the chat
|
||||
async for content in chat.invoke():
|
||||
print(f"# {content.name}: {content.content}")
|
||||
|
||||
"""
|
||||
Sample Output:
|
||||
# User: a slogan for a new line of electric cars.
|
||||
# CopyWriter: "Electrify your drive. Spare the gas, not the thrill."
|
||||
# ArtDirector: This slogan captures the essence of electric cars but could use refinement to ...
|
||||
# CopyWriter: "Go electric. Enjoy the thrill. Skip the gas."
|
||||
# ArtDirector: Approved. This slogan is clear, concise, and effectively communicates the ...
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
|
||||
from pydantic import BaseModel, ValidationError
|
||||
|
||||
from semantic_kernel import Kernel
|
||||
from semantic_kernel.agents import AgentGroupChat, ChatCompletionAgent
|
||||
from semantic_kernel.agents.strategies import TerminationStrategy
|
||||
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion, OpenAIChatPromptExecutionSettings
|
||||
from semantic_kernel.functions import KernelArguments
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to configure an Agent Group Chat, and invoke an
|
||||
agent with only a single turn.A custom termination strategy is provided where the model
|
||||
is to rate the user input on creativity and expressiveness and end the chat when a score
|
||||
of 70 or higher is provided.
|
||||
|
||||
Note: This sample use the `AgentGroupChat` feature of Semantic Kernel, which is
|
||||
no longer maintained. For a replacement, consider using the `GroupChatOrchestration`.
|
||||
|
||||
Read more about the `GroupChatOrchestration` here:
|
||||
https://learn.microsoft.com/semantic-kernel/frameworks/agent/agent-orchestration/group-chat?pivots=programming-language-python
|
||||
|
||||
Here is a migration guide from `AgentGroupChat` to `GroupChatOrchestration`:
|
||||
https://learn.microsoft.com/semantic-kernel/support/migration/group-chat-orchestration-migration-guide?pivots=programming-language-python
|
||||
"""
|
||||
|
||||
|
||||
def _create_kernel_with_chat_completion(service_id: str) -> Kernel:
|
||||
kernel = Kernel()
|
||||
kernel.add_service(OpenAIChatCompletion(service_id=service_id))
|
||||
return kernel
|
||||
|
||||
|
||||
class InputScore(BaseModel):
|
||||
"""A model for the input score."""
|
||||
|
||||
score: int
|
||||
notes: str
|
||||
|
||||
|
||||
class ThresholdTerminationStrategy(TerminationStrategy):
|
||||
"""A strategy for determining when an agent should terminate."""
|
||||
|
||||
threshold: int = 70
|
||||
|
||||
async def should_agent_terminate(self, agent, history):
|
||||
"""Check if the agent should terminate."""
|
||||
try:
|
||||
result = InputScore.model_validate_json(history[-1].content or "")
|
||||
return result.score >= self.threshold
|
||||
except ValidationError:
|
||||
return False
|
||||
|
||||
|
||||
INSTRUCTION = """
|
||||
Think step-by-step and rate the user input on creativity and expressiveness from 1-100 with some notes on improvements.
|
||||
"""
|
||||
|
||||
# Simulate a conversation with the agent
|
||||
USER_INPUTS = {
|
||||
"The sunset is very colorful.",
|
||||
"The sunset is setting over the mountains.",
|
||||
"The sunset is setting over the mountains and fills the sky with a deep red flame, setting the clouds ablaze.",
|
||||
}
|
||||
|
||||
|
||||
async def main():
|
||||
# 1. Create the instance of the Kernel to register a service
|
||||
service_id = "agent"
|
||||
kernel = _create_kernel_with_chat_completion(service_id)
|
||||
|
||||
# 2. Configure the prompt execution settings to return the score in the desired format
|
||||
settings = kernel.get_prompt_execution_settings_from_service_id(service_id)
|
||||
assert isinstance(settings, OpenAIChatPromptExecutionSettings) # nosec
|
||||
settings.response_format = InputScore
|
||||
|
||||
# 3. Create the agent
|
||||
agent = ChatCompletionAgent(
|
||||
kernel=kernel,
|
||||
name="Tutor",
|
||||
instructions=INSTRUCTION,
|
||||
arguments=KernelArguments(settings),
|
||||
)
|
||||
|
||||
# 4. Create the group chat with the custom termination strategy
|
||||
group_chat = AgentGroupChat(termination_strategy=ThresholdTerminationStrategy(maximum_iterations=10))
|
||||
|
||||
for user_input in USER_INPUTS:
|
||||
# 5. Add the user input to the chat history
|
||||
await group_chat.add_chat_message(message=user_input)
|
||||
print(f"# User: {user_input}")
|
||||
|
||||
# 6. Invoke the chat with the agent for a response
|
||||
async for content in group_chat.invoke_single_turn(agent):
|
||||
print(f"# {content.name}: {content.content}")
|
||||
|
||||
"""
|
||||
Sample output:
|
||||
# User: The sunset is very colorful.
|
||||
# Tutor: {"score":45,"notes":"The sentence 'The sunset is very colorful' is simple and direct. While it ..."}
|
||||
# User: The sunset is setting over the mountains.
|
||||
# Tutor: {"score":50,"notes":"This sentence provides a basic scene of a sunset over mountains, which ..."}
|
||||
# User: The sunset is setting over the mountains and fills the sky with a deep red flame, setting the clouds ablaze.
|
||||
# Tutor: {"score":75,"notes":"This sentence demonstrates improved creativity and expressiveness by ..."}
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
from semantic_kernel import Kernel
|
||||
from semantic_kernel.agents import AgentGroupChat, ChatCompletionAgent
|
||||
from semantic_kernel.agents.strategies import TerminationStrategy
|
||||
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create a simple, agent group chat that
|
||||
utilizes An Art Director Chat Completion Agent along with a Copy Writer Chat
|
||||
Completion Agent to complete a task. The main point of this sample is to note
|
||||
how to enable logging to view all interactions between the agents and the model.
|
||||
|
||||
Note: This sample use the `AgentGroupChat` feature of Semantic Kernel, which is
|
||||
no longer maintained. For a replacement, consider using the `GroupChatOrchestration`.
|
||||
|
||||
Read more about the `GroupChatOrchestration` here:
|
||||
https://learn.microsoft.com/semantic-kernel/frameworks/agent/agent-orchestration/group-chat?pivots=programming-language-python
|
||||
|
||||
Here is a migration guide from `AgentGroupChat` to `GroupChatOrchestration`:
|
||||
https://learn.microsoft.com/semantic-kernel/support/migration/group-chat-orchestration-migration-guide?pivots=programming-language-python
|
||||
"""
|
||||
|
||||
# 0. Enable logging
|
||||
# NOTE: This is all that is required to enable logging.
|
||||
# Set the desired level to INFO, DEBUG, etc.
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
|
||||
class ApprovalTerminationStrategy(TerminationStrategy):
|
||||
"""A strategy for determining when an agent should terminate."""
|
||||
|
||||
async def should_agent_terminate(self, agent, history):
|
||||
"""Check if the agent should terminate."""
|
||||
return "approved" in history[-1].content.lower()
|
||||
|
||||
|
||||
def _create_kernel_with_chat_completion(service_id: str) -> Kernel:
|
||||
kernel = Kernel()
|
||||
kernel.add_service(AzureChatCompletion(service_id=service_id, credential=AzureCliCredential()))
|
||||
return kernel
|
||||
|
||||
|
||||
REVIEWER_NAME = "ArtDirector"
|
||||
REVIEWER_INSTRUCTIONS = """
|
||||
You are an art director who has opinions about copywriting born of a love for David Ogilvy.
|
||||
The goal is to determine if the given copy is acceptable to print.
|
||||
If so, state that it is approved.
|
||||
If not, provide insight on how to refine suggested copy without example.
|
||||
"""
|
||||
|
||||
COPYWRITER_NAME = "CopyWriter"
|
||||
COPYWRITER_INSTRUCTIONS = """
|
||||
You are a copywriter with ten years of experience and are known for brevity and a dry humor.
|
||||
The goal is to refine and decide on the single best copy as an expert in the field.
|
||||
Only provide a single proposal per response.
|
||||
You're laser focused on the goal at hand.
|
||||
Don't waste time with chit chat.
|
||||
Consider suggestions when refining an idea.
|
||||
"""
|
||||
|
||||
TASK = "a slogan for a new line of electric cars."
|
||||
|
||||
|
||||
async def main():
|
||||
# 1. Create the reviewer agent based on the chat completion service
|
||||
agent_reviewer = ChatCompletionAgent(
|
||||
kernel=_create_kernel_with_chat_completion("artdirector"),
|
||||
name=REVIEWER_NAME,
|
||||
instructions=REVIEWER_INSTRUCTIONS,
|
||||
)
|
||||
|
||||
# 2. Create the copywriter agent based on the chat completion service
|
||||
agent_writer = ChatCompletionAgent(
|
||||
kernel=_create_kernel_with_chat_completion("copywriter"),
|
||||
name=COPYWRITER_NAME,
|
||||
instructions=COPYWRITER_INSTRUCTIONS,
|
||||
)
|
||||
|
||||
# 3. Place the agents in a group chat with a custom termination strategy
|
||||
group_chat = AgentGroupChat(
|
||||
agents=[agent_writer, agent_reviewer],
|
||||
termination_strategy=ApprovalTerminationStrategy(agents=[agent_reviewer], maximum_iterations=10),
|
||||
)
|
||||
|
||||
# 4. Add the task as a message to the group chat
|
||||
await group_chat.add_chat_message(message=TASK)
|
||||
print(f"# User: {TASK}")
|
||||
|
||||
# 5. Invoke the chat
|
||||
async for content in group_chat.invoke():
|
||||
print(f"# {content.name}: {content.content}")
|
||||
|
||||
"""
|
||||
Sample output:
|
||||
INFO:semantic_kernel.agents.group_chat.agent_chat:Adding `1` agent chat messages
|
||||
# User: a slogan for a new line of electric cars.
|
||||
INFO:semantic_kernel.agents.strategies.selection.sequential_selection_strategy:Selected agent at index 0 (ID: ...
|
||||
INFO:semantic_kernel.agents.group_chat.agent_chat:Invoking agent CopyWriter
|
||||
INFO:semantic_kernel.utils.telemetry.model_diagnostics.decorators:{"role": "system", "content": "\nYou are a ...
|
||||
INFO:semantic_kernel.utils.telemetry.model_diagnostics.decorators:{"role": "user", "content": "a slogan for ...
|
||||
INFO:semantic_kernel.connectors.ai.open_ai.services.open_ai_handler:OpenAI usage: CompletionUsage(completion_...
|
||||
INFO:semantic_kernel.utils.telemetry.model_diagnostics.decorators:{"message": {"role": "assistant", "content": ...
|
||||
INFO:semantic_kernel.agents.chat_completion.chat_completion_agent:[ChatCompletionAgent] Invoked AzureChatCompl...
|
||||
INFO:semantic_kernel.agents.strategies.termination.termination_strategy:Evaluating termination criteria for ...
|
||||
INFO:semantic_kernel.agents.strategies.termination.termination_strategy:Agent 598d827e-ce5e-44fa-879b-42793bb...
|
||||
# CopyWriter: "Drive Change. Literally."
|
||||
INFO:semantic_kernel.agents.strategies.selection.sequential_selection_strategy:Selected agent at index 1 (ID: ...
|
||||
INFO:semantic_kernel.agents.group_chat.agent_chat:Invoking agent ArtDirector
|
||||
INFO:semantic_kernel.utils.telemetry.model_diagnostics.decorators:{"role": "system", "content": "\nYou are an ...
|
||||
INFO:semantic_kernel.utils.telemetry.model_diagnostics.decorators:{"role": "user", "content": "a slogan for a ...
|
||||
INFO:semantic_kernel.utils.telemetry.model_diagnostics.decorators:{"role": "assistant", "content": "\"Drive ...
|
||||
...
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
|
||||
from azure.identity import AzureCliCredential
|
||||
from pydantic import BaseModel
|
||||
|
||||
from semantic_kernel.agents import ChatCompletionAgent, ChatHistoryAgentThread
|
||||
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion, AzureChatPromptExecutionSettings
|
||||
from semantic_kernel.functions.kernel_arguments import KernelArguments
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create a chat completion agent that
|
||||
answers user questions using structured outputs. The `Reasoning` model is defined
|
||||
on the prompt execution settings. The settings are then passed into the agent
|
||||
via the `KernelArguments` object.
|
||||
|
||||
The interaction with the agent is via the `get_response` method, which sends a
|
||||
user input to the agent and receives a response from the agent. The conversation
|
||||
history needs to be maintained by the caller in the chat history object.
|
||||
"""
|
||||
|
||||
|
||||
# Define the BaseModel we will use for structured outputs
|
||||
class Step(BaseModel):
|
||||
explanation: str
|
||||
output: str
|
||||
|
||||
|
||||
class Reasoning(BaseModel):
|
||||
steps: list[Step]
|
||||
final_answer: str
|
||||
|
||||
|
||||
# Simulate a conversation with the agent
|
||||
USER_INPUT = "how can I solve 8x + 7y = -23, and 4x=12?"
|
||||
|
||||
|
||||
async def main():
|
||||
# 1. Create the prompt settings
|
||||
settings = AzureChatPromptExecutionSettings()
|
||||
settings.response_format = Reasoning
|
||||
|
||||
# 2. Create the agent by specifying the service
|
||||
agent = ChatCompletionAgent(
|
||||
service=AzureChatCompletion(credential=AzureCliCredential()),
|
||||
name="Assistant",
|
||||
instructions="Answer the user's questions.",
|
||||
arguments=KernelArguments(settings=settings),
|
||||
)
|
||||
|
||||
# 3. Create a thread to hold the conversation
|
||||
# If no thread is provided, a new thread will be
|
||||
# created and returned with the initial response
|
||||
thread: ChatHistoryAgentThread = None
|
||||
|
||||
print(f"# User: {USER_INPUT}")
|
||||
# 4. Invoke the agent for a response
|
||||
response = await agent.get_response(messages=USER_INPUT, thread=thread)
|
||||
# 5. Validate the response and print the structured output
|
||||
reasoned_result = Reasoning.model_validate(json.loads(response.message.content))
|
||||
print(f"# {response.name}:\n\n{reasoned_result.model_dump_json(indent=4)}")
|
||||
|
||||
# 6. Cleanup: Clear the thread
|
||||
await thread.delete() if thread else None
|
||||
|
||||
"""
|
||||
Sample output:
|
||||
# User: how can I solve 8x + 7y = -23, and 4x=12?
|
||||
# Assistant:
|
||||
|
||||
{
|
||||
"steps": [
|
||||
{
|
||||
"explanation": "The second equation 4x = 12 can be solved for x by dividing both sides by 4.",
|
||||
"output": "x = 3."
|
||||
},
|
||||
{
|
||||
"explanation": "Substitute x = 3 from the second equation into the first equation 8x + 7y = -23.",
|
||||
"output": "8(3) + 7y = -23."
|
||||
},
|
||||
{
|
||||
"explanation": "Calculate 8 times 3 to simplify the equation.",
|
||||
"output": "24 + 7y = -23."
|
||||
},
|
||||
{
|
||||
"explanation": "Subtract 24 from both sides to isolate the term with y.",
|
||||
"output": "7y = -23 - 24."
|
||||
},
|
||||
{
|
||||
"explanation": "Perform the subtraction.",
|
||||
"output": "7y = -47."
|
||||
},
|
||||
{
|
||||
"explanation": "Divide both sides by 7 to solve for y.",
|
||||
"output": "y = -47 / 7."
|
||||
},
|
||||
{
|
||||
"explanation": "Simplify the division to get the value of y.",
|
||||
"output": "y = -6.714285714285714 (approximately -6.71)."
|
||||
}
|
||||
],
|
||||
"final_answer": "The solution to the system of equations is x = 3 and y = -6.71."
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
from typing import Annotated
|
||||
|
||||
from azure.identity import AzureCliCredential
|
||||
from pydantic import BaseModel
|
||||
|
||||
from semantic_kernel import Kernel
|
||||
from semantic_kernel.agents import AgentRegistry, ChatHistoryAgentThread
|
||||
from semantic_kernel.agents.chat_completion.chat_completion_agent import ChatCompletionAgent
|
||||
from semantic_kernel.connectors.ai.open_ai import (
|
||||
AzureChatCompletion,
|
||||
AzureChatPromptExecutionSettings,
|
||||
)
|
||||
from semantic_kernel.functions import KernelArguments, kernel_function
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create a chat completion agent using a
|
||||
declarative approach. The Chat Completion Agent is created from a YAML spec,
|
||||
with a specific service and plugins. The agent is then used to answer user questions.
|
||||
|
||||
This sample also demonstrates how to properly pass execution settings (like response format)
|
||||
when using AgentRegistry.create_from_yaml().
|
||||
"""
|
||||
|
||||
|
||||
# Example structure for structured output
|
||||
class StructuredResult(BaseModel):
|
||||
"""Example structure for demonstrating response format."""
|
||||
|
||||
response: str
|
||||
category: str
|
||||
|
||||
|
||||
# 1. Define a Sample Plugin
|
||||
class MenuPlugin:
|
||||
"""A sample Menu Plugin used for the concept sample."""
|
||||
|
||||
@kernel_function(description="Provides a list of specials from the menu.")
|
||||
def get_specials(self) -> Annotated[str, "Returns the specials from the menu."]:
|
||||
return """
|
||||
Special Soup: Clam Chowder
|
||||
Special Salad: Cobb Salad
|
||||
Special Drink: Chai Tea
|
||||
"""
|
||||
|
||||
@kernel_function(description="Provides the price of the requested menu item.")
|
||||
def get_item_price(
|
||||
self, menu_item: Annotated[str, "The name of the menu item."]
|
||||
) -> Annotated[str, "Returns the price of the menu item."]:
|
||||
return "$9.99"
|
||||
|
||||
|
||||
# 2. Define the YAML string
|
||||
AGENT_YAML = """
|
||||
type: chat_completion_agent
|
||||
name: Assistant
|
||||
description: A helpful assistant.
|
||||
instructions: Answer the user's questions using the menu functions.
|
||||
tools:
|
||||
- id: MenuPlugin.get_specials
|
||||
type: function
|
||||
- id: MenuPlugin.get_item_price
|
||||
type: function
|
||||
model:
|
||||
options:
|
||||
temperature: 0.7
|
||||
"""
|
||||
|
||||
# 3. Define your simulated conversation
|
||||
USER_INPUTS = [
|
||||
"Hello",
|
||||
"What is the special soup?",
|
||||
"What does that cost?",
|
||||
"Thank you",
|
||||
]
|
||||
|
||||
|
||||
async def main():
|
||||
# 4. Create a Kernel and add the plugin
|
||||
# For declarative agents, the kernel is required to resolve the plugin
|
||||
kernel = Kernel()
|
||||
kernel.add_plugin(MenuPlugin(), plugin_name="MenuPlugin")
|
||||
|
||||
# 5. Create execution settings with structured output
|
||||
execution_settings = AzureChatPromptExecutionSettings()
|
||||
execution_settings.response_format = StructuredResult
|
||||
|
||||
# 6. Create KernelArguments with the execution settings
|
||||
arguments = KernelArguments(settings=execution_settings)
|
||||
|
||||
# 7. Create the agent from YAML + inject the AI service
|
||||
agent: ChatCompletionAgent = await AgentRegistry.create_from_yaml(
|
||||
AGENT_YAML, kernel=kernel, service=AzureChatCompletion(credential=AzureCliCredential()), arguments=arguments
|
||||
)
|
||||
|
||||
# 8. Create a thread to hold the conversation
|
||||
thread: ChatHistoryAgentThread | None = None
|
||||
|
||||
for user_input in USER_INPUTS:
|
||||
print(f"# User: {user_input}")
|
||||
# 9. Invoke the agent for a response
|
||||
response = await agent.get_response(messages=user_input, thread=thread)
|
||||
print(f"# {response.name}: {response}")
|
||||
thread = response.thread
|
||||
|
||||
# 10. Cleanup the thread
|
||||
await thread.delete() if thread else None
|
||||
|
||||
"""
|
||||
# Sample output:
|
||||
|
||||
# User: Hello
|
||||
# Assistant: {"response":"Hello! How can I help you today? If you have any questions about the menu, feel free to ask!","category":"Greeting"}
|
||||
# User: What is the special soup?
|
||||
# Assistant: {"response":"Today's special soup is Clam Chowder. Would you like to know more about it or see other specials?","category":"Menu Specials"}
|
||||
# User: What does that cost?
|
||||
# Assistant: {"response":"The Clam Chowder special soup costs $9.99.","category":"Menu Pricing"}
|
||||
# User: Thank you
|
||||
# Assistant: {"response":"You're welcome! If you have any more questions or need assistance with the menu, just let me know. Enjoy your meal!","category":"Polite Closing"}
|
||||
""" # noqa: E501
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import ChatCompletionAgent
|
||||
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
|
||||
from semantic_kernel.contents import ChatMessageContent, FunctionCallContent, FunctionResultContent
|
||||
from semantic_kernel.core_plugins import SessionsPythonTool
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create a chat completion agent with
|
||||
code interpreter capabilities using the Azure Container Apps session pool service.
|
||||
"""
|
||||
|
||||
|
||||
async def handle_intermediate_steps(message: ChatMessageContent) -> None:
|
||||
for item in message.items or []:
|
||||
if isinstance(item, FunctionResultContent):
|
||||
print(f"# Function Result:> {item.result}")
|
||||
elif isinstance(item, FunctionCallContent):
|
||||
print(f"# Function Call:> {item.name} with arguments: {item.arguments}")
|
||||
else:
|
||||
print(f"# {message.name}: {message} ")
|
||||
|
||||
|
||||
async def main():
|
||||
credential = AzureCliCredential()
|
||||
|
||||
# Define the resources directory for file uploads
|
||||
resources_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "resources")
|
||||
|
||||
# 1. Create the python code interpreter tool using the SessionsPythonTool
|
||||
# allowed_upload_directories restricts which local directories can be accessed for uploads
|
||||
python_code_interpreter = SessionsPythonTool(
|
||||
credential=credential,
|
||||
allowed_upload_directories=[resources_dir],
|
||||
)
|
||||
|
||||
# 2. Create the agent
|
||||
agent = ChatCompletionAgent(
|
||||
service=AzureChatCompletion(credential=credential),
|
||||
name="Host",
|
||||
instructions="Answer questions about the menu.",
|
||||
plugins=[python_code_interpreter],
|
||||
)
|
||||
|
||||
# 3. Upload a CSV file to the session
|
||||
csv_file_path = os.path.join(resources_dir, "sales.csv")
|
||||
file_metadata = await python_code_interpreter.upload_file(local_file_path=csv_file_path)
|
||||
|
||||
# 4. Invoke the agent for a response to a task
|
||||
TASK = (
|
||||
"What's the total sum of all sales for all segments using Python? "
|
||||
f"Use the uploaded file {file_metadata.full_path} for reference."
|
||||
)
|
||||
print(f"# User: '{TASK}'")
|
||||
async for response in agent.invoke(
|
||||
messages=TASK,
|
||||
on_intermediate_message=handle_intermediate_steps,
|
||||
):
|
||||
print(f"# {response.name}: {response} ")
|
||||
|
||||
"""
|
||||
Sample output:
|
||||
# User: 'What's the total sum of all sales for all segments using Python?
|
||||
Use the uploaded file /mnt/data/sales.csv for reference.'
|
||||
# Function Call:> SessionsPythonTool-execute_code with arguments: {
|
||||
"code": "
|
||||
import pandas as pd
|
||||
|
||||
# Load the sales data
|
||||
file_path = '/mnt/data/sales.csv'
|
||||
sales_data = pd.read_csv(file_path)
|
||||
|
||||
# Calculate the total sum of sales
|
||||
# Assuming there's a column named 'Sales' which contains the sales amounts
|
||||
total_sales = sales_data['Sales'].sum()
|
||||
total_sales"
|
||||
}
|
||||
# Function Result:> Status:
|
||||
Success
|
||||
Result:
|
||||
118726350.28999999
|
||||
Stdout:
|
||||
|
||||
Stderr:
|
||||
# Host: The total sum of all sales for all segments is approximately $118,726,350.29.
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user