Skip to content

Commit

Permalink
Add more samples
Browse files Browse the repository at this point in the history
  • Loading branch information
TaoChenOSU committed Jan 30, 2025
1 parent a26d902 commit 40bc545
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 17 deletions.
14 changes: 10 additions & 4 deletions python/samples/concepts/agents/bedrock_agent/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,25 @@
| Sample | Description |
|--------|-------------|
| [bedrock_agent_simple_chat.py](bedrock_agent_simple_chat.py) | Demonstrates basic usage of the Bedrock agent. |
| [bedrock_agent_simple_chat_with_kernel_function.py](bedrock_agent_simple_chat_with_kernel_function.py) | Shows how to use the Bedrock agent with a kernel function. |
| [bedrock_agent_simple_chat_with_code_interpreter.py](bedrock_agent_simple_chat_with_code_interpreter.py) | Example of using the Bedrock agent with a code interpreter. |
| [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. |
| [bedrock_agent_update_agent.py](bedrock_agent_update_agent.py) | Example of updating an agent. |
| [bedrock_agent_use_existing.py](bedrock_agent_use_existing.py) | Example of using an existing agent. |

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

### `AGENT_ROLE_AMAZON_RESOURCE_NAME`
### `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.

### `FOUNDATION_MODEL`
### `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.

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Copyright (c) Microsoft. All rights reserved.

import asyncio
import uuid

from semantic_kernel.agents.bedrock.bedrock_agent import BedrockAgent

# This sample shows how to update an existing Bedrock agent.
# This sample uses the following main component(s):
# - a Bedrock agent
# You will learn how to connect to a Bedrock agent and update its properties.


# Make sure to replace AGENT_NAME and AGENT_ID with the correct values
AGENT_NAME = "semantic-kernel-bedrock-agent"
INSTRUCTION = "You are a friendly assistant but you don't know anything about AI."
NEW_INSTRUCTION = "You are a friendly assistant and you know a lot about AI."


async def main():
bedrock_agent = await BedrockAgent.create(AGENT_NAME, instructions=INSTRUCTION)

async def ask_about_ai():
new_session_id = str(uuid.uuid4())
async for response in bedrock_agent.invoke(
session_id=new_session_id,
input_text="What is AI in one sentence?",
):
print(response)

try:
print("Before updating the agent:")
await ask_about_ai()

await bedrock_agent.update_agent(instruction=NEW_INSTRUCTION)

print("After updating the agent:")
await ask_about_ai()
finally:
# Delete the agent
await bedrock_agent.delete_agent()

# Sample output (using anthropic.claude-3-haiku-20240307-v1:0):
# Before updating the agent:
# I apologize, but I do not have any information about AI or the ability to define it.
# As I mentioned, I am a friendly assistant without any knowledge about AI. I cannot
# provide a definition for AI in one sentence. If you have a different question I can
# try to assist with, please let me know.
# After updating the agent:
# AI is the field of computer science that aims to create systems and machines that can
# perform tasks that typically require human intelligence, such as learning, problem-solving,
# perception, and decision-making.


if __name__ == "__main__":
asyncio.run(main())
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Copyright (c) Microsoft. All rights reserved.

import asyncio
import uuid

from semantic_kernel.agents.bedrock.bedrock_agent import BedrockAgent

# 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 that has already been created
# You will learn how to connect to an existing Bedrock agent and talk to it.


# Make sure to replace AGENT_NAME and AGENT_ID with the correct values
AGENT_NAME = "semantic-kernel-bedrock-agent"
AGENT_ID = "..."


async def main():
bedrock_agent = await BedrockAgent.retrieve(AGENT_ID, AGENT_NAME)

# Use a uiud as the session id
new_session_id = str(uuid.uuid4())

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(
session_id=new_session_id,
input_text=user_input,
):
print(f"Bedrock agent: {response}")
except KeyboardInterrupt:
print("\n\nExiting chat...")
return False
except EOFError:
print("\n\nExiting chat...")
return False

# 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())
6 changes: 2 additions & 4 deletions python/semantic_kernel/agents/bedrock/bedrock_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ def __init__(
raise AgentInitializationException("Failed to initialize the Amazon Bedrock Agent settings.") from e

bedrock_agent_model = BedrockAgentModel(
agent_arn=bedrock_agent_settings.agent_resource_role_arn,
agent_id=id,
agent_name=name,
foundation_model=bedrock_agent_settings.foundation_model,
Expand All @@ -101,14 +100,13 @@ def __init__(
prompt_template: PromptTemplateBase | None = None
if instructions and prompt_template_config:
raise AgentInitializationException("Cannot set both instructions and prompt_template_config.")
if not instructions and not prompt_template_config:
raise AgentInitializationException("Either instructions or prompt_template_config must be set.")
if prompt_template_config:
prompt_template = TEMPLATE_FORMAT_MAP[prompt_template_config.template_format](
prompt_template_config=prompt_template_config
)

args: dict[str, Any] = {
"agent_resource_role_arn": bedrock_agent_settings.agent_resource_role_arn,
"name": name,
"agent_model": bedrock_agent_model,
}
Expand Down Expand Up @@ -264,7 +262,7 @@ async def create_agent(
raise AgentInitializationException("Foundation model is required to create an agent.")

await self._create_agent(
self.instructions or await self.format_instructions(self.kernel, self.arguments),
self.instructions or await self.format_instructions(self.kernel, self.arguments) or "",
**kwargs,
)

Expand Down
22 changes: 14 additions & 8 deletions python/semantic_kernel/agents/bedrock/bedrock_agent_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,12 @@ class BedrockAgentBase(KernelBaseModel):
function_choice_behavior: FunctionChoiceBehavior = Field(default=FunctionChoiceBehavior.Auto())
# Agent Model: stores the agent information
agent_model: BedrockAgentModel
# Agent ARN: The Amazon Resource Name (ARN) of the agent.
agent_resource_role_arn: str

def __init__(
self,
agent_resource_role_arn: str,
agent_model: BedrockAgentModel,
*,
function_choice_behavior: FunctionChoiceBehavior | None = None,
Expand All @@ -54,13 +57,15 @@ def __init__(
"""Initialize the Bedrock Agent Base.
Args:
agent_resource_role_arn: The Amazon Resource Name (ARN) of the agent.
agent_model: The Bedrock Agent Model.
function_choice_behavior: The function choice behavior.
bedrock_runtime_client: The Bedrock Runtime Client.
bedrock_client: The Bedrock Client.
kwargs: Additional keyword arguments.
"""
args = {
"agent_resource_role_arn": agent_resource_role_arn,
"agent_model": agent_model,
"bedrock_runtime_client": bedrock_runtime_client or boto3.client("bedrock-agent-runtime"),
"bedrock_client": bedrock_client or boto3.client("bedrock-agent"),
Expand Down Expand Up @@ -111,7 +116,7 @@ async def _create_agent(
self.bedrock_client.create_agent,
agentName=self.agent_model.agent_name,
foundationModel=self.agent_model.foundation_model,
agentResourceRoleArn=self.agent_model.agent_arn,
agentResourceRoleArn=self.agent_resource_role_arn,
instruction=instruction,
**kwargs,
),
Expand Down Expand Up @@ -159,7 +164,7 @@ async def _create_agent_alias(self, alias_name: str, **kwargs) -> dict[str, Any]
return await self._run_in_executor(
None,
partial(
self.bedrock_client.create_client_alias,
self.bedrock_client.create_agent_alias,
agentAliasName=alias_name,
agentId=self.agent_model.agent_id,
**kwargs,
Expand All @@ -186,17 +191,18 @@ async def _update_agent(
raise ValueError("Agent has not been created. Please create the agent before updating it.")

try:
self.agent_model = await self._run_in_executor(
response = await self._run_in_executor(
None,
partial(
self.bedrock_client.update_client,
self.bedrock_client.update_agent,
agentId=self.agent_model.agent_id,
agentResourceRoleArn=self.agent_model.agent_arn,
agentResourceRoleArn=self.agent_resource_role_arn,
agentName=agent_name,
foundationModel=foundation_model,
**kwargs,
),
)
self.agent_model = response["agent"]

await self._wait_for_agent_status(BedrockAgentStatus.PREPARED)
except ClientError as e:
Expand Down Expand Up @@ -348,7 +354,7 @@ async def associate_agent_knowledge_base(self, knowledge_base_id: str, **kwargs)
return await self._run_in_executor(
None,
partial(
self.bedrock_client.associate_client_knowledge_base,
self.bedrock_client.associate_agent_knowledge_base,
agentId=self.agent_model.agent_id,
agentVersion=self.agent_model.agent_version,
knowledgeBaseId=knowledge_base_id,
Expand All @@ -372,7 +378,7 @@ async def disassociate_agent_knowledge_base(self, knowledge_base_id: str, **kwar
await self._run_in_executor(
None,
partial(
self.bedrock_client.disassociate_client_knowledge_base,
self.bedrock_client.disassociate_agent_knowledge_base,
agentId=self.agent_model.agent_id,
agentVersion=self.agent_model.agent_version,
knowledgeBaseId=knowledge_base_id,
Expand All @@ -394,7 +400,7 @@ async def list_associated_agent_knowledge_bases(self, **kwargs) -> dict[str, Any
return await self._run_in_executor(
None,
partial(
self.bedrock_client.list_client_knowledge_bases,
self.bedrock_client.list_agent_knowledge_bases,
agentId=self.agent_model.agent_id,
agentVersion=self.agent_model.agent_version,
**kwargs,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ class BedrockAgentModel(KernelBaseModel):
# This model_config will merge with the KernelBaseModel.model_config
model_config = ConfigDict(extra="allow")

agent_arn: str = Field(..., alias="agentArn", description="The Amazon Resource Name (ARN) of the agent.")
agent_id: str | None = Field(None, alias="agentId", description="The unique identifier of the agent.")
agent_name: str | None = Field(None, alias="agentName", description="The name of the agent.")
agent_version: str | None = Field(None, alias="agentVersion", description="The version of the agent.")
Expand Down

0 comments on commit 40bc545

Please sign in to comment.