chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
AZURE_AI_AGENT_PROJECT_CONNECTION_STRING = "<example-connection-string>"
|
||||
AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME = "<example-model-deployment-name>"
|
||||
AZURE_AI_AGENT_ENDPOINT = "<example-endpoint>"
|
||||
AZURE_AI_AGENT_SUBSCRIPTION_ID = "<example-subscription-id>"
|
||||
AZURE_AI_AGENT_RESOURCE_GROUP_NAME = "<example-resource-group-name>"
|
||||
AZURE_AI_AGENT_PROJECT_NAME = "<example-project-name>"
|
||||
@@ -0,0 +1,13 @@
|
||||
## Azure AI Agents
|
||||
|
||||
For details on using Azure AI Agents within Semantic Kernel, see the [README](../../../getting_started_with_agents/azure_ai_agent/README.md) in the `getting_started_with_agents/azure_ai_agent` directory.
|
||||
|
||||
### Running the `azure_ai_agent_ai_search.py` Sample
|
||||
|
||||
Before running this sample, ensure you have a valid index configured in your Azure AI Search resource. This sample queries hotel data using the sample Azure AI Search hotels index.
|
||||
|
||||
For configuration details, refer to the comments in the sample script. For additional guidance, consult the [README](../../memory/azure_ai_search_hotel_samples/README.md), which provides step-by-step instructions for creating the sample index and generating vectors. This is one approach to setting up the index; you can also follow other tutorials, such as those on "Import and Vectorize Data" in your Azure AI Search resource.
|
||||
|
||||
### Requests and Rate Limits
|
||||
|
||||
For information on configuring rate limits or adjusting polling, refer [here](../../../getting_started_with_agents/azure_ai_agent/README.md#requests-and-rate-limits)
|
||||
@@ -0,0 +1,160 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
from semantic_kernel import Kernel
|
||||
from semantic_kernel.agents import (
|
||||
AzureAIAgent,
|
||||
AzureAIAgentSettings,
|
||||
ChatCompletionAgent,
|
||||
ChatHistoryAgentThread,
|
||||
)
|
||||
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
|
||||
from semantic_kernel.filters import FunctionInvocationContext
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create an Azure AI Agent Agent
|
||||
and a ChatCompletionAgent use them as tools available for a Triage Agent
|
||||
to delegate requests to the appropriate agent. A Function Invocation Filter
|
||||
is used to show the function call content and the function result content so the caller
|
||||
can see which agent was called and what the response was.
|
||||
"""
|
||||
|
||||
|
||||
# Define the auto function invocation filter that will be used by the kernel
|
||||
async def function_invocation_filter(context: FunctionInvocationContext, next):
|
||||
"""A filter that will be called for each function call in the response."""
|
||||
if "messages" not in context.arguments:
|
||||
await next(context)
|
||||
return
|
||||
print(f" Agent [{context.function.name}] called with messages: {context.arguments['messages']}")
|
||||
await next(context)
|
||||
print(f" Response from agent [{context.function.name}]: {context.result.value}")
|
||||
|
||||
|
||||
async def chat(triage_agent: ChatCompletionAgent, thread: ChatHistoryAgentThread = None) -> bool:
|
||||
"""
|
||||
Continuously prompt the user for input and show the assistant's response.
|
||||
Type 'exit' to exit.
|
||||
"""
|
||||
try:
|
||||
user_input = input("User:> ")
|
||||
except (KeyboardInterrupt, EOFError):
|
||||
print("\n\nExiting chat...")
|
||||
return False
|
||||
|
||||
if user_input.lower().strip() == "exit":
|
||||
print("\n\nExiting chat...")
|
||||
return False
|
||||
|
||||
response = await triage_agent.get_response(
|
||||
messages=user_input,
|
||||
thread=thread,
|
||||
)
|
||||
|
||||
if response:
|
||||
print(f"Agent :> {response}")
|
||||
|
||||
return True
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
# Create and configure the kernel.
|
||||
kernel = Kernel()
|
||||
|
||||
# The filter is used for demonstration purposes to show the function invocation.
|
||||
kernel.add_filter("function_invocation", function_invocation_filter)
|
||||
|
||||
ai_agent_settings = AzureAIAgentSettings()
|
||||
|
||||
credential = AzureCliCredential()
|
||||
|
||||
async with (
|
||||
AzureAIAgent.create_client(credential=credential, endpoint=ai_agent_settings.endpoint) as client,
|
||||
):
|
||||
# Create the agent definition
|
||||
agent_definition = await client.agents.create_agent(
|
||||
model=ai_agent_settings.model_deployment_name,
|
||||
name="BillingAgent",
|
||||
instructions=(
|
||||
"You specialize in handling customer questions related to billing issues. "
|
||||
"This includes clarifying invoice charges, payment methods, billing cycles, "
|
||||
"explaining fees, addressing discrepancies in billed amounts, updating payment details, "
|
||||
"assisting with subscription changes, and resolving payment failures. "
|
||||
"Your goal is to clearly communicate and resolve issues specifically about payments and charges."
|
||||
),
|
||||
)
|
||||
|
||||
# Create the AzureAI Agent
|
||||
billing_agent = AzureAIAgent(
|
||||
client=client,
|
||||
definition=agent_definition,
|
||||
)
|
||||
|
||||
refund_agent = ChatCompletionAgent(
|
||||
service=AzureChatCompletion(credential=credential),
|
||||
name="RefundAgent",
|
||||
instructions=(
|
||||
"You specialize in addressing customer inquiries regarding refunds. "
|
||||
"This includes evaluating eligibility for refunds, explaining refund policies, "
|
||||
"processing refund requests, providing status updates on refunds, handling complaints related to "
|
||||
"refunds, and guiding customers through the refund claim process. "
|
||||
"Your goal is to assist users clearly and empathetically to successfully resolve their refund-related "
|
||||
"concerns."
|
||||
),
|
||||
)
|
||||
|
||||
triage_agent = ChatCompletionAgent(
|
||||
service=AzureChatCompletion(credential=credential),
|
||||
kernel=kernel,
|
||||
name="TriageAgent",
|
||||
instructions=(
|
||||
"Your role is to evaluate the user's request and forward it to the appropriate agent based on the "
|
||||
"nature of the query. Forward requests about charges, billing cycles, payment methods, fees, or "
|
||||
"payment issues to the BillingAgent. Forward requests concerning refunds, refund eligibility, "
|
||||
"refund policies, or the status of refunds to the RefundAgent. Your goal is accurate identification "
|
||||
"of the appropriate specialist to ensure the user receives targeted assistance."
|
||||
),
|
||||
plugins=[billing_agent, refund_agent],
|
||||
)
|
||||
|
||||
thread: ChatHistoryAgentThread = None
|
||||
|
||||
print("Welcome to the chat bot!\n Type 'exit' to exit.\n Try to get some billing or refund help.")
|
||||
|
||||
chatting = True
|
||||
while chatting:
|
||||
chatting = await chat(triage_agent, thread)
|
||||
|
||||
"""
|
||||
Sample Output:
|
||||
|
||||
I canceled my subscription but I was still charged.
|
||||
Agent [BillingAgent] called with messages: I canceled my subscription but I was still charged.
|
||||
Response from agent [BillingAgent]: I understand how concerning that can be. It's possible that the charge you
|
||||
received is for a billing cycle that was initiated before your cancellation was processed. Here are a few
|
||||
steps you can take:
|
||||
|
||||
1. **Check Cancellation Confirmation**: Make sure you received a confirmation of your cancellation.
|
||||
This usually comes via email.
|
||||
|
||||
2. **Billing Cycle**: Review your billing cycle to confirm whether the charge aligns with your subscription terms.
|
||||
If your billing is monthly, charges can occur even if you cancel before the period ends.
|
||||
|
||||
3. **Contact Support**: If you believe the charge was made in error, please reach out to customer support for
|
||||
further clarification and to rectify the situation.
|
||||
|
||||
If you can provide more details about the subscription and when you canceled it, I can help you further understand
|
||||
the charges.
|
||||
|
||||
Agent :> It's possible that the charge you received is for a billing cycle initiated before your cancellation was
|
||||
processed. Please check if you received a cancellation confirmation, review your billing cycle, and contact
|
||||
support for further clarification if you believe the charge was made in error. If you have more details,
|
||||
I can help you understand the charges better.
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+178
@@ -0,0 +1,178 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
from typing import Annotated
|
||||
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import AzureAIAgent, AzureAIAgentSettings, AzureAIAgentThread
|
||||
from semantic_kernel.contents import ChatMessageContent, FunctionCallContent, FunctionResultContent
|
||||
from semantic_kernel.filters import (
|
||||
AutoFunctionInvocationContext,
|
||||
FilterTypes,
|
||||
)
|
||||
from semantic_kernel.functions import FunctionResult, kernel_function
|
||||
from semantic_kernel.kernel import Kernel
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create an Azure AI agent that answers
|
||||
user questions. This sample demonstrates the basic steps to create an agent
|
||||
and simulate a conversation with the agent.
|
||||
|
||||
This sample demonstrates how to create a filter that will be called for each
|
||||
function call in the response. The filter can be used to modify the function
|
||||
result or to terminate the function call. The filter can also be used to
|
||||
log the function call or to perform any other action before or after the
|
||||
function call.
|
||||
"""
|
||||
|
||||
|
||||
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"
|
||||
|
||||
|
||||
# Define a kernel instance so we can attach the filter to it
|
||||
kernel = Kernel()
|
||||
|
||||
|
||||
# Define a list to store intermediate steps
|
||||
intermediate_steps: list[ChatMessageContent] = []
|
||||
|
||||
|
||||
# Define a callback function to handle intermediate step content messages
|
||||
async def handle_intermediate_steps(message: ChatMessageContent) -> None:
|
||||
intermediate_steps.append(message)
|
||||
|
||||
|
||||
@kernel.filter(FilterTypes.AUTO_FUNCTION_INVOCATION)
|
||||
async def auto_function_invocation_filter(context: AutoFunctionInvocationContext, next):
|
||||
"""A filter that will be called for each function call in the response."""
|
||||
print("\nAuto function invocation filter")
|
||||
print(f"Function: {context.function.name}")
|
||||
|
||||
# if we don't call next, it will skip this function, and go to the next one
|
||||
await next(context)
|
||||
"""
|
||||
Note: to simply return the unaltered function results, uncomment the `context.terminate = True` line and
|
||||
comment out the lines starting with `result = context.function_result` through `context.terminate = True`.
|
||||
context.terminate = True
|
||||
For this sample, simply setting `context.terminate = True` will return the unaltered function result:
|
||||
|
||||
Auto function invocation filter
|
||||
Function: get_specials
|
||||
# Assistant: MenuPlugin-get_specials -
|
||||
Special Soup: Clam Chowder
|
||||
Special Salad: Cobb Salad
|
||||
Special Drink: Chai Tea
|
||||
"""
|
||||
result = context.function_result
|
||||
if "menu" in context.function.plugin_name.lower():
|
||||
print("Altering the Menu plugin function result...\n")
|
||||
context.function_result = FunctionResult(
|
||||
function=result.function,
|
||||
value="We are sold out, sorry!",
|
||||
)
|
||||
context.terminate = True
|
||||
|
||||
|
||||
# Simulate a conversation with the agent
|
||||
USER_INPUTS = ["What's the special food on the menu?", "What should I do then?"]
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
ai_agent_settings = AzureAIAgentSettings.create()
|
||||
|
||||
async with (
|
||||
AzureCliCredential() as creds,
|
||||
AzureAIAgent.create_client(credential=creds) as client,
|
||||
):
|
||||
# 1. Create an agent on the Azure AI agent service
|
||||
agent_definition = await client.agents.create_agent(
|
||||
model=ai_agent_settings.model_deployment_name,
|
||||
name="Host",
|
||||
instructions="Answer the user's questions about the menu.",
|
||||
)
|
||||
|
||||
# 2. Create a Semantic Kernel agent for the Azure AI agent
|
||||
agent = AzureAIAgent(
|
||||
kernel=kernel,
|
||||
client=client,
|
||||
definition=agent_definition,
|
||||
plugins=[MenuPlugin()], # Add the plugin to the agent
|
||||
)
|
||||
|
||||
# 3. 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
|
||||
|
||||
try:
|
||||
for user_input in USER_INPUTS:
|
||||
print(f"# User: {user_input}")
|
||||
# 4. Invoke the agent with the specified message for response
|
||||
async for response in agent.invoke(
|
||||
messages=user_input, thread=thread, on_intermediate_message=handle_intermediate_steps
|
||||
):
|
||||
# 5. Print the response
|
||||
print(f"# {response.name}: {response}")
|
||||
thread = response.thread
|
||||
finally:
|
||||
# 6. 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: What's the special food on the menu?
|
||||
|
||||
Auto function invocation filter
|
||||
Function: get_specials
|
||||
Altering the Menu plugin function result...
|
||||
|
||||
# Host: I'm sorry, but all the specials on the menu are currently sold out. If there's anything else you're
|
||||
looking for, please let me know!
|
||||
# User: What should I do then?
|
||||
# Host: You might consider ordering from the regular menu items instead. If you need any recommendations or
|
||||
information about specific items, such as prices or ingredients, feel free to ask!
|
||||
|
||||
Intermediate Steps:
|
||||
Function Call:> MenuPlugin-get_specials with arguments: {}
|
||||
Function Result:> We are sold out, sorry! for function: MenuPlugin-get_specials
|
||||
AuthorRole.ASSISTANT: I'm sorry, but all the specials on the menu are currently sold out. If there's anything
|
||||
else you're looking for, please let me know!
|
||||
AuthorRole.ASSISTANT: You might consider ordering from the regular menu items instead. If you need any
|
||||
recommendations or information about specific items, such as prices or ingredients, feel free to ask!
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+183
@@ -0,0 +1,183 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
from typing import Annotated
|
||||
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import AzureAIAgent, AzureAIAgentSettings, AzureAIAgentThread
|
||||
from semantic_kernel.contents import ChatMessageContent, FunctionCallContent, FunctionResultContent
|
||||
from semantic_kernel.filters import (
|
||||
AutoFunctionInvocationContext,
|
||||
FilterTypes,
|
||||
)
|
||||
from semantic_kernel.functions import FunctionResult, kernel_function
|
||||
from semantic_kernel.kernel import Kernel
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create an Azure AI agent that answers
|
||||
user questions. This sample demonstrates the basic steps to create an agent
|
||||
and simulate a streaming conversation with the agent.
|
||||
|
||||
This sample demonstrates how to create a filter that will be called for each
|
||||
function call in the response. The filter can be used to modify the function
|
||||
result or to terminate the function call. The filter can also be used to
|
||||
log the function call or to perform any other action before or after the
|
||||
function call.
|
||||
"""
|
||||
|
||||
|
||||
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"
|
||||
|
||||
|
||||
# Define a kernel instance so we can attach the filter to it
|
||||
kernel = Kernel()
|
||||
|
||||
|
||||
# Define a list to store intermediate steps
|
||||
intermediate_steps: list[ChatMessageContent] = []
|
||||
|
||||
|
||||
# Define a callback function to handle intermediate step content messages
|
||||
async def handle_intermediate_steps(message: ChatMessageContent) -> None:
|
||||
intermediate_steps.append(message)
|
||||
|
||||
|
||||
@kernel.filter(FilterTypes.AUTO_FUNCTION_INVOCATION)
|
||||
async def auto_function_invocation_filter(context: AutoFunctionInvocationContext, next):
|
||||
"""A filter that will be called for each function call in the response."""
|
||||
print("\nAuto function invocation filter")
|
||||
print(f"Function: {context.function.name}")
|
||||
|
||||
# if we don't call next, it will skip this function, and go to the next one
|
||||
await next(context)
|
||||
"""
|
||||
Note: to simply return the unaltered function results, uncomment the `context.terminate = True` line and
|
||||
comment out the lines starting with `result = context.function_result` through `context.terminate = True`.
|
||||
context.terminate = True
|
||||
For this sample, simply setting `context.terminate = True` will return the unaltered function result:
|
||||
|
||||
Auto function invocation filter
|
||||
Function: get_specials
|
||||
# Assistant: MenuPlugin-get_specials -
|
||||
Special Soup: Clam Chowder
|
||||
Special Salad: Cobb Salad
|
||||
Special Drink: Chai Tea
|
||||
"""
|
||||
result = context.function_result
|
||||
if "menu" in context.function.plugin_name.lower():
|
||||
print("Altering the Menu plugin function result...\n")
|
||||
context.function_result = FunctionResult(
|
||||
function=result.function,
|
||||
value="We are sold out, sorry!",
|
||||
)
|
||||
context.terminate = True
|
||||
|
||||
|
||||
# Simulate a conversation with the agent
|
||||
USER_INPUTS = ["What's the special food on the menu?", "What should I do then?"]
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
ai_agent_settings = AzureAIAgentSettings.create()
|
||||
|
||||
async with (
|
||||
AzureCliCredential() as creds,
|
||||
AzureAIAgent.create_client(credential=creds) as client,
|
||||
):
|
||||
# 1. Create an agent on the Azure AI agent service
|
||||
agent_definition = await client.agents.create_agent(
|
||||
model=ai_agent_settings.model_deployment_name,
|
||||
name="Host",
|
||||
instructions="Answer the user's questions about the menu.",
|
||||
)
|
||||
|
||||
# 2. Create a Semantic Kernel agent for the Azure AI agent
|
||||
agent = AzureAIAgent(
|
||||
kernel=kernel,
|
||||
client=client,
|
||||
definition=agent_definition,
|
||||
plugins=[MenuPlugin()], # Add the plugin to the agent
|
||||
)
|
||||
|
||||
# 3. 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
|
||||
|
||||
try:
|
||||
for user_input in USER_INPUTS:
|
||||
print(f"# User: {user_input}")
|
||||
# 4. Invoke the agent with the specified message for response
|
||||
first_chunk = True
|
||||
async for response in agent.invoke_stream(
|
||||
messages=user_input, thread=thread, on_intermediate_message=handle_intermediate_steps
|
||||
):
|
||||
# 5. Print the response
|
||||
if first_chunk:
|
||||
print(f"# {response.name}: ", end="", flush=True)
|
||||
first_chunk = False
|
||||
print(f"{response}", end="", flush=True)
|
||||
thread = response.thread
|
||||
print()
|
||||
finally:
|
||||
# 6. 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: What's the special food on the menu?
|
||||
|
||||
Auto function invocation filter
|
||||
Function: get_specials
|
||||
Altering the Menu plugin function result...
|
||||
|
||||
# Host: I'm sorry, but all the specials on the menu are currently sold out. If there's anything else you're
|
||||
looking for, please let me know!
|
||||
# User: What should I do then?
|
||||
# Host: You might consider ordering from the regular menu items instead. If you need any recommendations or
|
||||
information about specific items, such as prices or ingredients, feel free to ask!
|
||||
|
||||
Intermediate Steps:
|
||||
Function Call:> MenuPlugin-get_specials with arguments: {}
|
||||
Function Result:> We are sold out, sorry! for function: MenuPlugin-get_specials
|
||||
AuthorRole.ASSISTANT: I'm sorry, but all the specials on the menu are currently sold out. If there's anything
|
||||
else you're looking for, please let me know!
|
||||
AuthorRole.ASSISTANT: You might consider ordering from the regular menu items instead. If you need any
|
||||
recommendations or information about specific items, such as prices or ingredients, feel free to ask!
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,139 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from azure.ai.agents.models import AzureAISearchTool
|
||||
from azure.ai.projects.models import ConnectionType
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import AzureAIAgent, AzureAIAgentSettings, AzureAIAgentThread
|
||||
|
||||
logging.basicConfig(level=logging.WARNING)
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create a simple,
|
||||
Azure AI agent that uses the Azure AI Search tool and the demo
|
||||
hotels-sample-index to answer questions about hotels.
|
||||
|
||||
This sample requires:
|
||||
- A "Standard" Agent Setup (choose the Python (Azure SDK) tab):
|
||||
https://learn.microsoft.com/en-us/azure/ai-services/agents/quickstart
|
||||
- An Azure AI Search index named 'hotels-sample-index' created in your
|
||||
Azure AI Search service. You may follow this guide to create the index:
|
||||
https://learn.microsoft.com/azure/search/search-get-started-portal
|
||||
- You will need to make sure your Azure AI Agent project is set up with
|
||||
the required Knowledge Source to be able to use the Azure AI Search tool.
|
||||
Refer to the following link for information on how to do this:
|
||||
https://learn.microsoft.com/en-us/azure/ai-services/agents/how-to/tools/azure-ai-search
|
||||
|
||||
Refer to the README for information about configuring the index to work
|
||||
with the sample data model in Azure AI Search.
|
||||
"""
|
||||
|
||||
# The name of the Azure AI Search index, rename as needed
|
||||
AZURE_AI_SEARCH_INDEX_NAME = "hotels-sample-index"
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
ai_agent_settings = AzureAIAgentSettings()
|
||||
|
||||
async with (
|
||||
AzureCliCredential() as creds,
|
||||
AzureAIAgent.create_client(credential=creds, endpoint=ai_agent_settings.endpoint) as client,
|
||||
):
|
||||
ai_search_conn_id = ""
|
||||
async for connection in client.connections.list():
|
||||
if connection.type == ConnectionType.AZURE_AI_SEARCH:
|
||||
ai_search_conn_id = connection.id
|
||||
break
|
||||
|
||||
ai_search = AzureAISearchTool(index_connection_id=ai_search_conn_id, index_name=AZURE_AI_SEARCH_INDEX_NAME)
|
||||
|
||||
# Create agent definition
|
||||
agent_definition = await client.agents.create_agent(
|
||||
model=ai_agent_settings.model_deployment_name,
|
||||
instructions="Answer questions about hotels using your index.",
|
||||
tools=ai_search.definitions,
|
||||
tool_resources=ai_search.resources,
|
||||
headers={"x-ms-enable-preview": "true"},
|
||||
)
|
||||
|
||||
# Create the AzureAI Agent
|
||||
agent = AzureAIAgent(
|
||||
client=client,
|
||||
definition=agent_definition,
|
||||
)
|
||||
|
||||
# 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 = [
|
||||
"Which hotels are available with full-sized kitchens in Nashville, TN?",
|
||||
"Fun hotels with free WiFi.",
|
||||
]
|
||||
|
||||
try:
|
||||
for user_input in user_inputs:
|
||||
print(f"# User: '{user_input}'\n")
|
||||
# Invoke the agent for the specified thread
|
||||
async for response in agent.invoke(messages=user_input, thread=thread):
|
||||
print(f"# Agent: {response}\n")
|
||||
thread = response.thread
|
||||
finally:
|
||||
# Cleanup: Delete the thread and agent
|
||||
await thread.delete() if thread else None
|
||||
await client.agents.delete_agent(agent.id)
|
||||
|
||||
"""
|
||||
Sample output:
|
||||
|
||||
# User: 'Which hotels are available with full-sized kitchens in Nashville, TN?'
|
||||
|
||||
# Agent: In Nashville, TN, there are several hotels available that feature full-sized kitchens:
|
||||
|
||||
1. **Extended-Stay Hotel Options**:
|
||||
- Many extended-stay hotels offer suites equipped with full-sized kitchens, which include cookware and
|
||||
appliances. These hotels are designed for longer stays, making them a great option for those needing more space
|
||||
and kitchen facilities【3:0†source】【3:1†source】.
|
||||
|
||||
2. **Amenities Included**:
|
||||
- Most of these hotels provide additional amenities like free Wi-Fi, laundry services, fitness centers, and some
|
||||
have on-site dining options【3:1†source】【3:2†source】.
|
||||
|
||||
3. **Location**:
|
||||
- The extended-stay hotels are often located near downtown Nashville, making it convenient for guests to
|
||||
explore the vibrant local music scene while enjoying the comfort of a home-like
|
||||
environment【3:0†source】【3:4†source】.
|
||||
|
||||
If you are looking for specific names or more detailed options, I can further assist you with that!
|
||||
|
||||
# User: 'Fun hotels with free WiFi.'
|
||||
|
||||
# Agent: Here are some fun hotels that offer free WiFi:
|
||||
|
||||
1. **Vibrant Downtown Hotel**:
|
||||
- Located near the heart of downtown, this hotel offers a warm atmosphere with free WiFi and even provides a
|
||||
delightful milk and cookies treat【7:2†source】.
|
||||
|
||||
2. **Extended-Stay Options**:
|
||||
- These hotels often feature fun amenities such as a bowling alley, fitness center, and themed rooms. They also
|
||||
provide free WiFi and are well-situated near local attractions【7:0†source】【7:1†source】.
|
||||
|
||||
3. **Luxury Hotel**:
|
||||
- Ranked highly by Traveler magazine, this 5-star luxury hotel boasts the biggest rooms in the city, free WiFi,
|
||||
espresso in the room, and flexible check-in/check-out options【7:1†source】.
|
||||
|
||||
4. **Budget-Friendly Hotels**:
|
||||
- Several budget hotels offer free WiFi, breakfast, and shuttle services to nearby attractions and airports
|
||||
while still providing a fun stay【7:3†source】.
|
||||
|
||||
These options ensure you stay connected while enjoying your visit! If you need more specific recommendations or
|
||||
details, feel free to ask!
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,110 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
|
||||
from azure.ai.agents.models import BingGroundingTool
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import AzureAIAgent, AzureAIAgentSettings, AzureAIAgentThread
|
||||
from semantic_kernel.contents import (
|
||||
AnnotationContent,
|
||||
ChatMessageContent,
|
||||
FunctionCallContent,
|
||||
FunctionResultContent,
|
||||
)
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create an Azure AI agent that
|
||||
uses the Bing grounding tool to answer a user's question.
|
||||
|
||||
Note: Please visit the following link to learn more about the Bing grounding tool:
|
||||
|
||||
https://learn.microsoft.com/en-us/azure/ai-services/agents/how-to/tools/bing-grounding?tabs=python&pivots=overview
|
||||
"""
|
||||
|
||||
TASK = "Which team won the 2025 NCAA basketball championship?"
|
||||
|
||||
|
||||
async def handle_intermediate_steps(message: ChatMessageContent) -> None:
|
||||
for item in message.items or []:
|
||||
if isinstance(item, FunctionResultContent):
|
||||
print(f"Function Result:> {item.result} for function: {item.name}")
|
||||
elif isinstance(item, FunctionCallContent):
|
||||
print(f"Function Call:> {item.name} with arguments: {item.arguments}")
|
||||
else:
|
||||
print(f"{item}")
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
async with (
|
||||
AzureCliCredential() as creds,
|
||||
AzureAIAgent.create_client(credential=creds) as client,
|
||||
):
|
||||
# 1. Enter your Bing Grounding Connection Name
|
||||
bing_connection = await client.connections.get(name="<your-bing-grounding-connection-name>")
|
||||
conn_id = bing_connection.id
|
||||
|
||||
# 2. Initialize agent bing tool and add the connection id
|
||||
bing_grounding = BingGroundingTool(connection_id=conn_id)
|
||||
|
||||
# 3. Create an agent with Bing grounding on the Azure AI agent service
|
||||
agent_definition = await client.agents.create_agent(
|
||||
name="BingGroundingAgent",
|
||||
instructions="Use the Bing grounding tool to answer the user's question.",
|
||||
model=AzureAIAgentSettings().model_deployment_name,
|
||||
tools=bing_grounding.definitions,
|
||||
)
|
||||
|
||||
# 4. Create a Semantic Kernel agent for the Azure AI agent
|
||||
agent = AzureAIAgent(
|
||||
client=client,
|
||||
definition=agent_definition,
|
||||
)
|
||||
|
||||
# 5. 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 = None
|
||||
|
||||
try:
|
||||
print(f"# User: '{TASK}'")
|
||||
# 6. Invoke the agent for the specified thread for response
|
||||
async for response in agent.invoke(
|
||||
messages=TASK, thread=thread, on_intermediate_message=handle_intermediate_steps
|
||||
):
|
||||
print(f"# {response.name}: {response}")
|
||||
thread = response.thread
|
||||
|
||||
# 7. Show annotations
|
||||
if any(isinstance(item, AnnotationContent) for item in response.items):
|
||||
for annotation in response.items:
|
||||
if isinstance(annotation, AnnotationContent):
|
||||
print(
|
||||
f"Annotation :> {annotation.url}, source={annotation.quote}, with "
|
||||
f"start_index={annotation.start_index} and end_index={annotation.end_index}"
|
||||
)
|
||||
finally:
|
||||
# 8. Cleanup: Delete the thread and agent
|
||||
await thread.delete() if thread else None
|
||||
await client.agents.delete_agent(agent.id)
|
||||
|
||||
"""
|
||||
Sample Output:
|
||||
|
||||
# User: 'Which team won the 2025 NCAA basketball championship?'
|
||||
Function Call:> bing_grounding with arguments:
|
||||
{
|
||||
'requesturl': 'https://api.bing.microsoft.com/v7.0/search?q=search(query:2025 NCAA basketball championship winner)',
|
||||
'response_metadata': "{'market': 'en-US', 'num_docs_retrieved': 5, 'num_docs_actually_used': 5}"
|
||||
}
|
||||
# BingGroundingAgent: The team that won the 2025 NCAA men's basketball championship was the Florida Gators. They defeated the Houston Cougars with a final score of 65-63.
|
||||
The championship game took place in San Antonio, Texas, and the Florida team was coached by Todd Golden. This victory made Florida the national champion for the 2024-25
|
||||
NCAA Division I men's basketball season【3:0†source】【3:1†source】【3:2†source】.
|
||||
Annotation :> https://en.wikipedia.org/wiki/2025_NCAA_Division_I_men%27s_basketball_championship_game, source=【3:0†source】, with start_index=357 and end_index=369
|
||||
Annotation :> https://www.ncaa.com/history/basketball-men/d1, source=【3:1†source】, with start_index=369 and end_index=381
|
||||
Annotation :> https://sports.yahoo.com/article/won-march-madness-2025-ncaa-100551421.html, source=【3:2†source】, with start_index=381 and end_index=393
|
||||
""" # noqa: E501
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
|
||||
from azure.ai.agents.models import BingGroundingTool
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import AzureAIAgent, AzureAIAgentSettings, AzureAIAgentThread
|
||||
from semantic_kernel.contents import (
|
||||
ChatMessageContent,
|
||||
FunctionCallContent,
|
||||
FunctionResultContent,
|
||||
StreamingAnnotationContent,
|
||||
)
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create an Azure AI agent that
|
||||
uses the Bing grounding tool to answer a user's question.
|
||||
|
||||
Additionally, the `on_intermediate_message` callback is used to handle intermediate messages
|
||||
from the agent.
|
||||
|
||||
Note: Please visit the following link to learn more about the Bing grounding tool:
|
||||
|
||||
https://learn.microsoft.com/en-us/azure/ai-services/agents/how-to/tools/bing-grounding?tabs=python&pivots=overview
|
||||
"""
|
||||
|
||||
TASK = "Which team won the 2025 NCAA basketball championship?"
|
||||
|
||||
intermediate_steps: list[ChatMessageContent] = []
|
||||
|
||||
|
||||
async def handle_streaming_intermediate_steps(message: ChatMessageContent) -> None:
|
||||
for item in message.items or []:
|
||||
if isinstance(item, FunctionResultContent):
|
||||
print(f"Function Result:> {item.result} for function: {item.name}")
|
||||
elif isinstance(item, FunctionCallContent):
|
||||
print(f"Function Call:> {item.name} with arguments: {item.arguments}")
|
||||
else:
|
||||
print(f"{item}")
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
async with (
|
||||
AzureCliCredential() as creds,
|
||||
AzureAIAgent.create_client(credential=creds) as client,
|
||||
):
|
||||
# 1. Enter your Bing Grounding Connection Name
|
||||
bing_connection = await client.connections.get(name="<your-bing-grounding-connection-name>")
|
||||
conn_id = bing_connection.id
|
||||
|
||||
# 2. Initialize agent bing tool and add the connection id
|
||||
bing_grounding = BingGroundingTool(connection_id=conn_id)
|
||||
|
||||
# 3. Create an agent with Bing grounding on the Azure AI agent service
|
||||
agent_definition = await client.agents.create_agent(
|
||||
name="BingGroundingAgent",
|
||||
instructions="Use the Bing grounding tool to answer the user's question.",
|
||||
model=AzureAIAgentSettings().model_deployment_name,
|
||||
tools=bing_grounding.definitions,
|
||||
)
|
||||
|
||||
# 4. Create a Semantic Kernel agent for the Azure AI agent
|
||||
agent = AzureAIAgent(
|
||||
client=client,
|
||||
definition=agent_definition,
|
||||
)
|
||||
|
||||
# 5. 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 = None
|
||||
|
||||
try:
|
||||
print(f"# User: '{TASK}'")
|
||||
# 6. Invoke the agent for the specified thread for response
|
||||
first_chunk = True
|
||||
async for response in agent.invoke_stream(
|
||||
messages=TASK, thread=thread, on_intermediate_message=handle_streaming_intermediate_steps
|
||||
):
|
||||
if first_chunk:
|
||||
print(f"# {response.name}: ", end="", flush=True)
|
||||
first_chunk = False
|
||||
print(f"{response}", end="", flush=True)
|
||||
thread = response.thread
|
||||
|
||||
# 7. Show annotations
|
||||
if any(isinstance(item, StreamingAnnotationContent) for item in response.items):
|
||||
print()
|
||||
for annotation in response.items:
|
||||
if isinstance(annotation, StreamingAnnotationContent):
|
||||
print(
|
||||
f"Annotation :> {annotation.url}, source={annotation.quote}, with "
|
||||
f"start_index={annotation.start_index} and end_index={annotation.end_index}"
|
||||
)
|
||||
finally:
|
||||
# 8. Cleanup: Delete the thread and agent
|
||||
await thread.delete() if thread else None
|
||||
await client.agents.delete_agent(agent.id)
|
||||
|
||||
"""
|
||||
Sample Output:
|
||||
|
||||
# User: 'Which team won the 2025 NCAA basketball championship?'
|
||||
Function Call:> bing_grounding with arguments: {'requesturl': 'https://api.bing.microsoft.com/v7.0/search?q=search(query: 2025 NCAA basketball championship winner)'}
|
||||
Function Call:> bing_grounding with arguments: {'response_metadata': "{'market': 'en-US', 'num_docs_retrieved': 5, 'num_docs_actually_used': 5}"}
|
||||
# BingGroundingAgent: The Florida Gators won the 2025 NCAA men's basketball championship. They defeated the Houston Cougars with a close score of 65-63 in the championship game held in San Antonio, Texas. This victory marked their third national title. Florida overcame a 12-point deficit during the game to claim the championship【3:0†source】
|
||||
Annotation :> https://en.wikipedia.org/wiki/2025_NCAA_Division_I_men%27s_basketball_championship_game, source=None, with start_index=308 and end_index=320
|
||||
【3:1†source】
|
||||
Annotation :> https://www.ncaa.com/history/basketball-men/d1, source=None, with start_index=320 and end_index=332
|
||||
【3:2†source】
|
||||
Annotation :> https://sports.yahoo.com/article/florida-gators-win-2025-ncaa-034021303.html, source=None, with start_index=332 and end_index=344.
|
||||
""" # noqa: E501
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
from functools import reduce
|
||||
|
||||
from azure.ai.agents.models import CodeInterpreterTool
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import AzureAIAgent, AzureAIAgentSettings, AzureAIAgentThread
|
||||
from semantic_kernel.contents import ChatMessageContent, StreamingChatMessageContent
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create an Azure AI agent that
|
||||
uses the code interpreter tool and returns streaming responses to answer a coding question.
|
||||
Additionally, the `on_intermediate_message` callback is used to handle intermediate messages
|
||||
from the agent.
|
||||
"""
|
||||
|
||||
TASK = "Use code to determine the values in the Fibonacci sequence that that are less then the value of 101."
|
||||
|
||||
intermediate_steps: list[ChatMessageContent] = []
|
||||
|
||||
|
||||
async def handle_streaming_intermediate_steps(message: ChatMessageContent) -> None:
|
||||
intermediate_steps.append(message)
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
async with (
|
||||
AzureCliCredential() as creds,
|
||||
AzureAIAgent.create_client(credential=creds) as client,
|
||||
):
|
||||
# 1. Create an agent with a code interpreter on the Azure AI agent service
|
||||
code_interpreter = CodeInterpreterTool()
|
||||
agent_definition = await client.agents.create_agent(
|
||||
model=AzureAIAgentSettings().model_deployment_name,
|
||||
tools=code_interpreter.definitions,
|
||||
tool_resources=code_interpreter.resources,
|
||||
)
|
||||
|
||||
# 2. Create a Semantic Kernel agent for the Azure AI agent
|
||||
agent = AzureAIAgent(
|
||||
client=client,
|
||||
definition=agent_definition,
|
||||
)
|
||||
|
||||
# 3. 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 = None
|
||||
|
||||
try:
|
||||
print(f"# User: '{TASK}'")
|
||||
# 4. Invoke the agent for the specified thread for response
|
||||
is_code = False
|
||||
last_role = None
|
||||
async for response in agent.invoke_stream(
|
||||
messages=TASK, thread=thread, on_intermediate_message=handle_streaming_intermediate_steps
|
||||
):
|
||||
current_is_code = response.metadata.get("code", False)
|
||||
|
||||
if current_is_code:
|
||||
if not is_code:
|
||||
print("\n\n```python")
|
||||
is_code = True
|
||||
print(response.content, end="", flush=True)
|
||||
else:
|
||||
if is_code:
|
||||
print("\n```")
|
||||
is_code = False
|
||||
last_role = None
|
||||
if hasattr(response, "role") and response.role is not None and last_role != response.role:
|
||||
print(f"\n# {response.role}: ", end="", flush=True)
|
||||
last_role = response.role
|
||||
print(response.content, end="", flush=True)
|
||||
thread = response.thread
|
||||
if is_code:
|
||||
print("```\n")
|
||||
print()
|
||||
finally:
|
||||
# 6. Cleanup: Delete the thread and agent
|
||||
await thread.delete() if thread else None
|
||||
await client.agents.delete_agent(agent.id)
|
||||
|
||||
print("====================================================")
|
||||
print("\nResponse complete:\n")
|
||||
# Combine the intermediate `StreamingChatMessageContent` chunks into a single message
|
||||
filtered_steps = [step for step in intermediate_steps if isinstance(step, StreamingChatMessageContent)]
|
||||
streaming_full_completion: StreamingChatMessageContent = reduce(lambda x, y: x + y, filtered_steps)
|
||||
# Grab the other messages that are not `StreamingChatMessageContent`
|
||||
other_steps = [s for s in intermediate_steps if not isinstance(s, StreamingChatMessageContent)]
|
||||
final_msgs = [streaming_full_completion] + other_steps
|
||||
for msg in final_msgs:
|
||||
print(f"{msg.content}")
|
||||
|
||||
r"""
|
||||
Sample Output:
|
||||
# User: 'Use code to determine the values in the Fibonacci sequence that that are less then the value of 101.'
|
||||
|
||||
```python
|
||||
def fibonacci_sequence(limit):
|
||||
fib_sequence = []
|
||||
a, b = 0, 1
|
||||
while a < limit:
|
||||
fib_sequence.append(a)
|
||||
a, b = b, a + b
|
||||
return fib_sequence
|
||||
|
||||
# Get Fibonacci sequence values less than 101
|
||||
fibonacci_values = fibonacci_sequence(101)
|
||||
fibonacci_values
|
||||
```
|
||||
|
||||
# AuthorRole.ASSISTANT: The values in the Fibonacci sequence that are less than 101 are:
|
||||
|
||||
\[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89\]
|
||||
====================================================
|
||||
|
||||
Response complete:
|
||||
|
||||
def fibonacci_sequence(limit):
|
||||
fib_sequence = []
|
||||
a, b = 0, 1
|
||||
while a < limit:
|
||||
fib_sequence.append(a)
|
||||
a, b = b, a + b
|
||||
return fib_sequence
|
||||
|
||||
# Get Fibonacci sequence values less than 101
|
||||
fibonacci_values = fibonacci_sequence(101)
|
||||
fibonacci_values
|
||||
The values in the Fibonacci sequence that are less than 101 are:
|
||||
|
||||
\[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89\]
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import AgentRegistry, AzureAIAgent, AzureAIAgentSettings
|
||||
from semantic_kernel.contents.chat_message_content import ChatMessageContent
|
||||
from semantic_kernel.contents.function_call_content import FunctionCallContent
|
||||
from semantic_kernel.contents.function_result_content import FunctionResultContent
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create an Azure AI agent that answers
|
||||
user questions using the Azure AI Search tool.
|
||||
|
||||
The agent is created using a YAML declarative spec that configures the
|
||||
Azure AI Search tool. The agent is then used to answer user questions
|
||||
that required grounding context from the Azure AI Search index.
|
||||
|
||||
Note: the `AzureAISearchConnectionId` is in the format of:
|
||||
/subscriptions/<sub-id>/resourceGroups/<rg>/providers/Microsoft.MachineLearningServices/workspaces/<workspace>/connections/AzureAISearch
|
||||
|
||||
It can either be configured as an env var `AZURE_AI_AGENT_BING_CONNECTION_ID` or passed in as an extra to
|
||||
`create_from_yaml`: extras={
|
||||
"AzureAISearchConnectionId": "<azure_ai_search_connection_id>",
|
||||
"AzureAISearchIndexName": "<azure_ai_search_index_name>"
|
||||
}
|
||||
"""
|
||||
|
||||
# Define the YAML string for the sample
|
||||
spec = """
|
||||
type: foundry_agent
|
||||
name: AzureAISearchAgent
|
||||
instructions: Answer questions using your index to provide grounding context.
|
||||
description: This agent answers questions using AI Search to provide grounding context.
|
||||
model:
|
||||
id: ${AzureAI:ChatModelId}
|
||||
options:
|
||||
temperature: 0.4
|
||||
tools:
|
||||
- type: azure_ai_search
|
||||
options:
|
||||
tool_connections:
|
||||
- ${AzureAI:AzureAISearchConnectionId}
|
||||
index_name: ${AzureAI:AzureAISearchIndexName}
|
||||
"""
|
||||
|
||||
settings = AzureAIAgentSettings() # ChatModelId comes from .env/env vars
|
||||
|
||||
|
||||
async def main():
|
||||
async with (
|
||||
AzureCliCredential() as creds,
|
||||
AzureAIAgent.create_client(credential=creds) as client,
|
||||
):
|
||||
try:
|
||||
# Create the AzureAI Agent from the YAML spec
|
||||
# Note: the extras can be provided in the short-format (shown below) or
|
||||
# in the long-format (as shown in the YAML spec, with the `AzureAI:` prefix).
|
||||
# The short-format is used here for brevity
|
||||
agent: AzureAIAgent = await AgentRegistry.create_from_yaml(
|
||||
yaml_str=spec,
|
||||
client=client,
|
||||
settings=settings,
|
||||
extras={
|
||||
"AzureAISearchConnectionId": "<azure-ai-search-connection-id>",
|
||||
"AzureAISearchIndexName": "<azure-ai-search-index-name>",
|
||||
},
|
||||
)
|
||||
|
||||
# Define the task for the agent
|
||||
TASK = "What is Semantic Kernel?"
|
||||
|
||||
print(f"# User: '{TASK}'")
|
||||
|
||||
# Define a callback function to handle intermediate messages
|
||||
async def on_intermediate_message(message: ChatMessageContent):
|
||||
if message.items:
|
||||
for item in message.items:
|
||||
if isinstance(item, FunctionCallContent):
|
||||
print(f"# FunctionCallContent: arguments={item.arguments}")
|
||||
elif isinstance(item, FunctionResultContent):
|
||||
print(f"# FunctionResultContent: result={item.result}")
|
||||
|
||||
# Invoke the agent for the specified task
|
||||
async for response in agent.invoke(messages=TASK, on_intermediate_message=on_intermediate_message):
|
||||
print(f"# {response.name}: {response}")
|
||||
finally:
|
||||
# Cleanup: Delete the agent
|
||||
await client.agents.delete_agent(agent.id)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import AgentRegistry, AzureAIAgent, AzureAIAgentSettings
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create an Azure AI agent that answers
|
||||
user questions using the Bing Grounding tool.
|
||||
|
||||
The agent is created using a YAML declarative spec that configures the
|
||||
Bing Grounding tool. The agent is then used to answer user questions
|
||||
that require web search to answer correctly.
|
||||
|
||||
Note: the `BingConnectionId` is in the format of:
|
||||
/subscriptions/<sub_id>/resourceGroups/<rg>/providers/Microsoft.MachineLearningServices/workspaces/<workspace>/connections/<bing_connection_id>
|
||||
|
||||
It can either be configured as an env var `AZURE_AI_AGENT_BING_CONNECTION_ID` or passed in as an extra to
|
||||
`create_from_yaml`: extras={"BingConnectionId": "<bing_connection_id>"}
|
||||
"""
|
||||
|
||||
# Define the YAML string for the sample
|
||||
spec = """
|
||||
type: foundry_agent
|
||||
name: BingAgent
|
||||
instructions: Answer questions using Bing to provide grounding context.
|
||||
description: This agent answers questions using Bing to provide grounding context.
|
||||
model:
|
||||
id: ${AzureAI:ChatModelId}
|
||||
options:
|
||||
temperature: 0.4
|
||||
tools:
|
||||
- type: bing_grounding
|
||||
options:
|
||||
tool_connections:
|
||||
- ${AzureAI:BingConnectionId}
|
||||
"""
|
||||
|
||||
settings = AzureAIAgentSettings() # ChatModelId & BingConnectionId come from .env/env vars
|
||||
|
||||
|
||||
async def main():
|
||||
async with (
|
||||
AzureCliCredential() as creds,
|
||||
AzureAIAgent.create_client(credential=creds) as client,
|
||||
):
|
||||
try:
|
||||
# Create the AzureAI Agent from the YAML spec
|
||||
agent: AzureAIAgent = await AgentRegistry.create_from_yaml(
|
||||
yaml_str=spec,
|
||||
client=client,
|
||||
settings=settings,
|
||||
)
|
||||
|
||||
# Define the task for the agent
|
||||
TASK = "Who won the 2025 NCAA basketball championship?"
|
||||
|
||||
print(f"# User: '{TASK}'")
|
||||
|
||||
# Invoke the agent for the specified task
|
||||
async for response in agent.invoke(
|
||||
messages=TASK,
|
||||
):
|
||||
print(f"# {response.name}: {response}")
|
||||
finally:
|
||||
# Cleanup: Delete the thread and agent
|
||||
await client.agents.delete_agent(agent.id)
|
||||
|
||||
"""
|
||||
Sample output:
|
||||
|
||||
# User: 'Who won the 2025 NCAA basketball championship?'
|
||||
# BingAgent: The Florida Gators won the 2025 NCAA men's basketball championship, narrowly defeating the Houston
|
||||
Cougars 65-63 in the final game. This marked Florida's first national title since
|
||||
2007【3:5†source】【3:9†source】.
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
from azure.ai.agents.models import FilePurpose
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import AgentRegistry, AzureAIAgent, AzureAIAgentSettings
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create an Azure AI agent that answers
|
||||
user questions using the code interpreter tool.
|
||||
|
||||
The agent is then used to answer user questions that require code to be generated and
|
||||
executed. The responses are handled in a streaming manner.
|
||||
"""
|
||||
|
||||
# Define the YAML string for the sample
|
||||
spec = """
|
||||
type: foundry_agent
|
||||
name: CodeInterpreterAgent
|
||||
description: Agent with code interpreter tool.
|
||||
instructions: >
|
||||
Use the code interpreter tool to answer questions that require code to be generated
|
||||
and executed.
|
||||
model:
|
||||
id: ${AzureAI:ChatModelId}
|
||||
connection:
|
||||
endpoint: ${AzureAI:Endpoint}
|
||||
tools:
|
||||
- type: code_interpreter
|
||||
options:
|
||||
file_ids:
|
||||
- ${AzureAI:FileId1}
|
||||
"""
|
||||
|
||||
settings = AzureAIAgentSettings() # ChatModelId & Endpoint come from env vars
|
||||
|
||||
|
||||
async def main():
|
||||
async with (
|
||||
AzureCliCredential() as creds,
|
||||
AzureAIAgent.create_client(credential=creds) as client,
|
||||
):
|
||||
# Create the CSV file path for the sample
|
||||
csv_file_path = os.path.join(
|
||||
os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))),
|
||||
"resources",
|
||||
"agent_assistant_file_manipulation",
|
||||
"sales.csv",
|
||||
)
|
||||
|
||||
try:
|
||||
# Upload the CSV file to the agent service
|
||||
file = await client.agents.files.upload_and_poll(file_path=csv_file_path, purpose=FilePurpose.AGENTS)
|
||||
|
||||
# Create the AzureAI Agent from the YAML spec
|
||||
# Note: the extras can be provided in the short-format (shown below) or
|
||||
# in the long-format (as shown in the YAML spec, with the `AzureAI:` prefix).
|
||||
# The short-format is used here for brevity
|
||||
agent: AzureAIAgent = await AgentRegistry.create_from_yaml(
|
||||
yaml_str=spec,
|
||||
client=client,
|
||||
settings=settings,
|
||||
extras={"FileId1": file.id},
|
||||
)
|
||||
|
||||
# Define the task for the agent
|
||||
TASK = "Give me the code to calculate the total sales for all segments."
|
||||
|
||||
print(f"# User: '{TASK}'")
|
||||
|
||||
# Invoke the agent for the specified task
|
||||
is_code = False
|
||||
last_role = None
|
||||
async for response in agent.invoke_stream(
|
||||
messages=TASK,
|
||||
):
|
||||
current_is_code = response.metadata.get("code", False)
|
||||
|
||||
if current_is_code:
|
||||
if not is_code:
|
||||
print("\n\n```python")
|
||||
is_code = True
|
||||
print(response.content, end="", flush=True)
|
||||
else:
|
||||
if is_code:
|
||||
print("\n```")
|
||||
is_code = False
|
||||
last_role = None
|
||||
if hasattr(response, "role") and response.role is not None and last_role != response.role:
|
||||
print(f"\n# {response.role}: ", end="", flush=True)
|
||||
last_role = response.role
|
||||
print(response.content, end="", flush=True)
|
||||
if is_code:
|
||||
print("```\n")
|
||||
print()
|
||||
finally:
|
||||
# Cleanup: Delete the thread and agent
|
||||
await client.agents.delete_agent(agent.id)
|
||||
await client.agents.files.delete(file.id)
|
||||
|
||||
"""
|
||||
Sample output:
|
||||
|
||||
# User: 'Give me the code to calculate the total sales for all segments.'
|
||||
|
||||
# AuthorRole.ASSISTANT: Let me first examine the contents of the uploaded file to determine its structure. This
|
||||
will allow me to create the appropriate code for calculating the total sales for all segments. Hang tight!
|
||||
|
||||
```python
|
||||
import pandas as pd
|
||||
|
||||
# Load the uploaded file to examine its contents
|
||||
file_path = '/mnt/data/assistant-3nXizu2EX2EwXikUz71uNc'
|
||||
data = pd.read_csv(file_path)
|
||||
|
||||
# Display the first few rows and column names to understand the structure of the dataset
|
||||
data.head(), data.columns
|
||||
```
|
||||
|
||||
# AuthorRole.ASSISTANT: The dataset contains several columns, including `Segment`, `Sales`, and others such as
|
||||
`Country`, `Product`, and date-related information. To calculate the total sales for all segments, we will:
|
||||
|
||||
1. Group the data by the `Segment` column.
|
||||
2. Sum the `Sales` column for each segment.
|
||||
3. Calculate the grand total of all sales across all segments.
|
||||
|
||||
Here is the code snippet for this task:
|
||||
|
||||
```python
|
||||
# Group by 'Segment' and sum up 'Sales'
|
||||
segment_sales = data.groupby('Segment')['Sales'].sum()
|
||||
|
||||
# Calculate the total sales across all segments
|
||||
total_sales = segment_sales.sum()
|
||||
|
||||
print("Total Sales per Segment:")
|
||||
print(segment_sales)
|
||||
print(f"\nGrand Total Sales: {total_sales}")
|
||||
```
|
||||
|
||||
Would you like me to execute this directly for the uploaded data?
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
from azure.ai.agents.models import VectorStore
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import AgentRegistry, AzureAIAgent, AzureAIAgentSettings
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create an Azure AI agent that answers
|
||||
user questions using the file search tool from a declarative spec.
|
||||
"""
|
||||
|
||||
# Define the YAML string for the sample
|
||||
spec = """
|
||||
type: foundry_agent
|
||||
name: FileSearchAgent
|
||||
description: Agent with file search tool.
|
||||
instructions: >
|
||||
Use the file search tool to answer questions from the user.
|
||||
model:
|
||||
id: ${AzureAI:ChatModelId}
|
||||
connection:
|
||||
endpoint: ${AzureAI:Endpoint}
|
||||
tools:
|
||||
- type: file_search
|
||||
options:
|
||||
vector_store_ids:
|
||||
- ${AzureAI:VectorStoreId}
|
||||
"""
|
||||
|
||||
settings = AzureAIAgentSettings() # ChatModelId & Endpoint come from .env/env vars
|
||||
|
||||
|
||||
async def main():
|
||||
async with (
|
||||
AzureCliCredential() as creds,
|
||||
AzureAIAgent.create_client(credential=creds) as client,
|
||||
):
|
||||
# Read and upload the file to the Azure AI agent service
|
||||
pdf_file_path = os.path.join(
|
||||
os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))),
|
||||
"resources",
|
||||
"file_search",
|
||||
"employees.pdf",
|
||||
)
|
||||
# Upload the pdf file to the agent service
|
||||
file = await client.agents.files.upload_and_poll(file_path=pdf_file_path, purpose="assistants")
|
||||
vector_store: VectorStore = await client.agents.vector_stores.create(file_ids=[file.id], name="my_vectorstore")
|
||||
|
||||
try:
|
||||
# Create the AzureAI Agent from the YAML spec
|
||||
# Note: the extras can be provided in the short-format (shown below) or
|
||||
# in the long-format (as shown in the YAML spec, with the `AzureAI:` prefix).
|
||||
# The short-format is used here for brevity
|
||||
agent: AzureAIAgent = await AgentRegistry.create_from_yaml(
|
||||
yaml_str=spec,
|
||||
client=client,
|
||||
settings=settings,
|
||||
extras={"VectorStoreId": vector_store.id},
|
||||
)
|
||||
|
||||
# Define the task for the agent
|
||||
TASK = "Who can help me if I have a sales question?"
|
||||
|
||||
print(f"# User: '{TASK}'")
|
||||
|
||||
# Invoke the agent for the specified task
|
||||
async for response in agent.invoke(
|
||||
messages=TASK,
|
||||
):
|
||||
print(f"# {response.name}: {response}")
|
||||
finally:
|
||||
# Cleanup: Delete the agent, vector store, and file
|
||||
await client.agents.delete_agent(agent.id)
|
||||
await client.agents.vector_stores.delete(vector_store.id)
|
||||
await client.agents.files.delete(file.id)
|
||||
|
||||
"""
|
||||
Sample output:
|
||||
|
||||
# User: 'Who can help me if I have a sales question?'
|
||||
# FileSearchAgent: If you have a sales question, you may contact the following individuals:
|
||||
|
||||
1. **Hicran Bea** - Sales Manager
|
||||
2. **Mariam Jaslyn** - Sales Representative
|
||||
3. **Angelino Embla** - Sales Representative
|
||||
|
||||
This information comes from the employee records【4:0†source】.
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
from typing import Annotated
|
||||
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import AgentRegistry, AzureAIAgent, AzureAIAgentSettings, AzureAIAgentThread
|
||||
from semantic_kernel.functions.kernel_function_decorator import kernel_function
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create an Azure AI agent that answers
|
||||
user questions. The sample shows how to load a declarative spec from a file.
|
||||
The plugins/functions must already exist in the kernel.
|
||||
They are not created declaratively via the spec.
|
||||
"""
|
||||
|
||||
|
||||
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"
|
||||
|
||||
|
||||
async def main():
|
||||
async with (
|
||||
AzureCliCredential() as creds,
|
||||
AzureAIAgent.create_client(credential=creds) as client,
|
||||
):
|
||||
try:
|
||||
# Define the YAML file path for the sample
|
||||
file_path = os.path.join(
|
||||
os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))),
|
||||
"resources",
|
||||
"declarative_spec",
|
||||
"spec.yaml",
|
||||
)
|
||||
|
||||
# Create the AzureAI Agent from the YAML spec
|
||||
agent: AzureAIAgent = await AgentRegistry.create_from_file(
|
||||
file_path,
|
||||
plugins=[MenuPlugin()],
|
||||
client=client,
|
||||
settings=AzureAIAgentSettings(), # The Spec's ChatModelId & Endpoint come from .env/env vars
|
||||
)
|
||||
|
||||
# Create the agent
|
||||
user_inputs = [
|
||||
"Hello",
|
||||
"What is the special soup?",
|
||||
"How much does that cost?",
|
||||
"Thank you",
|
||||
]
|
||||
|
||||
# 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 = None
|
||||
|
||||
for user_input in user_inputs:
|
||||
print(f"# User: '{user_input}'")
|
||||
# Invoke the agent for the specified task
|
||||
async for response in agent.invoke(
|
||||
messages=user_input,
|
||||
thread=thread,
|
||||
):
|
||||
print(f"# {response.name}: {response}")
|
||||
# Store the thread for the next iteration
|
||||
thread = response.thread
|
||||
finally:
|
||||
# Cleanup: Delete the thread and agent
|
||||
await client.agents.delete_agent(agent.id) if agent else None
|
||||
await thread.delete() if thread else None
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,196 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import AgentRegistry, AzureAIAgent, AzureAIAgentSettings
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create an Azure AI agent that answers
|
||||
user questions using the OpenAPI tool. The agent is then used to answer user
|
||||
questions that leverage a free weather API.
|
||||
"""
|
||||
|
||||
# Toggle between a JSON or a YAML OpenAPI spec
|
||||
USE_JSON_OPENAPI_SPEC = True
|
||||
|
||||
json_openapi_spec = """
|
||||
type: foundry_agent
|
||||
name: WeatherAgent
|
||||
instructions: Answer questions about the weather. For all other questions politely decline to answer.
|
||||
description: This agent answers question about the weather.
|
||||
model:
|
||||
id: ${AzureAI:ChatModelId}
|
||||
connection:
|
||||
endpoint: ${AzureAI:Endpoint}
|
||||
options:
|
||||
temperature: 0.4
|
||||
tools:
|
||||
- type: openapi
|
||||
id: GetCurrentWeather
|
||||
description: Retrieves current weather data for a location based on wttr.in.
|
||||
options:
|
||||
specification: |
|
||||
{
|
||||
"openapi": "3.1.0",
|
||||
"info": {
|
||||
"title": "Get Weather Data",
|
||||
"description": "Retrieves current weather data for a location based on wttr.in.",
|
||||
"version": "v1.0.0"
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "https://wttr.in"
|
||||
}
|
||||
],
|
||||
"auth": [],
|
||||
"paths": {
|
||||
"/{location}": {
|
||||
"get": {
|
||||
"description": "Get weather information for a specific location",
|
||||
"operationId": "GetCurrentWeather",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "location",
|
||||
"in": "path",
|
||||
"description": "City or location to retrieve the weather for",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "format",
|
||||
"in": "query",
|
||||
"description": "Always use j1 value for this parameter",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"default": "j1"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful response",
|
||||
"content": {
|
||||
"text/plain": {
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Location not found"
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemes": {}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
yaml_openapi_spec = """
|
||||
type: foundry_agent
|
||||
name: WeatherAgent
|
||||
instructions: Answer questions about the weather. For all other questions politely decline to answer.
|
||||
description: This agent answers question about the weather.
|
||||
model:
|
||||
id: ${AzureAI:ChatModelId}
|
||||
options:
|
||||
temperature: 0.4
|
||||
tools:
|
||||
- type: openapi
|
||||
id: GetCurrentWeather
|
||||
description: Retrieves current weather data for a location based on wttr.in.
|
||||
options:
|
||||
specification:
|
||||
openapi: "3.1.0"
|
||||
info:
|
||||
title: "Get Weather Data"
|
||||
description: "Retrieves current weather data for a location based on wttr.in."
|
||||
version: "v1.0.0"
|
||||
servers:
|
||||
- url: "https://wttr.in"
|
||||
auth: []
|
||||
paths:
|
||||
"/{location}":
|
||||
get:
|
||||
description: "Get weather information for a specific location"
|
||||
operationId: "GetCurrentWeather"
|
||||
parameters:
|
||||
- name: "location"
|
||||
in: "path"
|
||||
description: "City or location to retrieve the weather for"
|
||||
required: true
|
||||
schema:
|
||||
type: "string"
|
||||
- name: "format"
|
||||
in: "query"
|
||||
description: "Always use j1 value for this parameter"
|
||||
required: true
|
||||
schema:
|
||||
type: "string"
|
||||
default: "j1"
|
||||
responses:
|
||||
"200":
|
||||
description: "Successful response"
|
||||
content:
|
||||
text/plain:
|
||||
schema:
|
||||
type: "string"
|
||||
"404":
|
||||
description: "Location not found"
|
||||
deprecated: false
|
||||
components:
|
||||
schemes: {}
|
||||
"""
|
||||
|
||||
settings = AzureAIAgentSettings() # ChatModelId & Endpoint come from .env/env vars
|
||||
|
||||
|
||||
async def main():
|
||||
async with (
|
||||
AzureCliCredential() as creds,
|
||||
AzureAIAgent.create_client(credential=creds) as client,
|
||||
):
|
||||
try:
|
||||
# Create the AzureAI Agent from the YAML spec
|
||||
agent: AzureAIAgent = await AgentRegistry.create_from_yaml(
|
||||
yaml_str=json_openapi_spec if USE_JSON_OPENAPI_SPEC else yaml_openapi_spec,
|
||||
client=client,
|
||||
settings=settings,
|
||||
)
|
||||
|
||||
# Define the task for the agent
|
||||
TASK = "What is the current weather in Seoul?"
|
||||
|
||||
print(f"# User: '{TASK}'")
|
||||
|
||||
# Invoke the agent for the specified task
|
||||
async for response in agent.invoke(
|
||||
messages=TASK,
|
||||
):
|
||||
print(f"# {response.name}: {response}")
|
||||
finally:
|
||||
# Cleanup: Delete the agent, vector store, and file
|
||||
await client.agents.delete_agent(agent.id)
|
||||
|
||||
"""
|
||||
Sample output:
|
||||
|
||||
# User: 'What is the current weather in Seoul?'
|
||||
# WeatherAgent: The current weather in Seoul is 14°C (57°F) with "light drizzle." It feels like 13°C (55°F).
|
||||
The humidity is at 81%, and there is heavy cloud cover (99%). The visibility is reduced to 2 km (1 mile),
|
||||
and the wind is coming from the east at 11 km/h (7 mph)
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import AgentRegistry, AzureAIAgent
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create an Azure AI Agent that invokes
|
||||
a story generation task using a prompt template and a declarative spec.
|
||||
"""
|
||||
|
||||
# Define the YAML string for the sample
|
||||
spec = """
|
||||
type: foundry_agent
|
||||
name: StoryAgent
|
||||
description: An agent that generates a story about a topic.
|
||||
instructions: Tell a story about {{$topic}} that is {{$length}} sentences long.
|
||||
model:
|
||||
id: ${AzureAI:ChatModelId}
|
||||
connection:
|
||||
connection_string: ${AzureAI:Endpoint}
|
||||
inputs:
|
||||
topic:
|
||||
description: The topic of the story.
|
||||
required: true
|
||||
default: Cats
|
||||
length:
|
||||
description: The number of sentences in the story.
|
||||
required: true
|
||||
default: 2
|
||||
outputs:
|
||||
output1:
|
||||
description: The generated story.
|
||||
template:
|
||||
format: semantic-kernel
|
||||
"""
|
||||
|
||||
|
||||
async def main():
|
||||
async with (
|
||||
AzureCliCredential() as creds,
|
||||
AzureAIAgent.create_client(credential=creds) as client,
|
||||
):
|
||||
try:
|
||||
# Create the AzureAI Agent from the YAML spec
|
||||
agent: AzureAIAgent = await AgentRegistry.create_from_yaml(
|
||||
yaml_str=spec,
|
||||
client=client,
|
||||
)
|
||||
|
||||
# Invoke the agent for the specified task
|
||||
async for response in agent.invoke(
|
||||
messages=None,
|
||||
):
|
||||
print(f"# {response.name}: {response}")
|
||||
finally:
|
||||
# Cleanup: Delete the agent, vector store, and file
|
||||
await client.agents.delete_agent(agent.id)
|
||||
|
||||
"""
|
||||
Sample output:
|
||||
|
||||
# StoryAgent: Under the silvery moon, three mischievous cats tiptoed across the rooftop, chasing
|
||||
shadows and sharing secret whispers. By dawn, they curled up together, purring softly, dreaming
|
||||
of adventures yet to come.
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import AgentRegistry, AzureAIAgent
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create an Azure AI agent based
|
||||
on an existing agent ID.
|
||||
"""
|
||||
|
||||
# Define the YAML string for the sample
|
||||
spec = """
|
||||
id: ${AzureAI:AgentId}
|
||||
type: foundry_agent
|
||||
instructions: You are helpful agent who always responds in French.
|
||||
"""
|
||||
|
||||
|
||||
async def main():
|
||||
async with (
|
||||
AzureCliCredential() as creds,
|
||||
AzureAIAgent.create_client(credential=creds) as client,
|
||||
):
|
||||
try:
|
||||
# Create the AzureAI Agent from the YAML spec
|
||||
# Note: the extras can be provided in the short-format (shown below) or
|
||||
# in the long-format (as shown in the YAML spec, with the `AzureAI:` prefix).
|
||||
# The short-format is used here for brevity
|
||||
agent: AzureAIAgent = await AgentRegistry.create_from_yaml(
|
||||
yaml_str=spec,
|
||||
client=client,
|
||||
extras={"AgentId": "<my-agent-id>"}, # Specify the existing agent ID
|
||||
)
|
||||
|
||||
# Define the task for the agent
|
||||
TASK = "Why is the sky blue?"
|
||||
|
||||
print(f"# User: '{TASK}'")
|
||||
|
||||
# Invoke the agent for the specified task
|
||||
async for response in agent.invoke(
|
||||
messages=TASK,
|
||||
):
|
||||
print(f"# {response.name}: {response}")
|
||||
finally:
|
||||
# Cleanup: Delete the thread and agent
|
||||
await client.agents.delete_agent(agent.id)
|
||||
|
||||
"""
|
||||
Sample output:
|
||||
|
||||
# User: 'Why is the sky blue?'
|
||||
# WeatherAgent: Le ciel est bleu à cause d'un phénomène appelé **diffusion de Rayleigh**. La lumière du
|
||||
Soleil est composée de toutes les couleurs du spectre visible, mais lorsqu'elle traverse l'atmosphère
|
||||
terrestre, elle entre en contact avec les molécules d'air et les particules présentes.
|
||||
|
||||
Les couleurs à courtes longueurs d'onde, comme le bleu et le violet, sont diffusées dans toutes les directions
|
||||
beaucoup plus efficacement que les couleurs à longues longueurs d'onde, comme le rouge et l'orange. Bien que le
|
||||
violet ait une longueur d'onde encore plus courte que le bleu, nos yeux sont moins sensibles à cette couleur,
|
||||
et une partie du violet est également absorbée par la haute atmosphère. Ainsi, le bleu domine, donnant au ciel
|
||||
sa couleur caractéristique.
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
|
||||
from azure.ai.agents.models import DeepResearchTool
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import AzureAIAgent, AzureAIAgentSettings, AzureAIAgentThread
|
||||
from semantic_kernel.contents import (
|
||||
ChatMessageContent,
|
||||
FunctionCallContent,
|
||||
FunctionResultContent,
|
||||
StreamingAnnotationContent,
|
||||
)
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create an AzureAIAgent along
|
||||
with the Deep Research Tool. Please visit the following documentation for more info
|
||||
on what is required to run the sample: https://aka.ms/agents-deep-research. Please pay
|
||||
attention to the purple `Note` boxes in the Azure docs.
|
||||
|
||||
Note that when you use your Bing Connection ID, it needs to be the connection ID from the project, not the resource.
|
||||
It has the following format:
|
||||
|
||||
'/subscriptions/<sub_id>/resourceGroups/<rg_name>/providers/<provider_name>/accounts/<account_name>/projects/<project_name>/connections/<connection_name>'
|
||||
"""
|
||||
|
||||
TASK = (
|
||||
"Research the current state of studies on orca intelligence and orca language, "
|
||||
"including what is currently known about orcas' cognitive capabilities and communication systems."
|
||||
)
|
||||
|
||||
|
||||
async def handle_intermediate_messages(message: ChatMessageContent) -> None:
|
||||
for item in message.items or []:
|
||||
if isinstance(item, FunctionResultContent):
|
||||
print(f"Function Result:> {item.result} for function: {item.name}")
|
||||
elif isinstance(item, FunctionCallContent):
|
||||
print(f"Function Call:> {item.name} with arguments: {item.arguments}")
|
||||
elif isinstance(item, StreamingAnnotationContent):
|
||||
label = item.title or item.url or "Annotation"
|
||||
print(f"Annotation:> {label} ({item.citation_type}) -> {item.url}")
|
||||
else:
|
||||
print(f"{item}")
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
async with (
|
||||
AzureCliCredential() as creds,
|
||||
AzureAIAgent.create_client(credential=creds) as client,
|
||||
):
|
||||
azure_ai_agent_settings = AzureAIAgentSettings()
|
||||
# 1. Define the Deep Research tool
|
||||
deep_research_tool = DeepResearchTool(
|
||||
bing_grounding_connection_id=azure_ai_agent_settings.bing_connection_id,
|
||||
deep_research_model=azure_ai_agent_settings.deep_research_model,
|
||||
)
|
||||
|
||||
# 2. Create an agent with the tool on the Azure AI agent service
|
||||
agent_definition = await client.agents.create_agent(
|
||||
model="gpt-4o", # Deep Research requires the use of gpt-4o for scope clarification.
|
||||
tools=deep_research_tool.definitions,
|
||||
instructions="You are a helpful Agent that assists in researching scientific topics.",
|
||||
)
|
||||
|
||||
# 3. Create a Semantic Kernel agent for the Azure AI agent
|
||||
agent = AzureAIAgent(client=client, definition=agent_definition, name="DeepResearchAgent")
|
||||
|
||||
# 4. 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 = None
|
||||
|
||||
try:
|
||||
print(f"# User: '{TASK}'")
|
||||
# 5. Invoke the agent for the specified thread for response
|
||||
first_chunk = True
|
||||
async for response in agent.invoke_stream(
|
||||
messages=TASK,
|
||||
thread=thread,
|
||||
on_intermediate_message=handle_intermediate_messages,
|
||||
):
|
||||
if first_chunk:
|
||||
print(f"# {response.name}: ", end="", flush=True)
|
||||
first_chunk = False
|
||||
# Print the text chunk
|
||||
print(f"{response}", end="", flush=True)
|
||||
# Print any streaming annotations that may arrive in this chunk
|
||||
for item in response.items or []:
|
||||
if isinstance(item, StreamingAnnotationContent):
|
||||
label = item.title or item.url or (item.quote or "Annotation")
|
||||
print(f"\n[Annotation] {label} -> {item.url}")
|
||||
thread = response.thread
|
||||
print()
|
||||
finally:
|
||||
# 6. Cleanup: Delete the thread, agent, and file
|
||||
await thread.delete() if thread else None
|
||||
await client.agents.delete_agent(agent.id)
|
||||
|
||||
"""
|
||||
Sample Output:
|
||||
|
||||
# User: 'Research the current state of studies on orca intelligence and orca language, including what is
|
||||
currently known about orcas' cognitive capabilities and communication systems.'
|
||||
Function Call:> deep_research with arguments: {'input': '{"prompt": "Research the current state of studies on
|
||||
orca intelligence and orca communication, focusing on their cognitive capabilities and language systems.
|
||||
Provide an overview of key discoveries, critical experiments, and major conclusions about their
|
||||
intelligence and communication systems. Prioritize primary research papers, reputable academic sources,
|
||||
and recent updates in the field (from the past 5 years if available). Format as a structured report with
|
||||
appropriate headings for clarity, and respond in English."}'}
|
||||
# azure_agent_QhTQHlUs: Title: Current Studies on Orca Intelligence and Communication
|
||||
|
||||
Starting deep research...
|
||||
|
||||
The user's task is to research orca intelligence, focusing on cognitive capabilities and communication.
|
||||
【1†Bing Search】
|
||||
|
||||
[Annotation] Bing Search: 'orca communication research 2020 killer whale cognitive study' -> https://www.bing.com/search?q=orca%20communication%20research%202020%20killer%20whale%20cognitive%20study
|
||||
|
||||
**Weighing options**
|
||||
|
||||
I'm examining the research on orca social dynamics, comparing a potential review to a recent journal article
|
||||
on large-scale unsupervised clustering of orca calls.
|
||||
|
||||
**Investigating orca datasets**
|
||||
|
||||
OK, let me see. PDF, Interspeech 2020, "ORCA-CLEAN: A Deep Denoising Toolkit for Killer Whale Communication"
|
||||
seems relevant. They focus on cognitive capabilities, language systems, and communication.
|
||||
|
||||
I'm considering if the PDF is relevant and may not need it. ResearchGate's content might need a login
|
||||
to access. 【1†Bing Search】
|
||||
|
||||
[Annotation] Bing Search: '"Social Dynamics and Intelligence of Killer Whales (Orcinus orca)"' -> https://www.bing.com/search?q=%22Social%20Dynamics%20and%20Intelligence%20of%20Killer%20Whales%20%28Orcinus%20orca%29%22
|
||||
|
||||
**Evaluating sources**
|
||||
|
||||
I'm gathering info on "Social Dynamics and Intelligence of Killer Whales," weighing access to PDFs through
|
||||
ResearchGate, and considering associated online references for credibility.
|
||||
|
||||
**Considering capabilities**
|
||||
|
||||
I'm piecing together the intricacies of killer whale creativity under chemical stimuli, as explored
|
||||
in "Manitzas, Hill, et al 2022." Would love to learn more about their findings.
|
||||
|
||||
**Exploring external options**
|
||||
I'm weighing opening the PDF directly or using an external search. 【1†Bing Search】
|
||||
|
||||
[Annotation] Bing Search: 'Manitzas Hill 2022 killer whale creativity cognitive abilities' -> https://www.bing.com/search?q=Manitzas%20Hill%202022%20killer%20whale%20creativity%20cognitive%20abilities
|
||||
|
||||
...
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,88 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
from azure.ai.agents.models import CodeInterpreterTool, FilePurpose
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import AzureAIAgent, AzureAIAgentSettings, AzureAIAgentThread
|
||||
from semantic_kernel.contents.annotation_content import AnnotationContent
|
||||
from semantic_kernel.contents.utils.author_role import AuthorRole
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create a simple,
|
||||
Azure AI agent that uses the code interpreter tool to answer
|
||||
a coding question.
|
||||
"""
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
ai_agent_settings = AzureAIAgentSettings()
|
||||
|
||||
async with (
|
||||
AzureCliCredential() as creds,
|
||||
AzureAIAgent.create_client(credential=creds, endpoint=ai_agent_settings.endpoint) as client,
|
||||
):
|
||||
csv_file_path = os.path.join(
|
||||
os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))),
|
||||
"resources",
|
||||
"agent_assistant_file_manipulation",
|
||||
"sales.csv",
|
||||
)
|
||||
|
||||
file = await client.agents.files.upload_and_poll(file_path=csv_file_path, purpose=FilePurpose.AGENTS)
|
||||
|
||||
code_interpreter = CodeInterpreterTool(file_ids=[file.id])
|
||||
|
||||
# Create agent definition
|
||||
agent_definition = await client.agents.create_agent(
|
||||
model=ai_agent_settings.model_deployment_name,
|
||||
tools=code_interpreter.definitions,
|
||||
tool_resources=code_interpreter.resources,
|
||||
)
|
||||
|
||||
# Create the AzureAI Agent
|
||||
agent = AzureAIAgent(
|
||||
client=client,
|
||||
definition=agent_definition,
|
||||
)
|
||||
|
||||
# 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 = [
|
||||
"Which segment had the most sales?",
|
||||
"List the top 5 countries that generated the most profit.",
|
||||
"Create a tab delimited file report of profit by each country per month.",
|
||||
]
|
||||
|
||||
try:
|
||||
for user_input in user_inputs:
|
||||
print(f"# User: '{user_input}'")
|
||||
# Invoke the agent for the specified user input
|
||||
async for response in agent.invoke(messages=user_input, thread=thread):
|
||||
if response.role != AuthorRole.TOOL:
|
||||
print(f"# Agent: {response}")
|
||||
if len(response.items) > 0:
|
||||
for item in response.items:
|
||||
# Show Annotation Content if it exist
|
||||
if isinstance(item, AnnotationContent):
|
||||
print(f"\n`{item.quote}` => {item.file_id}")
|
||||
response_content = await client.agents.get_file_content(file_id=item.file_id)
|
||||
content_bytes = bytearray()
|
||||
async for chunk in response_content:
|
||||
content_bytes.extend(chunk)
|
||||
tab_delimited_text = content_bytes.decode("utf-8")
|
||||
print(tab_delimited_text)
|
||||
thread = response.thread
|
||||
finally:
|
||||
# Cleanup: Delete the thread and agent
|
||||
await thread.delete() if thread else None
|
||||
await client.agents.delete_agent(agent.id)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,121 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
|
||||
from azure.ai.agents.models import McpTool
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import AzureAIAgent, AzureAIAgentSettings, AzureAIAgentThread
|
||||
from semantic_kernel.contents import ChatMessageContent, FunctionCallContent, FunctionResultContent
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create a simple, Azure AI agent that
|
||||
uses the mcp tool to connect to an mcp server with streaming responses.
|
||||
"""
|
||||
|
||||
TASK = "Please summarize the Azure REST API specifications Readme"
|
||||
|
||||
|
||||
async def handle_intermediate_messages(message: ChatMessageContent) -> None:
|
||||
for item in message.items or []:
|
||||
if isinstance(item, FunctionResultContent):
|
||||
print(f"Function Result:> {item.result} for function: {item.name}")
|
||||
elif isinstance(item, FunctionCallContent):
|
||||
print(f"Function Call:> {item.name} with arguments: {item.arguments}")
|
||||
else:
|
||||
print(f"{item}")
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
async with (
|
||||
AzureCliCredential() as creds,
|
||||
AzureAIAgent.create_client(credential=creds) as client,
|
||||
):
|
||||
# 1. Define the MCP tool with the server URL
|
||||
mcp_tool = McpTool(
|
||||
server_label="github",
|
||||
server_url="https://gitmcp.io/Azure/azure-rest-api-specs",
|
||||
allowed_tools=[], # Specify allowed tools if needed
|
||||
)
|
||||
|
||||
# Optionally you may configure to require approval
|
||||
# Allowed values are "never" or "always"
|
||||
mcp_tool.set_approval_mode("never")
|
||||
|
||||
# 2. Create an agent with the MCP tool on the Azure AI agent service
|
||||
agent_definition = await client.agents.create_agent(
|
||||
model=AzureAIAgentSettings().model_deployment_name,
|
||||
tools=mcp_tool.definitions,
|
||||
instructions="You are a helpful agent that can use MCP tools to assist users.",
|
||||
)
|
||||
|
||||
# 3. Create a Semantic Kernel agent for the Azure AI agent
|
||||
agent = AzureAIAgent(
|
||||
client=client,
|
||||
definition=agent_definition,
|
||||
)
|
||||
|
||||
# 4. 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 = None
|
||||
|
||||
try:
|
||||
print(f"# User: '{TASK}'")
|
||||
# 5. Invoke the agent for the specified thread for response
|
||||
async for response in agent.invoke_stream(
|
||||
messages=TASK,
|
||||
thread=thread,
|
||||
on_intermediate_message=handle_intermediate_messages,
|
||||
):
|
||||
print(f"{response}", end="", flush=True)
|
||||
thread = response.thread
|
||||
finally:
|
||||
# 6. Cleanup: Delete the thread, agent, and file
|
||||
await thread.delete() if thread else None
|
||||
await client.agents.delete_agent(agent.id)
|
||||
|
||||
"""
|
||||
Sample Output:
|
||||
|
||||
# User: 'Please summarize the Azure REST API specifications Readme'
|
||||
Function Call:> fetch_azure_rest_api_docs with arguments: {}
|
||||
The Azure REST API specifications Readme provides comprehensive documentation and guidelines for designing,
|
||||
authoring, validating, and evolving Azure REST APIs. It covers key areas including:
|
||||
|
||||
1. Breaking changes and versioning: Guidelines to manage API changes that break backward compatibility, when to
|
||||
increment API versions, and how to maintain smooth API evolution.
|
||||
|
||||
2. OpenAPI/Swagger specifications: How to author REST APIs using OpenAPI specification 2.0 (Swagger), including
|
||||
structure, conventions, validation tools, and extensions used by AutoRest for generating client SDKs.
|
||||
|
||||
3. TypeSpec language: Introduction to TypeSpec, a powerful language for describing and generating REST API
|
||||
specifications and client SDKs with extensibility to other API styles.
|
||||
|
||||
4. Directory structure and uniform versioning: Organizing service specifications by teams, resource provider
|
||||
namespaces, and following uniform versioning to keep API versions consistent across documentation and SDKs.
|
||||
|
||||
5. Validation and tooling: Tools and processes like OAV, AutoRest, RESTler, and CI checks used to validate API
|
||||
specs, generate SDKs, detect breaking changes, lint specifications, and test service contract accuracy.
|
||||
|
||||
6. Authoring best practices: Manual and automated guidelines for quality API spec authoring, including writing
|
||||
effective descriptions, resource modeling, naming conventions, and examples.
|
||||
|
||||
7. Code generation configurations: How to configure readme files to generate SDKs for various languages
|
||||
including .NET, Java, Python, Go, Typescript, and Azure CLI using AutoRest.
|
||||
|
||||
8. API Scenarios and testing: Defining API scenario test files for end-to-end REST API workflows, including
|
||||
variables, ARM template integration, and usage of test-proxy for recording traffic.
|
||||
|
||||
9. SDK automation and release requests: Workflows for SDK generation validation, suppressing breaking change
|
||||
warnings, and requesting official Azure SDK releases.
|
||||
|
||||
Overall, the Readme acts as a central hub providing references, guidelines, examples, and tools for maintaining
|
||||
high-quality Azure REST API specifications and seamless SDK generation across multiple languages and
|
||||
platforms. It ensures consistent API design, versioning, validation, and developer experience in the Azure
|
||||
ecosystem.
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,132 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
from typing import Annotated
|
||||
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
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
|
||||
|
||||
"""
|
||||
This sample demonstrates how to create an Azure AI Agent and invoke it using the non-streaming `invoke()` method.
|
||||
|
||||
While `invoke()` returns only the final assistant message, the agent can optionally emit intermediate messages
|
||||
(e.g., function calls and results) via a callback by supplying `on_intermediate_message`.
|
||||
|
||||
In this example, the agent is configured with a plugin that provides menu specials and item pricing. As the user
|
||||
asks about the menu, the agent performs tool calls mid-invocation, and those intermediate steps are surfaced
|
||||
via the callback function while the invocation is still in progress.
|
||||
"""
|
||||
|
||||
|
||||
# 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"
|
||||
|
||||
|
||||
# This callback function will be called for each intermediate message,
|
||||
# which will allow one to handle FunctionCallContent and FunctionResultContent.
|
||||
# If the callback is not provided, the agent will return the final response
|
||||
# with no intermediate tool call steps.
|
||||
async def handle_intermediate_steps(message: ChatMessageContent) -> None:
|
||||
for item in message.items or []:
|
||||
if isinstance(item, FunctionResultContent):
|
||||
print(f"Function Result:> {item.result} for function: {item.name}")
|
||||
elif isinstance(item, FunctionCallContent):
|
||||
print(f"Function Call:> {item.name} with arguments: {item.arguments}")
|
||||
else:
|
||||
print(f"{item}")
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
ai_agent_settings = AzureAIAgentSettings()
|
||||
|
||||
async with (
|
||||
AzureCliCredential() as creds,
|
||||
AzureAIAgent.create_client(credential=creds, endpoint=ai_agent_settings.endpoint) 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)
|
||||
|
||||
"""
|
||||
Sample Output:
|
||||
|
||||
# User: 'Hello'
|
||||
# Agent: Hi there! How can I assist you today?
|
||||
# User: 'What is the special soup?'
|
||||
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
|
||||
# Agent: The special soup is Clam Chowder. Would you like to know anything else about the menu?
|
||||
# User: 'How much does that cost?'
|
||||
Function Call:> MenuPlugin-get_item_price with arguments: {"menu_item":"Clam Chowder"}
|
||||
Function Result:> $9.99 for function: MenuPlugin-get_item_price
|
||||
# Agent: The Clam Chowder costs $9.99. Let me know if you'd like assistance with anything else!
|
||||
# User: 'Thank you'
|
||||
# Agent: You're welcome! Enjoy your meal! 😊
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
from typing import Annotated
|
||||
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import AzureAIAgent, AzureAIAgentSettings, AzureAIAgentThread
|
||||
from semantic_kernel.contents import ChatMessageContent, FunctionCallContent, FunctionResultContent
|
||||
from semantic_kernel.core_plugins import MathPlugin
|
||||
from semantic_kernel.functions import kernel_function
|
||||
|
||||
"""
|
||||
This sample demonstrates how to create an Azure AI Agent and use it with the streaming `invoke_stream()` method.
|
||||
|
||||
The agent returns assistant messages as a stream of incremental chunks. In addition, you can specify
|
||||
an `on_intermediate_message` callback to receive fully-formed tool-related messages — such as function
|
||||
calls and their results — while the assistant response is still being streamed.
|
||||
|
||||
In this example, the agent is configured with a plugin that provides menu specials and item pricing.
|
||||
As the user interacts with the agent, tool messages (like function calls) are emitted via the callback,
|
||||
while assistant replies stream back incrementally through the main response loop.
|
||||
"""
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
|
||||
# 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"
|
||||
|
||||
|
||||
# This callback function will be called for each intermediate message,
|
||||
# which will allow one to handle FunctionCallContent and FunctionResultContent.
|
||||
# If the callback is not provided, the agent will return the final response
|
||||
# with no intermediate tool call steps.
|
||||
async def handle_streaming_intermediate_steps(message: ChatMessageContent) -> None:
|
||||
for item in message.items or []:
|
||||
if isinstance(item, FunctionResultContent):
|
||||
print(f"Function Result:> {item.result} for function: {item.name}")
|
||||
elif isinstance(item, FunctionCallContent):
|
||||
print(f"Function Call:> {item.name} with arguments: {item.arguments}")
|
||||
else:
|
||||
print(f"{item}")
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
ai_agent_settings = AzureAIAgentSettings()
|
||||
|
||||
async with (
|
||||
AzureCliCredential() as creds,
|
||||
AzureAIAgent.create_client(credential=creds, endpoint=ai_agent_settings.endpoint) as client,
|
||||
):
|
||||
# Create agent definition
|
||||
agent_definition = await client.agents.create_agent(
|
||||
model=ai_agent_settings.model_deployment_name,
|
||||
name="Host",
|
||||
instructions="Answer questions from the user using your provided functions. You must invoke multiple functions to answer the user's questions. ", # noqa: E501
|
||||
)
|
||||
|
||||
# Create the AzureAI Agent
|
||||
agent = AzureAIAgent(
|
||||
client=client,
|
||||
definition=agent_definition,
|
||||
plugins=[MenuPlugin(), MathPlugin()],
|
||||
)
|
||||
|
||||
# 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 = [
|
||||
"What is the price of the special drink and the special food item added together?",
|
||||
]
|
||||
|
||||
try:
|
||||
for user_input in user_inputs:
|
||||
print(f"# User: '{user_input}'")
|
||||
first_chunk = True
|
||||
async for response in agent.invoke_stream(
|
||||
messages=user_input,
|
||||
thread=thread,
|
||||
on_intermediate_message=handle_streaming_intermediate_steps,
|
||||
):
|
||||
if first_chunk:
|
||||
print(f"# {response.role}: ", end="", flush=True)
|
||||
first_chunk = False
|
||||
print(response.content, end="", flush=True)
|
||||
thread = response.thread
|
||||
print()
|
||||
finally:
|
||||
# Cleanup: Delete the thread and agent
|
||||
await thread.delete() if thread else None
|
||||
await client.agents.delete_agent(agent.id)
|
||||
|
||||
"""
|
||||
Sample Output:
|
||||
|
||||
# User: 'What is the price of the special drink and then special food item added together?'
|
||||
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": "Chai Tea"}
|
||||
Function Call:> MenuPlugin-get_item_price with arguments: {"menu_item": "Clam Chowder"}
|
||||
Function Result:> $9.99 for function: MenuPlugin-get_item_price
|
||||
Function Result:> $9.99 for function: MenuPlugin-get_item_price
|
||||
Function Call:> MathPlugin-Add with arguments: {"input":9.99,"amount":9.99}
|
||||
Function Result:> 19.98 for function: MathPlugin-Add
|
||||
# AuthorRole.ASSISTANT: The price of the special drink, Chai Tea, is $9.99 and the price of the special food
|
||||
item, Clam Chowder, is $9.99. Added together, the total price is $19.98.
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,111 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import AzureAIAgent, AzureAIAgentSettings
|
||||
from semantic_kernel.functions import KernelArguments
|
||||
from semantic_kernel.prompt_template import PromptTemplateConfig
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create an Azure AI
|
||||
agent using Azure OpenAI within Semantic Kernel.
|
||||
It uses parameterized prompts and shows how to swap between
|
||||
"semantic-kernel," "jinja2," and "handlebars" template formats,
|
||||
This sample highlights the agent's prompt templates are managed
|
||||
and how kernel arguments are passed in and used.
|
||||
"""
|
||||
|
||||
# Define the inputs and styles to be used in the agent
|
||||
inputs = [
|
||||
("Home cooking is great.", None),
|
||||
("Talk about world peace.", "iambic pentameter"),
|
||||
("Say something about doing your best.", "e. e. cummings"),
|
||||
("What do you think about having fun?", "old school rap"),
|
||||
]
|
||||
|
||||
|
||||
async def invoke_chat_completion_agent(agent: AzureAIAgent, inputs):
|
||||
"""Invokes the given agent with each (input, style) in inputs."""
|
||||
|
||||
thread = None
|
||||
|
||||
for user_input, style in inputs:
|
||||
print(f"[USER]: {user_input}\n")
|
||||
|
||||
# If style is specified, override the 'style' argument
|
||||
argument_overrides = None
|
||||
if style:
|
||||
argument_overrides = KernelArguments(style=style)
|
||||
|
||||
# Stream agent responses
|
||||
async for response in agent.invoke_stream(messages=user_input, thread=thread, arguments=argument_overrides):
|
||||
print(f"{response.content}", end="", flush=True)
|
||||
thread = response.thread
|
||||
print("\n")
|
||||
|
||||
|
||||
async def invoke_agent_with_template(template_str: str, template_format: str, default_style: str = "haiku"):
|
||||
"""Creates an agent with the specified template and format, then invokes it using invoke_chat_completion_agent."""
|
||||
|
||||
# Configure the prompt template
|
||||
prompt_config = PromptTemplateConfig(template=template_str, template_format=template_format)
|
||||
|
||||
ai_agent_settings = AzureAIAgentSettings()
|
||||
|
||||
async with (
|
||||
AzureCliCredential() as creds,
|
||||
AzureAIAgent.create_client(credential=creds, endpoint=ai_agent_settings.endpoint) as client,
|
||||
):
|
||||
# Create agent definition
|
||||
agent_definition = await client.agents.create_agent(
|
||||
model=ai_agent_settings.model_deployment_name,
|
||||
name="MyPoetAgent",
|
||||
)
|
||||
|
||||
# Create the AzureAI Agent
|
||||
agent = AzureAIAgent(
|
||||
client=client,
|
||||
definition=agent_definition,
|
||||
prompt_template_config=prompt_config,
|
||||
arguments=KernelArguments(style=default_style),
|
||||
)
|
||||
|
||||
await invoke_chat_completion_agent(agent, inputs)
|
||||
|
||||
|
||||
async def main():
|
||||
# 1) Using "semantic-kernel" format
|
||||
print("\n===== SEMANTIC-KERNEL FORMAT =====\n")
|
||||
semantic_kernel_template = """
|
||||
Write a one verse poem on the requested topic in the style of {{$style}}.
|
||||
Always state the requested style of the poem.
|
||||
"""
|
||||
await invoke_agent_with_template(
|
||||
template_str=semantic_kernel_template,
|
||||
template_format="semantic-kernel",
|
||||
default_style="haiku",
|
||||
)
|
||||
|
||||
# 2) Using "jinja2" format
|
||||
print("\n===== JINJA2 FORMAT =====\n")
|
||||
jinja2_template = """
|
||||
Write a one verse poem on the requested topic in the style of {{style}}.
|
||||
Always state the requested style of the poem.
|
||||
"""
|
||||
await invoke_agent_with_template(template_str=jinja2_template, template_format="jinja2", default_style="haiku")
|
||||
|
||||
# 3) Using "handlebars" format
|
||||
print("\n===== HANDLEBARS FORMAT =====\n")
|
||||
handlebars_template = """
|
||||
Write a one verse poem on the requested topic in the style of {{style}}.
|
||||
Always state the requested style of the poem.
|
||||
"""
|
||||
await invoke_agent_with_template(
|
||||
template_str=handlebars_template, template_format="handlebars", default_style="haiku"
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
from typing import Annotated
|
||||
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import AzureAIAgent, AzureAIAgentSettings, AzureAIAgentThread
|
||||
from semantic_kernel.functions import kernel_function
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create an Azure AI agent that answers
|
||||
questions about a sample menu using a Semantic Kernel Plugin. After all questions
|
||||
are answered, it retrieves and prints the messages from the thread.
|
||||
"""
|
||||
|
||||
|
||||
# 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?",
|
||||
"How much does that cost?",
|
||||
"Thank you",
|
||||
]
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
async with (
|
||||
AzureCliCredential() as creds,
|
||||
AzureAIAgent.create_client(credential=creds) as client,
|
||||
):
|
||||
# 1. Create an agent on the Azure AI agent service
|
||||
agent_definition = await client.agents.create_agent(
|
||||
model=AzureAIAgentSettings().model_deployment_name,
|
||||
name="Host",
|
||||
instructions="Answer questions about the menu.",
|
||||
)
|
||||
|
||||
# 2. Create a Semantic Kernel agent for the Azure AI agent
|
||||
agent = AzureAIAgent(
|
||||
client=client,
|
||||
definition=agent_definition,
|
||||
plugins=[MenuPlugin()], # Add the plugin to the agent
|
||||
)
|
||||
|
||||
# 3. 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 = None
|
||||
|
||||
try:
|
||||
for user_input in USER_INPUTS:
|
||||
print(f"# User: {user_input}")
|
||||
# 4. Invoke the agent for the specified thread for response
|
||||
async for response in agent.invoke(
|
||||
messages=user_input,
|
||||
thread=thread,
|
||||
):
|
||||
print(f"# {response.name}: {response}")
|
||||
thread = response.thread
|
||||
finally:
|
||||
# 5. Cleanup: Delete the thread and agent
|
||||
# await thread.delete() if thread else None
|
||||
await client.agents.delete_agent(agent.id)
|
||||
|
||||
print("*" * 50)
|
||||
print("# Messages in the thread (asc order):\n")
|
||||
async for msg in thread.get_messages(sort_order="asc"):
|
||||
print(f"# {msg.role} for name={msg.name}: {msg.content}")
|
||||
print("*" * 50)
|
||||
|
||||
await thread.delete() if thread else None
|
||||
|
||||
"""
|
||||
# User: Hello
|
||||
# Host: Hello! How can I assist you with the menu today?
|
||||
# User: What is the special soup?
|
||||
# Host: The special soup today is Clam Chowder. Would you like to know more about it or anything else
|
||||
on the menu?
|
||||
# User: How much does that cost?
|
||||
# Host: The Clam Chowder costs $9.99. Would you like to order it or need information on other items?
|
||||
# User: Thank you
|
||||
# Host: You're welcome! If you have any more questions or need assistance with the menu, feel free to ask.
|
||||
Enjoy your meal!
|
||||
**************************************************
|
||||
# Messages in the thread (asc order):
|
||||
|
||||
# AuthorRole.USER for name=asst_mXwZOwyJLxXGtaYKHizRH6Ip: Hello
|
||||
# AuthorRole.ASSISTANT for name=asst_mXwZOwyJLxXGtaYKHizRH6Ip: Hello! How can I assist you with the menu today?
|
||||
# AuthorRole.USER for name=asst_mXwZOwyJLxXGtaYKHizRH6Ip: What is the special soup?
|
||||
# AuthorRole.ASSISTANT for name=asst_mXwZOwyJLxXGtaYKHizRH6Ip: The special soup today is Clam Chowder. Would
|
||||
you like to know more about it or anything else on the menu?
|
||||
# AuthorRole.USER for name=asst_mXwZOwyJLxXGtaYKHizRH6Ip: How much does that cost?
|
||||
# AuthorRole.ASSISTANT for name=asst_mXwZOwyJLxXGtaYKHizRH6Ip: The Clam Chowder costs $9.99. Would you like to
|
||||
order it or need information on other items?
|
||||
# AuthorRole.USER for name=asst_mXwZOwyJLxXGtaYKHizRH6Ip: Thank you
|
||||
# AuthorRole.ASSISTANT for name=asst_mXwZOwyJLxXGtaYKHizRH6Ip: You're welcome! If you have any more questions
|
||||
or need assistance with the menu, feel free to ask. Enjoy your meal!
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,120 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
from typing import Annotated
|
||||
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import AzureAIAgent, AzureAIAgentSettings, AzureAIAgentThread
|
||||
from semantic_kernel.functions import kernel_function
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create an Azure AI Agent
|
||||
and use it with streaming responses. 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. The thread message ID is also printed as each
|
||||
message is processed.
|
||||
"""
|
||||
|
||||
|
||||
# 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"
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
ai_agent_settings = AzureAIAgentSettings()
|
||||
|
||||
async with (
|
||||
AzureCliCredential() as creds,
|
||||
AzureAIAgent.create_client(credential=creds, endpoint=ai_agent_settings.endpoint) 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:
|
||||
last_thread_msg_id = None
|
||||
for user_input in user_inputs:
|
||||
print(f"# User: '{user_input}'")
|
||||
first_chunk = True
|
||||
async for response in agent.invoke_stream(
|
||||
messages=user_input,
|
||||
thread=thread,
|
||||
):
|
||||
if first_chunk:
|
||||
print(f"# {response.role}: ", end="", flush=True)
|
||||
# Show the thread message id before the first text chunk
|
||||
if "thread_message_id" in response.content.metadata:
|
||||
current_id = response.content.metadata["thread_message_id"]
|
||||
if current_id != last_thread_msg_id:
|
||||
print(f"(thread message id: {current_id}) ", end="", flush=True)
|
||||
last_thread_msg_id = current_id
|
||||
first_chunk = False
|
||||
print(response.content, end="", flush=True)
|
||||
thread = response.thread
|
||||
print()
|
||||
finally:
|
||||
# Cleanup: Delete the thread and agent
|
||||
await thread.delete() if thread else None
|
||||
await client.agents.delete_agent(agent.id)
|
||||
|
||||
"""
|
||||
Sample Output:
|
||||
|
||||
# User: 'Hello'
|
||||
# AuthorRole.ASSISTANT: (thread message id: msg_HZ2h4Wzbj7GEcnVCjnyEuYWT) Hello! How can I assist you with
|
||||
the menu today?
|
||||
# User: 'What is the special soup?'
|
||||
# AuthorRole.ASSISTANT: (thread message id: msg_TSjkJK6hHJojIkPvF6uUofHD) The special soup today is
|
||||
Clam Chowder. Would you like to know more about it or anything else from the menu?
|
||||
# User: 'How much does that cost?'
|
||||
# AuthorRole.ASSISTANT: (thread message id: msg_liwTpBFrB9JpCM1oM9EXKiwq) The Clam Chowder costs $9.99.
|
||||
Is there anything else you'd like to know?
|
||||
# User: 'Thank you'
|
||||
# AuthorRole.ASSISTANT: (thread message id: msg_K6lpR3gYIHethXq17T6gJcxi) You're welcome!
|
||||
If you have any more questions or need assistance, feel free to ask. Enjoy your meal!
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,93 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
from enum import Enum
|
||||
|
||||
from azure.ai.agents.models import (
|
||||
ResponseFormatJsonSchema,
|
||||
ResponseFormatJsonSchemaType,
|
||||
)
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
from pydantic import BaseModel
|
||||
|
||||
from semantic_kernel.agents import (
|
||||
AzureAIAgent,
|
||||
AzureAIAgentSettings,
|
||||
)
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create an Azure AI Agent
|
||||
and leverage the agent's ability to return structured outputs,
|
||||
based on a user-defined Pydantic model.
|
||||
"""
|
||||
|
||||
|
||||
# Define a Pydantic model that represents the structured output from the agent
|
||||
class Planets(str, Enum):
|
||||
Earth = "Earth"
|
||||
Mars = "Mars"
|
||||
Jupyter = "Jupyter"
|
||||
|
||||
|
||||
class Planet(BaseModel):
|
||||
planet: Planets
|
||||
mass: float
|
||||
|
||||
|
||||
async def main():
|
||||
ai_agent_settings = AzureAIAgentSettings()
|
||||
async with (
|
||||
AzureCliCredential() as creds,
|
||||
AzureAIAgent.create_client(credential=creds, endpoint=ai_agent_settings.endpoint) as client,
|
||||
):
|
||||
# Create the agent definition
|
||||
agent_definition = await client.agents.create_agent(
|
||||
model=ai_agent_settings.model_deployment_name,
|
||||
name="Assistant",
|
||||
instructions="Extract the information about planets.",
|
||||
response_format=ResponseFormatJsonSchemaType(
|
||||
json_schema=ResponseFormatJsonSchema(
|
||||
name="planet_mass",
|
||||
description="Extract planet mass.",
|
||||
schema=Planet.model_json_schema(),
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
# Create the AzureAI Agent
|
||||
agent = AzureAIAgent(
|
||||
client=client,
|
||||
definition=agent_definition,
|
||||
)
|
||||
|
||||
# Create a new thread for use with the assistant
|
||||
# If no thread is provided, a new thread will be
|
||||
# created and returned with the initial response
|
||||
thread = None
|
||||
|
||||
user_inputs = ["The mass of the Mars is 6.4171E23 kg; the mass of the Earth is 5.972168E24 kg;"]
|
||||
|
||||
try:
|
||||
for user_input in user_inputs:
|
||||
print(f"# User: '{user_input}'")
|
||||
async for response in agent.invoke(messages=user_input, thread=thread):
|
||||
# The response returned is a Pydantic Model, so we can validate it using the
|
||||
# model_validate_json method
|
||||
response_model = Planet.model_validate_json(str(response.content))
|
||||
print(f"# {response.role}: {response_model}")
|
||||
thread = response.thread
|
||||
finally:
|
||||
await thread.delete() if thread else None
|
||||
await client.agents.delete_agent(agent_definition.id)
|
||||
|
||||
"""
|
||||
Sample Output:
|
||||
|
||||
# User: 'The mass of the Mars is 6.4171E23 kg; the mass of the Earth is 5.972168E24 kg;'
|
||||
# AuthorRole.ASSISTANT: planet=<Planets.Earth: 'Earth'> mass=5.972168e+24
|
||||
# AuthorRole.ASSISTANT: planet=<Planets.Mars: 'Mars'> mass=6.4171e+23
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,82 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
|
||||
from azure.ai.agents.models import TruncationObject
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import (
|
||||
AzureAIAgent,
|
||||
AzureAIAgentSettings,
|
||||
AzureAIAgentThread,
|
||||
)
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create an Azure AI Agent Agent
|
||||
and configure a truncation strategy for the agent.
|
||||
"""
|
||||
|
||||
USER_INPUTS = [
|
||||
"Why is the sky blue?",
|
||||
"What is the speed of light?",
|
||||
"What have we been talking about?",
|
||||
]
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
ai_agent_settings = AzureAIAgentSettings.create()
|
||||
|
||||
async with (
|
||||
AzureCliCredential() as creds,
|
||||
AzureAIAgent.create_client(credential=creds, endpoint=ai_agent_settings.endpoint) as client,
|
||||
):
|
||||
# Create the agent definition
|
||||
agent_definition = await client.agents.create_agent(
|
||||
model=ai_agent_settings.model_deployment_name,
|
||||
name="TruncateAgent",
|
||||
instructions="You are a helpful assistant that answers user questions in one sentence.",
|
||||
)
|
||||
|
||||
# Create the AzureAI Agent
|
||||
agent = AzureAIAgent(
|
||||
client=client,
|
||||
definition=agent_definition,
|
||||
)
|
||||
|
||||
thread: AzureAIAgentThread | None = None
|
||||
|
||||
# Options are "auto" or "last_messages"
|
||||
# If using "last_messages", specify the number of messages to keep with `last_messages` kwarg
|
||||
truncation_strategy = TruncationObject(type="last_messages", last_messages=2)
|
||||
|
||||
try:
|
||||
for user_input in USER_INPUTS:
|
||||
print(f"# User: {user_input}")
|
||||
# 4. Invoke the agent with the specified message for response
|
||||
response = await agent.get_response(
|
||||
messages=user_input, thread=thread, truncation_strategy=truncation_strategy
|
||||
)
|
||||
print(f"# {response.name}: {response}")
|
||||
thread = response.thread
|
||||
finally:
|
||||
# 6. Cleanup: Delete the thread and agent
|
||||
await thread.delete() if thread else None
|
||||
await client.agents.delete_agent(agent.id)
|
||||
|
||||
"""
|
||||
Sample Output:
|
||||
|
||||
# User: Why is the sky blue?
|
||||
# TruncateAgent: The sky appears blue because molecules in the Earth's atmosphere scatter sunlight in all
|
||||
directions, and blue light is scattered more than other colors due to its shorter wavelength.
|
||||
# User: What is the speed of light?
|
||||
# TruncateAgent: The speed of light in a vacuum is approximately 299,792,458 meters per second
|
||||
(or about 186,282 miles per second).
|
||||
# User: What have we been talking about?
|
||||
# TruncateAgent: I'm sorry, but I don't have access to previous interactions. Could you remind me what
|
||||
we've been discussing?
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user