Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions python/samples/concepts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
- [Azure AI Agent with Azure AI Search](./agents/azure_ai_agent/azure_ai_agent_azure_ai_search.py)
- [Azure AI Agent File Manipulation](./agents/azure_ai_agent/azure_ai_agent_file_manipulation.py)
- [Azure AI Agent Prompt Templating](./agents/azure_ai_agent/azure_ai_agent_prompt_templating.py)
- [Azure AI Agent Chat History Callback](./agents/azure_ai_agent/azure_ai_agent_streaming_chat_history_callback.py)
- [Azure AI Agent Message Callback Streaming](./agents/azure_ai_agent/azure_ai_agent_message_callback_streaming.py)
- [Azure AI Agent Message Callback](./agents/azure_ai_agent/azure_ai_agent_message_callback.py)
- [Azure AI Agent Streaming](./agents/azure_ai_agent/azure_ai_agent_streaming.py)
- [Azure AI Agent Structured Outputs](./agents/azure_ai_agent/azure_ai_agent_structured_outputs.py)

Expand All @@ -31,6 +32,8 @@
- [Chat Completion Agent as Kernel Function](./agents/chat_completion_agent/chat_completion_agent_as_kernel_function.py)
- [Chat Completion Agent Function Termination](./agents/chat_completion_agent/chat_completion_agent_function_termination.py)
- [Chat Completion Agent Templating](./agents/chat_completion_agent/chat_completion_agent_prompt_templating.py)
- [Chat Completion Agent Message Callback Streaming](./agents/chat_completion_agent/chat_completion_agent_message_callback_streaming.py)
- [Chat Completion Agent Message Callback](./agents/chat_completion_agent/chat_completion_agent_message_callback.py)
- [Chat Completion Agent Summary History Reducer Agent Chat](./agents/chat_completion_agent/chat_completion_agent_summary_history_reducer_agent_chat.py)
- [Chat Completion Agent Summary History Reducer Single Agent](./agents/chat_completion_agent/chat_completion_agent_summary_history_reducer_single_agent.py)
- [Chat Completion Agent Truncate History Reducer Agent Chat](./agents/chat_completion_agent/chat_completion_agent_truncate_history_reducer_agent_chat.py)
Expand All @@ -51,9 +54,9 @@
- [OpenAI Assistant Chart Maker](./agents/openai_assistant/openai_assistant_chart_maker.py)
- [OpenAI Assistant File Manipulation Streaming](./agents/openai_assistant/openai_assistant_file_manipulation_streaming.py)
- [OpenAI Assistant File Manipulation](./agents/openai_assistant/openai_assistant_file_manipulation.py)
- [OpenAI Assistant File Manipulation Streaming](./agents/openai_assistant/openai_assistant_file_manipulation_streaming.py)
- [OpenAI Assistant Retrieval](./agents/openai_assistant/openai_assistant_retrieval.py)
- [OpenAI Assistant Streaming Chat History Callback](./agents/openai_assistant/openai_assistant_streaming_chat_history_callback.py)
- [OpenAI Assistant Message Callback Streaming](./agents/openai_assistant/openai_assistant_message_callback_streaming.py)
- [OpenAI Assistant Message Callback](./agents/openai_assistant/openai_assistant_message_callback.py)
- [OpenAI Assistant Streaming](./agents/openai_assistant/openai_assistant_streaming.py)
- [OpenAI Assistant Structured Outputs](./agents/openai_assistant/openai_assistant_structured_outputs.py)
- [OpenAI Assistant Templating Streaming](./agents/openai_assistant/openai_assistant_templating_streaming.py)
Expand Down
3 changes: 1 addition & 2 deletions python/samples/concepts/agents/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

This project contains a step by step guide to get started with _Semantic Kernel Agents_ in Python.

## PyPI:
## PyPI

- For the use of Chat Completion agents, the minimum allowed Semantic Kernel pypi version is 1.3.0.
- For the use of OpenAI Assistant agents, the minimum allowed Semantic Kernel pypi version is 1.4.0.
Expand All @@ -12,7 +12,6 @@ This project contains a step by step guide to get started with _Semantic Kernel
- For the use of Crew.AI as a plugin, the minimum allowed Semantic Kernel pypi version is 1.21.1.
- For the use of OpenAI Responses agents, the minimum allowed Semantic Kernel pypi version is 1.27.0.


## Source

- [Semantic Kernel Agent Framework](../../../semantic_kernel/agents/)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
# Copyright (c) Microsoft. All rights reserved.

import asyncio
from typing import Annotated

from azure.identity.aio import DefaultAzureCredential

from semantic_kernel.agents import AzureAIAgent, AzureAIAgentSettings, AzureAIAgentThread
from semantic_kernel.contents import FunctionCallContent, FunctionResultContent
from semantic_kernel.contents.chat_message_content import ChatMessageContent
from semantic_kernel.functions import kernel_function

"""
The following sample demonstrates how to create an Azure AI Agent
and use it with functions. In order to answer user questions, the
agent internally uses the functions. These internal steps are returned
to the user as part of the agent's response. Thus, the invoke method
configures a message callback to receive the agent's internal messages.

The agent is configured to use a plugin that provides a list of
specials from the menu and the price of the requested menu item.
"""


# 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"


intermediate_steps: list[ChatMessageContent] = []


async def handle_intermediate_steps(message: ChatMessageContent) -> None:
intermediate_steps.append(message)


async def main() -> None:
ai_agent_settings = AzureAIAgentSettings.create()

async with (
DefaultAzureCredential() as creds,
AzureAIAgent.create_client(
credential=creds,
conn_str=ai_agent_settings.project_connection_string.get_secret_value(),
) as client,
):
AGENT_NAME = "Host"
AGENT_INSTRUCTIONS = "Answer questions about the menu."

# Create agent definition
agent_definition = await client.agents.create_agent(
model=ai_agent_settings.model_deployment_name,
name=AGENT_NAME,
instructions=AGENT_INSTRUCTIONS,
)

# Create the AzureAI Agent
agent = AzureAIAgent(
client=client,
definition=agent_definition,
plugins=[MenuPlugin()], # add the sample plugin to the agent
)

# Create a thread for the agent
# If no thread is provided, a new thread will be
# created and returned with the initial response
thread: AzureAIAgentThread = None

user_inputs = [
"Hello",
"What is the special soup?",
"How much does that cost?",
"Thank you",
]

try:
for user_input in user_inputs:
print(f"# User: '{user_input}'")
async for response in agent.invoke(
messages=user_input,
thread=thread,
on_intermediate_message=handle_intermediate_steps,
):
print(f"# Agent: {response}")
thread = response.thread
finally:
# Cleanup: Delete the thread and agent
await thread.delete() if thread else None
await client.agents.delete_agent(agent.id)

# Print the intermediate steps
print("\nIntermediate Steps:")
for msg in intermediate_steps:
if any(isinstance(item, FunctionResultContent) for item in msg.items):
for fr in msg.items:
if isinstance(fr, FunctionResultContent):
print(f"Function Result:> {fr.result} for function: {fr.name}")
elif any(isinstance(item, FunctionCallContent) for item in msg.items):
for fcc in msg.items:
if isinstance(fcc, FunctionCallContent):
print(f"Function Call:> {fcc.name} with arguments: {fcc.arguments}")
else:
print(f"{msg.role}: {msg.content}")

# Sample output:
# User: 'Hello'
# Agent: Hello! How can I assist you today?
# User: 'What is the special soup?'
# Agent: The special soup is Clam Chowder. Would you like to know more about the menu or anything else?
# User: 'How much does that cost?'
# Agent: The Clam Chowder costs $9.99. If you have any more questions or need further assistance, feel free to ask!
# User: 'Thank you'
# Agent: You're welcome! If you have any more questions in the future, don't hesitate to ask. Have a great day!
#
# Intermediate Steps:
# AuthorRole.ASSISTANT: Hello! How can I assist you today?
# Function Call:> MenuPlugin-get_specials with arguments: {}
# Function Result:>
# Special Soup: Clam Chowder
# Special Salad: Cobb Salad
# Special Drink: Chai Tea
# for function: MenuPlugin-get_specials
# AuthorRole.ASSISTANT: The special soup is Clam Chowder. Would you like to know more about the menu or anything
# else?
# Function Call:> MenuPlugin-get_item_price with arguments: {"menu_item":"Clam Chowder"}
# Function Result:> $9.99 for function: MenuPlugin-get_item_price
# AuthorRole.ASSISTANT: The Clam Chowder costs $9.99. If you have any more questions or need further assistance,
# feel free to ask!
# AuthorRole.ASSISTANT: You're welcome! If you have any more questions in the future, don't hesitate to ask.
# Have a great day!


if __name__ == "__main__":
asyncio.run(main())
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
from azure.identity.aio import DefaultAzureCredential

from semantic_kernel.agents import AzureAIAgent, AzureAIAgentSettings, AzureAIAgentThread
from semantic_kernel.contents import ChatHistory, FunctionCallContent, FunctionResultContent
from semantic_kernel.contents import FunctionCallContent, FunctionResultContent
from semantic_kernel.contents.chat_message_content import ChatMessageContent
from semantic_kernel.functions import kernel_function

"""
The following sample demonstrates how to create an Azure AI Agent
and use it with streaming responses. Additionally, the invoke_stream
configures a chat history callback to receive the conversation history
once the streaming invocation is complete. The agent is configured to use
configures a message callback to receive fully formed messages once
the streaming invocation is complete. The agent is configured to use
a plugin that provides a list of specials from the menu and the price
of the requested menu item.
"""
Expand All @@ -38,11 +39,11 @@ def get_item_price(
return "$9.99"


final_chat_history = ChatHistory()
intermediate_steps: list[ChatMessageContent] = []


def handle_stream_completion(history: ChatHistory) -> None:
final_chat_history.messages.extend(history.messages)
async def handle_streaming_intermediate_steps(message: ChatMessageContent) -> None:
intermediate_steps.append(message)


async def main() -> None:
Expand Down Expand Up @@ -91,7 +92,7 @@ async def main() -> None:
async for response in agent.invoke_stream(
messages=user_input,
thread=thread,
on_complete=handle_stream_completion,
on_intermediate_message=handle_streaming_intermediate_steps,
):
if first_chunk:
print(f"# {response.role}: ", end="", flush=True)
Expand All @@ -104,9 +105,9 @@ async def main() -> None:
await thread.delete() if thread else None
await client.agents.delete_agent(agent.id)

# Print the final chat history
print("\nFinal chat history:")
for msg in final_chat_history.messages:
# Print the intermediate steps
print("\nIntermediate Steps:")
for msg in intermediate_steps:
if any(isinstance(item, FunctionResultContent) for item in msg.items):
for fr in msg.items:
if isinstance(fr, FunctionResultContent):
Expand All @@ -118,6 +119,31 @@ async def main() -> None:
else:
print(f"{msg.role}: {msg.content}")

# Sample output:
# User: 'Hello'
# AuthorRole.ASSISTANT: Hello! How can I assist you today?
# User: 'What is the special soup?'
# AuthorRole.ASSISTANT: The special soup is Clam Chowder. Would you like to know more about the menu or any
# specific items?
# User: 'How much does that cost?'
# AuthorRole.ASSISTANT: The Clam Chowder costs $9.99. Would you like to explore anything else on the menu?
# User: 'Thank you'
# AuthorRole.ASSISTANT: You're welcome! If you have any more questions or need assistance in the future, feel
# free to ask. Have a great day!
#
# Intermediate Steps:
# AuthorRole.ASSISTANT: Hello! How can I assist you today?
# Function Call:> MenuPlugin-get_specials with arguments: {}
# Function Result:>
# Special Soup: Clam Chowder
# Special Salad: Cobb Salad
# Special Drink: Chai Tea
# for function: MenuPlugin-get_specials
# Function Call:> MenuPlugin-get_item_price with arguments: {"menu_item":"Clam Chowder"}
# Function Result:> $9.99 for function: MenuPlugin-get_item_price
# AuthorRole.ASSISTANT: You're welcome! If you have any more questions or need assistance in the future, feel
# free to ask. Have a great day!


if __name__ == "__main__":
asyncio.run(main())
Loading
Loading