chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
BEDROCK_AGENT_AGENT_RESOURCE_ROLE_ARN=[YOUR_AGENT_ROLE_AMAZON_RESOURCE_NAME]
|
||||
BEDROCK_AGENT_FOUNDATION_MODEL=[YOUR_FOUNDATION_MODEL]
|
||||
@@ -0,0 +1,74 @@
|
||||
# Concept samples on how to use AWS Bedrock agents
|
||||
|
||||
## Pre-requisites
|
||||
|
||||
1. You need to have an AWS account and [access to the foundation models](https://docs.aws.amazon.com/bedrock/latest/userguide/model-access-permissions.html)
|
||||
2. [AWS CLI installed](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) and [configured](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html#configuration)
|
||||
|
||||
### Configuration
|
||||
|
||||
Follow this [guide](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html#configuration) to configure your environment to use the Bedrock API.
|
||||
|
||||
Please configure the `aws_access_key_id`, `aws_secret_access_key`, and `region` otherwise you will need to create custom clients for the services. For example:
|
||||
|
||||
```python
|
||||
runtime_client=boto.client(
|
||||
"bedrock-runtime",
|
||||
aws_access_key_id="your_access_key",
|
||||
aws_secret_access_key="your_secret_key",
|
||||
region_name="your_region",
|
||||
[...other parameters you may need...]
|
||||
)
|
||||
client=boto.client(
|
||||
"bedrock",
|
||||
aws_access_key_id="your_access_key",
|
||||
aws_secret_access_key="your_secret_key",
|
||||
region_name="your_region",
|
||||
[...other parameters you may need...]
|
||||
)
|
||||
|
||||
bedrock_agent = BedrockAgent.create_and_prepare_agent(
|
||||
name="your_agent_name",
|
||||
instructions="your_instructions",
|
||||
runtime_client=runtime_client,
|
||||
client=client,
|
||||
[...other parameters you may need...]
|
||||
)
|
||||
```
|
||||
|
||||
## Samples
|
||||
|
||||
| Sample | Description |
|
||||
|--------|-------------|
|
||||
| [bedrock_agent_simple_chat.py](bedrock_agent_simple_chat.py) | Demonstrates basic usage of the Bedrock agent. |
|
||||
| [bedrock_agent_simple_chat_streaming.py](bedrock_agent_simple_chat_streaming.py) | Demonstrates basic usage of the Bedrock agent with streaming. |
|
||||
| [bedrock_agent_with_kernel_function.py](bedrock_agent_with_kernel_function.py) | Shows how to use the Bedrock agent with a kernel function. |
|
||||
| [bedrock_agent_with_kernel_function_streaming.py](bedrock_agent_with_kernel_function_streaming.py) | Shows how to use the Bedrock agent with a kernel function with streaming. |
|
||||
| [bedrock_agent_with_code_interpreter.py](bedrock_agent_with_code_interpreter.py) | Example of using the Bedrock agent with a code interpreter. |
|
||||
| [bedrock_agent_with_code_interpreter_streaming.py](bedrock_agent_with_code_interpreter_streaming.py) | Example of using the Bedrock agent with a code interpreter and streaming. |
|
||||
| [bedrock_mixed_chat_agents.py](bedrock_mixed_chat_agents.py) | Example of using multiple chat agents in a single script. |
|
||||
| [bedrock_mixed_chat_agents_streaming.py](bedrock_mixed_chat_agents_streaming.py) | Example of using multiple chat agents in a single script with streaming. |
|
||||
|
||||
## Before running the samples
|
||||
|
||||
You need to set up some environment variables to run the samples. Please refer to the [.env.example](.env.example) file for the required environment variables.
|
||||
|
||||
### `BEDROCK_AGENT_AGENT_RESOURCE_ROLE_ARN`
|
||||
|
||||
On your AWS console, go to the IAM service and go to **Roles**. Find the role you want to use and click on it. You will find the ARN in the summary section.
|
||||
|
||||
### `BEDROCK_AGENT_FOUNDATION_MODEL`
|
||||
|
||||
You need to make sure you have permission to access the foundation model. You can find the model ID in the [AWS documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html). To see the models you have access to, find the policy attached to your role you should see a list of models you have access to under the `Resource` section.
|
||||
|
||||
### How to add the `bedrock:InvokeModelWithResponseStream` action to an IAM policy
|
||||
|
||||
1. Open the [IAM console](https://console.aws.amazon.com/iam/).
|
||||
2. On the left navigation pane, choose `Roles` under `Access management`.
|
||||
3. Find the role you want to edit and click on it.
|
||||
4. Under the `Permissions policies` tab, click on the policy you want to edit.
|
||||
5. Under the `Permissions defined in this policy` section, click on the service. You should see **Bedrock** if you already have access to the Bedrock agent service.
|
||||
6. Click on the service, and then click `Edit`.
|
||||
7. On the right, you will be able to add an action. Find the service and search for `InvokeModelWithResponseStream`.
|
||||
8. Check the box next to the action and then scroll all the way down and click `Next`.
|
||||
9. Follow the prompts to save the changes.
|
||||
@@ -0,0 +1,62 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
|
||||
import boto3
|
||||
|
||||
from semantic_kernel.agents import BedrockAgent, BedrockAgentThread
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to use an already existing
|
||||
Bedrock Agent within Semantic Kernel. This sample requires that you
|
||||
have an existing agent created either previously in code or via the
|
||||
AWS Console.
|
||||
This sample uses the following main component(s):
|
||||
- a Bedrock agent
|
||||
You will learn how to retrieve a Bedrock agent and talk to it.
|
||||
"""
|
||||
|
||||
# Replace "your-agent-id" with the ID of the agent you want to use
|
||||
AGENT_ID = "your-agent-id"
|
||||
|
||||
|
||||
async def main():
|
||||
client = boto3.client("bedrock-agent")
|
||||
agent_model = client.get_agent(agentId=AGENT_ID)["agent"]
|
||||
bedrock_agent = BedrockAgent(agent_model)
|
||||
thread: BedrockAgentThread = None
|
||||
|
||||
try:
|
||||
while True:
|
||||
user_input = input("User:> ")
|
||||
if user_input == "exit":
|
||||
print("\n\nExiting chat...")
|
||||
break
|
||||
|
||||
# Invoke the agent
|
||||
# The chat history is maintained in the session
|
||||
async for response in bedrock_agent.invoke(
|
||||
messages=user_input,
|
||||
thread=thread,
|
||||
):
|
||||
print(f"Bedrock agent: {response}")
|
||||
thread = response.thread
|
||||
except KeyboardInterrupt:
|
||||
print("\n\nExiting chat...")
|
||||
return False
|
||||
except EOFError:
|
||||
print("\n\nExiting chat...")
|
||||
return False
|
||||
finally:
|
||||
# Cleanup: Delete the thread
|
||||
await thread.delete() if thread else None
|
||||
|
||||
# Sample output (using anthropic.claude-3-haiku-20240307-v1:0):
|
||||
# User:> Hi, my name is John.
|
||||
# Bedrock agent: Hello John. How can I help you?
|
||||
# User:> What is my name?
|
||||
# Bedrock agent: Your name is John.
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,60 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
|
||||
from semantic_kernel.agents import BedrockAgent, BedrockAgentThread
|
||||
|
||||
"""
|
||||
This sample shows how to interact with a Bedrock agent in the simplest way.
|
||||
This sample uses the following main component(s):
|
||||
- a Bedrock agent
|
||||
You will learn how to create a new Bedrock agent and talk to it.
|
||||
"""
|
||||
|
||||
AGENT_NAME = "semantic-kernel-bedrock-agent"
|
||||
INSTRUCTION = "You are a friendly assistant. You help people find information."
|
||||
|
||||
|
||||
async def main():
|
||||
bedrock_agent = await BedrockAgent.create_and_prepare_agent(AGENT_NAME, instructions=INSTRUCTION)
|
||||
|
||||
# Create a thread for the agent
|
||||
# If no thread is provided, a new thread will be
|
||||
# created and returned with the initial response
|
||||
thread: BedrockAgentThread = None
|
||||
|
||||
try:
|
||||
while True:
|
||||
user_input = input("User:> ")
|
||||
if user_input == "exit":
|
||||
print("\n\nExiting chat...")
|
||||
break
|
||||
|
||||
# Invoke the agent
|
||||
# The chat history is maintained in the session
|
||||
response = await bedrock_agent.get_response(
|
||||
messages=user_input,
|
||||
thread=thread,
|
||||
)
|
||||
print(f"Bedrock agent: {response}")
|
||||
thread = response.thread
|
||||
except KeyboardInterrupt:
|
||||
print("\n\nExiting chat...")
|
||||
return False
|
||||
except EOFError:
|
||||
print("\n\nExiting chat...")
|
||||
return False
|
||||
finally:
|
||||
# Delete the agent
|
||||
await bedrock_agent.delete_agent()
|
||||
await thread.delete() if thread else None
|
||||
|
||||
# Sample output (using anthropic.claude-3-haiku-20240307-v1:0):
|
||||
# User:> Hi, my name is John.
|
||||
# Bedrock agent: Hello John. How can I help you?
|
||||
# User:> What is my name?
|
||||
# Bedrock agent: Your name is John.
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,55 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
|
||||
from semantic_kernel.agents import BedrockAgent, BedrockAgentThread
|
||||
|
||||
"""
|
||||
This sample shows how to interact with a Bedrock agent via streaming in the simplest way.
|
||||
This sample uses the following main component(s):
|
||||
- a Bedrock agent
|
||||
You will learn how to create a new Bedrock agent and talk to it.
|
||||
"""
|
||||
|
||||
AGENT_NAME = "semantic-kernel-bedrock-agent"
|
||||
INSTRUCTION = "You are a friendly assistant. You help people find information."
|
||||
|
||||
|
||||
async def main():
|
||||
bedrock_agent = await BedrockAgent.create_and_prepare_agent(AGENT_NAME, instructions=INSTRUCTION)
|
||||
thread: BedrockAgentThread = None
|
||||
|
||||
try:
|
||||
while True:
|
||||
user_input = input("User:> ")
|
||||
if user_input == "exit":
|
||||
print("\n\nExiting chat...")
|
||||
break
|
||||
|
||||
# Invoke the agent
|
||||
# The chat history is maintained in the thread
|
||||
print("Bedrock agent: ", end="")
|
||||
async for response in bedrock_agent.invoke_stream(messages=user_input, thread=thread):
|
||||
print(response, end="")
|
||||
thread = response.thread
|
||||
print()
|
||||
except KeyboardInterrupt:
|
||||
print("\n\nExiting chat...")
|
||||
return False
|
||||
except EOFError:
|
||||
print("\n\nExiting chat...")
|
||||
return False
|
||||
finally:
|
||||
# Delete the agent
|
||||
await bedrock_agent.delete_agent()
|
||||
await thread.delete() if thread else None
|
||||
|
||||
# Sample output (using anthropic.claude-3-haiku-20240307-v1:0):
|
||||
# User:> Hi, my name is John.
|
||||
# Bedrock agent: Hello John. How can I help you?
|
||||
# User:> What is my name?
|
||||
# Bedrock agent: Your name is John.
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,85 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
|
||||
from semantic_kernel.agents import BedrockAgent, BedrockAgentThread
|
||||
from semantic_kernel.contents.binary_content import BinaryContent
|
||||
|
||||
"""
|
||||
This sample shows how to interact with a Bedrock agent that is capable of writing and executing code.
|
||||
This sample uses the following main component(s):
|
||||
- a Bedrock agent
|
||||
You will learn how to create a new Bedrock agent and ask it a question that requires coding to answer.
|
||||
After running this sample, a bar chart will be generated and saved to a file in the same directory
|
||||
as this script.
|
||||
"""
|
||||
|
||||
AGENT_NAME = "semantic-kernel-bedrock-agent"
|
||||
INSTRUCTION = "You are a friendly assistant. You help people find information."
|
||||
|
||||
|
||||
ASK = """
|
||||
Create a bar chart for the following data:
|
||||
Panda 5
|
||||
Tiger 8
|
||||
Lion 3
|
||||
Monkey 6
|
||||
Dolphin 2
|
||||
"""
|
||||
|
||||
|
||||
async def main():
|
||||
bedrock_agent = await BedrockAgent.create_and_prepare_agent(AGENT_NAME, instructions=INSTRUCTION)
|
||||
await bedrock_agent.create_code_interpreter_action_group()
|
||||
|
||||
thread: BedrockAgentThread = None
|
||||
|
||||
# Placeholder for the file generated by the code interpreter
|
||||
binary_item: BinaryContent | None = None
|
||||
|
||||
try:
|
||||
# Invoke the agent
|
||||
async for response in bedrock_agent.invoke(
|
||||
messages=ASK,
|
||||
thread=thread,
|
||||
):
|
||||
print(f"Response:\n{response}")
|
||||
thread = response.thread
|
||||
if not binary_item:
|
||||
binary_item = next((item for item in response.items if isinstance(item, BinaryContent)), None)
|
||||
finally:
|
||||
# Delete the agent
|
||||
await bedrock_agent.delete_agent()
|
||||
await thread.delete() if thread else None
|
||||
|
||||
# Save the chart to a file
|
||||
if not binary_item:
|
||||
raise RuntimeError("No chart generated")
|
||||
|
||||
# Securely assemble the file path and validate it's within the expected directory
|
||||
# This is a defense-in-depth measure against directory traversal attacks
|
||||
output_dir = Path(__file__).parent.resolve()
|
||||
file_path = (output_dir / binary_item.metadata["name"]).resolve()
|
||||
|
||||
# Verify the resolved path is within the expected directory
|
||||
if not file_path.is_relative_to(output_dir):
|
||||
raise RuntimeError("Invalid filename: would write outside the expected directory")
|
||||
|
||||
binary_item.write_to_file(file_path)
|
||||
print(f"Chart saved to {file_path}")
|
||||
|
||||
# Sample output (using anthropic.claude-3-haiku-20240307-v1:0):
|
||||
# Response:
|
||||
# Here is the bar chart for the given data:
|
||||
# [A bar chart showing the following data:
|
||||
# Panda 5
|
||||
# Tiger 8
|
||||
# Lion 3
|
||||
# Monkey 6
|
||||
# Dolpin 2]
|
||||
# Chart saved to ...
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
|
||||
from semantic_kernel.agents import BedrockAgent, BedrockAgentThread
|
||||
from semantic_kernel.contents.binary_content import BinaryContent
|
||||
|
||||
"""
|
||||
This sample shows how to interact with a Bedrock agent that is capable of writing and executing code.
|
||||
This sample uses the following main component(s):
|
||||
- a Bedrock agent
|
||||
You will learn how to create a new Bedrock agent and ask it a question that requires coding to answer.
|
||||
After running this sample, a bar chart will be generated and saved to a file in the same directory
|
||||
as this script.
|
||||
"""
|
||||
|
||||
AGENT_NAME = "semantic-kernel-bedrock-agent"
|
||||
INSTRUCTION = "You are a friendly assistant. You help people find information."
|
||||
|
||||
|
||||
ASK = """
|
||||
Create a bar chart for the following data:
|
||||
Panda 5
|
||||
Tiger 8
|
||||
Lion 3
|
||||
Monkey 6
|
||||
Dolphin 2
|
||||
"""
|
||||
|
||||
|
||||
async def main():
|
||||
bedrock_agent = await BedrockAgent.create_and_prepare_agent(AGENT_NAME, instructions=INSTRUCTION)
|
||||
await bedrock_agent.create_code_interpreter_action_group()
|
||||
|
||||
thread: BedrockAgentThread = None
|
||||
|
||||
# Placeholder for the file generated by the code interpreter
|
||||
binary_item: BinaryContent | None = None
|
||||
|
||||
try:
|
||||
# Invoke the agent
|
||||
print("Response: ")
|
||||
async for response in bedrock_agent.invoke_stream(
|
||||
messages=ASK,
|
||||
thread=thread,
|
||||
):
|
||||
print(response, end="")
|
||||
thread = response.thread
|
||||
if not binary_item:
|
||||
binary_item = next((item for item in response.items if isinstance(item, BinaryContent)), None)
|
||||
print()
|
||||
finally:
|
||||
# Delete the agent
|
||||
await bedrock_agent.delete_agent()
|
||||
await thread.delete() if thread else None
|
||||
|
||||
# Save the chart to a file
|
||||
if not binary_item:
|
||||
raise RuntimeError("No chart generated")
|
||||
|
||||
# Securely assemble the file path and validate it's within the expected directory
|
||||
# This is a defense-in-depth measure against directory traversal attacks
|
||||
output_dir = Path(__file__).parent.resolve()
|
||||
file_path = (output_dir / binary_item.metadata["name"]).resolve()
|
||||
|
||||
# Verify the resolved path is within the expected directory
|
||||
if not file_path.is_relative_to(output_dir):
|
||||
raise RuntimeError("Invalid filename: would write outside the expected directory")
|
||||
|
||||
binary_item.write_to_file(file_path)
|
||||
print(f"Chart saved to {file_path}")
|
||||
|
||||
# Sample output (using anthropic.claude-3-haiku-20240307-v1:0):
|
||||
# Response:
|
||||
# Here is the bar chart for the given data:
|
||||
# [A bar chart showing the following data:
|
||||
# Panda 5
|
||||
# Tiger 8
|
||||
# Lion 3
|
||||
# Monkey 6
|
||||
# Dolpin 2]
|
||||
# Chart saved to ...
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,72 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
from typing import Annotated
|
||||
|
||||
from semantic_kernel.agents import BedrockAgent, BedrockAgentThread
|
||||
from semantic_kernel.functions.kernel_function_decorator import kernel_function
|
||||
from semantic_kernel.kernel import Kernel
|
||||
|
||||
"""
|
||||
This sample shows how to interact with a Bedrock agent that is capable of using kernel functions.
|
||||
This sample uses the following main component(s):
|
||||
- a Bedrock agent
|
||||
- a kernel function
|
||||
- a kernel
|
||||
You will learn how to create a new Bedrock agent and ask it a question that requires a kernel function to answer.
|
||||
"""
|
||||
|
||||
AGENT_NAME = "semantic-kernel-bedrock-agent"
|
||||
INSTRUCTION = "You are a friendly assistant. You help people find information."
|
||||
|
||||
|
||||
class WeatherPlugin:
|
||||
"""Mock weather plugin."""
|
||||
|
||||
@kernel_function(description="Get real-time weather information.")
|
||||
def current(self, location: Annotated[str, "The location to get the weather"]) -> str:
|
||||
"""Returns the current weather."""
|
||||
return f"The weather in {location} is sunny."
|
||||
|
||||
|
||||
def get_kernel() -> Kernel:
|
||||
kernel = Kernel()
|
||||
kernel.add_plugin(WeatherPlugin(), plugin_name="weather")
|
||||
|
||||
return kernel
|
||||
|
||||
|
||||
async def main():
|
||||
# Create a kernel
|
||||
kernel = get_kernel()
|
||||
|
||||
bedrock_agent = await BedrockAgent.create_and_prepare_agent(
|
||||
AGENT_NAME,
|
||||
INSTRUCTION,
|
||||
kernel=kernel,
|
||||
)
|
||||
# Note: We still need to create the kernel function action group on the service side.
|
||||
await bedrock_agent.create_kernel_function_action_group()
|
||||
|
||||
thread: BedrockAgentThread = None
|
||||
|
||||
try:
|
||||
# Invoke the agent
|
||||
async for response in bedrock_agent.invoke(
|
||||
messages="What is the weather in Seattle?",
|
||||
thread=thread,
|
||||
):
|
||||
print(f"Response:\n{response}")
|
||||
thread = response.thread
|
||||
finally:
|
||||
# Delete the agent
|
||||
await bedrock_agent.delete_agent()
|
||||
await thread.delete() if thread else None
|
||||
|
||||
# Sample output (using anthropic.claude-3-haiku-20240307-v1:0):
|
||||
# Response:
|
||||
# The current weather in Seattle is sunny.
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
from typing import Annotated
|
||||
|
||||
from semantic_kernel.agents import BedrockAgent, BedrockAgentThread
|
||||
from semantic_kernel.functions.kernel_function_decorator import kernel_function
|
||||
|
||||
"""
|
||||
This sample shows how to interact with a Bedrock agent that is capable of using kernel functions.
|
||||
Instead of creating a kernel and adding plugins to it, you can directly pass the plugins to the
|
||||
agent when creating it.
|
||||
This sample uses the following main component(s):
|
||||
- a Bedrock agent
|
||||
- a kernel function
|
||||
- a kernel
|
||||
You will learn how to create a new Bedrock agent and ask it a question that requires a kernel function to answer.
|
||||
"""
|
||||
|
||||
AGENT_NAME = "semantic-kernel-bedrock-agent"
|
||||
INSTRUCTION = "You are a friendly assistant. You help people find information."
|
||||
|
||||
|
||||
class WeatherPlugin:
|
||||
"""Mock weather plugin."""
|
||||
|
||||
@kernel_function(description="Get real-time weather information.")
|
||||
def current(self, location: Annotated[str, "The location to get the weather"]) -> str:
|
||||
"""Returns the current weather."""
|
||||
return f"The weather in {location} is sunny."
|
||||
|
||||
|
||||
async def main():
|
||||
bedrock_agent = await BedrockAgent.create_and_prepare_agent(
|
||||
AGENT_NAME,
|
||||
INSTRUCTION,
|
||||
plugins=[WeatherPlugin()],
|
||||
)
|
||||
# Note: We still need to create the kernel function action group on the service side.
|
||||
await bedrock_agent.create_kernel_function_action_group()
|
||||
|
||||
thread: BedrockAgentThread = None
|
||||
|
||||
try:
|
||||
# Invoke the agent
|
||||
async for response in bedrock_agent.invoke(
|
||||
messages="What is the weather in Seattle?",
|
||||
thread=thread,
|
||||
):
|
||||
print(f"Response:\n{response}")
|
||||
thread = response.thread
|
||||
finally:
|
||||
# Delete the agent
|
||||
await bedrock_agent.delete_agent()
|
||||
await thread.delete() if thread else None
|
||||
|
||||
# Sample output (using anthropic.claude-3-haiku-20240307-v1:0):
|
||||
# Response:
|
||||
# The current weather in Seattle is sunny.
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
from typing import Annotated
|
||||
|
||||
from semantic_kernel.agents import BedrockAgent, BedrockAgentThread
|
||||
from semantic_kernel.functions.kernel_function_decorator import kernel_function
|
||||
from semantic_kernel.kernel import Kernel
|
||||
|
||||
"""
|
||||
This sample shows how to interact with a Bedrock agent that is capable of using kernel functions.
|
||||
This sample uses the following main component(s):
|
||||
- a Bedrock agent
|
||||
- a kernel function
|
||||
- a kernel
|
||||
You will learn how to create a new Bedrock agent and ask it a question that requires a kernel function to answer.
|
||||
"""
|
||||
|
||||
AGENT_NAME = "semantic-kernel-bedrock-agent"
|
||||
INSTRUCTION = "You are a friendly assistant. You help people find information."
|
||||
|
||||
|
||||
class WeatherPlugin:
|
||||
"""Mock weather plugin."""
|
||||
|
||||
@kernel_function(description="Get real-time weather information.")
|
||||
def current(self, location: Annotated[str, "The location to get the weather"]) -> str:
|
||||
"""Returns the current weather."""
|
||||
return f"The weather in {location} is sunny."
|
||||
|
||||
|
||||
def get_kernel() -> Kernel:
|
||||
kernel = Kernel()
|
||||
kernel.add_plugin(WeatherPlugin(), plugin_name="weather")
|
||||
|
||||
return kernel
|
||||
|
||||
|
||||
async def main():
|
||||
# Create a kernel
|
||||
kernel = get_kernel()
|
||||
|
||||
bedrock_agent = await BedrockAgent.create_and_prepare_agent(
|
||||
AGENT_NAME,
|
||||
INSTRUCTION,
|
||||
kernel=kernel,
|
||||
)
|
||||
# Note: We still need to create the kernel function action group on the service side.
|
||||
await bedrock_agent.create_kernel_function_action_group()
|
||||
|
||||
thread: BedrockAgentThread = None
|
||||
|
||||
try:
|
||||
# Invoke the agent
|
||||
print("Response: ")
|
||||
async for response in bedrock_agent.invoke_stream(
|
||||
messages="What is the weather in Seattle?",
|
||||
thread=thread,
|
||||
):
|
||||
print(response, end="")
|
||||
thread = response.thread
|
||||
finally:
|
||||
# Delete the agent
|
||||
await bedrock_agent.delete_agent()
|
||||
await thread.delete() if thread else None
|
||||
|
||||
# Sample output (using anthropic.claude-3-haiku-20240307-v1:0):
|
||||
# Response:
|
||||
# The current weather in Seattle is sunny.
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,113 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import AgentGroupChat, BedrockAgent, ChatCompletionAgent
|
||||
from semantic_kernel.agents.strategies.termination.termination_strategy import TerminationStrategy
|
||||
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
|
||||
from semantic_kernel.contents.utils.author_role import AuthorRole
|
||||
from semantic_kernel.kernel import Kernel
|
||||
|
||||
"""
|
||||
This sample shows how to use a bedrock agent in a group chat that includes multiple agents of different roles.
|
||||
This sample uses the following main component(s):
|
||||
- a Bedrock agent
|
||||
- a ChatCompletionAgent
|
||||
- an AgentGroupChat
|
||||
You will learn how to create a new or connect to an existing Bedrock agent and put it in a group chat with
|
||||
another agent.
|
||||
|
||||
Note: This sample use the `AgentGroupChat` feature of Semantic Kernel, which is
|
||||
no longer maintained. For a replacement, consider using the `GroupChatOrchestration`.
|
||||
|
||||
Read more about the `GroupChatOrchestration` here:
|
||||
https://learn.microsoft.com/semantic-kernel/frameworks/agent/agent-orchestration/group-chat?pivots=programming-language-python
|
||||
|
||||
Here is a migration guide from `AgentGroupChat` to `GroupChatOrchestration`:
|
||||
https://learn.microsoft.com/semantic-kernel/support/migration/group-chat-orchestration-migration-guide?pivots=programming-language-python
|
||||
"""
|
||||
|
||||
# This will be a chat completion agent
|
||||
REVIEWER_NAME = "ArtDirector"
|
||||
REVIEWER_INSTRUCTIONS = """
|
||||
You are an art director who has opinions about copywriting born of a love for David Ogilvy.
|
||||
The goal is to determine if the given copy is acceptable to print.
|
||||
If so, state that it is approved. Only include the word "approved" if it is so.
|
||||
If not, provide insight on how to refine suggested copy without example.
|
||||
"""
|
||||
|
||||
# This will be a bedrock agent
|
||||
COPYWRITER_NAME = "CopyWriter"
|
||||
COPYWRITER_INSTRUCTIONS = """
|
||||
You are a copywriter with ten years of experience and are known for brevity and a dry humor.
|
||||
The goal is to refine and decide on the single best copy as an expert in the field.
|
||||
Only provide a single proposal per response.
|
||||
You're laser focused on the goal at hand.
|
||||
Don't waste time with chit chat.
|
||||
Consider suggestions when refining an idea.
|
||||
"""
|
||||
|
||||
|
||||
class ApprovalTerminationStrategy(TerminationStrategy):
|
||||
"""A strategy for determining when an agent should terminate."""
|
||||
|
||||
async def should_agent_terminate(self, agent, history):
|
||||
"""Check if the agent should terminate."""
|
||||
return "approved" in history[-1].content.lower()
|
||||
|
||||
|
||||
def _create_kernel_with_chat_completion() -> Kernel:
|
||||
kernel = Kernel()
|
||||
kernel.add_service(AzureChatCompletion(credential=AzureCliCredential()))
|
||||
return kernel
|
||||
|
||||
|
||||
async def main():
|
||||
agent_reviewer = ChatCompletionAgent(
|
||||
kernel=_create_kernel_with_chat_completion(),
|
||||
name=REVIEWER_NAME,
|
||||
instructions=REVIEWER_INSTRUCTIONS,
|
||||
)
|
||||
|
||||
agent_writer = await BedrockAgent.create_and_prepare_agent(
|
||||
COPYWRITER_NAME,
|
||||
instructions=COPYWRITER_INSTRUCTIONS,
|
||||
)
|
||||
|
||||
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."
|
||||
|
||||
await chat.add_chat_message(message=input)
|
||||
print(f"# {AuthorRole.USER}: '{input}'")
|
||||
|
||||
try:
|
||||
async for message in chat.invoke():
|
||||
print(f"# {message.role} - {message.name or '*'}: '{message.content}'")
|
||||
print(f"# IS COMPLETE: {chat.is_complete}")
|
||||
finally:
|
||||
# Delete the agent
|
||||
await agent_writer.delete_agent()
|
||||
|
||||
# Sample output (using anthropic.claude-3-haiku-20240307-v1:0):
|
||||
# AuthorRole.USER: 'A slogan for a new line of electric cars.'
|
||||
# AuthorRole.ASSISTANT - CopyWriter: 'Charge Ahead: The Future of Driving'
|
||||
# AuthorRole.ASSISTANT - ArtDirector: 'The slogan "Charge Ahead: The Future of Driving" is compelling but could be
|
||||
# made even more impactful. Consider clarifying the unique selling proposition of the electric cars. Focus on what
|
||||
# sets them apart in terms of performance, eco-friendliness, or innovation. This will help create an emotional
|
||||
# connection and a clearer message for the audience.'
|
||||
# AuthorRole.ASSISTANT - CopyWriter: 'Charge Forward: The Electrifying Future of Driving'
|
||||
# AuthorRole.ASSISTANT - ArtDirector: 'Approved'
|
||||
# IS COMPLETE: True
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,118 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import AgentGroupChat, BedrockAgent, ChatCompletionAgent
|
||||
from semantic_kernel.agents.strategies.termination.termination_strategy import TerminationStrategy
|
||||
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
|
||||
from semantic_kernel.contents.utils.author_role import AuthorRole
|
||||
from semantic_kernel.kernel import Kernel
|
||||
|
||||
"""
|
||||
This sample shows how to use a bedrock agent in a group chat that includes multiple agents of different roles.
|
||||
This sample uses the following main component(s):
|
||||
- a Bedrock agent
|
||||
- a ChatCompletionAgent
|
||||
- an AgentGroupChat
|
||||
You will learn how to create a new or connect to an existing Bedrock agent and put it in a group chat with
|
||||
another agent.
|
||||
|
||||
Note: This sample use the `AgentGroupChat` feature of Semantic Kernel, which is
|
||||
no longer maintained. For a replacement, consider using the `GroupChatOrchestration`.
|
||||
|
||||
Read more about the `GroupChatOrchestration` here:
|
||||
https://learn.microsoft.com/semantic-kernel/frameworks/agent/agent-orchestration/group-chat?pivots=programming-language-python
|
||||
|
||||
Here is a migration guide from `AgentGroupChat` to `GroupChatOrchestration`:
|
||||
https://learn.microsoft.com/semantic-kernel/support/migration/group-chat-orchestration-migration-guide?pivots=programming-language-python
|
||||
"""
|
||||
|
||||
# This will be a chat completion agent
|
||||
REVIEWER_NAME = "ArtDirector"
|
||||
REVIEWER_INSTRUCTIONS = """
|
||||
You are an art director who has opinions about copywriting born of a love for David Ogilvy.
|
||||
The goal is to determine if the given copy is acceptable to print.
|
||||
If so, state that it is approved. Only include the word "approved" if it is so.
|
||||
If not, provide insight on how to refine suggested copy without example.
|
||||
"""
|
||||
|
||||
# This will be a bedrock agent
|
||||
COPYWRITER_NAME = "CopyWriter"
|
||||
COPYWRITER_INSTRUCTIONS = """
|
||||
You are a copywriter with ten years of experience and are known for brevity and a dry humor.
|
||||
The goal is to refine and decide on the single best copy as an expert in the field.
|
||||
Only provide a single proposal per response.
|
||||
You're laser focused on the goal at hand.
|
||||
Don't waste time with chit chat.
|
||||
Consider suggestions when refining an idea.
|
||||
"""
|
||||
|
||||
|
||||
class ApprovalTerminationStrategy(TerminationStrategy):
|
||||
"""A strategy for determining when an agent should terminate."""
|
||||
|
||||
async def should_agent_terminate(self, agent, history):
|
||||
"""Check if the agent should terminate."""
|
||||
return "approved" in history[-1].content.lower()
|
||||
|
||||
|
||||
def _create_kernel_with_chat_completion() -> Kernel:
|
||||
kernel = Kernel()
|
||||
kernel.add_service(AzureChatCompletion(credential=AzureCliCredential()))
|
||||
return kernel
|
||||
|
||||
|
||||
async def main():
|
||||
agent_reviewer = ChatCompletionAgent(
|
||||
kernel=_create_kernel_with_chat_completion(),
|
||||
name=REVIEWER_NAME,
|
||||
instructions=REVIEWER_INSTRUCTIONS,
|
||||
)
|
||||
|
||||
agent_writer = await BedrockAgent.create_and_prepare_agent(
|
||||
COPYWRITER_NAME,
|
||||
instructions=COPYWRITER_INSTRUCTIONS,
|
||||
)
|
||||
|
||||
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."
|
||||
|
||||
await chat.add_chat_message(message=input)
|
||||
print(f"# {AuthorRole.USER}: '{input}'")
|
||||
|
||||
try:
|
||||
current_agent = "*"
|
||||
async for message_chunk in chat.invoke_stream():
|
||||
if current_agent != message_chunk.name:
|
||||
current_agent = message_chunk.name or "*"
|
||||
print(f"\n# {message_chunk.role} - {current_agent}: ", end="")
|
||||
print(message_chunk.content, end="")
|
||||
print()
|
||||
print(f"# IS COMPLETE: {chat.is_complete}")
|
||||
finally:
|
||||
# Delete the agent
|
||||
await agent_writer.delete_agent()
|
||||
|
||||
# Sample output (using anthropic.claude-3-haiku-20240307-v1:0):
|
||||
# AuthorRole.USER: 'A slogan for a new line of electric cars.'
|
||||
# AuthorRole.ASSISTANT - CopyWriter: 'Charge Ahead: The Future of Driving'
|
||||
# AuthorRole.ASSISTANT - ArtDirector: 'The slogan "Charge Ahead: The Future of Driving" is compelling but could be
|
||||
# made even more impactful. Consider clarifying the unique selling proposition of the electric cars. Focus on what
|
||||
# sets them apart in terms of performance, eco-friendliness, or innovation. This will help create an emotional
|
||||
# connection and a clearer message for the audience.'
|
||||
# AuthorRole.ASSISTANT - CopyWriter: 'Charge Forward: The Electrifying Future of Driving'
|
||||
# AuthorRole.ASSISTANT - ArtDirector: 'Approved'
|
||||
# IS COMPLETE: True
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user