|
| 1 | +# Dream Destination Finder with CrewAI and Amazon Bedrock |
| 2 | + |
| 3 | +In this notebook, we will explore how to use the CrewAI framework with Amazon Bedrock to build an intelligent agent that can find dream travel destinations based on user preferences. The agent will utilize a large language model (LLM) and web search capabilities to research and recommend destinations that match the user's description. |
| 4 | + |
| 5 | +## What's CrewAI: |
| 6 | +CrewAI is one of the leading open-source Python frameworks designed to help developers create and manage multi-agent AI systems. |
| 7 | + |
| 8 | +<img src="assets/crewai_diagram.png"> |
| 9 | + |
| 10 | +Diagram Representation of CrewAI architecture |
| 11 | + |
| 12 | +__!pip install boto3 botocore crewai crewai_tools duckduckgo-search langchain-community -q__ |
| 13 | + |
| 14 | +We start by importing the necessary modules from the crewai and crewai_tools packages. |
| 15 | + |
| 16 | +#### Configuring AWS Credentials: |
| 17 | +Before using Amazon Bedrock, ensure that your AWS credentials are configured correctly. You can set them up using the AWS CLI or by setting environment variables. For this notebook, we’ll assume that the credentials are already configured. |
| 18 | + |
| 19 | +To use bedrock we will use [__CrewAI__ __LLM__ api](https://docs.crewai.com/how-to/llm-connections#supported-providers) |
| 20 | + |
| 21 | + |
| 22 | +```python |
| 23 | +from crewai import Agent, Task, Crew, LLM |
| 24 | +from crewai_tools import tool |
| 25 | +from langchain_community.tools import DuckDuckGoSearchRun |
| 26 | +``` |
| 27 | + |
| 28 | +#### Define web-search tool: |
| 29 | + |
| 30 | + |
| 31 | +```python |
| 32 | +@tool('DuckDuckGoSearch') |
| 33 | +def search(search_query: str): |
| 34 | + """Search the web for information on a given topic""" |
| 35 | + return DuckDuckGoSearchRun().run(search_query) |
| 36 | +``` |
| 37 | + |
| 38 | +### Configuring the LLM |
| 39 | + |
| 40 | +We will use Anthropic’s Claude-3 model via Amazon Bedrock as our LLM. CrewAI uses LiteLLM under the hood to interact with different LLM providers. |
| 41 | + |
| 42 | + |
| 43 | + |
| 44 | +```python |
| 45 | +# Configure the LLM |
| 46 | +llm = LLM(model="bedrock/anthropic.claude-3-sonnet-20240229-v1:0") |
| 47 | +``` |
| 48 | + |
| 49 | +### Defining the Agent |
| 50 | + |
| 51 | +We will create an agent with the role of a “Travel Destination Researcher.” This agent will be responsible for finding destinations that match the user’s travel preferences. |
| 52 | + |
| 53 | + |
| 54 | +```python |
| 55 | +# Define the Agent |
| 56 | +travel_agent = Agent( |
| 57 | + role='Travel Destination Researcher', |
| 58 | + goal='Find dream destinations matching user preferences', |
| 59 | + backstory="You are an experienced travel agent specializing in personalized travel recommendations.", |
| 60 | + verbose=True, |
| 61 | + allow_delegation=False, |
| 62 | + llm=llm, |
| 63 | + tools=[search] # Tool for online searching |
| 64 | +) |
| 65 | +``` |
| 66 | + |
| 67 | +### Defining the Task |
| 68 | + |
| 69 | +We need to specify the task that the agent will perform. The task includes a description, expected output, and is assigned to the agent we just created. |
| 70 | + |
| 71 | + |
| 72 | +```python |
| 73 | +# Define the Task |
| 74 | +task = Task( |
| 75 | + description="Based on the user's travel preferences: {preferences}, research and recommend suitable travel destinations.", |
| 76 | + expected_output="A list of recommended destinations with brief descriptions.", |
| 77 | + agent=travel_agent |
| 78 | +) |
| 79 | +``` |
| 80 | + |
| 81 | +### Creating the Crew |
| 82 | + |
| 83 | +A crew is a team of agents working together to achieve a common goal. In this case, we have only one agent, but the framework allows for scalability. |
| 84 | + |
| 85 | + |
| 86 | + |
| 87 | +```python |
| 88 | +# Create the Crew |
| 89 | +crew = Crew( |
| 90 | + agents=[travel_agent], |
| 91 | + tasks=[task], |
| 92 | + verbose=True, |
| 93 | +) |
| 94 | +``` |
| 95 | + |
| 96 | +### Executing the Workflow |
| 97 | + |
| 98 | +Now, we can execute the crew with the user’s travel preferences as input. |
| 99 | + |
| 100 | + |
| 101 | +```python |
| 102 | +# User input for travel preferences |
| 103 | +user_input = { |
| 104 | + "preferences": "I want a tropical beach vacation with great snorkeling and vibrant nightlife." |
| 105 | +} |
| 106 | + |
| 107 | +# Execute the Crew |
| 108 | +result = crew.kickoff(inputs=user_input) |
| 109 | +``` |
| 110 | + |
| 111 | +#### As the crew executes, CrewAI will: |
| 112 | + |
| 113 | +• Decompose the task into actions using ReAct (Reasoning and Act), optionally using the tools assigned to the agent. |
| 114 | + |
| 115 | +• Make multiple calls to Amazon Bedrock to complete each step from the previous phase. |
| 116 | + |
| 117 | + |
| 118 | +```python |
| 119 | +from IPython.display import Markdown |
| 120 | +``` |
| 121 | + |
| 122 | + |
| 123 | +```python |
| 124 | +Markdown(result.raw) |
| 125 | +``` |
| 126 | + |
| 127 | +### Adding Memory to the Agent |
| 128 | +CrewAI supports [several memory types](https://docs.crewai.com/concepts/memory#implementing-memory-in-your-crew), which help agents remember and learn from past interactions. In this case, we’ll enable short-term memory using Amazon Bedrock’s embedding model. |
| 129 | + |
| 130 | + |
| 131 | +```python |
| 132 | +# Enabling Memory in the Agent |
| 133 | +crew_with_memory = Crew( |
| 134 | + agents=[travel_agent], |
| 135 | + tasks=[task], |
| 136 | + verbose=True, |
| 137 | + memory=True, # Enable memory |
| 138 | + embedder={ |
| 139 | + "provider": "aws_bedrock", |
| 140 | + "config": { |
| 141 | + "model": "amazon.titan-embed-text-v2:0", # Embedding model for memory |
| 142 | + "vector_dimension": 1024 |
| 143 | + } |
| 144 | + }, |
| 145 | + |
| 146 | +) |
| 147 | +``` |
| 148 | + |
| 149 | + |
| 150 | +```python |
| 151 | +# Executing the Crew with Memory |
| 152 | +result_with_memory = crew_with_memory.kickoff(inputs=user_input) |
| 153 | +``` |
| 154 | + |
| 155 | + |
| 156 | +```python |
| 157 | +Markdown(result_with_memory.raw) |
| 158 | +``` |
| 159 | + |
| 160 | +### Integrating Retrieval-Augmented Generation (RAG) with Amazon Bedrock Knowledge Base |
| 161 | +In this section, we will enhance our dream destination finder agent by incorporating Retrieval-Augmented Generation (RAG) using Amazon Bedrock’s Knowledge Base. This will allow our agent to access up-to-date and domain-specific travel information, improving the accuracy and relevance of its recommendations. |
| 162 | + |
| 163 | + |
| 164 | + |
| 165 | +#### What is Retrieval-Augmented Generation (RAG)? |
| 166 | + |
| 167 | +RAG is a technique that combines the capabilities of large language models (LLMs) with a retrieval mechanism to fetch relevant information from external data sources. By integrating RAG, our agent can retrieve the most recent and specific information from a knowledge base, overcoming the limitations of LLMs that may have outdated or insufficient data. |
| 168 | + |
| 169 | +Setting Up Amazon Bedrock Knowledge Base |
| 170 | + |
| 171 | +Before we proceed, ensure you have access to Amazon Bedrock and the necessary permissions to create and manage knowledge bases. |
| 172 | + |
| 173 | +* Step 1: Prepare Your Data |
| 174 | +* Step 2: Create a Knowledge Base in Amazon Bedrock |
| 175 | +* Step 3: Note the Knowledge Base ID |
| 176 | + |
| 177 | +After the knowledge base is created, note down its Knowledge Base ID (kb_id), which will be used in our code. |
| 178 | + |
| 179 | +<img src="assets/KB-pannel.png"> |
| 180 | + |
| 181 | +Updating the Agent to Use RAG with CrewAI |
| 182 | + |
| 183 | +We will modify our agent to include a custom tool that queries the Amazon Bedrock Knowledge Base. This allows the agent to retrieve up-to-date information during its reasoning process. |
| 184 | + |
| 185 | + |
| 186 | +```python |
| 187 | +import boto3 |
| 188 | +# Initialize the Bedrock client |
| 189 | +bedrock_agent_runtime_client = boto3.client("bedrock-agent-runtime", region_name="{YOUR-REGION}") |
| 190 | +``` |
| 191 | + |
| 192 | +### Knowledge Base Tool Set up: |
| 193 | +Using the __kb id__, __model arn__ (either foundational or custom) we can leverage Amazons Knowledge Bases. In this example the question will also be broken down using __orchestrationConfiguration__ settings. |
| 194 | + |
| 195 | + |
| 196 | +```python |
| 197 | +@tool("TravelExpertSearchEngine") |
| 198 | +def query_knowledge_base(question: str) -> str: |
| 199 | + """Queries the Amazon Bedrock Knowledge Base for travel-related information.""" |
| 200 | + kb_id = "XXXX" # Replace with your Knowledge Base ID |
| 201 | + model_id = "foundation-model/anthropic.claude-3-sonnet-20240229-v1:0" # Use an available model in Bedrock |
| 202 | + model_arn = f'arn:aws:bedrock:YOUR-REGION::{model_id}' |
| 203 | + |
| 204 | + response = bedrock_agent_runtime_client.retrieve_and_generate( |
| 205 | + input={'text': question}, |
| 206 | + retrieveAndGenerateConfiguration={ |
| 207 | + "type": "KNOWLEDGE_BASE", |
| 208 | + "knowledgeBaseConfiguration" : {'knowledgeBaseId': kb_id, |
| 209 | + 'modelArn': model_arn, |
| 210 | + 'orchestrationConfiguration': { |
| 211 | + 'queryTransformationConfiguration': { |
| 212 | + 'type': 'QUERY_DECOMPOSITION' |
| 213 | + } |
| 214 | + } |
| 215 | + } |
| 216 | + } |
| 217 | + ) |
| 218 | + try: |
| 219 | + return str({"Results": response['output']['text'], "Citations": response['citations'][0]}) |
| 220 | + except KeyError: |
| 221 | + return "No data available" |
| 222 | + |
| 223 | + |
| 224 | +``` |
| 225 | + |
| 226 | +### Update the Agent with the New Tool |
| 227 | +We will update our agent to include the TravelExpert tool. |
| 228 | + |
| 229 | + |
| 230 | +```python |
| 231 | +# Configure the LLM |
| 232 | +llm = LLM(model="bedrock/anthropic.claude-3-sonnet-20240229-v1:0") |
| 233 | + |
| 234 | +# Update the Agent |
| 235 | +agent_with_rag = Agent( |
| 236 | + role='Travel Destination Researcher', |
| 237 | + goal='Find dream destinations in the USA, first think about cities matching user preferences and then use information from the search engine, nothing else.', |
| 238 | + backstory="""You are an experienced travel agent specializing in personalized travel recommendations. |
| 239 | + Your approach is as follows: |
| 240 | + Deduce which regions within the USA will have those activities listed by the user. |
| 241 | + List major cities within that region |
| 242 | + Only then use the tool provided to look up information, look up should be done by passing city highlights and activities. |
| 243 | + """, |
| 244 | + verbose=True, |
| 245 | + allow_delegation=False, |
| 246 | + llm=llm, |
| 247 | + tools=[query_knowledge_base], # Include the RAG tool |
| 248 | + max_iter=5 |
| 249 | +) |
| 250 | + |
| 251 | +``` |
| 252 | + |
| 253 | +### Update the task and set up the Crew |
| 254 | + |
| 255 | + |
| 256 | +```python |
| 257 | +# Define the Task |
| 258 | +task_with_rag = Task( |
| 259 | + description="Based on the user's travel request, research and recommend suitable travel destinations using the latest information. Only use output provided by the Travel Destination Researcher, nothing else: USER: {preferences}", |
| 260 | + expected_output="A place where they can travel to along with recommendations on what to see and do while there.", |
| 261 | + agent=agent_with_rag |
| 262 | +) |
| 263 | + |
| 264 | + |
| 265 | +# Create the Crew |
| 266 | +crew_with_rag = Crew( |
| 267 | + agents=[agent_with_rag], |
| 268 | + tasks=[task_with_rag], |
| 269 | + verbose=True, |
| 270 | +) |
| 271 | +``` |
| 272 | + |
| 273 | + |
| 274 | +```python |
| 275 | +# User input for travel preferences |
| 276 | +user_input = { |
| 277 | + "preferences": "Where can I go for cowboy vibes, watch a rodeo, and a museum or two?" |
| 278 | +} |
| 279 | + |
| 280 | +# Execute the Crew |
| 281 | +result_with_rag = crew_with_rag.kickoff(inputs=user_input) |
| 282 | + |
| 283 | +``` |
| 284 | + |
| 285 | +### Display the results |
| 286 | + |
| 287 | + |
| 288 | +```python |
| 289 | +# Display the result |
| 290 | +Markdown(result_with_rag.raw) |
| 291 | +``` |
| 292 | + |
| 293 | + |
| 294 | +```python |
| 295 | + |
| 296 | +``` |
0 commit comments