(Click the image above to view video of this lesson)
Metacognition in AI Agents
Welcome to the lesson on metacognition in AI agents! This chapter is designed for beginners who are curious about how AI agents can think about their own thinking processes. By the end of this lesson, you’ll understand key concepts and be equipped with practical examples to apply metacognition in AI agent design.
After completing this lesson, you’ll be able to:
Metacognition refers to the higher-order cognitive processes that involve thinking about one’s own thinking. For AI agents, this means being able to evaluate and adjust their actions based on self-awareness and past experiences. Metacognition, or “thinking about thinking,” is an important concept in the development of agentic AI systems. It involves AI systems being aware of their own internal processes and being able to monitor, regulate, and adapt their behavior accordingly. Much like we do when we read the room or look at a problem. This self-awareness can help AI systems make better decisions, identify errors, and improve their performance over time- again linking back to the Turing test and the debate over whether AI is going to take over.
In the context of agentic AI systems, metacognition can help address several challenges, such as:
Metacognition, or “thinking about thinking,” is a higher-order cognitive process that involves self-awareness and self-regulation of one’s cognitive processes. In the realm of AI, metacognition empowers agents to evaluate and adapt their strategies and actions, leading to improved problem-solving and decision-making capabilities. By understanding metacognition, you can design AI agents that are not only more intelligent but also more adaptable and efficient. In true metacognition, you’d see the AI explicitly reasoning about its own reasoning.
Example: “I prioritized cheaper flights because… I might be missing out on direct flights, so let me re-check.”. Keeping track of how or why it chose a certain route.
Metacognition plays a crucial role in AI agent design for several reasons:
Before diving into metacognitive processes, it’s essential to understand the basic components of an AI agent. An AI agent typically consists of:
These components work together to create an “expertise unit” that can perform specific tasks.
Example: Consider a travel agent, agent services that not only plans your holiday but also adjusts its path based on real-time data and past customer journey experiences.
Imagine you’re designing a travel agent service powered by AI. This agent, “Travel Agent,” assists users with planning their vacations. To incorporate metacognition, Travel Agents needs to evaluate and adjust its actions based on self-awareness and past experiences. Here’s how metacognition could play a role:
The current task is to help a user plan a trip to Paris.
Travel Agent uses metacognition to evaluate its performance and learn from past experiences. For example:
Here’s a simplified example of how Travel Agents code might look when incorporating metacognition:
class Travel_Agent:
def __init__(self):
self.user_preferences = {}
self.experience_data = []
def gather_preferences(self, preferences):
self.user_preferences = preferences
def retrieve_information(self):
# Search for flights, hotels, and attractions based on preferences
flights = search_flights(self.user_preferences)
hotels = search_hotels(self.user_preferences)
attractions = search_attractions(self.user_preferences)
return flights, hotels, attractions
def generate_recommendations(self):
flights, hotels, attractions = self.retrieve_information()
itinerary = create_itinerary(flights, hotels, attractions)
return itinerary
def adjust_based_on_feedback(self, feedback):
self.experience_data.append(feedback)
# Analyze feedback and adjust future recommendations
self.user_preferences = adjust_preferences(self.user_preferences, feedback)
# Example usage
travel_agent = Travel_Agent()
preferences = {
"destination": "Paris",
"dates": "2025-04-01 to 2025-04-10",
"budget": "moderate",
"interests": ["museums", "cuisine"]
}
travel_agent.gather_preferences(preferences)
itinerary = travel_agent.generate_recommendations()
print("Suggested Itinerary:", itinerary)
feedback = {"liked": ["Louvre Museum"], "disliked": ["Eiffel Tower (too crowded)"]}
travel_agent.adjust_based_on_feedback(feedback)
By incorporating metacognition, Travel Agent can provide more personalized and accurate travel recommendations, enhancing the overall user experience.
Planning is a critical component of AI agent behavior. It involves outlining the steps needed to achieve a goal, considering the current state, resources, and possible obstacles.
Example: Here are the steps Travel Agent needs to take to assist a user in planning their trip effectively:
class Travel_Agent:
def __init__(self):
self.user_preferences = {}
self.experience_data = []
def gather_preferences(self, preferences):
self.user_preferences = preferences
def retrieve_information(self):
flights = search_flights(self.user_preferences)
hotels = search_hotels(self.user_preferences)
attractions = search_attractions(self.user_preferences)
return flights, hotels, attractions
def generate_recommendations(self):
flights, hotels, attractions = self.retrieve_information()
itinerary = create_itinerary(flights, hotels, attractions)
return itinerary
def adjust_based_on_feedback(self, feedback):
self.experience_data.append(feedback)
self.user_preferences = adjust_preferences(self.user_preferences, feedback)
# Example usage within a booing request
travel_agent = Travel_Agent()
preferences = {
"destination": "Paris",
"dates": "2025-04-01 to 2025-04-10",
"budget": "moderate",
"interests": ["museums", "cuisine"]
}
travel_agent.gather_preferences(preferences)
itinerary = travel_agent.generate_recommendations()
print("Suggested Itinerary:", itinerary)
feedback = {"liked": ["Louvre Museum"], "disliked": ["Eiffel Tower (too crowded)"]}
travel_agent.adjust_based_on_feedback(feedback)
Firstly let’s start by understanding the difference between RAG Tool and Pre-emptive Context Load
RAG combines a retrieval system with a generative model. When a query is made, the retrieval system fetches relevant documents or data from an external source, and this retrieved information is used to augment the input to the generative model. This helps the model generate more accurate and contextually relevant responses.
In a RAG system, the agent retrieves relevant information from a knowledge base and uses it to generate appropriate responses or actions.
The Corrective RAG approach focuses on using RAG techniques to correct errors and improve the accuracy of AI agents. This involves:
Consider a search agent that retrieves information from the web to answer user queries. The Corrective RAG approach might involve:
Corrective RAG (Retrieval-Augmented Generation) enhances an AI’s ability to retrieve and generate information while correcting any inaccuracies. Let’s see how Travel Agent can use the Corrective RAG approach to provide more accurate and relevant travel recommendations.
This involves:
Example:
preferences = {
"destination": "Paris",
"dates": "2025-04-01 to 2025-04-10",
"budget": "moderate",
"interests": ["museums", "cuisine"]
}
Example:
flights = search_flights(preferences)
hotels = search_hotels(preferences)
attractions = search_attractions(preferences)
Example:
itinerary = create_itinerary(flights, hotels, attractions)
print("Suggested Itinerary:", itinerary)
Example:
feedback = {
"liked": ["Louvre Museum"],
"disliked": ["Eiffel Tower (too crowded)"]
}
Example:
if "disliked" in feedback:
preferences["avoid"] = feedback["disliked"]
Example:
new_attractions = search_attractions(preferences)
new_itinerary = create_itinerary(flights, hotels, new_attractions)
print("Updated Itinerary:", new_itinerary)
Example:
def adjust_preferences(preferences, feedback):
if "liked" in feedback:
preferences["favorites"] = feedback["liked"]
if "disliked" in feedback:
preferences["avoid"] = feedback["disliked"]
return preferences
preferences = adjust_preferences(preferences, feedback)
Here’s a simplified Python code example incorporating the Corrective RAG approach in Travel Agent:
class Travel_Agent:
def __init__(self):
self.user_preferences = {}
self.experience_data = []
def gather_preferences(self, preferences):
self.user_preferences = preferences
def retrieve_information(self):
flights = search_flights(self.user_preferences)
hotels = search_hotels(self.user_preferences)
attractions = search_attractions(self.user_preferences)
return flights, hotels, attractions
def generate_recommendations(self):
flights, hotels, attractions = self.retrieve_information()
itinerary = create_itinerary(flights, hotels, attractions)
return itinerary
def adjust_based_on_feedback(self, feedback):
self.experience_data.append(feedback)
self.user_preferences = adjust_preferences(self.user_preferences, feedback)
new_itinerary = self.generate_recommendations()
return new_itinerary
# Example usage
travel_agent = Travel_Agent()
preferences = {
"destination": "Paris",
"dates": "2025-04-01 to 2025-04-10",
"budget": "moderate",
"interests": ["museums", "cuisine"]
}
travel_agent.gather_preferences(preferences)
itinerary = travel_agent.generate_recommendations()
print("Suggested Itinerary:", itinerary)
feedback = {"liked": ["Louvre Museum"], "disliked": ["Eiffel Tower (too crowded)"]}
new_itinerary = travel_agent.adjust_based_on_feedback(feedback)
print("Updated Itinerary:", new_itinerary)
Pre-emptive Context Load involves loading relevant context or background information into the model before processing a query. This means the model has access to this information from the start, which can help it generate more informed responses without needing to retrieve additional data during the process.
Here’s a simplified example of how a pre-emptive context load might look for a travel agent application in Python:
class TravelAgent:
def __init__(self):
# Pre-load popular destinations and their information
self.context = {
"Paris": {"country": "France", "currency": "Euro", "language": "French", "attractions": ["Eiffel Tower", "Louvre Museum"]},
"Tokyo": {"country": "Japan", "currency": "Yen", "language": "Japanese", "attractions": ["Tokyo Tower", "Shibuya Crossing"]},
"New York": {"country": "USA", "currency": "Dollar", "language": "English", "attractions": ["Statue of Liberty", "Times Square"]},
"Sydney": {"country": "Australia", "currency": "Dollar", "language": "English", "attractions": ["Sydney Opera House", "Bondi Beach"]}
}
def get_destination_info(self, destination):
# Fetch destination information from pre-loaded context
info = self.context.get(destination)
if info:
return f"{destination}:\nCountry: {info['country']}\nCurrency: {info['currency']}\nLanguage: {info['language']}\nAttractions: {', '.join(info['attractions'])}"
else:
return f"Sorry, we don't have information on {destination}."
# Example usage
travel_agent = TravelAgent()
print(travel_agent.get_destination_info("Paris"))
print(travel_agent.get_destination_info("Tokyo"))
Initialization (__init__
method): The TravelAgent
class pre-loads a dictionary containing information about popular destinations such as Paris, Tokyo, New York, and Sydney. This dictionary includes details like the country, currency, language, and major attractions for each destination.
Retrieving Information (get_destination_info
method): When a user queries about a specific destination, the get_destination_info
method fetches the relevant information from the pre-loaded context dictionary.
By pre-loading the context, the travel agent application can quickly respond to user queries without having to retrieve this information from an external source in real-time. This makes the application more efficient and responsive.
Bootstrapping a plan with a goal involves starting with a clear objective or target outcome in mind. By defining this goal upfront, the model can use it as a guiding principle throughout the iterative process. This helps ensure that each iteration moves closer to achieving the desired outcome, making the process more efficient and focused.
Here’s an example of how you might bootstrap a travel plan with a goal before iterating for a travel agent in Python:
A travel agent wants to plan a customized vacation for a client. The goal is to create a travel itinerary that maximizes the client’s satisfaction based on their preferences and budget.
class TravelAgent:
def __init__(self, destinations):
self.destinations = destinations
def bootstrap_plan(self, preferences, budget):
plan = []
total_cost = 0
for destination in self.destinations:
if total_cost + destination['cost'] <= budget and self.match_preferences(destination, preferences):
plan.append(destination)
total_cost += destination['cost']
return plan
def match_preferences(self, destination, preferences):
for key, value in preferences.items():
if destination.get(key) != value:
return False
return True
def iterate_plan(self, plan, preferences, budget):
for i in range(len(plan)):
for destination in self.destinations:
if destination not in plan and self.match_preferences(destination, preferences) and self.calculate_cost(plan, destination) <= budget:
plan[i] = destination
break
return plan
def calculate_cost(self, plan, new_destination):
return sum(destination['cost'] for destination in plan) + new_destination['cost']
# Example usage
destinations = [
{"name": "Paris", "cost": 1000, "activity": "sightseeing"},
{"name": "Tokyo", "cost": 1200, "activity": "shopping"},
{"name": "New York", "cost": 900, "activity": "sightseeing"},
{"name": "Sydney", "cost": 1100, "activity": "beach"},
]
preferences = {"activity": "sightseeing"}
budget = 2000
travel_agent = TravelAgent(destinations)
initial_plan = travel_agent.bootstrap_plan(preferences, budget)
print("Initial Plan:", initial_plan)
refined_plan = travel_agent.iterate_plan(initial_plan, preferences, budget)
print("Refined Plan:", refined_plan)
Initialization (__init__
method): The TravelAgent
class is initialized with a list of potential destinations, each having attributes like name, cost, and activity type.
Bootstrapping the Plan (bootstrap_plan
method): This method creates an initial travel plan based on the client’s preferences and budget. It iterates through the list of destinations and adds them to the plan if they match the client’s preferences and fit within the budget.
Matching Preferences (match_preferences
method): This method checks if a destination matches the client’s preferences.
Iterating the Plan (iterate_plan
method): This method refines the initial plan by trying to replace each destination in the plan with a better match, considering the client’s preferences and budget constraints.
Calculating Cost (calculate_cost
method): This method calculates the total cost of the current plan, including a potential new destination.
By bootstrapping the plan with a clear goal (e.g., maximizing client satisfaction) and iterating to refine the plan, the travel agent can create a customized and optimized travel itinerary for the client. This approach ensures that the travel plan aligns with the client’s preferences and budget from the start and improves with each iteration.
Large Language Models (LLMs) can be used for re-ranking and scoring by evaluating the relevance and quality of retrieved documents or generated responses. Here’s how it works:
Retrieval: The initial retrieval step fetches a set of candidate documents or responses based on the query.
Re-ranking: The LLM evaluates these candidates and re-ranks them based on their relevance and quality. This step ensures that the most relevant and high-quality information is presented first.
Scoring: The LLM assigns scores to each candidate, reflecting their relevance and quality. This helps in selecting the best response or document for the user.
By leveraging LLMs for re-ranking and scoring, the system can provide more accurate and contextually relevant information, improving the overall user experience.
Here’s an example of how a travel agent might use a Large Language Model (LLM) for re-ranking and scoring travel destinations based on user preferences in Python:
A travel agent wants to recommend the best travel destinations to a client based on their preferences. The LLM will help re-rank and score the destinations to ensure the most relevant options are presented.
Here’s how you can update the previous example to use Azure OpenAI Services:
import requests
import json
class TravelAgent:
def __init__(self, destinations):
self.destinations = destinations
def get_recommendations(self, preferences, api_key, endpoint):
# Generate a prompt for the Azure OpenAI
prompt = self.generate_prompt(preferences)
# Define headers and payload for the request
headers = {
'Content-Type': 'application/json',
'Authorization': f'Bearer {api_key}'
}
payload = {
"prompt": prompt,
"max_tokens": 150,
"temperature": 0.7
}
# Call the Azure OpenAI API to get the re-ranked and scored destinations
response = requests.post(endpoint, headers=headers, json=payload)
response_data = response.json()
# Extract and return the recommendations
recommendations = response_data['choices'][0]['text'].strip().split('\n')
return recommendations
def generate_prompt(self, preferences):
prompt = "Here are the travel destinations ranked and scored based on the following user preferences:\n"
for key, value in preferences.items():
prompt += f"{key}: {value}\n"
prompt += "\nDestinations:\n"
for destination in self.destinations:
prompt += f"- {destination['name']}: {destination['description']}\n"
return prompt
# Example usage
destinations = [
{"name": "Paris", "description": "City of lights, known for its art, fashion, and culture."},
{"name": "Tokyo", "description": "Vibrant city, famous for its modernity and traditional temples."},
{"name": "New York", "description": "The city that never sleeps, with iconic landmarks and diverse culture."},
{"name": "Sydney", "description": "Beautiful harbour city, known for its opera house and stunning beaches."},
]
preferences = {"activity": "sightseeing", "culture": "diverse"}
api_key = 'your_azure_openai_api_key'
endpoint = 'https://your-endpoint.com/openai/deployments/your-deployment-name/completions?api-version=2022-12-01'
travel_agent = TravelAgent(destinations)
recommendations = travel_agent.get_recommendations(preferences, api_key, endpoint)
print("Recommended Destinations:")
for rec in recommendations:
print(rec)
Initialization: The TravelAgent
class is initialized with a list of potential travel destinations, each having attributes like name and description.
Getting Recommendations (get_recommendations
method): This method generates a prompt for the Azure OpenAI service based on the user’s preferences and makes an HTTP POST request to the Azure OpenAI API to get re-ranked and scored destinations.
Generating Prompt (generate_prompt
method): This method constructs a prompt for the Azure OpenAI, including the user’s preferences and the list of destinations. The prompt guides the model to re-rank and score the destinations based on the provided preferences.
API Call: The requests
library is used to make an HTTP POST request to the Azure OpenAI API endpoint. The response contains the re-ranked and scored destinations.
Example Usage: The travel agent collects user preferences (e.g., interest in sightseeing and diverse culture) and uses the Azure OpenAI service to get re-ranked and scored recommendations for travel destinations.
Make sure to replace your_azure_openai_api_key
with your actual Azure OpenAI API key and https://your-endpoint.com/...
with the actual endpoint URL of your Azure OpenAI deployment.
By leveraging the LLM for re-ranking and scoring, the travel agent can provide more personalized and relevant travel recommendations to clients, enhancing their overall experience.
Retrieval-Augmented Generation (RAG) can be both a prompting technique and a tool in the development of AI agents. Understanding the distinction between the two can help you leverage RAG more effectively in your projects.
What is it?
How it works:
Example in Travel Agent:
What is it?
How it works:
Example in Travel Agent:
Aspect | Prompting Technique | Tool |
---|---|---|
Manual vs Automatic | Manual formulation of prompts for each query. | Automated process for retrieval and generation. |
Control | Offers more control over the retrieval process. | Streamlines and automates the retrieval and generation. |
Flexibility | Allows for customized prompts based on specific needs. | More efficient for large-scale implementations. |
Complexity | Requires crafting and tweaking of prompts. | Easier to integrate within an AI agent’s architecture. |
Prompting Technique Example:
def search_museums_in_paris():
prompt = "Find top museums in Paris"
search_results = search_web(prompt)
return search_results
museums = search_museums_in_paris()
print("Top Museums in Paris:", museums)
Tool Example:
class Travel_Agent:
def __init__(self):
self.rag_tool = RAGTool()
def get_museums_in_paris(self):
user_input = "I want to visit museums in Paris."
response = self.rag_tool.retrieve_and_generate(user_input)
return response
travel_agent = Travel_Agent()
museums = travel_agent.get_museums_in_paris()
print("Top Museums in Paris:", museums)
Evaluating relevancy is a crucial aspect of AI agent performance. It ensures that the information retrieved and generated by the agent is appropriate, accurate, and useful to the user. Let’s explore how to evaluate relevancy in AI agents, including practical examples and techniques.
Example:
def relevance_score(item, query):
score = 0
if item['category'] in query['interests']:
score += 1
if item['price'] <= query['budget']:
score += 1
if item['location'] == query['destination']:
score += 1
return score
Example:
def filter_and_rank(items, query):
ranked_items = sorted(items, key=lambda item: relevance_score(item, query), reverse=True)
return ranked_items[:10] # Return top 10 relevant items
Example:
def process_query(query):
# Use NLP to extract key information from the user's query
processed_query = nlp(query)
return processed_query
Example:
def adjust_based_on_feedback(feedback, items):
for item in items:
if item['name'] in feedback['liked']:
item['relevance'] += 1
if item['name'] in feedback['disliked']:
item['relevance'] -= 1
return items
Here’s a practical example of how Travel Agent can evaluate the relevancy of travel recommendations:
class Travel_Agent:
def __init__(self):
self.user_preferences = {}
self.experience_data = []
def gather_preferences(self, preferences):
self.user_preferences = preferences
def retrieve_information(self):
flights = search_flights(self.user_preferences)
hotels = search_hotels(self.user_preferences)
attractions = search_attractions(self.user_preferences)
return flights, hotels, attractions
def generate_recommendations(self):
flights, hotels, attractions = self.retrieve_information()
ranked_hotels = self.filter_and_rank(hotels, self.user_preferences)
itinerary = create_itinerary(flights, ranked_hotels, attractions)
return itinerary
def filter_and_rank(self, items, query):
ranked_items = sorted(items, key=lambda item: self.relevance_score(item, query), reverse=True)
return ranked_items[:10] # Return top 10 relevant items
def relevance_score(self, item, query):
score = 0
if item['category'] in query['interests']:
score += 1
if item['price'] <= query['budget']:
score += 1
if item['location'] == query['destination']:
score += 1
return score
def adjust_based_on_feedback(self, feedback, items):
for item in items:
if item['name'] in feedback['liked']:
item['relevance'] += 1
if item['name'] in feedback['disliked']:
item['relevance'] -= 1
return items
# Example usage
travel_agent = Travel_Agent()
preferences = {
"destination": "Paris",
"dates": "2025-04-01 to 2025-04-10",
"budget": "moderate",
"interests": ["museums", "cuisine"]
}
travel_agent.gather_preferences(preferences)
itinerary = travel_agent.generate_recommendations()
print("Suggested Itinerary:", itinerary)
feedback = {"liked": ["Louvre Museum"], "disliked": ["Eiffel Tower (too crowded)"]}
updated_items = travel_agent.adjust_based_on_feedback(feedback, itinerary['hotels'])
print("Updated Itinerary with Feedback:", updated_items)
Searching with intent involves understanding and interpreting the underlying purpose or goal behind a user’s query to retrieve and generate the most relevant and useful information. This approach goes beyond simply matching keywords and focuses on grasping the user’s actual needs and context.
Let’s take Travel Agent as an example to see how searching with intent can be implemented.
Gathering User Preferences
class Travel_Agent:
def __init__(self):
self.user_preferences = {}
def gather_preferences(self, preferences):
self.user_preferences = preferences
Understanding User Intent
def identify_intent(query):
if "book" in query or "purchase" in query:
return "transactional"
elif "website" in query or "official" in query:
return "navigational"
else:
return "informational"
Context Awareness
def analyze_context(query, user_history):
# Combine current query with user history to understand context
context = {
"current_query": query,
"user_history": user_history
}
return context
Search and Personalize Results
def search_with_intent(query, preferences, user_history):
intent = identify_intent(query)
context = analyze_context(query, user_history)
if intent == "informational":
search_results = search_information(query, preferences)
elif intent == "navigational":
search_results = search_navigation(query)
elif intent == "transactional":
search_results = search_transaction(query, preferences)
personalized_results = personalize_results(search_results, user_history)
return personalized_results
def search_information(query, preferences):
# Example search logic for informational intent
results = search_web(f"best {preferences['interests']} in {preferences['destination']}")
return results
def search_navigation(query):
# Example search logic for navigational intent
results = search_web(query)
return results
def search_transaction(query, preferences):
# Example search logic for transactional intent
results = search_web(f"book {query} to {preferences['destination']}")
return results
def personalize_results(results, user_history):
# Example personalization logic
personalized = [result for result in results if result not in user_history]
return personalized[:10] # Return top 10 personalized results
Example Usage
travel_agent = Travel_Agent()
preferences = {
"destination": "Paris",
"interests": ["museums", "cuisine"]
}
travel_agent.gather_preferences(preferences)
user_history = ["Louvre Museum website", "Book flight to Paris"]
query = "best museums in Paris"
results = search_with_intent(query, preferences, user_history)
print("Search Results:", results)
Code generating agents use AI models to write and execute code, solving complex problems and automating tasks.
Code generating agents use generative AI models to write and execute code. These agents can solve complex problems, automate tasks, and provide valuable insights by generating and running code in various programming languages.
Imagine you’re designing a code generating agent. Here’s how it might work:
In this example, we’ll design a code generating agent, Travel Agent, to assist users in planning their travel by generating and executing code. This agent can handle tasks such as fetching travel options, filtering results, and compiling an itinerary using generative AI.
Gathering User Preferences
class Travel_Agent:
def __init__(self):
self.user_preferences = {}
def gather_preferences(self, preferences):
self.user_preferences = preferences
Generating Code to Fetch Data
def generate_code_to_fetch_data(preferences):
# Example: Generate code to search for flights based on user preferences
code = f"""
def search_flights():
import requests
response = requests.get('https://api.example.com/flights', params={preferences})
return response.json()
"""
return code
def generate_code_to_fetch_hotels(preferences):
# Example: Generate code to search for hotels
code = f"""
def search_hotels():
import requests
response = requests.get('https://api.example.com/hotels', params={preferences})
return response.json()
"""
return code
Executing Generated Code
def execute_code(code):
# Execute the generated code using exec
exec(code)
result = locals()
return result
travel_agent = Travel_Agent()
preferences = {
"destination": "Paris",
"dates": "2025-04-01 to 2025-04-10",
"budget": "moderate",
"interests": ["museums", "cuisine"]
}
travel_agent.gather_preferences(preferences)
flight_code = generate_code_to_fetch_data(preferences)
hotel_code = generate_code_to_fetch_hotels(preferences)
flights = execute_code(flight_code)
hotels = execute_code(hotel_code)
print("Flight Options:", flights)
print("Hotel Options:", hotels)
Generating Itinerary
def generate_itinerary(flights, hotels, attractions):
itinerary = {
"flights": flights,
"hotels": hotels,
"attractions": attractions
}
return itinerary
attractions = search_attractions(preferences)
itinerary = generate_itinerary(flights, hotels, attractions)
print("Suggested Itinerary:", itinerary)
Adjusting Based on Feedback
def adjust_based_on_feedback(feedback, preferences):
# Adjust preferences based on user feedback
if "liked" in feedback:
preferences["favorites"] = feedback["liked"]
if "disliked" in feedback:
preferences["avoid"] = feedback["disliked"]
return preferences
feedback = {"liked": ["Louvre Museum"], "disliked": ["Eiffel Tower (too crowded)"]}
updated_preferences = adjust_based_on_feedback(feedback, preferences)
# Regenerate and execute code with updated preferences
updated_flight_code = generate_code_to_fetch_data(updated_preferences)
updated_hotel_code = generate_code_to_fetch_hotels(updated_preferences)
updated_flights = execute_code(updated_flight_code)
updated_hotels = execute_code(updated_hotel_code)
updated_itinerary = generate_itinerary(updated_flights, updated_hotels, attractions)
print("Updated Itinerary:", updated_itinerary)
Based on the schema of the table can indeed enhance the query generation process by leveraging environmental awareness and reasoning.
Here’s an example of how this can be done:
Here is an updated Python code example that incorporates these concepts:
def adjust_based_on_feedback(feedback, preferences, schema):
# Adjust preferences based on user feedback
if "liked" in feedback:
preferences["favorites"] = feedback["liked"]
if "disliked" in feedback:
preferences["avoid"] = feedback["disliked"]
# Reasoning based on schema to adjust other related preferences
for field in schema:
if field in preferences:
preferences[field] = adjust_based_on_environment(feedback, field, schema)
return preferences
def adjust_based_on_environment(feedback, field, schema):
# Custom logic to adjust preferences based on schema and feedback
if field in feedback["liked"]:
return schema[field]["positive_adjustment"]
elif field in feedback["disliked"]:
return schema[field]["negative_adjustment"]
return schema[field]["default"]
def generate_code_to_fetch_data(preferences):
# Generate code to fetch flight data based on updated preferences
return f"fetch_flights(preferences={preferences})"
def generate_code_to_fetch_hotels(preferences):
# Generate code to fetch hotel data based on updated preferences
return f"fetch_hotels(preferences={preferences})"
def execute_code(code):
# Simulate execution of code and return mock data
return {"data": f"Executed: {code}"}
def generate_itinerary(flights, hotels, attractions):
# Generate itinerary based on flights, hotels, and attractions
return {"flights": flights, "hotels": hotels, "attractions": attractions}
# Example schema
schema = {
"favorites": {"positive_adjustment": "increase", "negative_adjustment": "decrease", "default": "neutral"},
"avoid": {"positive_adjustment": "decrease", "negative_adjustment": "increase", "default": "neutral"}
}
# Example usage
preferences = {"favorites": "sightseeing", "avoid": "crowded places"}
feedback = {"liked": ["Louvre Museum"], "disliked": ["Eiffel Tower (too crowded)"]}
updated_preferences = adjust_based_on_feedback(feedback, preferences, schema)
# Regenerate and execute code with updated preferences
updated_flight_code = generate_code_to_fetch_data(updated_preferences)
updated_hotel_code = generate_code_to_fetch_hotels(updated_preferences)
updated_flights = execute_code(updated_flight_code)
updated_hotels = execute_code(updated_hotel_code)
updated_itinerary = generate_itinerary(updated_flights, updated_hotels, feedback["liked"])
print("Updated Itinerary:", updated_itinerary)
schema
dictionary defines how preferences should be adjusted based on feedback. It includes fields like favorites
and avoid
, with corresponding adjustments.adjust_based_on_feedback
method): This method adjusts preferences based on user feedback and the schema.adjust_based_on_environment
method): This method customizes the adjustments based on the schema and feedback.By making the system environment-aware and reasoning based on the schema, it can generate more accurate and relevant queries, leading to better travel recommendations and a more personalized user experience.
SQL (Structured Query Language) is a powerful tool for interacting with databases. When used as part of a Retrieval-Augmented Generation (RAG) approach, SQL can retrieve relevant data from databases to inform and generate responses or actions in AI agents. Let’s explore how SQL can be used as a RAG technique in the context of Travel Agent.
Example: A data analysis agent:
Gathering User Preferences
class Travel_Agent:
def __init__(self):
self.user_preferences = {}
def gather_preferences(self, preferences):
self.user_preferences = preferences
Generating SQL Queries
def generate_sql_query(table, preferences):
query = f"SELECT * FROM {table} WHERE "
conditions = []
for key, value in preferences.items():
conditions.append(f"{key}='{value}'")
query += " AND ".join(conditions)
return query
Executing SQL Queries
import sqlite3
def execute_sql_query(query, database="travel.db"):
connection = sqlite3.connect(database)
cursor = connection.cursor()
cursor.execute(query)
results = cursor.fetchall()
connection.close()
return results
Generating Recommendations
def generate_recommendations(preferences):
flight_query = generate_sql_query("flights", preferences)
hotel_query = generate_sql_query("hotels", preferences)
attraction_query = generate_sql_query("attractions", preferences)
flights = execute_sql_query(flight_query)
hotels = execute_sql_query(hotel_query)
attractions = execute_sql_query(attraction_query)
itinerary = {
"flights": flights,
"hotels": hotels,
"attractions": attractions
}
return itinerary
travel_agent = Travel_Agent()
preferences = {
"destination": "Paris",
"dates": "2025-04-01 to 2025-04-10",
"budget": "moderate",
"interests": ["museums", "cuisine"]
}
travel_agent.gather_preferences(preferences)
itinerary = generate_recommendations(preferences)
print("Suggested Itinerary:", itinerary)
Flight Query
SELECT * FROM flights WHERE destination='Paris' AND dates='2025-04-01 to 2025-04-10' AND budget='moderate';
Hotel Query
SELECT * FROM hotels WHERE destination='Paris' AND budget='moderate';
Attraction Query
SELECT * FROM attractions WHERE destination='Paris' AND interests='museums, cuisine';
By leveraging SQL as part of the Retrieval-Augmented Generation (RAG) technique, AI agents like Travel Agent can dynamically retrieve and utilize relevant data to provide accurate and personalized recommendations.
So to demonstrate an implementation of metacongition, let’s create a simple agent that reflects on its decision-making process while solving a problem. For this example, we’ll build a system where an agent tries to optimize the choice of a hotel, but then evaluates its own reasoning and adjusts its strategy when it makes errors or suboptimal choices.
We’ll simulate this using a basic example where the agent selects hotels based on a combination of price and quality, but it will “reflect” on its decisions and adjust accordingly.
Here’s an example:
class HotelRecommendationAgent:
def __init__(self):
self.previous_choices = [] # Stores the hotels chosen previously
self.corrected_choices = [] # Stores the corrected choices
self.recommendation_strategies = ['cheapest', 'highest_quality'] # Available strategies
def recommend_hotel(self, hotels, strategy):
"""
Recommend a hotel based on the chosen strategy.
The strategy can either be 'cheapest' or 'highest_quality'.
"""
if strategy == 'cheapest':
recommended = min(hotels, key=lambda x: x['price'])
elif strategy == 'highest_quality':
recommended = max(hotels, key=lambda x: x['quality'])
else:
recommended = None
self.previous_choices.append((strategy, recommended))
return recommended
def reflect_on_choice(self):
"""
Reflect on the last choice made and decide if the agent should adjust its strategy.
The agent considers if the previous choice led to a poor outcome.
"""
if not self.previous_choices:
return "No choices made yet."
last_choice_strategy, last_choice = self.previous_choices[-1]
# Let's assume we have some user feedback that tells us whether the last choice was good or not
user_feedback = self.get_user_feedback(last_choice)
if user_feedback == "bad":
# Adjust strategy if the previous choice was unsatisfactory
new_strategy = 'highest_quality' if last_choice_strategy == 'cheapest' else 'cheapest'
self.corrected_choices.append((new_strategy, last_choice))
return f"Reflecting on choice. Adjusting strategy to {new_strategy}."
else:
return "The choice was good. No need to adjust."
def get_user_feedback(self, hotel):
"""
Simulate user feedback based on hotel attributes.
For simplicity, assume if the hotel is too cheap, the feedback is "bad".
If the hotel has quality less than 7, feedback is "bad".
"""
if hotel['price'] < 100 or hotel['quality'] < 7:
return "bad"
return "good"
# Simulate a list of hotels (price and quality)
hotels = [
{'name': 'Budget Inn', 'price': 80, 'quality': 6},
{'name': 'Comfort Suites', 'price': 120, 'quality': 8},
{'name': 'Luxury Stay', 'price': 200, 'quality': 9}
]
# Create an agent
agent = HotelRecommendationAgent()
# Step 1: The agent recommends a hotel using the "cheapest" strategy
recommended_hotel = agent.recommend_hotel(hotels, 'cheapest')
print(f"Recommended hotel (cheapest): {recommended_hotel['name']}")
# Step 2: The agent reflects on the choice and adjusts strategy if necessary
reflection_result = agent.reflect_on_choice()
print(reflection_result)
# Step 3: The agent recommends again, this time using the adjusted strategy
adjusted_recommendation = agent.recommend_hotel(hotels, 'highest_quality')
print(f"Adjusted hotel recommendation (highest_quality): {adjusted_recommendation['name']}")
The key here is the agent’s ability to:
This is a simple form of metacognition where the system is capable of adjusting its reasoning process based on internal feedback.
Metacognition is a powerful tool that can significantly enhance the capabilities of AI agents. By incorporating metacognitive processes, you can design agents that are more intelligent, adaptable, and efficient. Use the additional resources to further explore the fascinating world of metacognition in AI agents.