chore: import upstream snapshot with attribution
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:21:23 +08:00
commit b957a53def
5423 changed files with 863745 additions and 0 deletions
@@ -0,0 +1,99 @@
## OpenAI Assistant Agents
The following getting started samples show how to use OpenAI Assistant agents with Semantic Kernel.
## Assistants API Overview
The Assistants API is a robust solution from OpenAI that empowers developers to integrate powerful, purpose-built AI assistants into their applications. It streamlines the development process by handling conversation histories, managing threads, and providing seamless access to advanced tools.
### Key Features
- **Purpose-Built AI Assistants:**
Assistants are specialized AIs that leverage OpenAIs models to interact with users, access files, maintain persistent threads, and call additional tools. This enables highly tailored and effective user interactions.
- **Simplified Conversation Management:**
The concept of a **thread** -- a dedicated conversation session between an assistant and a user -- ensures that message history is managed automatically. Threads optimize the conversation context by storing and truncating messages as needed.
- **Integrated Tool Access:**
The API provides built-in tools such as:
- **Code Interpreter:** Allows the assistant to execute code, enhancing its ability to solve complex tasks.
- **File Search:** Implements best practices for retrieving data from uploaded files, including advanced chunking and embedding techniques.
- **Enhanced Function Calling:**
With improved support for third-party tool integration, the Assistants API enables assistants to extend their capabilities beyond native functions.
For more detailed technical information, refer to the [Assistants API](https://platform.openai.com/docs/assistants/overview).
### Semantic Kernel OpenAI Assistant Agents
OpenAI Assistant Agents are created in the following way:
```python
from semantic_kernel.agents import OpenAIAssistantAgent
# Create the client using OpenAI resources and configuration
client = OpenAIAssistantAgent.create_client()
# Create the assistant definition
definition = await client.beta.assistants.create(
model=AzureOpenAISettings().chat_deployment_name
instructions="<instructions>",
name="<name>",
)
# Define the Semantic Kernel OpenAI Assistant Agent
agent = OpenAIAssistantAgent(
client=client,
definition=definition,
)
# Define a thread
thread = None
# Invoke the agent
async for content in agent.invoke(messages="user input", thread=thread):
print(f"# {content.role}: {content.content}")
# Grab the thread from the response to continue with the current context
thread = response.thread
```
### Semantic Kernel Azure Assistant Agents
Azure Assistant Agents are currently in preview and require a `-preview` API version (minimum version: `2024-05-01-preview`). As new features are introduced, API versions will be updated accordingly. For the latest versioning details, please refer to the [Azure OpenAI API preview lifecycle](https://learn.microsoft.com/azure/ai-services/openai/api-version-deprecation).
To specify the correct API version, set the following environment variable (for example, in your `.env` file):
```bash
AZURE_OPENAI_API_VERSION="2025-01-01-preview"
```
Alternatively, you can pass the `api_version` parameter when creating an `AzureAssistantAgent`:
```python
from semantic_kernel.agents import AzureAssistantAgent
# Create the client using Azure OpenAI resources and configuration
client = AzureAssistantAgent.create_client()
# Create the assistant definition
definition = await client.beta.assistants.create(
model=AzureOpenAISettings().chat_deployment_name
instructions="<instructions>",
name="<name>",
)
# Define the Semantic Kernel Azure OpenAI Assistant Agent
agent = AzureAssistantAgent(
client=client,
definition=definition,
)
# Define a thread
thread = None
# Invoke the agent
async for content in agent.invoke(messages="user input", thread=thread):
print(f"# {content.role}: {content.content}")
# Grab the thread from the response to continue with the current context
thread = response.thread
```
@@ -0,0 +1,143 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from azure.identity import AzureCliCredential
from semantic_kernel.agents import AgentRegistry, AzureAssistantAgent
"""
The following sample demonstrates how to create an Azure Assistant 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: azure_assistant
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: ${AzureOpenAI:ChatModelId}
connection:
api_key: ${AzureOpenAI:ApiKey}
tools:
- type: code_interpreter
options:
file_ids:
- ${AzureOpenAI:FileId1}
"""
async def main():
client = AzureAssistantAgent.create_client(credential=AzureCliCredential())
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",
)
# Load the employees PDF file as a FileObject
with open(csv_file_path, "rb") as file:
file = await client.files.create(file=file, purpose="assistants")
try:
# Create the Assistant 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 `AzureOpenAI:` prefix).
# The short-format is used here for brevity
agent: AzureAssistantAgent = await AgentRegistry.create_from_yaml(
yaml_str=spec,
client=client,
extras={"AzureOpenAI: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.beta.assistants.delete(agent.id)
await client.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())
@@ -0,0 +1,99 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from azure.identity import AzureCliCredential
from semantic_kernel.agents import AgentRegistry, AzureAssistantAgent
"""
The following sample demonstrates how to create an Azure Assistant Agent that answers
user questions using the file search tool.
The agent is used to answer user questions that require file search to help ground
answers from the model.
"""
# Define the YAML string for the sample
spec = """
type: azure_assistant
name: FileSearchAgent
description: Agent with file search tool.
instructions: >
Use the file search tool to answer questions from the user.
model:
id: ${AzureOpenAI:ChatModelId}
connection:
api_key: ${AzureOpenAI:ApiKey}
tools:
- type: file_search
options:
vector_store_ids:
- ${AzureOpenAI:VectorStoreId}
"""
async def main():
# Setup the OpenAI Assistant client
client = AzureAssistantAgent.create_client(credential=AzureCliCredential())
# Read and upload the file to the OpenAI AI 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 assistant service
with open(pdf_file_path, "rb") as file:
file = await client.files.create(file=file, purpose="assistants")
vector_store = await client.vector_stores.create(
name="assistant_file_search",
file_ids=[file.id],
)
try:
# Create the Assistant 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 `AzureOpenAI:` prefix).
# The short-format is used here for brevity
agent: AzureAssistantAgent = await AgentRegistry.create_from_yaml(
yaml_str=spec,
client=client,
extras={"AzureOpenAI: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.beta.assistants.delete(agent.id)
await client.vector_stores.delete(vector_store.id)
await client.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())
@@ -0,0 +1,102 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from typing import Annotated
from azure.identity import AzureCliCredential
from semantic_kernel.agents import AgentRegistry, AzureAssistantAgent
from semantic_kernel.functions import kernel_function
"""
The following sample demonstrates how to create an Azure Assistant 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():
try:
client = AzureAssistantAgent.create_client(credential=AzureCliCredential())
# 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",
"azure_assistant_spec.yaml",
)
# Create the Assistant Agent from the YAML spec
agent: AzureAssistantAgent = await AgentRegistry.create_from_file(
file_path,
plugins=[MenuPlugin()],
client=client,
)
# 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 = 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.beta.assistants.delete(agent.id) if agent else None
await thread.delete() if thread else None
"""
Sample Output:
# User: 'Hello'
# Host: Hi there! How can I assist you today?
# User: 'What is the special soup?'
# Host: The special soup is Clam Chowder.
# User: 'What is the special drink?'
# Host: The special drink is Chai Tea.
# User: 'How much is it?'
# Host: The Chai Tea costs $9.99.
# User: 'Thank you'
# Host: You're welcome! If you have any more questions, feel free to ask.
"""
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,74 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from azure.identity import AzureCliCredential
from semantic_kernel.agents import AgentRegistry, AzureAssistantAgent
"""
The following sample demonstrates how to create an Azure Assistant Agent that invokes
a story generation task using a prompt template and a declarative spec.
"""
# Define the YAML string for the sample
spec = """
type: azure_assistant
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: ${AzureOpenAI:ChatModelId}
connection:
endpoint: ${AzureOpenAI: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():
# Setup the OpenAI Assistant client
client = AzureAssistantAgent.create_client(credential=AzureCliCredential())
try:
# Create the Assistant 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 `AzureOpenAI:` prefix).
# The short-format is used here for brevity
agent: AzureAssistantAgent = 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.beta.assistants.delete(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())
@@ -0,0 +1,66 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from azure.identity import AzureCliCredential
from semantic_kernel.agents import AgentRegistry, AzureAssistantAgent
"""
The following sample demonstrates how to create an Azure Assistant Agent based
on an existing agent ID.
"""
# Define the YAML string for the sample
spec = """
id: ${AzureOpenAI:AgentId}
type: azure_assistant
instructions: You are helpful agent who always responds in French.
"""
async def main():
try:
client = AzureAssistantAgent.create_client(credential=AzureCliCredential())
# Create the Assistant 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 `AzureOpenAI:` prefix).
# The short-format is used here for brevity
agent: AzureAssistantAgent = 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.beta.assistants.delete(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())
@@ -0,0 +1,176 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from typing import Annotated
from azure.identity import AzureCliCredential
from semantic_kernel.agents import AzureAssistantAgent
from semantic_kernel.connectors.ai.open_ai import AzureOpenAISettings
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 OpenAI Assistant 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:
# 1. Create the client using Azure OpenAI resources and configuration
client = AzureAssistantAgent.create_client(credential=AzureCliCredential())
# 2. Define the assistant definition
definition = await client.beta.assistants.create(
model=AzureOpenAISettings().chat_deployment_name,
name="Host",
instructions="Answer questions about the menu.",
)
# 3. Create the AzureAssistantAgent instance using the client and the assistant definition and the defined plugin
agent = AzureAssistantAgent(
client=client,
definition=definition,
plugins=[MenuPlugin()],
kernel=kernel,
)
# 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 = None
try:
for user_input in USER_INPUTS:
print(f"# User: {user_input}")
# 5. 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
):
# 6. Print the response from the agent
print(f"# {response.name}: {response}")
thread = response.thread
finally:
# 7. Cleanup: Delete the thread and agent
await thread.delete() if thread else None
await client.beta.assistants.delete(assistant_id=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,181 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from typing import Annotated
from azure.identity import AzureCliCredential
from semantic_kernel.agents import AzureAssistantAgent
from semantic_kernel.connectors.ai.open_ai import AzureOpenAISettings
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 OpenAI Assistant 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:
# 1. Create the client using Azure OpenAI resources and configuration
client = AzureAssistantAgent.create_client(credential=AzureCliCredential())
# 2. Define the assistant definition
definition = await client.beta.assistants.create(
model=AzureOpenAISettings().chat_deployment_name,
name="Host",
instructions="Answer questions about the menu.",
)
# 3. Create the AzureAssistantAgent instance using the client and the assistant definition and the defined plugin
agent = AzureAssistantAgent(
client=client,
definition=definition,
plugins=[MenuPlugin()],
kernel=kernel,
)
# 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 = None
try:
for user_input in USER_INPUTS:
print(f"# User: {user_input}")
# 5. 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
):
# 6. 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:
# 7. Cleanup: Delete the thread and agent
await thread.delete() if thread else None
await client.beta.assistants.delete(assistant_id=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,86 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from azure.identity import AzureCliCredential
from samples.concepts.agents.openai_assistant.openai_assistant_sample_utils import download_response_images
from semantic_kernel.agents import AssistantAgentThread, AzureAssistantAgent
from semantic_kernel.connectors.ai.open_ai import AzureOpenAISettings
from semantic_kernel.contents import FileReferenceContent
"""
The following sample demonstrates how to create an OpenAI
assistant using either Azure OpenAI or OpenAI and leverage the
assistant and leverage the assistant's code interpreter tool
in a streaming fashion.
"""
async def main():
# Create the client using Azure OpenAI resources and configuration
client = AzureAssistantAgent.create_client(credential=AzureCliCredential())
# Get the code interpreter tool and resources
code_interpreter_tool, code_interpreter_resource = AzureAssistantAgent.configure_code_interpreter_tool()
# Define the assistant definition
definition = await client.beta.assistants.create(
model=AzureOpenAISettings().chat_deployment_name,
instructions="Create charts as requested without explanation.",
name="ChartMaker",
tools=code_interpreter_tool,
tool_resources=code_interpreter_resource,
)
# Create the AzureAssistantAgent instance using the client and the assistant definition
agent = AzureAssistantAgent(
client=client,
definition=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: AssistantAgentThread = None
user_inputs = [
"""
Display this data using a bar-chart:
Banding Brown Pink Yellow Sum
X00000 339 433 126 898
X00300 48 421 222 691
X12345 16 395 352 763
Others 23 373 156 552
Sum 426 1622 856 2904
""",
"Can you regenerate this same chart using the category names as the bar colors?",
]
try:
for user_input in user_inputs:
file_ids = []
async for response in agent.invoke(messages=user_input, thread=thread):
thread = response.thread
if response.content:
print(f"# {response.role}: {response}")
if len(response.items) > 0:
for item in response.items:
if isinstance(item, FileReferenceContent):
file_ids.extend([
item.file_id
for item in response.items
if isinstance(item, FileReferenceContent) and item.file_id is not None
])
# Use a sample utility method to download the files to the current working directory
await download_response_images(agent, file_ids)
finally:
await thread.delete() if thread else None
await client.beta.assistants.delete(assistant_id=agent.id)
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,103 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from azure.identity import AzureCliCredential
from samples.concepts.agents.openai_assistant.openai_assistant_sample_utils import download_response_images
from semantic_kernel.agents import AssistantAgentThread, AzureAssistantAgent
from semantic_kernel.connectors.ai.open_ai import AzureOpenAISettings
from semantic_kernel.contents import StreamingFileReferenceContent
"""
The following sample demonstrates how to create an OpenAI
assistant using either Azure OpenAI or OpenAI and leverage the
assistant and leverage the assistant's code interpreter tool
in a streaming fashion.
"""
async def main():
# Create the client using Azure OpenAI resources and configuration
client = AzureAssistantAgent.create_client(credential=AzureCliCredential())
# Get the code interpreter tool and resources
code_interpreter_tool, code_interpreter_resource = AzureAssistantAgent.configure_code_interpreter_tool()
# Define the assistant definition
definition = await client.beta.assistants.create(
model=AzureOpenAISettings().chat_deployment_name,
instructions="Create charts as requested without explanation.",
name="ChartMaker",
tools=code_interpreter_tool,
tool_resources=code_interpreter_resource,
)
# Create the AzureAssistantAgent instance using the client and the assistant definition
agent = AzureAssistantAgent(
client=client,
definition=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: AssistantAgentThread = None
user_inputs = [
"""
Display this data using a bar-chart:
Banding Brown Pink Yellow Sum
X00000 339 433 126 898
X00300 48 421 222 691
X12345 16 395 352 763
Others 23 373 156 552
Sum 426 1622 856 2904
""",
"Can you regenerate this same chart using the category names as the bar colors?",
]
try:
for user_input in user_inputs:
print(f"# User: '{user_input}'")
file_ids: list[str] = []
is_code = False
last_role = None
async for response in agent.invoke_stream(messages=user_input, thread=thread):
thread = response.thread
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)
file_ids.extend([
item.file_id
for item in response.items
if isinstance(item, StreamingFileReferenceContent) and item.file_id is not None
])
if is_code:
print("```\n")
# Use a sample utility method to download the files to the current working directory
await download_response_images(agent, file_ids)
file_ids.clear()
finally:
await thread.delete() if thread else None
await client.beta.assistants.delete(assistant_id=agent.id)
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,141 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from semantic_kernel.agents import AgentRegistry, OpenAIAssistantAgent
"""
The following sample demonstrates how to create an OpenAI Assistant 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: openai_assistant
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: ${OpenAI:ChatModelId}
connection:
api_key: ${OpenAI:ApiKey}
tools:
- type: code_interpreter
options:
file_ids:
- ${OpenAI:FileId1}
"""
async def main():
client = OpenAIAssistantAgent.create_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",
)
# Load the employees PDF file as a FileObject
with open(csv_file_path, "rb") as file:
file = await client.files.create(file=file, purpose="assistants")
try:
# Create the Assistant 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 `OpenAI:` prefix).
# The short-format is used here for brevity
agent: OpenAIAssistantAgent = await AgentRegistry.create_from_yaml(
yaml_str=spec,
client=client,
extras={"OpenAI: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.beta.assistants.delete(agent.id)
await client.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())
@@ -0,0 +1,94 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from semantic_kernel.agents import AgentRegistry, OpenAIAssistantAgent
"""
The following sample demonstrates how to create an OpenAI Assistant Agent that answers
user questions using the file search tool.
The agent is used to answer user questions that require file search to help ground
answers from the model.
"""
# Define the YAML string for the sample
spec = """
type: openai_assistant
name: FileSearchAgent
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: ${OpenAI:ChatModelId}
connection:
api_key: ${OpenAI:ApiKey}
tools:
- type: file_search
options:
vector_store_ids:
- ${OpenAI:VectorStoreId}
"""
async def main():
# Setup the OpenAI Assistant client
client = OpenAIAssistantAgent.create_client()
# Read and upload the file to the OpenAI AI 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 assistant service
with open(pdf_file_path, "rb") as file:
file = await client.files.create(file=file, purpose="assistants")
vector_store = await client.vector_stores.create(
name="assistant_file_search",
file_ids=[file.id],
)
try:
# Create the Assistant 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 `OpenAI:` prefix).
# The short-format is used here for brevity
agent: OpenAIAssistantAgent = await AgentRegistry.create_from_yaml(
yaml_str=spec,
client=client,
extras={"OpenAI: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.beta.assistants.delete(agent.id)
await client.vector_stores.delete(vector_store.id)
await client.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 can contact either Mariam Jaslyn or Angelino Embla, who
are both listed as Sales Representatives. Alternatively, you may also reach out to Hicran Bea,
the Sales Manager【4:0†employees.pdf】.
"""
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,100 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from typing import Annotated
from semantic_kernel.agents import AgentRegistry, OpenAIAssistantAgent
from semantic_kernel.functions import kernel_function
"""
The following sample demonstrates how to create an OpenAI Assistant 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():
try:
client = OpenAIAssistantAgent.create_client()
# 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",
"openai_assistant_spec.yaml",
)
# Create the Assistant Agent from the YAML spec
agent: OpenAIAssistantAgent = await AgentRegistry.create_from_file(
file_path,
plugins=[MenuPlugin()],
client=client,
)
# 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 = 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.beta.assistants.delete(agent.id) if agent else None
await thread.delete() if thread else None
"""
Sample Output:
# User: 'Hello'
# Host: Hi there! How can I assist you today?
# User: 'What is the special soup?'
# Host: The special soup is Clam Chowder.
# User: 'What is the special drink?'
# Host: The special drink is Chai Tea.
# User: 'How much is it?'
# Host: The Chai Tea costs $9.99.
# User: 'Thank you'
# Host: You're welcome! If you have any more questions, feel free to ask.
"""
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,70 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from semantic_kernel.agents import AgentRegistry, OpenAIAssistantAgent
"""
The following sample demonstrates how to create an OpenAI Assistant Agent that invokes
a story generation task using a prompt template and a declarative spec.
"""
# Define the YAML string for the sample
spec = """
type: openai_assistant
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: ${OpenAI:ChatModelId}
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():
# Setup the OpenAI Assistant client
client = OpenAIAssistantAgent.create_client()
try:
# Create the Assistant 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 `OpenAI:` prefix).
# The short-format is used here for brevity
agent: OpenAIAssistantAgent = 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.beta.assistants.delete(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())
@@ -0,0 +1,65 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from semantic_kernel.agents import AgentRegistry, OpenAIAssistantAgent
"""
The following sample demonstrates how to create an OpenAI Assistant Agent based
on an existing agent ID.
"""
# Define the YAML string for the sample
spec = """
id: ${OpenAI:AgentId}
type: openai_assistant
instructions: You are helpful agent who always responds in French.
"""
async def main():
client = OpenAIAssistantAgent.create_client()
try:
# Create the Assistant 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 `OpenAI:` prefix).
# The short-format is used here for brevity
agent: OpenAIAssistantAgent = 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())
@@ -0,0 +1,87 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from azure.identity import AzureCliCredential
from samples.concepts.agents.openai_assistant.openai_assistant_sample_utils import download_response_files
from semantic_kernel.agents import AssistantAgentThread, AzureAssistantAgent
from semantic_kernel.connectors.ai.open_ai import AzureOpenAISettings
from semantic_kernel.contents import AnnotationContent
"""
The following sample demonstrates how to create an OpenAI
assistant using either Azure OpenAI or OpenAI and leverage the
assistant's ability to have the code interpreter work with
uploaded files. This sample uses non-streaming responses.
"""
async def main():
# Create the client using Azure OpenAI resources and configuration
client = AzureAssistantAgent.create_client(credential=AzureCliCredential())
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",
)
# Load the employees PDF file as a FileObject
with open(csv_file_path, "rb") as file:
file = await client.files.create(file=file, purpose="assistants")
# Get the code interpreter tool and resources
code_interpreter_tool, code_interpreter_tool_resource = AzureAssistantAgent.configure_code_interpreter_tool(file.id)
# Create the assistant definition
definition = await client.beta.assistants.create(
model=AzureOpenAISettings().chat_deployment_name,
name="FileManipulation",
instructions="Find answers to the user's questions in the provided file.",
tools=code_interpreter_tool,
tool_resources=code_interpreter_tool_resource,
)
# Create the AzureAssistantAgent instance using the client and the assistant definition
agent = AzureAssistantAgent(
client=client,
definition=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: AssistantAgentThread = None
try:
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.",
]
for user_input in user_inputs:
print(f"# User: '{user_input}'")
async for response in agent.invoke(messages=user_input, thread=thread):
thread = response.thread
if response.metadata.get("code", False):
print(f"# {response.role}:\n\n```python")
print(response)
print("```")
else:
print(f"# {response.role}: {response}")
if response.items:
for item in response.items:
if isinstance(item, AnnotationContent):
await download_response_files(agent, [item])
finally:
await client.files.delete(file.id)
await thread.delete() if thread else None
await client.beta.assistants.delete(agent.id)
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,107 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from azure.identity import AzureCliCredential
from samples.concepts.agents.openai_assistant.openai_assistant_sample_utils import download_response_files
from semantic_kernel.agents import AssistantAgentThread, AzureAssistantAgent
from semantic_kernel.connectors.ai.open_ai import AzureOpenAISettings
from semantic_kernel.contents import ChatMessageContent, StreamingAnnotationContent
"""
The following sample demonstrates how to create an Azure Assistant Agent
to leverage the assistant's ability to have the code interpreter work with
uploaded files. This sample uses streaming responses.
"""
async def main():
# Create the client using Azure OpenAI resources and configuration
client = AzureAssistantAgent.create_client(credential=AzureCliCredential())
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",
)
# Load the employees PDF file as a FileObject
with open(csv_file_path, "rb") as file:
file = await client.files.create(file=file, purpose="assistants")
# Get the code interpreter tool and resources
code_interpreter_tools, code_interpreter_tool_resources = AzureAssistantAgent.configure_code_interpreter_tool(
file.id
)
# Create the assistant definition
definition = await client.beta.assistants.create(
model=AzureOpenAISettings().chat_deployment_name,
name="FileManipulation",
instructions="Find answers to the user's questions in the provided file.",
tools=code_interpreter_tools,
tool_resources=code_interpreter_tool_resources,
)
# Create the AzureAssistantAgent instance using the client and the assistant definition
agent = AzureAssistantAgent(
client=client,
definition=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: AssistantAgentThread = None
try:
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.",
]
for user_input in user_inputs:
print(f"# User: '{user_input}'")
annotations: list[StreamingAnnotationContent] = []
messages: list[ChatMessageContent] = []
is_code = False
last_role = None
async for response in agent.invoke_stream(messages=user_input, thread=thread):
thread = response.thread
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")
else:
print()
# Use a sample utility method to download the files to the current working directory
annotations.extend(
item for message in messages for item in message.items if isinstance(item, StreamingAnnotationContent)
)
await download_response_files(agent, annotations)
annotations.clear()
finally:
await client.files.delete(file.id)
await thread.delete() if thread else None
await client.beta.assistants.delete(agent.id)
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,131 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from typing import Annotated
from azure.identity import AzureCliCredential
from semantic_kernel.agents import AssistantAgentThread, AzureAssistantAgent
from semantic_kernel.connectors.ai.open_ai import AzureOpenAISettings
from semantic_kernel.contents import AuthorRole, 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 AzureAssistantAgent/OpenAIAssistantAgent 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():
# Create the client using Azure OpenAI resources and configuration
client = AzureAssistantAgent.create_client(credential=AzureCliCredential())
# Define the assistant definition
definition = await client.beta.assistants.create(
model=AzureOpenAISettings().chat_deployment_name,
name="Host",
instructions="Answer questions about the menu.",
)
# Create the AzureAssistantAgent instance using the client and the assistant definition and the defined plugin
agent = AzureAssistantAgent(
client=client,
definition=definition,
plugins=[MenuPlugin()],
)
# 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: AssistantAgentThread = None
user_inputs = [
"Hello",
"What is the special soup?",
"What is the special drink?",
"How much is that?",
"Thank you",
]
try:
for user_input in user_inputs:
print(f"# {AuthorRole.USER}: '{user_input}'")
async for response in agent.invoke(
messages=user_input,
thread=thread,
on_intermediate_message=handle_intermediate_steps,
):
print(f"# {response.role}: {response}")
thread = response.thread
finally:
await thread.delete() if thread else None
await client.beta.assistants.delete(assistant_id=agent.id)
"""
Sample Output:
# AuthorRole.USER: 'Hello'
# AuthorRole.ASSISTANT: Hello! How can I assist you today?
# AuthorRole.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
# AuthorRole.ASSISTANT: The special soup is Clam Chowder. Would you like to know more about the specials or
anything else?
# AuthorRole.USER: 'What is the special drink?'
# AuthorRole.ASSISTANT: The special drink is Chai Tea. If you have any more questions, feel free to ask!
# AuthorRole.USER: 'How much is that?'
Function Call:> MenuPlugin-get_item_price with arguments: {"menu_item":"Chai Tea"}
Function Result:> $9.99 for function: MenuPlugin-get_item_price
# AuthorRole.ASSISTANT: The Chai Tea is priced at $9.99. If there's anything else you'd like to know,
just let me know!
# AuthorRole.USER: 'Thank you'
# AuthorRole.ASSISTANT: You're welcome! If you have any more questions or need further assistance, feel free to
ask. Enjoy your day!
"""
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,138 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from typing import Annotated
from azure.identity import AzureCliCredential
from semantic_kernel.agents import AssistantAgentThread, AzureAssistantAgent
from semantic_kernel.connectors.ai.open_ai import AzureOpenAISettings
from semantic_kernel.contents import AuthorRole, 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 AzureAssistantAgent/OpenAIAssistantAgent 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.
"""
# 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():
# Create the client using Azure OpenAI resources and configuration
client = AzureAssistantAgent.create_client(credential=AzureCliCredential())
# Define the assistant definition
definition = await client.beta.assistants.create(
model=AzureOpenAISettings().chat_deployment_name,
name="Host",
instructions="Answer questions about the menu.",
)
# Create the AzureAssistantAgent instance using the client and the assistant definition and the defined plugin
agent = AzureAssistantAgent(
client=client,
definition=definition,
plugins=[MenuPlugin()],
)
# 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: AssistantAgentThread = None
user_inputs = [
"Hello",
"What is the special soup?",
"What is the special drink?",
"How much is that?",
"Thank you",
]
try:
for user_input in user_inputs:
print(f"# {AuthorRole.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,
):
thread = response.thread
if first_chunk:
print(f"# {response.role}: ", end="", flush=True)
first_chunk = False
print(response.content, end="", flush=True)
print()
finally:
await thread.delete() if thread else None
await client.beta.assistants.delete(assistant_id=agent.id)
"""
Sample Output:
# AuthorRole.USER: 'Hello'
# AuthorRole.ASSISTANT: Hello! How can I help you with the menu today?
# AuthorRole.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
# AuthorRole.ASSISTANT: The special soup today is Clam Chowder. Would you like to know more about it or see other
specials?
# AuthorRole.USER: 'What is the special drink?'
# AuthorRole.ASSISTANT: The special drink is Chai Tea. Would you like more information about it or the other
specials?
# AuthorRole.USER: 'How much is that?'
Function Call:> MenuPlugin-get_item_price with arguments: {"menu_item":"Chai Tea"}
Function Result:> $9.99 for function: MenuPlugin-get_item_price
# AuthorRole.ASSISTANT: The special drink, Chai Tea, is $9.99. Would you like to order one or have questions about
something else on the menu?
# AuthorRole.USER: 'Thank you'
# AuthorRole.ASSISTANT: You're welcome! If you have any more questions or need help with the menu, just let me
know. Enjoy your meal!
"""
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,60 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from azure.identity import AzureCliCredential
from semantic_kernel.agents import AssistantAgentThread, AzureAssistantAgent
from semantic_kernel.connectors.ai.open_ai import AzureOpenAISettings
"""
The following sample demonstrates how to create an OpenAI
assistant using either Azure OpenAI or OpenAI and retrieve it from
the server to create a new instance of the assistant. This is done by
retrieving the assistant definition from the server using the Assistant's
ID and creating a new instance of the assistant using the retrieved definition.
"""
async def main():
# Create the client using Azure OpenAI resources and configuration
client = AzureAssistantAgent.create_client(credential=AzureCliCredential())
# Create the assistant definition
definition = await client.beta.assistants.create(
model=AzureOpenAISettings().chat_deployment_name,
name="Assistant",
instructions="You are a helpful assistant answering questions about the world in one sentence.",
)
# Store the assistant ID
assistant_id = definition.id
# Retrieve the assistant definition from the server based on the assistant ID
new_asst_definition = await client.beta.assistants.retrieve(assistant_id)
# Create the AzureAssistantAgent instance using the client and the assistant definition
agent = AzureAssistantAgent(
client=client,
definition=new_asst_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: AssistantAgentThread = None
user_inputs = ["Why is the sky blue?"]
try:
for user_input in user_inputs:
print(f"# User: '{user_input}'")
async for response in agent.invoke(messages=user_input, thread=thread):
print(f"# {response.role}: {response.content}")
thread = response.thread
finally:
await thread.delete() if thread else None
await client.beta.assistants.delete(agent.id)
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,54 @@
# Copyright (c) Microsoft. All rights reserved.
import os
from collections.abc import Sequence
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from semantic_kernel.agents import OpenAIAssistantAgent
from semantic_kernel.contents import AnnotationContent, StreamingAnnotationContent
async def download_file_content(agent: "OpenAIAssistantAgent", file_id: str, file_extension: str):
"""A sample utility method to download the content of a file."""
try:
# Fetch the content of the file using the provided method
response_content = await agent.client.files.content(file_id)
# Get the current working directory of the file
current_directory = os.path.dirname(os.path.abspath(__file__))
# Define the path to save the image in the current directory
file_path = os.path.join(
current_directory, # Use the current directory of the file
f"{file_id}.{file_extension}", # You can modify this to use the actual filename with proper extension
)
# Save content to a file asynchronously
with open(file_path, "wb") as file:
file.write(response_content.content)
print(f"\n\nFile saved to: {file_path}")
except Exception as e:
print(f"An error occurred while downloading file {file_id}: {str(e)}")
async def download_response_images(agent: "OpenAIAssistantAgent", file_ids: list[str]):
"""A sample utility method to download the content of a list of files."""
if file_ids:
# Iterate over file_ids and download each one
for file_id in file_ids:
await download_file_content(agent, file_id, "png")
async def download_response_files(
agent: "OpenAIAssistantAgent", annotations: Sequence["StreamingAnnotationContent | AnnotationContent"]
):
"""A sample utility method to download the content of a file."""
if annotations:
# Iterate over file_ids and download each one
for ann in annotations:
if ann.quote is None or ann.file_id is None:
continue
extension = os.path.splitext(ann.quote)[1].lstrip(".")
await download_file_content(agent, ann.file_id, extension)
@@ -0,0 +1,85 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from typing import Annotated
from azure.identity import AzureCliCredential
from semantic_kernel.agents import AssistantAgentThread, AzureAssistantAgent
from semantic_kernel.connectors.ai.open_ai import AzureOpenAISettings
from semantic_kernel.contents import AuthorRole
from semantic_kernel.functions import kernel_function
"""
The following sample demonstrates how to create an OpenAI
assistant using either Azure OpenAI or OpenAI. OpenAI Assistants
allow for function calling, the use of file search and a
code interpreter. Assistant Threads are used to manage the
conversation state, similar to a Semantic Kernel Chat History.
This sample also demonstrates the Assistants Streaming
capability and how to manage an Assistants chat history.
"""
# 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():
# Create the client using Azure OpenAI resources and configuration
client = AzureAssistantAgent.create_client(credential=AzureCliCredential())
# Define the assistant definition
definition = await client.beta.assistants.create(
model=AzureOpenAISettings().chat_deployment_name,
name="Host",
instructions="Answer questions about the menu.",
)
# Create the AzureAssistantAgent instance using the client and the assistant definition and the defined plugin
agent = AzureAssistantAgent(
client=client,
definition=definition,
plugins=[MenuPlugin()],
)
# 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: AssistantAgentThread = None
user_inputs = ["Hello", "What is the special soup?", "What is the special drink?", "How much is that?", "Thank you"]
try:
for user_input in user_inputs:
print(f"# {AuthorRole.USER}: '{user_input}'")
first_chunk = True
async for response in agent.invoke_stream(messages=user_input, thread=thread):
thread = response.thread
if first_chunk:
print(f"# {response.role}: ", end="", flush=True)
first_chunk = False
print(response.content, end="", flush=True)
print()
finally:
await thread.delete() if thread else None
await client.beta.assistants.delete(assistant_id=agent.id)
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,94 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from azure.identity import AzureCliCredential
from pydantic import BaseModel
from semantic_kernel.agents import AssistantAgentThread, AzureAssistantAgent
from semantic_kernel.connectors.ai.open_ai import AzureOpenAISettings
"""
The following sample demonstrates how to create an OpenAI
assistant using either Azure OpenAI or OpenAI and leverage the
assistant's ability to returned structured outputs, based on a user-defined
Pydantic model. This could also be a non-Pydantic model. Use the convenience
method on the OpenAIAssistantAgent class to configure the response format,
as shown below.
Note, you may specify your own JSON Schema. You'll need to make sure it is correct
if not using the convenience method, per the following format:
json_schema = {
"type": "json_schema",
"json_schema": {
"schema": {
"properties": {
"response": {"title": "Response", "type": "string"},
"items": {"items": {"type": "string"}, "title": "Items", "type": "array"},
},
"required": ["response", "items"],
"title": "ResponseModel",
"type": "object",
"additionalProperties": False,
},
"name": "ResponseModel",
"strict": True,
},
}
# Create the assistant definition
definition = await client.beta.assistants.create(
model=AzureOpenAISettings().chat_deployment_name
name="Assistant",
instructions="You are a helpful assistant answering questions about the world in one sentence.",
response_format=json_schema,
)
"""
# Define a Pydantic model that represents the structured output from the OpenAI service
class ResponseModel(BaseModel):
response: str
items: list[str]
async def main():
# Create the client using Azure OpenAI resources and configuration
client = AzureAssistantAgent.create_client(credential=AzureCliCredential())
# Create the assistant definition
definition = await client.beta.assistants.create(
model=AzureOpenAISettings().chat_deployment_name,
name="Assistant",
instructions="You are a helpful assistant answering questions about the world in one sentence.",
response_format=AzureAssistantAgent.configure_response_format(ResponseModel),
)
# Create the AzureAssistantAgent instance using the client and the assistant definition
agent = AzureAssistantAgent(
client=client,
definition=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: AssistantAgentThread = None
user_inputs = ["Why is the sky blue?"]
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 = ResponseModel.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.beta.assistants.delete(agent.id)
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,117 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from azure.identity import AzureCliCredential
from semantic_kernel.agents import AssistantAgentThread, AzureAssistantAgent
from semantic_kernel.connectors.ai.open_ai import AzureOpenAISettings
from semantic_kernel.functions import KernelArguments
from semantic_kernel.prompt_template import PromptTemplateConfig
from semantic_kernel.prompt_template.const import TEMPLATE_FORMAT_TYPES
"""
The following sample demonstrates how to create an assistant
agent using either Azure OpenAI or OpenAI within Semantic Kernel.
It uses parameterized prompts and shows how to swap between
"semantic-kernel," "jinja2," and "handlebars" template formats,
This sample highlights how the agent's threaded conversation
state parallels the Chat History in Semantic Kernel, ensuring
all responses and parameters remain consistent throughout the
session.
"""
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_agent_with_template(
template_str: str, template_format: TEMPLATE_FORMAT_TYPES, default_style: str = "haiku"
):
# Create the client using Azure OpenAI resources and configuration
client = AzureAssistantAgent.create_client(credential=AzureCliCredential())
# Configure the prompt template
prompt_template_config = PromptTemplateConfig(template=template_str, template_format=template_format)
# Create the assistant definition
definition = await client.beta.assistants.create(
model=AzureOpenAISettings().chat_deployment_name,
name="MyPoetAgent",
)
# Create the AzureAssistantAgent instance using the client, the assistant definition,
# the prompt template config, and the constructor-level Kernel Arguments
agent = AzureAssistantAgent(
client=client,
definition=definition,
prompt_template_config=prompt_template_config, # type: ignore
arguments=KernelArguments(style=default_style),
)
# 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: AssistantAgentThread = None
try:
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:
# Arguments passed in at invocation time take precedence over
# the default arguments that were added via the constructor.
argument_overrides = KernelArguments(style=style)
# Stream agent responses
async for response in agent.invoke_stream(messages=user_input, thread=thread, arguments=argument_overrides):
if response.content:
print(f"{response.content}", flush=True, end="")
thread = response.thread
print("\n")
finally:
# Clean up
await thread.delete() if thread else None
await client.beta.assistants.delete(agent.id)
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. Write appropriate G-rated content.
"""
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. Write appropriate G-rated content.
"""
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. Write appropriate G-rated content.
"""
await invoke_agent_with_template(
template_str=handlebars_template, template_format="handlebars", default_style="haiku"
)
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,97 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from azure.identity import AzureCliCredential
from semantic_kernel.agents import AssistantAgentThread, AzureAssistantAgent
from semantic_kernel.connectors.ai.open_ai import AzureOpenAISettings
from semantic_kernel.contents import AuthorRole, ChatMessageContent, FileReferenceContent, ImageContent, TextContent
"""
The following sample demonstrates how to create an OpenAI
assistant using either Azure OpenAI or OpenAI and leverage the
multi-modal content types to have the assistant describe images
and answer questions about them and provide streaming responses.
"""
async def main():
# Create the client using Azure OpenAI resources and configuration
client = AzureAssistantAgent.create_client(credential=AzureCliCredential())
file_path = os.path.join(
os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))), "resources", "cat.jpg"
)
with open(file_path, "rb") as file:
file = await client.files.create(file=file, purpose="assistants")
# Create the assistant definition
definition = await client.beta.assistants.create(
model=AzureOpenAISettings().chat_deployment_name,
instructions="Answer questions about the menu.",
name="Host",
)
# Create the AzureAssistantAgent instance using the client and the assistant definition
agent = AzureAssistantAgent(
client=client,
definition=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: AssistantAgentThread = None
# Define a series of message with either ImageContent or FileReferenceContent
user_inputs = {
ChatMessageContent(
role=AuthorRole.USER,
items=[
TextContent(text="Describe this image."),
ImageContent(
uri="https://upload.wikimedia.org/wikipedia/commons/thumb/4/47/New_york_times_square-terabass.jpg/1200px-New_york_times_square-terabass.jpg"
),
],
),
ChatMessageContent(
role=AuthorRole.USER,
items=[
TextContent(text="What is the main color in this image?"),
ImageContent(uri="https://upload.wikimedia.org/wikipedia/commons/5/56/White_shark.jpg"),
],
),
ChatMessageContent(
role=AuthorRole.USER,
items=[
TextContent(text="Is there an animal in this image?"),
FileReferenceContent(file_id=file.id),
],
),
}
try:
for user_input in user_inputs:
print(f"# User: '{user_input.items[0].text}'") # type: ignore
first_chunk = True
async for response in agent.invoke_stream(messages=user_input, thread=thread):
if response.role != AuthorRole.TOOL:
if first_chunk:
print("# Agent: ", end="", flush=True)
first_chunk = False
print(response.content, end="", flush=True)
thread = response.thread
print("\n")
finally:
await client.files.delete(file.id)
await thread.delete() if thread else None
await agent.client.beta.assistants.delete(assistant_id=agent.id)
if __name__ == "__main__":
asyncio.run(main())