Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python: Improve agent getting started samples #10667

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
from semantic_kernel.functions.kernel_function_decorator import kernel_function

###################################################################
# The following sample demonstrates how to create a simple, #
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just as a note, I've been updating these blocks to be contained within """<text> """ which makes it much easier to manage - no worries about having to add comment symbols to the end of lines and such...

# Azure AI agent that answers questions about a sample menu #
# using a Semantic Kernel Plugin. #
# The following sample demonstrates how to create an Azure AI #
# agent that answers questions about a sample menu using a #
# Semantic Kernel Plugin. #
###################################################################


Expand All @@ -36,8 +36,18 @@ def get_item_price(
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:
ai_agent_settings = AzureAIAgentSettings.create()
assert ai_agent_settings.project_connection_string, "Please provide a valid Azure AI connection string." # nosec

async with (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could probably clean up this a little bit by internally creating the AzureAIAgentSettings in the get_client method. User's can still pass in values to the method that take precedence, similar to what we do elsewhere.

DefaultAzureCredential() as creds,
Expand All @@ -46,55 +56,52 @@ async def main() -> None:
conn_str=ai_agent_settings.project_connection_string.get_secret_value(),
) as client,
):
AGENT_NAME = "Host"
AGENT_INSTRUCTIONS = "Answer questions about the menu."

# Create agent definition
# 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=AGENT_NAME,
instructions=AGENT_INSTRUCTIONS,
name="Host",
instructions="Answer questions about the menu.",
)

# Create the AzureAI Agent
# 2. Create a Semantic Kernel agent for the Azure AI agent
agent = AzureAIAgent(
client=client,
definition=agent_definition,
# Optionally configure polling options
# polling_options=RunPollingOptions(run_polling_interval=timedelta(seconds=1)),
)

# Add the sample plugin to the kernel
# 3. Add a plugin to the agent via the kernel
agent.kernel.add_plugin(MenuPlugin(), plugin_name="menu")

# Create a new thread
# 4. Create a new thread on the Azure AI agent service
thread = await client.agents.create_thread()

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

try:
for user_input in user_inputs:
# Add the user input as a chat message
for user_input in USER_INPUTS:
# 5. Add the user input as a chat message
await agent.add_chat_message(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As part of this PR, could we update the agent's add_chat_message signature to allow one to pass in a str, and if it's a str instance, we turn it into a ChatMessageContent(AuthorRole.USER, content=message).

thread_id=thread.id, message=ChatMessageContent(role=AuthorRole.USER, content=user_input)
)
print(f"# User: '{user_input}'")
# Invoke the agent for the specified thread
# 6. Invoke the agent for the specified thread for response
async for content in agent.invoke(
thread_id=thread.id,
temperature=0.2, # override the agent-level temperature setting with a run-time value
):
if content.role != AuthorRole.TOOL:
print(f"# Agent: {content.content}")
finally:
# 7. Cleanup: Delete the thread and agent
await client.agents.delete_thread(thread.id)
await client.agents.delete_agent(agent.id)

# Sample Output:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, I've been adding some sample output like:

"""
Sample Output:

# User: 'Hello"
...
"""

# User: 'Hello'
# Agent: Hello! How can I assist you today?
# User: 'What is the special soup?'
# ...


if __name__ == "__main__":
asyncio.run(main())
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,12 @@ async def should_agent_terminate(self, agent, history):
Consider suggestions when refining an idea.
"""

TASK = "a slogan for a new line of electric cars."


async def main():
ai_agent_settings = AzureAIAgentSettings.create()
assert ai_agent_settings.project_connection_string, "Please provide a valid Azure AI connection string." # nosec

async with (
DefaultAzureCredential() as creds,
Expand All @@ -55,55 +58,58 @@ async def main():
conn_str=ai_agent_settings.project_connection_string.get_secret_value(),
) as client,
):
# Create the reviewer agent definition
# 1. Create the reviewer agent on the Azure AI agent service
reviewer_agent_definition = await client.agents.create_agent(
model=ai_agent_settings.model_deployment_name,
name=REVIEWER_NAME,
instructions=REVIEWER_INSTRUCTIONS,
)
# Create the reviewer Azure AI Agent

# 2. Create a Semantic Kernel agent for the reviewer Azure AI agent
agent_reviewer = AzureAIAgent(
client=client,
definition=reviewer_agent_definition,
)

# Create the copy writer agent definition
# 3. Create the copy writer agent on the Azure AI agent service
copy_writer_agent_definition = await client.agents.create_agent(
model=ai_agent_settings.model_deployment_name,
name=COPYWRITER_NAME,
instructions=COPYWRITER_INSTRUCTIONS,
)
# Create the copy writer Azure AI Agent

# 4. Create a Semantic Kernel agent for the copy writer Azure AI agent
agent_writer = AzureAIAgent(
client=client,
definition=copy_writer_agent_definition,
)

# 5. Place the agents in a group chat with a custom termination strategy
chat = AgentGroupChat(
agents=[agent_writer, agent_reviewer],
termination_strategy=ApprovalTerminationStrategy(agents=[agent_reviewer], maximum_iterations=10),
)

input = "a slogan for a new line of electric cars."

try:
await chat.add_chat_message(ChatMessageContent(role=AuthorRole.USER, content=input))
print(f"# {AuthorRole.USER}: '{input}'")

# 6. Add the task as a message to the group chat
await chat.add_chat_message(ChatMessageContent(role=AuthorRole.USER, content=TASK))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a spot in my assistant agent PR where I've also allowed for await chat.add_chat_message(TASK) and we create the ChatMessageContent on behalf of the caller.

print(f"# {AuthorRole.USER}: '{TASK}'")
# 7. Invoke the chat
async for content in chat.invoke():
print(f"# {content.role} - {content.name or '*'}: '{content.content}'")

print(f"# IS COMPLETE: {chat.is_complete}")

print("*" * 60)
print("Chat History (In Descending Order):\n")
async for message in chat.get_chat_messages(agent=agent_reviewer):
print(f"# {message.role} - {message.name or '*'}: '{message.content}'")
finally:
# 8. Cleanup: Delete the agents
await chat.reset()
await client.agents.delete_agent(agent_reviewer.id)
await client.agents.delete_agent(agent_writer.id)

# Sample Output:
# AuthorRole.USER: 'a slogan for a new line of electric cars.'
# AuthorRole.ASSISTANT - CopyWriter: '"Charge Ahead: Drive the Future."'
# AuthorRole.ASSISTANT - ArtDirector: 'This slogan has a nice ring to it and captures the ...'
# AuthorRole.ASSISTANT - CopyWriter: '"Plug In. Drive Green."'
# ...


if __name__ == "__main__":
asyncio.run(main())
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@
# a coding question. #
###################################################################

TASK = "Use code to determine the values in the Fibonacci sequence that that are less then the value of 101."


async def main() -> None:
ai_agent_settings = AzureAIAgentSettings.create()
assert ai_agent_settings.project_connection_string, "Please provide a valid Azure AI connection string." # nosec

async with (
DefaultAzureCredential() as creds,
Expand All @@ -26,43 +29,66 @@ async def main() -> None:
conn_str=ai_agent_settings.project_connection_string.get_secret_value(),
) as client,
):
# 1. Create an agent with a code interpreter on the Azure AI agent service
code_interpreter = CodeInterpreterTool()

# 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
# 2. Create a Semantic Kernel agent for the Azure AI agent
agent = AzureAIAgent(
client=client,
definition=agent_definition,
)

# Create a new thread
# 3. Create a new thread on the Azure AI agent service
thread = await client.agents.create_thread()

user_inputs = [
"Use code to determine the values in the Fibonacci sequence that that are less then the value of 101."
]

try:
for user_input in user_inputs:
# Add the user input as a chat message
await agent.add_chat_message(
thread_id=thread.id, message=ChatMessageContent(role=AuthorRole.USER, content=user_input)
)
print(f"# User: '{user_input}'")
# Invoke the agent for the specified thread
async for content in agent.invoke(thread_id=thread.id):
if content.role != AuthorRole.TOOL:
print(f"# Agent: {content.content}")
# 4. Add the task as a chat message
await agent.add_chat_message(
thread_id=thread.id, message=ChatMessageContent(role=AuthorRole.USER, content=TASK)
)
print(f"# User: '{TASK}'")
# 5. Invoke the agent for the specified thread for response
async for content in agent.invoke(thread_id=thread.id):
if content.role != AuthorRole.TOOL:
print(f"# Agent: {content.content}")
finally:
# 6. Cleanup: Delete the thread and agent
await client.agents.delete_thread(thread.id)
await client.agents.delete_agent(agent.id)

# Sample Output:
# User: 'Use code to determine the values in the Fibonacci sequence that that are less then the value of 101.'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this be easier to read like:

"""
Sample Output:
User: 'Use code to determine the values in the Fibonacci sequence that that are less then the value of 101.'
Agent: # Function to generate Fibonacci sequence values less than a given limit
def fibonacci_less_than(limit):
    fib_sequence = []
    a, b = 0, 1
    while a < limit:
        fib_sequence.append(a)
        a, b = b, a + b
    a, b = 0, 1
    while a < limit:
        fib_sequence.append(a)
    a, b = 0, 1
    while a < limit:
    a, b = 0, 1
    a, b = 0, 1
    while a < limit:
        fib_sequence.append(a)
        a, b = b, a + b
    return fib_sequence

Generate Fibonacci sequence values less than 101
fibonacci_values = fibonacci_less_than(101)
fibonacci_values
Agent: The values in the Fibonacci sequence that are less than 101 are:

\[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89\]
"""

# Agent: # Function to generate Fibonacci sequence values less than a given limit
# def fibonacci_less_than(limit):
# fib_sequence = []
# a, b = 0, 1
# while a < limit:
# fib_sequence.append(a)
# a, b = b, a + b
# a, b = 0, 1
# while a < limit:
# fib_sequence.append(a)
# a, b = 0, 1
# while a < limit:
# a, b = 0, 1
# a, b = 0, 1
# while a < limit:
# fib_sequence.append(a)
# a, b = b, a + b
# return fib_sequence
#
# Generate Fibonacci sequence values less than 101
# fibonacci_values = fibonacci_less_than(101)
# fibonacci_values
# Agent: 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())
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,21 @@

###################################################################
# The following sample demonstrates how to create a simple, #
# Azure AI agent that uses the code interpreter tool to answer #
# a coding question. #
# Azure AI agent that uses a file search tool to answer user #
# questions. #
###################################################################

# Simulate a conversation with the agent
USER_INPUTS = [
"Who is the youngest employee?",
"Who works in sales?",
"I have a customer request, who can help me?",
]


async def main() -> None:
ai_agent_settings = AzureAIAgentSettings.create()
assert ai_agent_settings.project_connection_string, "Please provide a valid Azure AI connection string." # nosec

async with (
DefaultAzureCredential() as creds,
Expand All @@ -27,56 +35,55 @@ async def main() -> None:
conn_str=ai_agent_settings.project_connection_string.get_secret_value(),
) as client,
):
# 1. 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.realpath(__file__))), "resources", "employees.pdf"
)

file: OpenAIFile = await client.agents.upload_file_and_poll(file_path=pdf_file_path, purpose="assistants")

vector_store: VectorStore = await client.agents.create_vector_store_and_poll(
file_ids=[file.id], name="my_vectorstore"
)

# Create file search tool with resources followed by creating agent
# 2. Create file search tool with uploaded resources
file_search = FileSearchTool(vector_store_ids=[vector_store.id])

# Create agent definition
# 3. Create an agent on the Azure AI agent service with the file search tool
agent_definition = await client.agents.create_agent(
model=ai_agent_settings.model_deployment_name,
tools=file_search.definitions,
tool_resources=file_search.resources,
)

# Create the AzureAI Agent
# 4. Create a Semantic Kernel agent for the Azure AI agent
agent = AzureAIAgent(
client=client,
definition=agent_definition,
)

# Create a new thread
# 5. Create a new thread on the Azure AI agent service
thread = await client.agents.create_thread()

user_inputs = [
"Who is the youngest employee?",
"Who works in sales?",
"I have a customer request, who can help me?",
]

try:
for user_input in user_inputs:
# Add the user input as a chat message
for user_input in USER_INPUTS:
# 6. Add the user input as a chat message
await agent.add_chat_message(
thread_id=thread.id, message=ChatMessageContent(role=AuthorRole.USER, content=user_input)
)
print(f"# User: '{user_input}'")
# Invoke the agent for the specified thread
# 7. Invoke the agent for the specified thread for response
async for content in agent.invoke(thread_id=thread.id):
if content.role != AuthorRole.TOOL:
print(f"# Agent: {content.content}")
finally:
# 8. Cleanup: Delete the thread and agent
await client.agents.delete_thread(thread.id)
await client.agents.delete_agent(agent.id)

# Sample Output:
# User: 'Who is the youngest employee?'
# Agent: The youngest employee is Teodor Britton, who is an accountant and was born on January 9, 1997...
# User: 'Who works in sales?'


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