Umar - Bootcamp

This commit is contained in:
Umar Javed
2025-10-29 13:04:37 +05:00
parent 1f3fc0c00f
commit c15cb484e8
45 changed files with 2187 additions and 0 deletions

View File

@@ -0,0 +1,33 @@
import logging
class Agent:
"""
An abstract superclass for Agents
Used to log messages in a way that can identify each Agent
"""
# Foreground colors
RED = '\033[31m'
GREEN = '\033[32m'
YELLOW = '\033[33m'
BLUE = '\033[34m'
MAGENTA = '\033[35m'
CYAN = '\033[36m'
WHITE = '\033[37m'
# Background color
BG_BLACK = '\033[40m'
# Reset code to return to default color
RESET = '\033[0m'
name: str = ""
color: str = '\033[37m'
def log(self, message):
"""
Log this as an info message, identifying the agent
"""
color_code = self.BG_BLACK + self.color
message = f"[{self.name}] {message}"
logging.info(color_code + message + self.RESET)

View File

@@ -0,0 +1,75 @@
import os
import re
import sys
from typing import List, Dict
from openai import OpenAI
from sentence_transformers import SentenceTransformer
w8d5_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
if w8d5_path not in sys.path:
sys.path.insert(0, w8d5_path)
from agents.agent import Agent
class TravelEstimatorAgent(Agent):
name = "Travel Estimator"
color = Agent.BLUE
MODEL = "gpt-4o-mini"
def __init__(self, collection):
self.log("Travel Estimator initializing")
self.client = OpenAI()
self.MODEL = "gpt-4o-mini"
self.log("Travel Estimator using OpenAI")
self.collection = collection
self.model = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2')
self.log("Travel Estimator ready")
def make_context(self, similars: List[str], prices: List[float]) -> str:
message = "Here are similar travel deals for context:\n\n"
for similar, price in zip(similars, prices):
message += f"Similar deal:\n{similar}\nPrice: ${price:.2f}\n\n"
return message
def messages_for(self, description: str, similars: List[str], prices: List[float]) -> List[Dict[str, str]]:
system_message = "You estimate fair market prices for travel deals. Reply only with the price estimate, no explanation"
user_prompt = self.make_context(similars, prices)
user_prompt += "Now estimate the fair market price for:\n\n"
user_prompt += description
return [
{"role": "system", "content": system_message},
{"role": "user", "content": user_prompt},
{"role": "assistant", "content": "Fair price estimate: $"}
]
def find_similars(self, description: str):
self.log("Travel Estimator searching for similar deals")
vector = self.model.encode([description])
results = self.collection.query(query_embeddings=vector.astype(float).tolist(), n_results=5)
documents = results['documents'][0][:]
prices = [m['price'] for m in results['metadatas'][0][:]]
self.log("Travel Estimator found similar deals")
return documents, prices
def get_price(self, s) -> float:
s = s.replace('$','').replace(',','')
match = re.search(r"[-+]?\d*\.\d+|\d+", s)
return float(match.group()) if match else 0.0
def estimate(self, description: str) -> float:
documents, prices = self.find_similars(description)
self.log(f"Travel Estimator calling {self.MODEL}")
response = self.client.chat.completions.create(
model=self.MODEL,
messages=self.messages_for(description, documents, prices),
seed=42,
max_tokens=10
)
reply = response.choices[0].message.content
result = self.get_price(reply)
self.log(f"Travel Estimator complete - ${result:.2f}")
return result

View File

@@ -0,0 +1,48 @@
import os
import sys
import http.client
import urllib
w8d5_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
if w8d5_path not in sys.path:
sys.path.insert(0, w8d5_path)
from agents.agent import Agent
from helpers.travel_deals import TravelOpportunity
DO_PUSH = True
class TravelMessagingAgent(Agent):
name = "Travel Messenger"
color = Agent.WHITE
def __init__(self):
self.log("Travel Messenger initializing")
if DO_PUSH:
self.pushover_user = os.getenv('PUSHOVER_USER', 'your-pushover-user-if-not-using-env')
self.pushover_token = os.getenv('PUSHOVER_TOKEN', 'your-pushover-token-if-not-using-env')
self.log("Travel Messenger has initialized Pushover")
def push(self, text):
self.log("Travel Messenger sending push notification")
conn = http.client.HTTPSConnection("api.pushover.net:443")
conn.request("POST", "/1/messages.json",
urllib.parse.urlencode({
"token": self.pushover_token,
"user": self.pushover_user,
"message": text,
"sound": "cashregister"
}), { "Content-type": "application/x-www-form-urlencoded" })
conn.getresponse()
def alert(self, opportunity: TravelOpportunity):
text = f"Travel Deal! {opportunity.deal.destination} - "
text += f"Price=${opportunity.deal.price:.2f}, "
text += f"Est=${opportunity.estimate:.2f}, "
text += f"Save ${opportunity.discount:.2f}! "
text += opportunity.deal.url
if DO_PUSH:
self.push(text)
self.log("Travel Messenger completed")

View File

@@ -0,0 +1,57 @@
import os
import sys
from typing import Optional, List
w8d5_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
if w8d5_path not in sys.path:
sys.path.insert(0, w8d5_path)
from agents.agent import Agent
from helpers.travel_deals import TravelDeal, TravelOpportunity
from agents.travel_scanner_agent import TravelScannerAgent
from agents.travel_estimator_agent import TravelEstimatorAgent
from agents.travel_messaging_agent import TravelMessagingAgent
class TravelPlanningAgent(Agent):
name = "Travel Planner"
color = Agent.GREEN
DEAL_THRESHOLD = 50
def __init__(self, collection):
self.log("Travel Planner initializing")
self.scanner = TravelScannerAgent()
self.estimator = TravelEstimatorAgent(collection)
self.messenger = TravelMessagingAgent()
self.log("Travel Planner ready")
def evaluate(self, deal: TravelDeal) -> TravelOpportunity:
self.log(f"Travel Planner evaluating {deal.destination}")
estimate = self.estimator.estimate(deal.description)
discount = estimate - deal.price
self.log(f"Travel Planner found discount ${discount:.2f}")
return TravelOpportunity(deal=deal, estimate=estimate, discount=discount)
def plan(self, memory: List[str] = []) -> Optional[List[TravelOpportunity]]:
self.log("Travel Planner starting run")
selection = self.scanner.scan(memory=memory)
if selection and selection.deals:
opportunities = [self.evaluate(deal) for deal in selection.deals[:5]]
if not opportunities:
self.log("Travel Planner found no valid opportunities")
return None
opportunities.sort(key=lambda opp: opp.discount, reverse=True)
good_deals = [opp for opp in opportunities if opp.discount > self.DEAL_THRESHOLD]
if good_deals:
best = good_deals[0]
self.log(f"Travel Planner found {len(good_deals)} deals above threshold, best: ${best.discount:.2f} off")
self.messenger.alert(best)
self.log("Travel Planner completed")
return good_deals
else:
self.log(f"Travel Planner completed - no deals above ${self.DEAL_THRESHOLD} threshold")
return None
self.log("Travel Planner found no deals to evaluate")
return None

View File

@@ -0,0 +1,87 @@
import os
import sys
from typing import Optional, List
from openai import OpenAI
w8d5_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
if w8d5_path not in sys.path:
sys.path.insert(0, w8d5_path)
from agents.agent import Agent
from helpers.travel_deals import ScrapedTravelDeal, TravelDealSelection
class TravelScannerAgent(Agent):
MODEL = "gpt-4o-mini"
SYSTEM_PROMPT = """You identify and summarize the 5 most promising travel deals from a list.
Focus on deals with destinations, deal types (flight/hotel/package), and detailed descriptions.
If price is mentioned, extract it. If no specific price is given but there's a discount mentioned (e.g. "30% off"), estimate a reasonable price.
If absolutely no pricing information exists, use a placeholder price of 500.
Respond strictly in JSON with no explanation.
{"deals": [
{
"destination": "City or Country name",
"deal_type": "Flight, Hotel, or Package",
"description": "4-5 sentences describing the travel deal, dates, what's included, and key highlights",
"price": 499.99,
"url": "the url as provided"
},
...
]}"""
USER_PROMPT_PREFIX = """Respond with the 5 most promising travel deals with destinations, types, and descriptions.
Respond strictly in JSON. Provide detailed descriptions focusing on what travelers get.
Extract the destination and deal type (Flight/Hotel/Package) from the title and description.
For pricing: extract exact prices if available, estimate from percentage discounts, or use 500 as placeholder.
Travel Deals:
"""
USER_PROMPT_SUFFIX = "\n\nStrictly respond in JSON with exactly 5 deals."
name = "Travel Scanner"
color = Agent.CYAN
def __init__(self):
self.log("Travel Scanner is initializing")
self.openai = OpenAI()
self.log("Travel Scanner is ready")
def fetch_deals(self, memory) -> List[ScrapedTravelDeal]:
self.log("Travel Scanner fetching deals from RSS feeds")
urls = [opp.deal.url for opp in memory]
scraped = ScrapedTravelDeal.fetch()
result = [scrape for scrape in scraped if scrape.url not in urls]
self.log(f"Travel Scanner found {len(result)} new deals")
return result
def make_user_prompt(self, scraped) -> str:
user_prompt = self.USER_PROMPT_PREFIX
user_prompt += '\n\n'.join([scrape.describe() for scrape in scraped])
user_prompt += self.USER_PROMPT_SUFFIX
return user_prompt
def scan(self, memory: List[str]=[]) -> Optional[TravelDealSelection]:
scraped = self.fetch_deals(memory)
if scraped:
user_prompt = self.make_user_prompt(scraped)
self.log("Travel Scanner calling OpenAI")
result = self.openai.beta.chat.completions.parse(
model=self.MODEL,
messages=[
{"role": "system", "content": self.SYSTEM_PROMPT},
{"role": "user", "content": user_prompt}
],
response_format=TravelDealSelection
)
result = result.choices[0].message.parsed
valid_deals = [deal for deal in result.deals if deal.price > 0]
result.deals = valid_deals
self.log(f"Travel Scanner received {len(result.deals)} valid deals")
return result if result.deals else None
return None

View File

@@ -0,0 +1,73 @@
import os
import sys
import numpy as np
import joblib
from sentence_transformers import SentenceTransformer
import xgboost as xgb
w8d5_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
if w8d5_path not in sys.path:
sys.path.insert(0, w8d5_path)
from agents.agent import Agent
class TravelXGBoostAgent(Agent):
name = "XGBoost Estimator"
color = Agent.GREEN
def __init__(self, collection):
self.log("XGBoost Estimator initializing")
self.collection = collection
self.model_path = os.path.join(w8d5_path, 'helpers', 'travel_xgboost_model.pkl')
self.embedder = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2')
if os.path.exists(self.model_path):
self.log("Loading existing XGBoost model")
self.model = joblib.load(self.model_path)
else:
self.log("Training new XGBoost model")
self.model = self._train_model()
joblib.dump(self.model, self.model_path)
self.log(f"XGBoost model saved to {self.model_path}")
self.log("XGBoost Estimator ready")
def _train_model(self):
self.log("Fetching training data from ChromaDB")
result = self.collection.get(include=['embeddings', 'metadatas'])
X = np.array(result['embeddings'])
y = np.array([m['price'] for m in result['metadatas']])
self.log(f"Training on {len(X)} samples")
model = xgb.XGBRegressor(
n_estimators=100,
max_depth=6,
learning_rate=0.1,
subsample=0.8,
colsample_bytree=0.8,
random_state=42,
n_jobs=-1
)
model.fit(X, y)
self.log("XGBoost training complete")
return model
def estimate(self, description: str) -> float:
self.log(f"XGBoost estimating price for: {description[:50]}...")
embedding = self.embedder.encode([description])[0]
embedding_2d = embedding.reshape(1, -1)
prediction = self.model.predict(embedding_2d)[0]
prediction = max(0, prediction)
self.log(f"XGBoost estimate: ${prediction:.2f}")
return float(prediction)

View File

@@ -0,0 +1,230 @@
import os
import random
from dotenv import load_dotenv
from huggingface_hub import login
from sentence_transformers import SentenceTransformer
import chromadb
from tqdm import tqdm
load_dotenv(override=True)
os.environ['HF_TOKEN'] = os.getenv('HF_TOKEN', 'your-key-if-not-using-env')
hf_token = os.environ['HF_TOKEN']
login(hf_token, add_to_git_credential=True)
DB = "travel_vectorstore"
CATEGORIES = ['Flights', 'Hotels', 'Car_Rentals', 'Vacation_Packages', 'Cruises', 'Activities']
AIRLINES = ['American Airlines', 'Delta', 'United', 'Southwest', 'JetBlue', 'Spirit', 'Frontier', 'Alaska Airlines', 'Emirates', 'British Airways', 'Air France', 'Lufthansa', 'Qatar Airways']
CITIES = ['New York', 'Los Angeles', 'Chicago', 'Houston', 'Miami', 'San Francisco', 'Boston', 'Seattle', 'Denver', 'Atlanta', 'Las Vegas', 'Orlando', 'Phoenix', 'London', 'Paris', 'Tokyo', 'Dubai', 'Singapore', 'Sydney', 'Rome']
HOTELS = ['Hilton', 'Marriott', 'Hyatt', 'Holiday Inn', 'Best Western', 'Sheraton', 'Ritz-Carlton', 'Four Seasons', 'Westin', 'Radisson']
CLASSES = ['Economy', 'Premium Economy', 'Business', 'First Class']
CAR_COMPANIES = ['Hertz', 'Enterprise', 'Avis', 'Budget', 'National', 'Alamo']
CAR_TYPES = ['Compact', 'Sedan', 'SUV', 'Luxury', 'Van']
def generate_flight_description():
airline = random.choice(AIRLINES)
source = random.choice(CITIES)
dest = random.choice([c for c in CITIES if c != source])
flight_class = random.choice(CLASSES)
stops = random.choice(['non-stop', 'one-stop', 'two-stops'])
duration = f"{random.randint(1, 15)} hours {random.randint(0, 59)} minutes"
description = f"{airline} {flight_class} {stops} flight from {source} to {dest}. "
description += f"Flight duration approximately {duration}. "
if random.random() > 0.5:
description += f"Includes {random.randint(1, 2)} checked bag"
if random.random() > 0.5:
description += "s"
description += ". "
if flight_class in ['Business', 'First Class']:
description += random.choice(['Priority boarding included. ', 'Lounge access available. ', 'Lie-flat seats. '])
price = random.randint(150, 2500) if flight_class == 'Economy' else random.randint(800, 8000)
return description, price
def generate_hotel_description():
hotel = random.choice(HOTELS)
city = random.choice(CITIES)
stars = random.randint(2, 5)
room_type = random.choice(['Standard Room', 'Deluxe Room', 'Suite', 'Executive Suite'])
nights = random.randint(1, 7)
description = f"{hotel} {stars}-star hotel in {city}. {room_type} for {nights} night"
if nights > 1:
description += "s"
description += ". "
amenities = []
if random.random() > 0.3:
amenities.append('Free WiFi')
if random.random() > 0.5:
amenities.append('Breakfast included')
if random.random() > 0.6:
amenities.append('Pool access')
if random.random() > 0.7:
amenities.append('Gym')
if random.random() > 0.8:
amenities.append('Spa services')
if amenities:
description += f"Amenities: {', '.join(amenities)}. "
price_per_night = random.randint(80, 500) if stars <= 3 else random.randint(200, 1200)
total_price = price_per_night * nights
return description, total_price
def generate_car_rental_description():
company = random.choice(CAR_COMPANIES)
car_type = random.choice(CAR_TYPES)
city = random.choice(CITIES)
days = random.randint(1, 14)
description = f"{company} car rental in {city}. {car_type} class vehicle for {days} day"
if days > 1:
description += "s"
description += ". "
if random.random() > 0.6:
description += "Unlimited mileage included. "
if random.random() > 0.5:
description += "Airport pickup available. "
if random.random() > 0.7:
description += "GPS navigation included. "
daily_rate = {'Compact': random.randint(25, 45), 'Sedan': random.randint(35, 65), 'SUV': random.randint(50, 90), 'Luxury': random.randint(80, 200), 'Van': random.randint(60, 100)}
total_price = daily_rate[car_type] * days
return description, total_price
def generate_vacation_package_description():
city = random.choice(CITIES)
nights = random.randint(3, 10)
description = f"All-inclusive vacation package to {city} for {nights} nights. "
description += f"Includes round-trip {random.choice(CLASSES)} flights, {random.choice(HOTELS)} hotel accommodation, "
extras = []
if random.random() > 0.3:
extras.append('daily breakfast')
if random.random() > 0.5:
extras.append('airport transfers')
if random.random() > 0.6:
extras.append('city tour')
if random.random() > 0.7:
extras.append('travel insurance')
if extras:
description += f"and {', '.join(extras)}. "
base_price = random.randint(800, 4000)
return description, base_price
def generate_cruise_description():
destinations = [', '.join(random.sample(['Caribbean', 'Mediterranean', 'Alaska', 'Hawaii', 'Baltic Sea', 'South Pacific'], k=random.randint(2, 4)))]
nights = random.choice([3, 5, 7, 10, 14])
description = f"{nights}-night cruise visiting {destinations[0]}. "
description += f"All meals and entertainment included. "
cabin_type = random.choice(['Interior cabin', 'Ocean view cabin', 'Balcony cabin', 'Suite'])
description += f"{cabin_type}. "
if random.random() > 0.5:
description += "Unlimited beverage package available. "
if random.random() > 0.6:
description += "Shore excursions at each port. "
base_price = random.randint(500, 5000)
return description, base_price
def generate_activity_description():
city = random.choice(CITIES)
activities = ['City sightseeing tour', 'Museum pass', 'Adventure sports package', 'Wine tasting tour', 'Cooking class', 'Hot air balloon ride', 'Snorkeling excursion', 'Helicopter tour', 'Spa day package', 'Theme park tickets']
activity = random.choice(activities)
description = f"{activity} in {city}. "
if 'tour' in activity.lower():
description += f"Duration: {random.randint(2, 8)} hours. "
if random.random() > 0.5:
description += "Hotel pickup included. "
if random.random() > 0.6:
description += "Small group experience. "
price = random.randint(30, 500)
return description, price
GENERATORS = {
'Flights': generate_flight_description,
'Hotels': generate_hotel_description,
'Car_Rentals': generate_car_rental_description,
'Vacation_Packages': generate_vacation_package_description,
'Cruises': generate_cruise_description,
'Activities': generate_activity_description
}
print("Generating synthetic travel dataset...")
travel_data = []
items_per_category = 3334
for category in CATEGORIES:
print(f"Generating {category}...")
generator = GENERATORS[category]
for _ in range(items_per_category):
description, price = generator()
travel_data.append((description, float(price), category))
random.shuffle(travel_data)
print(f"Generated {len(travel_data)} travel deals")
print("\nInitializing SentenceTransformer model...")
model = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2')
print(f"Connecting to ChromaDB at {DB}...")
client = chromadb.PersistentClient(path=DB)
collection_name = "travel_deals"
existing_collections = [col.name for col in client.list_collections()]
if collection_name in existing_collections:
client.delete_collection(collection_name)
print(f"Deleted existing collection: {collection_name}")
collection = client.create_collection(collection_name)
print(f"Created new collection: {collection_name}")
print("\nCreating embeddings and adding to ChromaDB...")
for i in tqdm(range(0, len(travel_data), 1000)):
batch = travel_data[i:i+1000]
documents = [desc for desc, _, _ in batch]
vectors = model.encode(documents).astype(float).tolist()
metadatas = [{"category": cat, "price": price} for _, price, cat in batch]
ids = [f"travel_{j}" for j in range(i, i+len(batch))]
collection.add(
ids=ids,
documents=documents,
embeddings=vectors,
metadatas=metadatas
)
total_items = collection.count()
print(f"\nVectorstore created successfully with {total_items} travel deals")
result = collection.get(include=['metadatas'], limit=total_items)
categories = [m['category'] for m in result['metadatas']]
prices = [m['price'] for m in result['metadatas']]
category_counts = {}
for cat in categories:
category_counts[cat] = category_counts.get(cat, 0) + 1
print("\nCategory distribution:")
for category, count in sorted(category_counts.items()):
print(f" {category}: {count}")
avg_price = sum(prices) / len(prices) if prices else 0
print(f"\nAverage price: ${avg_price:.2f}")
print(f"Price range: ${min(prices):.2f} - ${max(prices):.2f}")

View File

@@ -0,0 +1,99 @@
import os
import sys
import logging
import json
from typing import List, Optional
from dotenv import load_dotenv
import chromadb
import numpy as np
from sklearn.manifold import TSNE
w8d5_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
if w8d5_path not in sys.path:
sys.path.insert(0, w8d5_path)
from agents.travel_planning_agent import TravelPlanningAgent
from helpers.travel_deals import TravelOpportunity
BG_BLUE = '\033[44m'
WHITE = '\033[37m'
RESET = '\033[0m'
CATEGORIES = ['Flights', 'Hotels', 'Car_Rentals', 'Vacation_Packages', 'Cruises', 'Activities']
COLORS = ['red', 'blue', 'green', 'orange', 'purple', 'cyan']
def init_logging():
root = logging.getLogger()
root.setLevel(logging.INFO)
handler = logging.StreamHandler(sys.stdout)
handler.setLevel(logging.INFO)
formatter = logging.Formatter(
"[%(asctime)s] [Travel Agents] [%(levelname)s] %(message)s",
datefmt="%Y-%m-%d %H:%M:%S %z",
)
handler.setFormatter(formatter)
root.addHandler(handler)
class TravelDealFramework:
DB = "travel_vectorstore"
MEMORY_FILENAME = "travel_memory.json"
def __init__(self):
init_logging()
load_dotenv()
client = chromadb.PersistentClient(path=self.DB)
self.memory = self.read_memory()
self.collection = client.get_or_create_collection('travel_deals')
self.planner = None
def init_agents_as_needed(self):
if not self.planner:
self.log("Initializing Travel Agent Framework")
self.planner = TravelPlanningAgent(self.collection)
self.log("Travel Agent Framework ready")
def read_memory(self) -> List[TravelOpportunity]:
if os.path.exists(self.MEMORY_FILENAME):
with open(self.MEMORY_FILENAME, "r") as file:
data = json.load(file)
opportunities = [TravelOpportunity(**item) for item in data]
return opportunities
return []
def write_memory(self) -> None:
data = [opportunity.dict() for opportunity in self.memory]
with open(self.MEMORY_FILENAME, "w") as file:
json.dump(data, file, indent=2)
def log(self, message: str):
text = BG_BLUE + WHITE + "[Travel Framework] " + message + RESET
logging.info(text)
def run(self) -> List[TravelOpportunity]:
self.init_agents_as_needed()
logging.info("Starting Travel Planning Agent")
results = self.planner.plan(memory=self.memory)
logging.info(f"Travel Planning Agent completed with {len(results) if results else 0} results")
if results:
self.memory.extend(results)
self.write_memory()
return self.memory
@classmethod
def get_plot_data(cls, max_datapoints=10000):
client = chromadb.PersistentClient(path=cls.DB)
collection = client.get_or_create_collection('travel_deals')
result = collection.get(include=['embeddings', 'documents', 'metadatas'], limit=max_datapoints)
vectors = np.array(result['embeddings'])
documents = result['documents']
categories = [metadata['category'] for metadata in result['metadatas']]
colors = [COLORS[CATEGORIES.index(c)] for c in categories]
tsne = TSNE(n_components=3, random_state=42, n_jobs=-1)
reduced_vectors = tsne.fit_transform(vectors)
return documents, reduced_vectors, colors
if __name__=="__main__":
TravelDealFramework().run()

View File

@@ -0,0 +1,67 @@
from pydantic import BaseModel
from typing import List, Dict, Self
from bs4 import BeautifulSoup
import re
import feedparser
from tqdm import tqdm
import requests
import time
feeds = [
"https://thepointsguy.com/feed/",
]
def extract(html_snippet: str) -> str:
soup = BeautifulSoup(html_snippet, 'html.parser')
text = soup.get_text(strip=True)
text = re.sub('<[^<]+?>', '', text)
return text.replace('\n', ' ').strip()
class ScrapedTravelDeal:
title: str
summary: str
url: str
details: str
def __init__(self, entry: Dict[str, str]):
self.title = entry.get('title', '')
summary_text = entry.get('summary', entry.get('description', ''))
self.summary = extract(summary_text)
self.url = entry.get('link', '')
self.details = self.summary
def __repr__(self):
return f"<{self.title}>"
def describe(self):
return f"Title: {self.title}\nDetails: {self.details.strip()}\nURL: {self.url}"
@classmethod
def fetch(cls, show_progress: bool = False) -> List[Self]:
deals = []
feed_iter = tqdm(feeds) if show_progress else feeds
for feed_url in feed_iter:
try:
feed = feedparser.parse(feed_url)
for entry in feed.entries[:10]:
deals.append(cls(entry))
time.sleep(0.3)
except Exception as e:
print(f"Error fetching {feed_url}: {e}")
return deals
class TravelDeal(BaseModel):
destination: str
deal_type: str
description: str
price: float
url: str
class TravelDealSelection(BaseModel):
deals: List[TravelDeal]
class TravelOpportunity(BaseModel):
deal: TravelDeal
estimate: float
discount: float

View File

@@ -0,0 +1,161 @@
import os
import sys
import logging
import json
from typing import List, Tuple
from dotenv import load_dotenv
import chromadb
import numpy as np
from sklearn.manifold import TSNE
w8d5_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
if w8d5_path not in sys.path:
sys.path.insert(0, w8d5_path)
from agents.travel_scanner_agent import TravelScannerAgent
from agents.travel_estimator_agent import TravelEstimatorAgent
from agents.travel_xgboost_agent import TravelXGBoostAgent
from agents.travel_messaging_agent import TravelMessagingAgent
from helpers.travel_deals import TravelOpportunity, TravelDeal
BG_BLUE = '\033[44m'
WHITE = '\033[37m'
RESET = '\033[0m'
CATEGORIES = ['Flights', 'Hotels', 'Car_Rentals', 'Vacation_Packages', 'Cruises', 'Activities']
COLORS = ['red', 'blue', 'green', 'orange', 'purple', 'cyan']
def init_logging():
root = logging.getLogger()
root.setLevel(logging.INFO)
handler = logging.StreamHandler(sys.stdout)
handler.setLevel(logging.INFO)
formatter = logging.Formatter(
"[%(asctime)s] [Travel Agents] [%(levelname)s] %(message)s",
datefmt="%Y-%m-%d %H:%M:%S %z",
)
handler.setFormatter(formatter)
root.addHandler(handler)
class TravelDualFramework:
DB = "travel_vectorstore"
LLM_MEMORY_FILE = "travel_memory_llm.json"
XGB_MEMORY_FILE = "travel_memory_xgb.json"
DEAL_THRESHOLD = 200.0
def __init__(self):
init_logging()
load_dotenv()
client = chromadb.PersistentClient(path=self.DB)
self.collection = client.get_or_create_collection('travel_deals')
self.llm_memory = self.read_memory(self.LLM_MEMORY_FILE)
self.xgb_memory = self.read_memory(self.XGB_MEMORY_FILE)
self.scanner = None
self.llm_estimator = None
self.xgb_estimator = None
self.messenger = None
def init_agents_as_needed(self):
if not self.scanner:
self.log("Initializing Travel Dual Estimation Framework")
self.scanner = TravelScannerAgent()
self.llm_estimator = TravelEstimatorAgent(self.collection)
self.xgb_estimator = TravelXGBoostAgent(self.collection)
self.messenger = TravelMessagingAgent()
self.log("Travel Dual Framework ready")
def read_memory(self, filename: str) -> List[TravelOpportunity]:
if os.path.exists(filename):
with open(filename, "r") as file:
data = json.load(file)
opportunities = [TravelOpportunity(**item) for item in data]
return opportunities
return []
def write_memory(self, opportunities: List[TravelOpportunity], filename: str) -> None:
data = [opportunity.dict() for opportunity in opportunities]
with open(filename, "w") as file:
json.dump(data, file, indent=2)
def log(self, message: str):
text = BG_BLUE + WHITE + "[Dual Framework] " + message + RESET
logging.info(text)
def run(self) -> Tuple[List[TravelOpportunity], List[TravelOpportunity]]:
self.init_agents_as_needed()
self.log("Starting dual estimation scan")
deal_selection = self.scanner.scan()
if not deal_selection or not deal_selection.deals:
self.log("No deals found")
return self.llm_memory, self.xgb_memory
deals = deal_selection.deals
self.log(f"Processing {len(deals)} deals with both estimators")
llm_opportunities = []
xgb_opportunities = []
for deal in deals:
llm_estimate = self.llm_estimator.estimate(deal.description)
llm_discount = llm_estimate - deal.price
if llm_discount >= self.DEAL_THRESHOLD:
llm_opp = TravelOpportunity(
deal=deal,
estimate=llm_estimate,
discount=llm_discount
)
llm_opportunities.append(llm_opp)
self.log(f"LLM found opportunity: {deal.destination} - ${llm_discount:.0f} savings")
self.messenger.alert(llm_opp)
xgb_estimate = self.xgb_estimator.estimate(deal.description)
xgb_discount = xgb_estimate - deal.price
if xgb_discount >= self.DEAL_THRESHOLD:
xgb_opp = TravelOpportunity(
deal=deal,
estimate=xgb_estimate,
discount=xgb_discount
)
xgb_opportunities.append(xgb_opp)
self.log(f"XGBoost found opportunity: {deal.destination} - ${xgb_discount:.0f} savings")
self.messenger.alert(xgb_opp)
if llm_opportunities:
self.llm_memory.extend(llm_opportunities)
self.write_memory(self.llm_memory, self.LLM_MEMORY_FILE)
if xgb_opportunities:
self.xgb_memory.extend(xgb_opportunities)
self.write_memory(self.xgb_memory, self.XGB_MEMORY_FILE)
self.log(f"Scan complete: {len(llm_opportunities)} LLM, {len(xgb_opportunities)} XGBoost opportunities")
return self.llm_memory, self.xgb_memory
@classmethod
def get_plot_data(cls, max_datapoints=10000):
client = chromadb.PersistentClient(path=cls.DB)
collection = client.get_or_create_collection('travel_deals')
result = collection.get(include=['embeddings', 'documents', 'metadatas'], limit=max_datapoints)
vectors = np.array(result['embeddings'])
documents = result['documents']
categories = [metadata['category'] for metadata in result['metadatas']]
colors = [COLORS[CATEGORIES.index(c)] for c in categories]
tsne = TSNE(n_components=3, random_state=42, n_jobs=-1)
reduced_vectors = tsne.fit_transform(vectors)
return documents, reduced_vectors, colors, categories
if __name__=="__main__":
framework = TravelDualFramework()
framework.run()

View File

@@ -0,0 +1,66 @@
import os
import sys
from dotenv import load_dotenv
project_root = os.path.join(os.path.dirname(__file__), '..')
sys.path.insert(0, project_root)
sys.path.insert(0, os.path.join(project_root, '..', '..'))
from helpers.travel_deals import ScrapedTravelDeal
from agents.travel_scanner_agent import TravelScannerAgent
from agents.travel_estimator_agent import TravelEstimatorAgent
load_dotenv()
print("\nTesting Travel Deal Hunter Components\n")
print("1. RSS Feed Scraping")
deals = ScrapedTravelDeal.fetch(show_progress=False)
print(f"Fetched {len(deals)} deals from RSS feeds")
if deals:
print(f"Sample: {deals[0].title[:60]}...")
print("\n2. OpenAI Connection")
if os.getenv("OPENAI_API_KEY"):
print("OPENAI_API_KEY found")
else:
print("OPENAI_API_KEY not found - set in .env file")
print("\n3. Scanner Agent")
scanner = TravelScannerAgent()
print("Scanner agent initialized")
print("\n4. Deal Scanning")
try:
selection = scanner.scan(memory=[])
if selection and selection.deals:
print(f"Scanner found {len(selection.deals)} processed deals")
print(f"Sample: {selection.deals[0].destination} - ${selection.deals[0].price}")
else:
print("No deals returned")
except Exception as e:
print(f"Error: {e}")
print("\n5. ChromaDB Access")
import chromadb
try:
db_path = "travel_vectorstore"
client = chromadb.PersistentClient(path=db_path)
collection = client.get_or_create_collection('travel_deals')
count = collection.count()
print(f"ChromaDB connected - {count} travel items in collection")
except Exception as e:
print(f"Error: {e}")
print("\n6. Estimator Check using travel vectorstore")
try:
estimator = TravelEstimatorAgent(collection)
sample = "Non-stop economy flight from New York to London, duration 7 hours"
estimate = estimator.estimate(sample)
print(f"Estimate: ${estimate:.2f}")
except Exception as e:
print(f"Error: {e}")
print("\nComponent tests complete")

View File

@@ -0,0 +1,49 @@
import os
import sys
from dotenv import load_dotenv
project_root = os.path.join(os.path.dirname(__file__), '..')
sys.path.insert(0, project_root)
sys.path.insert(0, os.path.join(project_root, '..', '..'))
from agents.travel_estimator_agent import TravelEstimatorAgent
from agents.travel_xgboost_agent import TravelXGBoostAgent
import chromadb
load_dotenv()
print("\nTesting Dual Estimation (LLM vs XGBoost)\n")
client = chromadb.PersistentClient(path='travel_vectorstore')
collection = client.get_collection('travel_deals')
print("Initializing agents...")
llm_agent = TravelEstimatorAgent(collection)
xgb_agent = TravelXGBoostAgent(collection)
test_cases = [
"Round trip flight from New York to London, Economy class, non-stop",
"5-star Marriott hotel in Paris, 3 nights, Suite with breakfast included",
"7-night Caribbean cruise, Balcony cabin, all meals included",
"Hertz SUV rental in Los Angeles for 5 days with unlimited mileage",
"All-inclusive vacation package to Dubai for 7 nights with Business class flights"
]
print("\n" + "="*80)
print(f"{'Travel Deal Description':<60} {'LLM Est.':<12} {'XGB Est.':<12}")
print("="*80)
for desc in test_cases:
llm_est = llm_agent.estimate(desc)
xgb_est = xgb_agent.estimate(desc)
short_desc = desc[:57] + "..." if len(desc) > 60 else desc
print(f"{short_desc:<60} ${llm_est:>9.2f} ${xgb_est:>9.2f}")
print("="*80)
print("\nDual estimation test complete!")
print("\nKey Observations:")
print("- LLM: Uses semantic understanding + RAG context")
print("- XGBoost: Uses pattern recognition from embeddings")
print("- Both trained on same 20K travel deals dataset")

View File

@@ -0,0 +1,38 @@
import os
import sys
from dotenv import load_dotenv
project_root = os.path.join(os.path.dirname(__file__), '..')
sys.path.insert(0, project_root)
sys.path.insert(0, os.path.join(project_root, '..', '..'))
from helpers.travel_deal_framework import TravelDealFramework
load_dotenv()
print("\nTesting Full Travel Deal Pipeline\n")
print("Initializing framework...")
framework = TravelDealFramework()
framework.init_agents_as_needed()
print("\nRunning one iteration...")
try:
result = framework.run()
print(f"\nPipeline completed")
print(f"Memory now has {len(result)} opportunities")
if result:
latest = result[-1]
print(f"\nLatest opportunity:")
print(f" Destination: {latest.deal.destination}")
print(f" Type: {latest.deal.deal_type}")
print(f" Price: ${latest.deal.price:.2f}")
print(f" Estimate: ${latest.estimate:.2f}")
print(f" Discount: ${latest.discount:.2f}")
except Exception as e:
print(f"\nError during pipeline: {e}")
import traceback
traceback.print_exc()
print("\n")

View File

@@ -0,0 +1,57 @@
[
{
"deal": {
"destination": "Southwest Airlines",
"deal_type": "Credit Card Offer",
"description": "Earn 85,000 bonus points with the current welcome bonus on any of the personal Southwest Airlines credit cards. This deal allows travelers to maximize their rewards for future flights and services. Perfect for frequent travelers looking to enhance their earning potential.",
"price": 500.0,
"url": "https://thepointsguy.com/credit-cards/southwest-cards-current-offers/"
},
"estimate": 800.0,
"discount": 300.0
},
{
"deal": {
"destination": "Riyadh, Saudi Arabia",
"deal_type": "Flight",
"description": "Delta Air Lines is launching non-stop flights from Atlanta to Riyadh in October. This move makes Delta the only U.S. airline with direct access to Saudi Arabia, offering travelers an excellent opportunity to explore this culturally rich and historically significant region.",
"price": 500.0,
"url": "https://thepointsguy.com/news/delta-air-lines-saudi-arabia-riyadh-nonstop-flights/"
},
"estimate": 1200.0,
"discount": 700.0
},
{
"deal": {
"destination": "Alaska",
"deal_type": "Cruise",
"description": "Discover the breathtaking beauty of Alaska through seasonal cruises that offer unique experiences month by month. Travelers can enjoy a range of activities from discounted pricing to wildlife sightings, depending on the timing of their trip. This deal provides valuable insights to help guests decide the best time to embark on their Alaskan adventure. Ideal for nature lovers and adventure seekers!",
"price": 500.0,
"url": "https://thepointsguy.com/cruise/best-time-to-cruise-alaska/"
},
"estimate": 1200.0,
"discount": 700.0
},
{
"deal": {
"destination": "Paris",
"deal_type": "Flight",
"description": "Book a flight to Paris this December for as low as 7,100 credit card points plus just $5.60. This deal offers fantastic award availability from select U.S. cities, making it an excellent opportunity for travelers looking to explore the City of Lights. Don't miss out on this limited-time offer to experience iconic attractions such as the Eiffel Tower and Louvre Museum.",
"price": 7.6,
"url": "https://thepointsguy.com/deals/deal-of-the-day/"
},
"estimate": 1200.0,
"discount": 1192.4
},
{
"deal": {
"destination": "Various Destinations with American Airlines",
"deal_type": "Flight",
"description": "American Airlines is enhancing its service by adding four new routes, including a resumption of a previously suspended transatlantic route. This expansion aims to provide travelers with more options and flexibility in their travel plans, catering especially to those looking for international travel. Book a flight on one of these new routes to explore exciting new destinations.",
"price": 500.0,
"url": "https://thepointsguy.com/airline/american-adds-new-routes-delta-turf-war/"
},
"estimate": 1200.0,
"discount": 700.0
}
]

View File

@@ -0,0 +1,244 @@
[
{
"deal": {
"destination": "Saudi Arabia",
"deal_type": "Flight",
"description": "Delta Air Lines is launching new nonstop flights from Atlanta to Riyadh, Saudi Arabia, starting next October. This makes Delta the only U.S. airline to offer this route, providing unique travel opportunities for those looking to explore the Middle East. Experience rich culture and history in the Kingdom of Saudi Arabia with convenient flight options.",
"price": 500.0,
"url": "https://thepointsguy.com/news/delta-air-lines-saudi-arabia-riyadh-nonstop-flights/"
},
"estimate": 1200.0,
"discount": 700.0
},
{
"deal": {
"destination": "Paris",
"deal_type": "Flight",
"description": "Travelers have a fantastic opportunity to fly to Paris for just 7,100 credit card points plus a minimal fee of $5.60 this December. This deal features excellent award availability from select U.S. cities, making it an exceptional choice for those looking to explore the City of Light. It's a great time to enjoy Parisian culture, cuisine, and landmarks while redeeming your points efficiently. Don't miss out on this limited-time offer to experience Europe's romantic capital without breaking the bank.",
"price": 500.0,
"url": "https://thepointsguy.com/deals/deal-of-the-day/"
},
"estimate": 7100.0,
"discount": 6600.0
},
{
"deal": {
"destination": "Alaska",
"deal_type": "Cruise",
"description": "Alaska is a breathtaking cruise destination with a limited season that offers various advantages depending on the month. This detailed guide helps travelers choose the best time to cruise, whether it's for discounted pricing or to witness abundant wildlife. Each month brings unique characteristics, ensuring every traveler can find the perfect time for their voyage. Embark on an unforgettable journey through stunning landscapes and vibrant marine life in Alaska.",
"price": 500.0,
"url": "https://thepointsguy.com/cruise/best-time-to-cruise-alaska/"
},
"estimate": 1200.0,
"discount": 700.0
},
{
"deal": {
"destination": "Saudi Arabia",
"deal_type": "Flight",
"description": "Delta Air Lines is set to become the only U.S. airline providing nonstop flights to Riyadh, Saudi Arabia, from Atlanta starting next October. This new route opens exciting travel opportunities for those interested in exploring the rich culture and history of Saudi Arabia's capital. Ideal for both business and leisure travelers, this service enhances connectivity to an emerging destination with much to offer. Book your ticket to be among the first to experience this new travel path.",
"price": 500.0,
"url": "https://thepointsguy.com/news/delta-air-lines-saudi-arabia-riyadh-nonstop-flights/"
},
"estimate": 1200.0,
"discount": 700.0
},
{
"deal": {
"destination": "Saudi Arabia",
"deal_type": "Flight",
"description": "Starting next October, Delta Air Lines will introduce nonstop flights from Atlanta to Riyadh, marking itself as the only U.S. airline offering this route. This is a significant opportunity for travelers interested in exploring the Kingdom with access to its rich culture and history. Plan your travels to take advantage of this new connection to Saudi Arabia.",
"price": 500.0,
"url": "https://thepointsguy.com/news/delta-air-lines-saudi-arabia-riyadh-nonstop-flights/"
},
"estimate": 900.0,
"discount": 400.0
},
{
"deal": {
"destination": "Saudi Arabia",
"deal_type": "Flight",
"description": "Delta Air Lines is set to introduce nonstop flights from Atlanta to Riyadh, Saudi Arabia, next October, making it the only U.S. airline offering this route. This exciting development opens up new travel opportunities for American travelers to explore the Kingdom's rich history and culture. Be among the first to book these flights and experience a new adventure!",
"price": 500.0,
"url": "https://thepointsguy.com/news/delta-air-lines-saudi-arabia-riyadh-nonstop-flights/"
},
"estimate": 900.0,
"discount": 400.0
},
{
"deal": {
"destination": "Alaska",
"deal_type": "Cruise",
"description": "Alaska is known for its breathtaking views and wildlife, and the best time to cruise there can vary. This guide helps travelers understand the advantages of cruising in Alaska based on the month they choose to embark. Travelers can benefit from discounted pricing during specific seasons, ensuring a unique and memorable experience out at sea. Enjoy the natural beauty and adventures that Alaska has to offer!",
"price": 500.0,
"url": "https://thepointsguy.com/cruise/best-time-to-cruise-alaska/"
},
"estimate": 1500.0,
"discount": 1000.0
},
{
"deal": {
"destination": "Paris",
"deal_type": "Flight",
"description": "This incredible deal allows you to fly to Paris for just 7,100 credit card points plus a mere $5.60. You can book this award flight departing from select U.S. cities this December, making it an affordable dream destination during the holiday season. Enjoy the beauty of Paris and explore its iconic landmarks without breaking the bank. Don't miss this opportunity to visit the City of Lights on a budget!",
"price": 500.0,
"url": "https://thepointsguy.com/deals/deal-of-the-day/"
},
"estimate": 2500.0,
"discount": 2000.0
},
{
"deal": {
"destination": "Alaska",
"deal_type": "Cruise",
"description": "Alaska offers a unique cruising experience with a limited season where travelers can see wildlife and stunning landscapes. This guide helps you choose the best time to cruise Alaska, discussing each month\u2019s pros and cons, including potential discounts and wildlife viewing opportunities. Planning your cruise around peak seasons can enhance your experience and save you money on your adventure.",
"price": 500.0,
"url": "https://thepointsguy.com/cruise/best-time-to-cruise-alaska/"
},
"estimate": 1500.0,
"discount": 1000.0
},
{
"deal": {
"destination": "Saudi Arabia",
"deal_type": "Flight",
"description": "Delta Air Lines is launching a new route from Atlanta to Riyadh in October, making it the only U.S. airline to offer direct flights to Saudi Arabia. This is a great opportunity for travelers interested in experiencing Middle Eastern culture and hospitality. Don\u2019t miss your chance to be among the first to explore this exciting new destination from the U.S.",
"price": 500.0,
"url": "https://thepointsguy.com/news/delta-air-lines-saudi-arabia-riyadh-nonstop-flights/"
},
"estimate": 6200.0,
"discount": 5700.0
},
{
"deal": {
"destination": "Multiple locations in Alaska",
"deal_type": "Cruise",
"description": "Discover the stunning beauty of Alaska on a cruise, best enjoyed during its limited season. Each month offers unique advantages, ranging from discounted pricing to the chance of seeing abundant wildlife like whales and bears. This guide helps travelers decide the optimal time to embark on their Alaskan adventure, ensuring they experience all the natural wonders this amazing destination has to offer.",
"price": 500.0,
"url": "https://thepointsguy.com/cruise/best-time-to-cruise-alaska/"
},
"estimate": 4333.0,
"discount": 3833.0
},
{
"deal": {
"destination": "Saudi Arabia",
"deal_type": "Flight",
"description": "Delta Air Lines will soon be the only U.S. airline offering nonstop flights to Saudi Arabia, specifically connecting Atlanta to Riyadh starting next October. This unique route presents a valuable travel opportunity for those looking to explore the rich culture and history of Saudi Arabia. Be among the first to experience this new connection and discover the fantastic landscapes and heritage of the Kingdom.",
"price": 500.0,
"url": "https://thepointsguy.com/news/delta-air-lines-saudi-arabia-riyadh-nonstop-flights/"
},
"estimate": 3600.0,
"discount": 3100.0
},
{
"deal": {
"destination": "Alaska",
"deal_type": "Cruise",
"description": "Alaska is known as a premier cruise destination with a limited season, each month providing unique advantages such as discounted pricing or exceptional wildlife viewing. This guide helps travelers determine the best time to experience the breathtaking landscapes and diverse wildlife of Alaska on a cruise. Whether looking for adventure or relaxation, this guide highlights the optimal months for your trip.",
"price": 500.0,
"url": "https://thepointsguy.com/cruise/best-time-to-cruise-alaska/"
},
"estimate": 2500.0,
"discount": 2000.0
},
{
"deal": {
"destination": "Saudi Arabia",
"deal_type": "Flight",
"description": "Starting in October, Delta Air Lines will be launching a new direct flight route from Atlanta to Riyadh, making it the only U.S. airline serving this destination. This offer provides an excellent opportunity for travelers interested in exploring the rich culture and history of Saudi Arabia. Book your flights in advance to secure your spot on this new route, which promises a convenient travel option to a growing destination.",
"price": 500.0,
"url": "https://thepointsguy.com/news/delta-air-lines-saudi-arabia-riyadh-nonstop-flights/"
},
"estimate": 3500.0,
"discount": 3000.0
},
{
"deal": {
"destination": "Hyatt Vacation Club properties",
"deal_type": "Hotel",
"description": "Earn 3,000 Hyatt points per night this winter when you stay at Hyatt Vacation Club properties, allowing you to enjoy luxurious accommodations and various amenities. This is a great way to enhance your travel experience while gaining significant rewards for future stays. The offer is available exclusively this winter, making it a perfect opportunity to plan a getaway.",
"price": 500.0,
"url": "https://thepointsguy.com/news/hyatt-vacation-club-bonus-points-offer/"
},
"estimate": 800.0,
"discount": 300.0
},
{
"deal": {
"destination": "Paris",
"deal_type": "Flight",
"description": "This deal allows travelers to fly to Paris for only 7,100 credit card points plus a minimal fee of $5.60. Award availability is particularly favorable from select U.S. cities, making this an incredible opportunity for those looking to explore the City of Light this December. With just a small cash outlay, travelers can experience all that Paris has to offer, from its iconic landmarks to its renowned cuisine.",
"price": 500.0,
"url": "https://thepointsguy.com/deals/deal-of-the-day/"
},
"estimate": 2500.0,
"discount": 2000.0
},
{
"deal": {
"destination": "Saudi Arabia",
"deal_type": "Flight",
"description": "Delta Air Lines is set to launch a new route connecting Atlanta to Riyadh, Saudi Arabia, starting next October. This will make Delta the only U.S. airline offering nonstop service to this growing destination. This route presents a unique opportunity for travelers looking to explore Saudi Arabia's rich culture and history, with convenient travel options from one of the largest U.S. cities.",
"price": 500.0,
"url": "https://thepointsguy.com/news/delta-air-lines-saudi-arabia-riyadh-nonstop-flights/"
},
"estimate": 6800.0,
"discount": 6300.0
},
{
"deal": {
"destination": "Alaska",
"deal_type": "Cruise",
"description": "Alaska's cruise season has specific months with unique advantages, including discounted pricing and abundant wildlife viewings. This guide helps travelers decide the best time for their Alaskan cruise adventure, whether they\u2019re looking for the best deals or the most scenic wildlife experiences. Ideal for nature lovers and adventure seekers alike, this destination promises thrilling experiences throughout the season.",
"price": 500.0,
"url": "https://thepointsguy.com/cruise/best-time-to-cruise-alaska/"
},
"estimate": 3500.0,
"discount": 3000.0
},
{
"deal": {
"destination": "Various Hyatt Vacation Club properties",
"deal_type": "Package",
"description": "Hyatt Vacation Club properties are offering an enticing promotion this winter where travelers can earn 3,000 points per night. This promotion is perfect for those looking to experience the luxury and comfort of Hyatt properties while accumulating points for future stays. Ideal for families or couples, it combines relaxation with the potential for rewards during the winter season.",
"price": 500.0,
"url": "https://thepointsguy.com/news/hyatt-vacation-club-bonus-points-offer/"
},
"estimate": 1200.0,
"discount": 700.0
},
{
"deal": {
"destination": "Saudi Arabia",
"deal_type": "Flight",
"description": "Delta Air Lines is launching a new nonstop route from Atlanta to Riyadh starting next October, making it the only US airline to connect directly to Saudi Arabia. This new service opens up opportunities for business and leisure travel to a historically rich destination. Travelers can expect a blend of modernity and tradition in Riyadh's stunning architecture and culture.",
"price": 500.0,
"url": "https://thepointsguy.com/news/delta-air-lines-saudi-arabia-riyadh-nonstop-flights/"
},
"estimate": 3500.0,
"discount": 3000.0
},
{
"deal": {
"destination": "Alaska",
"deal_type": "Cruise",
"description": "Experience the breathtaking beauty of Alaska with its limited cruise season. Each month offers unique perks, from discounted pricing to abundant wildlife sightings. This guide will help you determine the best timing for your Alaskan adventure, ensuring an unforgettable trip filled with natural wonders and exploration of majestic landscapes.",
"price": 500.0,
"url": "https://thepointsguy.com/cruise/best-time-to-cruise-alaska/"
},
"estimate": 2000.0,
"discount": 1500.0
},
{
"deal": {
"destination": "Multiple Hyatt locations",
"deal_type": "Hotel",
"description": "This winter, earn 3,000 Hyatt points per night at Hyatt Vacation Club properties. Enjoy spacious accommodations and upscale amenities across beautiful locations, ideal for family getaways or longer stays. Don't miss this chance to maximize your rewards while relaxing in comfort at a Hyatt destination of your choice.",
"price": 500.0,
"url": "https://thepointsguy.com/news/hyatt-vacation-club-bonus-points-offer/"
},
"estimate": 1500.0,
"discount": 1000.0
}
]

View File

@@ -0,0 +1,497 @@
[
{
"deal": {
"destination": "Paris",
"deal_type": "Flight",
"description": "This deal allows travelers to fly to Paris for just 7,100 credit card points and a minimal fee of $5.60. Award availability is great, particularly this December, making it an ideal time to explore the City of Light. Enjoy iconic attractions, delightful cuisine, and the beautiful winter ambiance of Paris without breaking the bank.",
"price": 500.0,
"url": "https://thepointsguy.com/deals/deal-of-the-day/"
},
"estimate": 2466.2734375,
"discount": 1966.2734375
},
{
"deal": {
"destination": "Alaska",
"deal_type": "Cruise",
"description": "Learn about the optimal times to cruise in Alaska with considerations for wildlife, discounted pricing, and unique experiences available throughout the different months. This destination offers breathtaking scenery and adventure opportunities that are perfect for nature lovers and cruisers alike. Make informed decisions on when to book your unforgettable Alaskan adventure.",
"price": 500.0,
"url": "https://thepointsguy.com/cruise/best-time-to-cruise-alaska/"
},
"estimate": 2976.80078125,
"discount": 2476.80078125
},
{
"deal": {
"destination": "Saudi Arabia",
"deal_type": "Flight",
"description": "Delta Air Lines is launching new nonstop flights from Atlanta to Riyadh, Saudi Arabia, starting next October. This makes Delta the only U.S. airline to offer this route, providing unique travel opportunities for those looking to explore the Middle East. Experience rich culture and history in the Kingdom of Saudi Arabia with convenient flight options.",
"price": 500.0,
"url": "https://thepointsguy.com/news/delta-air-lines-saudi-arabia-riyadh-nonstop-flights/"
},
"estimate": 2248.259521484375,
"discount": 1748.259521484375
},
{
"deal": {
"destination": "Hyatt Vacation Club",
"deal_type": "Hotel",
"description": "Earn 3,000 Hyatt points per night this winter when staying at Hyatt Vacation Club properties. This offer provides guests with rewards for their stays, adding significant value as those points can be redeemed for future accommodations and experiences. Travelers can enjoy high-quality accommodations in beautiful settings while accumulating points for future trips.",
"price": 500.0,
"url": "https://thepointsguy.com/news/hyatt-vacation-club-bonus-points-offer/"
},
"estimate": 2887.52685546875,
"discount": 2387.52685546875
},
{
"deal": {
"destination": "Various IHG properties",
"deal_type": "Hotel",
"description": "IHG One Rewards members can save up to 30% on stays at participating properties during this flash sale. Membership is free, allowing travelers to take advantage of significant savings on hotel bookings around the world. It's a perfect chance to enjoy luxurious stays while maximizing your budget during travel.",
"price": 500.0,
"url": "https://thepointsguy.com/deals/ihg-flash-sale/"
},
"estimate": 2464.5458984375,
"discount": 1964.5458984375
},
{
"deal": {
"destination": "Paris",
"deal_type": "Flight",
"description": "Travelers have a fantastic opportunity to fly to Paris for just 7,100 credit card points plus a minimal fee of $5.60 this December. This deal features excellent award availability from select U.S. cities, making it an exceptional choice for those looking to explore the City of Light. It's a great time to enjoy Parisian culture, cuisine, and landmarks while redeeming your points efficiently. Don't miss out on this limited-time offer to experience Europe's romantic capital without breaking the bank.",
"price": 500.0,
"url": "https://thepointsguy.com/deals/deal-of-the-day/"
},
"estimate": 2827.6220703125,
"discount": 2327.6220703125
},
{
"deal": {
"destination": "Alaska",
"deal_type": "Cruise",
"description": "Alaska is a breathtaking cruise destination with a limited season that offers various advantages depending on the month. This detailed guide helps travelers choose the best time to cruise, whether it's for discounted pricing or to witness abundant wildlife. Each month brings unique characteristics, ensuring every traveler can find the perfect time for their voyage. Embark on an unforgettable journey through stunning landscapes and vibrant marine life in Alaska.",
"price": 500.0,
"url": "https://thepointsguy.com/cruise/best-time-to-cruise-alaska/"
},
"estimate": 3351.845458984375,
"discount": 2851.845458984375
},
{
"deal": {
"destination": "Saudi Arabia",
"deal_type": "Flight",
"description": "Delta Air Lines is set to become the only U.S. airline providing nonstop flights to Riyadh, Saudi Arabia, from Atlanta starting next October. This new route opens exciting travel opportunities for those interested in exploring the rich culture and history of Saudi Arabia's capital. Ideal for both business and leisure travelers, this service enhances connectivity to an emerging destination with much to offer. Book your ticket to be among the first to experience this new travel path.",
"price": 500.0,
"url": "https://thepointsguy.com/news/delta-air-lines-saudi-arabia-riyadh-nonstop-flights/"
},
"estimate": 3028.00341796875,
"discount": 2528.00341796875
},
{
"deal": {
"destination": "IHG Hotels",
"deal_type": "Hotel",
"description": "IHG is currently running a flash sale that allows members to save up to 30% on stays at participating properties. This deal is perfect for IHG One Rewards members, and signing up is free, making the offer accessible to a broader audience. With a variety of locations and accommodations, guests can enjoy significant discounts, enhancing their travel experience without a hefty price tag. Take advantage of this limited-time offer to enjoy luxury stays at a fraction of the cost!",
"price": 500.0,
"url": "https://thepointsguy.com/deals/ihg-flash-sale/"
},
"estimate": 2123.265380859375,
"discount": 1623.265380859375
},
{
"deal": {
"destination": "Hyatt Vacation Club",
"deal_type": "Hotel",
"description": "This winter, guests can earn 3,000 Hyatt points per night at Hyatt Vacation Club properties, providing a great way to collect rewards while enjoying a winter getaway. Travelers can expect relaxing accommodations in scenic locations with premium amenities. This offer is designed to enhance the vacation experience, ensuring points earners can redeem for future travels. It's a perfect opportunity to enjoy luxury stays while also boosting your reward balance for even more adventures ahead.",
"price": 500.0,
"url": "https://thepointsguy.com/news/hyatt-vacation-club-bonus-points-offer/"
},
"estimate": 2416.3115234375,
"discount": 1916.3115234375
},
{
"deal": {
"destination": "Paris",
"deal_type": "Flight",
"description": "Book a flight to Paris this December for as low as 7,100 credit card points plus only $5.60. This fantastic deal comes with great award availability departing from select U.S. cities, making it an excellent opportunity for travelers looking to visit the City of Light. Don't miss out on experiencing Paris, with its iconic attractions like the Eiffel Tower and Louvre Museum, at such a minimal cost.",
"price": 500.0,
"url": "https://thepointsguy.com/deals/deal-of-the-day/"
},
"estimate": 2097.250732421875,
"discount": 1597.250732421875
},
{
"deal": {
"destination": "Alaska",
"deal_type": "Cruise",
"description": "Discover the best time to cruise Alaska with our detailed guide that highlights the limited cruise season from May to September. Each month offers unique advantages such as discounted pricing and opportunities to see incredible wildlife. Whether you prefer the bustling summer or the quieter late season, learn when to book your Alaskan adventure for the best experience.",
"price": 500.0,
"url": "https://thepointsguy.com/cruise/best-time-to-cruise-alaska/"
},
"estimate": 3514.16943359375,
"discount": 3014.16943359375
},
{
"deal": {
"destination": "Saudi Arabia",
"deal_type": "Flight",
"description": "Starting next October, Delta Air Lines will introduce nonstop flights from Atlanta to Riyadh, marking itself as the only U.S. airline offering this route. This is a significant opportunity for travelers interested in exploring the Kingdom with access to its rich culture and history. Plan your travels to take advantage of this new connection to Saudi Arabia.",
"price": 500.0,
"url": "https://thepointsguy.com/news/delta-air-lines-saudi-arabia-riyadh-nonstop-flights/"
},
"estimate": 3667.870361328125,
"discount": 3167.870361328125
},
{
"deal": {
"destination": "Various Locations (IHG Hotels)",
"deal_type": "Hotel",
"description": "IHG One Rewards members can enjoy a limited-time flash sale offering up to 30% off on stays at participating IHG properties. Membership is free, which provides additional travel perks. This offer is perfect for hotel stays across various destinations, making it an ideal opportunity for budget-conscious travelers.",
"price": 350.0,
"url": "https://thepointsguy.com/deals/ihg-flash-sale/"
},
"estimate": 2205.177978515625,
"discount": 1855.177978515625
},
{
"deal": {
"destination": "Hyatt Vacation Club",
"deal_type": "Hotel",
"description": "Earn 3,000 Hyatt points per night when you stay at Hyatt Vacation Club properties this winter. It's a great way to enhance your stay at beautiful locations while racking up points that can be redeemed for future travel. This offer is perfect for winter getaway seekers looking to enjoy a relaxing vacation while earning rewards.",
"price": 500.0,
"url": "https://thepointsguy.com/news/hyatt-vacation-club-bonus-points-offer/"
},
"estimate": 3293.184814453125,
"discount": 2793.184814453125
},
{
"deal": {
"destination": "Paris",
"deal_type": "Package",
"description": "Travelers can fly to Paris for an incredible deal of only 7,100 credit card points plus $5.60. The offer is valid from select U.S. cities this December, making it a perfect opportunity for holiday travel or a romantic getaway. Don\u2019t miss the chance to explore the City of Light while saving on airfare!",
"price": 500.0,
"url": "https://thepointsguy.com/deals/deal-of-the-day/"
},
"estimate": 1937.4169921875,
"discount": 1437.4169921875
},
{
"deal": {
"destination": "Saudi Arabia",
"deal_type": "Flight",
"description": "Delta Air Lines is set to introduce nonstop flights from Atlanta to Riyadh, Saudi Arabia, next October, making it the only U.S. airline offering this route. This exciting development opens up new travel opportunities for American travelers to explore the Kingdom's rich history and culture. Be among the first to book these flights and experience a new adventure!",
"price": 500.0,
"url": "https://thepointsguy.com/news/delta-air-lines-saudi-arabia-riyadh-nonstop-flights/"
},
"estimate": 2180.265625,
"discount": 1680.265625
},
{
"deal": {
"destination": "Various Hyatt Vacation Club properties",
"deal_type": "Hotel",
"description": "This winter, enjoy a stay at Hyatt Vacation Club properties and earn 3,000 points per night. This promotion encourages travelers to indulge in luxury at various locations, with every night spent contributing to your loyalty rewards. Experience comfort, amenities, and the revenue of points to redeem for future stays!",
"price": 500.0,
"url": "https://thepointsguy.com/news/hyatt-vacation-club-bonus-points-offer/"
},
"estimate": 2734.311767578125,
"discount": 2234.311767578125
},
{
"deal": {
"destination": "Various IHG properties",
"deal_type": "Hotel",
"description": "IHG One Rewards members can take advantage of a flash sale providing up to 30% off at participating properties. This limited-time offer allows members to book accommodations across various locations at significant discounts, perfect for weekend getaways or extended vacations. Sign up for free to access this amazing deal!",
"price": 500.0,
"url": "https://thepointsguy.com/deals/ihg-flash-sale/"
},
"estimate": 2387.095703125,
"discount": 1887.095703125
},
{
"deal": {
"destination": "Alaska",
"deal_type": "Cruise",
"description": "Alaska is known for its breathtaking views and wildlife, and the best time to cruise there can vary. This guide helps travelers understand the advantages of cruising in Alaska based on the month they choose to embark. Travelers can benefit from discounted pricing during specific seasons, ensuring a unique and memorable experience out at sea. Enjoy the natural beauty and adventures that Alaska has to offer!",
"price": 500.0,
"url": "https://thepointsguy.com/cruise/best-time-to-cruise-alaska/"
},
"estimate": 3685.193115234375,
"discount": 3185.193115234375
},
{
"deal": {
"destination": "Paris",
"deal_type": "Flight",
"description": "This incredible deal allows you to fly to Paris for just 7,100 credit card points plus a mere $5.60. You can book this award flight departing from select U.S. cities this December, making it an affordable dream destination during the holiday season. Enjoy the beauty of Paris and explore its iconic landmarks without breaking the bank. Don't miss this opportunity to visit the City of Lights on a budget!",
"price": 500.0,
"url": "https://thepointsguy.com/deals/deal-of-the-day/"
},
"estimate": 2293.15283203125,
"discount": 1793.15283203125
},
{
"deal": {
"destination": "Alaska",
"deal_type": "Cruise",
"description": "Alaska offers a unique cruising experience with a limited season where travelers can see wildlife and stunning landscapes. This guide helps you choose the best time to cruise Alaska, discussing each month\u2019s pros and cons, including potential discounts and wildlife viewing opportunities. Planning your cruise around peak seasons can enhance your experience and save you money on your adventure.",
"price": 500.0,
"url": "https://thepointsguy.com/cruise/best-time-to-cruise-alaska/"
},
"estimate": 2563.173583984375,
"discount": 2063.173583984375
},
{
"deal": {
"destination": "Saudi Arabia",
"deal_type": "Flight",
"description": "Delta Air Lines is launching a new route from Atlanta to Riyadh in October, making it the only U.S. airline to offer direct flights to Saudi Arabia. This is a great opportunity for travelers interested in experiencing Middle Eastern culture and hospitality. Don\u2019t miss your chance to be among the first to explore this exciting new destination from the U.S.",
"price": 500.0,
"url": "https://thepointsguy.com/news/delta-air-lines-saudi-arabia-riyadh-nonstop-flights/"
},
"estimate": 1687.6510009765625,
"discount": 1187.6510009765625
},
{
"deal": {
"destination": "Hyatt Vacation Club",
"deal_type": "Hotel",
"description": "Earn 3,000 Hyatt points per night this winter when staying at Hyatt Vacation Club properties. This limited-time offer allows travelers to enjoy a luxurious and comfortable stay while racking up points for future trips. Ideal for points-savvy travelers looking to maximize their rewards during their winter getaway.",
"price": 500.0,
"url": "https://thepointsguy.com/news/hyatt-vacation-club-bonus-points-offer/"
},
"estimate": 2384.860595703125,
"discount": 1884.860595703125
},
{
"deal": {
"destination": "Various IHG properties",
"deal_type": "Hotel",
"description": "IHG One Rewards members can save up to 30% on stays at participating properties through a flash sale. This deal is perfect for those planning a trip and willing to stay at IHG hotels. Become a member for free and take advantage of steep discounts on your accommodations, making your travels more affordable without compromising on comfort. Act fast, as this sale is limited.",
"price": 500.0,
"url": "https://thepointsguy.com/deals/ihg-flash-sale/"
},
"estimate": 2723.661376953125,
"discount": 2223.661376953125
},
{
"deal": {
"destination": "Paris",
"deal_type": "Flight",
"description": "Take advantage of this incredible deal to fly to Paris for only 7,100 credit card points plus a nominal fee of $5.60. With fantastic award availability from select U.S. cities this December, it's an opportunity for travelers to experience the City of Lights at a fraction of the usual point cost. This limited-time offer encourages travelers to book quickly to secure their tickets for a winter getaway in one of the world\u2019s most romantic destinations.",
"price": 500.0,
"url": "https://thepointsguy.com/deals/deal-of-the-day/"
},
"estimate": 1811.4459228515625,
"discount": 1311.4459228515625
},
{
"deal": {
"destination": "Multiple locations in Alaska",
"deal_type": "Cruise",
"description": "Discover the stunning beauty of Alaska on a cruise, best enjoyed during its limited season. Each month offers unique advantages, ranging from discounted pricing to the chance of seeing abundant wildlife like whales and bears. This guide helps travelers decide the optimal time to embark on their Alaskan adventure, ensuring they experience all the natural wonders this amazing destination has to offer.",
"price": 500.0,
"url": "https://thepointsguy.com/cruise/best-time-to-cruise-alaska/"
},
"estimate": 3470.741455078125,
"discount": 2970.741455078125
},
{
"deal": {
"destination": "Saudi Arabia",
"deal_type": "Flight",
"description": "Delta Air Lines will soon be the only U.S. airline offering nonstop flights to Saudi Arabia, specifically connecting Atlanta to Riyadh starting next October. This unique route presents a valuable travel opportunity for those looking to explore the rich culture and history of Saudi Arabia. Be among the first to experience this new connection and discover the fantastic landscapes and heritage of the Kingdom.",
"price": 500.0,
"url": "https://thepointsguy.com/news/delta-air-lines-saudi-arabia-riyadh-nonstop-flights/"
},
"estimate": 3656.968505859375,
"discount": 3156.968505859375
},
{
"deal": {
"destination": "Multiple IHG Hotels",
"deal_type": "Hotel",
"description": "IHG One Rewards members can take advantage of a flash sale that promises savings of up to 30% on stays at participating properties. This offer is a great way for travelers to enjoy top-notch accommodations while enjoying significant savings. Joining the IHG One Rewards program is free, allowing even more travelers to access this lucrative deal.",
"price": 350.0,
"url": "https://thepointsguy.com/deals/ihg-flash-sale/"
},
"estimate": 2630.43603515625,
"discount": 2280.43603515625
},
{
"deal": {
"destination": "Hyatt Vacation Club properties",
"deal_type": "Hotel",
"description": "Earn 3,000 Hyatt points per night this winter at Hyatt Vacation Club locations. This deal invites travelers to enjoy luxurious accommodations while earning valuable points that can be redeemed for future stays and perks. This offer is perfect for those looking to enjoy a winter getaway and build their loyalty points at the same time\u2014making it a win-win for leisure seekers.",
"price": 500.0,
"url": "https://thepointsguy.com/news/hyatt-vacation-club-bonus-points-offer/"
},
"estimate": 2742.44580078125,
"discount": 2242.44580078125
},
{
"deal": {
"destination": "Paris",
"deal_type": "Flight",
"description": "Book a flight to Paris for only 7,100 credit card points plus $5.60 this December. This is a fantastic opportunity to travel to one of the most romantic cities in the world at an unbelievably low cost. The deal includes round-trip flights from select U.S. cities with great award availability. Don't miss out on this limited-time offer to experience Parisian culture, cuisine, and landmarks.",
"price": 500.0,
"url": "https://thepointsguy.com/deals/deal-of-the-day/"
},
"estimate": 2132.895263671875,
"discount": 1632.895263671875
},
{
"deal": {
"destination": "Alaska",
"deal_type": "Cruise",
"description": "Alaska is known as a premier cruise destination with a limited season, each month providing unique advantages such as discounted pricing or exceptional wildlife viewing. This guide helps travelers determine the best time to experience the breathtaking landscapes and diverse wildlife of Alaska on a cruise. Whether looking for adventure or relaxation, this guide highlights the optimal months for your trip.",
"price": 500.0,
"url": "https://thepointsguy.com/cruise/best-time-to-cruise-alaska/"
},
"estimate": 2560.084716796875,
"discount": 2060.084716796875
},
{
"deal": {
"destination": "Saudi Arabia",
"deal_type": "Flight",
"description": "Starting in October, Delta Air Lines will be launching a new direct flight route from Atlanta to Riyadh, making it the only U.S. airline serving this destination. This offer provides an excellent opportunity for travelers interested in exploring the rich culture and history of Saudi Arabia. Book your flights in advance to secure your spot on this new route, which promises a convenient travel option to a growing destination.",
"price": 500.0,
"url": "https://thepointsguy.com/news/delta-air-lines-saudi-arabia-riyadh-nonstop-flights/"
},
"estimate": 1428.189697265625,
"discount": 928.189697265625
},
{
"deal": {
"destination": "Various IHG properties",
"deal_type": "Hotel",
"description": "IHG One Rewards members can take advantage of a flash sale offering up to 30% off at participating hotels. This limited-time offer allows you to enjoy significant savings on memorable stays at IHG properties around the world. Sign up for free to become an IHG One Rewards member and access this exclusive deal and more. Stay at top hotels while maximizing your rewards.",
"price": 350.0,
"url": "https://thepointsguy.com/deals/ihg-flash-sale/"
},
"estimate": 2310.8056640625,
"discount": 1960.8056640625
},
{
"deal": {
"destination": "Hyatt Vacation Club properties",
"deal_type": "Hotel",
"description": "Earn 3,000 Hyatt points per night this winter when you stay at Hyatt Vacation Club properties, allowing you to enjoy luxurious accommodations and various amenities. This is a great way to enhance your travel experience while gaining significant rewards for future stays. The offer is available exclusively this winter, making it a perfect opportunity to plan a getaway.",
"price": 500.0,
"url": "https://thepointsguy.com/news/hyatt-vacation-club-bonus-points-offer/"
},
"estimate": 2529.80712890625,
"discount": 2029.80712890625
},
{
"deal": {
"destination": "Paris",
"deal_type": "Flight",
"description": "This deal allows travelers to fly to Paris for only 7,100 credit card points plus a minimal fee of $5.60. Award availability is particularly favorable from select U.S. cities, making this an incredible opportunity for those looking to explore the City of Light this December. With just a small cash outlay, travelers can experience all that Paris has to offer, from its iconic landmarks to its renowned cuisine.",
"price": 500.0,
"url": "https://thepointsguy.com/deals/deal-of-the-day/"
},
"estimate": 2171.856201171875,
"discount": 1671.856201171875
},
{
"deal": {
"destination": "Saudi Arabia",
"deal_type": "Flight",
"description": "Delta Air Lines is set to launch a new route connecting Atlanta to Riyadh, Saudi Arabia, starting next October. This will make Delta the only U.S. airline offering nonstop service to this growing destination. This route presents a unique opportunity for travelers looking to explore Saudi Arabia's rich culture and history, with convenient travel options from one of the largest U.S. cities.",
"price": 500.0,
"url": "https://thepointsguy.com/news/delta-air-lines-saudi-arabia-riyadh-nonstop-flights/"
},
"estimate": 2526.151123046875,
"discount": 2026.151123046875
},
{
"deal": {
"destination": "Various IHG properties",
"deal_type": "Hotel",
"description": "IHG One Rewards members can take advantage of a flash sale offering up to 30% off on stays at participating properties. With various locations available, this deal allows for substantial savings on accommodations, ideal for travelers looking to book winter getaways or holiday trips. Signing up for the rewards program is free, making this an accessible option for all.",
"price": 350.0,
"url": "https://thepointsguy.com/deals/ihg-flash-sale/"
},
"estimate": 2769.24365234375,
"discount": 2419.24365234375
},
{
"deal": {
"destination": "Alaska",
"deal_type": "Cruise",
"description": "Alaska's cruise season has specific months with unique advantages, including discounted pricing and abundant wildlife viewings. This guide helps travelers decide the best time for their Alaskan cruise adventure, whether they\u2019re looking for the best deals or the most scenic wildlife experiences. Ideal for nature lovers and adventure seekers alike, this destination promises thrilling experiences throughout the season.",
"price": 500.0,
"url": "https://thepointsguy.com/cruise/best-time-to-cruise-alaska/"
},
"estimate": 2547.8408203125,
"discount": 2047.8408203125
},
{
"deal": {
"destination": "Various Hyatt Vacation Club properties",
"deal_type": "Package",
"description": "Hyatt Vacation Club properties are offering an enticing promotion this winter where travelers can earn 3,000 points per night. This promotion is perfect for those looking to experience the luxury and comfort of Hyatt properties while accumulating points for future stays. Ideal for families or couples, it combines relaxation with the potential for rewards during the winter season.",
"price": 500.0,
"url": "https://thepointsguy.com/news/hyatt-vacation-club-bonus-points-offer/"
},
"estimate": 2638.575439453125,
"discount": 2138.575439453125
},
{
"deal": {
"destination": "Paris",
"deal_type": "Flight",
"description": "Fly to Paris for only 7,100 credit card points plus a minimal fee of $5.60. The deal offers terrific award availability for trips from select U.S. cities in December, making it an ideal time to explore the City of Light. Enjoy an unforgettable holiday season with landmarks, culture, and cuisine awaiting you in Paris.",
"price": 500.0,
"url": "https://thepointsguy.com/deals/deal-of-the-day/"
},
"estimate": 2073.568603515625,
"discount": 1573.568603515625
},
{
"deal": {
"destination": "Saudi Arabia",
"deal_type": "Flight",
"description": "Delta Air Lines is launching a new nonstop route from Atlanta to Riyadh starting next October, making it the only US airline to connect directly to Saudi Arabia. This new service opens up opportunities for business and leisure travel to a historically rich destination. Travelers can expect a blend of modernity and tradition in Riyadh's stunning architecture and culture.",
"price": 500.0,
"url": "https://thepointsguy.com/news/delta-air-lines-saudi-arabia-riyadh-nonstop-flights/"
},
"estimate": 3828.263427734375,
"discount": 3328.263427734375
},
{
"deal": {
"destination": "Alaska",
"deal_type": "Cruise",
"description": "Experience the breathtaking beauty of Alaska with its limited cruise season. Each month offers unique perks, from discounted pricing to abundant wildlife sightings. This guide will help you determine the best timing for your Alaskan adventure, ensuring an unforgettable trip filled with natural wonders and exploration of majestic landscapes.",
"price": 500.0,
"url": "https://thepointsguy.com/cruise/best-time-to-cruise-alaska/"
},
"estimate": 2574.424560546875,
"discount": 2074.424560546875
},
{
"deal": {
"destination": "Multiple Hyatt locations",
"deal_type": "Hotel",
"description": "This winter, earn 3,000 Hyatt points per night at Hyatt Vacation Club properties. Enjoy spacious accommodations and upscale amenities across beautiful locations, ideal for family getaways or longer stays. Don't miss this chance to maximize your rewards while relaxing in comfort at a Hyatt destination of your choice.",
"price": 500.0,
"url": "https://thepointsguy.com/news/hyatt-vacation-club-bonus-points-offer/"
},
"estimate": 2946.070556640625,
"discount": 2446.070556640625
},
{
"deal": {
"destination": "Multiple IHG locations",
"deal_type": "Hotel",
"description": "IHG is offering a flash sale for its One Rewards members with discounts of up to 30% on stays at participating properties. This is a perfect opportunity for frequent travelers to save substantially while enjoying the hotel brand's high standards. Membership is free, making it a great time to sign up and take advantage of the offer.",
"price": 500.0,
"url": "https://thepointsguy.com/deals/ihg-flash-sale/"
},
"estimate": 1302.68408203125,
"discount": 802.68408203125
}
]

View File

@@ -0,0 +1,306 @@
import os
import sys
import logging
import queue
import threading
import time
import gradio as gr
import plotly.graph_objects as go
w8d5_path = os.path.abspath(os.path.dirname(__file__))
week8_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
if w8d5_path not in sys.path:
sys.path.insert(0, w8d5_path)
if week8_path not in sys.path:
sys.path.insert(0, week8_path)
from log_utils import reformat
from helpers.travel_dual_framework import TravelDualFramework
from helpers.travel_deals import TravelOpportunity, TravelDeal
class QueueHandler(logging.Handler):
def __init__(self, log_queue):
super().__init__()
self.log_queue = log_queue
def emit(self, record):
self.log_queue.put(self.format(record))
log_queue = queue.Queue()
queue_handler = QueueHandler(log_queue)
queue_handler.setFormatter(
logging.Formatter(
"[%(asctime)s] [%(levelname)s] %(message)s",
datefmt="%Y-%m-%d %H:%M:%S"
)
)
logging.getLogger().addHandler(queue_handler)
logging.getLogger().setLevel(logging.INFO)
agent_framework = TravelDualFramework()
agent_framework.init_agents_as_needed()
CHECK_INTERVAL = 300
def run_agent_framework():
while True:
try:
agent_framework.run()
except Exception as e:
logging.error(f"Error in agent framework: {e}")
time.sleep(CHECK_INTERVAL)
framework_thread = threading.Thread(target=run_agent_framework, daemon=True)
framework_thread.start()
def get_llm_table(llm_opps):
return [[
opp.deal.destination,
opp.deal.deal_type,
f"${opp.deal.price:.2f}",
f"${opp.estimate:.2f}",
f"${opp.discount:.2f}",
opp.deal.url[:50] + "..." if len(opp.deal.url) > 50 else opp.deal.url
] for opp in llm_opps]
def get_xgb_table(xgb_opps):
return [[
opp.deal.destination,
opp.deal.deal_type,
f"${opp.deal.price:.2f}",
f"${opp.estimate:.2f}",
f"${opp.discount:.2f}",
opp.deal.url[:50] + "..." if len(opp.deal.url) > 50 else opp.deal.url
] for opp in xgb_opps]
log_data = []
def update_ui():
global log_data
llm_data = get_llm_table(agent_framework.llm_memory)
xgb_data = get_xgb_table(agent_framework.xgb_memory)
while not log_queue.empty():
try:
message = log_queue.get_nowait()
log_data.append(reformat(message))
except:
break
logs_html = '<div style="height: 500px; overflow-y: auto; border: 1px solid #ccc; background-color: #1a1a1a; padding: 10px; font-family: monospace; font-size: 12px; color: #fff;">'
logs_html += '<br>'.join(log_data[-50:])
logs_html += '</div>'
llm_count = len(agent_framework.llm_memory)
xgb_count = len(agent_framework.xgb_memory)
stats = f"LLM Opportunities: {llm_count} | XGBoost Opportunities: {xgb_count}"
return llm_data, xgb_data, logs_html, stats
def create_3d_plot():
try:
documents, vectors, colors, categories = TravelDualFramework.get_plot_data(max_datapoints=5000)
if len(vectors) == 0:
fig = go.Figure()
fig.add_annotation(
text="No data available yet. Vectorstore will load after initialization.",
xref="paper", yref="paper",
x=0.5, y=0.5, showarrow=False,
font=dict(size=16)
)
return fig
fig = go.Figure()
unique_categories = list(set(categories))
category_colors = {cat: colors[categories.index(cat)] for cat in unique_categories}
for category in unique_categories:
mask = [cat == category for cat in categories]
cat_vectors = vectors[mask]
fig.add_trace(go.Scatter3d(
x=cat_vectors[:, 0],
y=cat_vectors[:, 1],
z=cat_vectors[:, 2],
mode='markers',
marker=dict(
size=3,
color=category_colors[category],
opacity=0.6
),
name=category.replace('_', ' '),
hovertemplate='<b>%{text}</b><extra></extra>',
text=[category] * len(cat_vectors)
))
fig.update_layout(
title={
'text': f'3D Travel Vectorstore Visualization ({len(vectors):,} deals)',
'x': 0.5,
'xanchor': 'center'
},
scene=dict(
xaxis_title='Dimension 1',
yaxis_title='Dimension 2',
zaxis_title='Dimension 3',
camera=dict(
eye=dict(x=1.5, y=1.5, z=1.5)
)
),
width=1200,
height=600,
margin=dict(r=0, b=0, l=0, t=40),
showlegend=True,
legend=dict(
yanchor="top",
y=0.99,
xanchor="left",
x=0.01
)
)
return fig
except Exception as e:
logging.error(f"Error creating 3D plot: {e}")
fig = go.Figure()
fig.add_annotation(
text=f"Error loading plot: {str(e)}",
xref="paper", yref="paper",
x=0.5, y=0.5, showarrow=False,
font=dict(size=14, color="red")
)
return fig
with gr.Blocks(title="Travel Deal Hunter - Dual Estimation", fill_width=True, theme=gr.themes.Soft()) as ui:
gr.Markdown(
"""
<div style="text-align: center;">
<h1 style="margin-bottom: 10px;">Travel Deal Hunter - Dual Estimation System</h1>
<p style="color: #666; font-size: 16px;">
Comparing LLM-based Semantic Estimation vs XGBoost Machine Learning
</p>
<p style="color: #999; font-size: 14px; margin-top: 10px;">
System scans RSS feeds every 5 minutes. Use the button below to trigger a manual scan.
</p>
</div>
"""
)
with gr.Row():
with gr.Column(scale=3):
stats_display = gr.Textbox(
label="",
value="LLM Opportunities: 0 | XGBoost Opportunities: 0",
interactive=False,
show_label=False,
container=False
)
with gr.Column(scale=1):
scan_button = gr.Button("Scan Now", variant="primary")
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("### LLM Estimates")
llm_dataframe = gr.Dataframe(
headers=["Destination", "Type", "Price", "LLM Est.", "Savings", "URL"],
datatype=["str", "str", "str", "str", "str", "str"],
wrap=True,
column_widths=[2, 1, 1, 1, 1, 2],
row_count=5,
col_count=6,
interactive=False
)
with gr.Column(scale=1):
gr.Markdown("### XGBoost Estimates")
xgb_dataframe = gr.Dataframe(
headers=["Destination", "Type", "Price", "XGB Est.", "Savings", "URL"],
datatype=["str", "str", "str", "str", "str", "str"],
wrap=True,
column_widths=[2, 1, 1, 1, 1, 2],
row_count=5,
col_count=6,
interactive=False
)
with gr.Row():
with gr.Column(scale=2):
plot_output = gr.Plot(label="3D Travel Vectorstore Visualization")
with gr.Column(scale=1):
gr.Markdown("### Agent Activity Logs")
log_output = gr.HTML(
value='<div style="height: 500px; overflow-y: auto; border: 1px solid #ccc; background-color: #1a1a1a; padding: 10px; font-family: monospace; font-size: 12px; color: #fff;"></div>'
)
ui.load(
fn=lambda: (
get_llm_table(agent_framework.llm_memory),
get_xgb_table(agent_framework.xgb_memory),
"",
f"LLM Opportunities: {len(agent_framework.llm_memory)} | XGBoost Opportunities: {len(agent_framework.xgb_memory)}",
create_3d_plot()
),
outputs=[llm_dataframe, xgb_dataframe, log_output, stats_display, plot_output]
)
# Manual scan button
def manual_scan():
try:
agent_framework.run()
return update_ui()
except Exception as e:
logging.error(f"Manual scan error: {e}")
return update_ui()
scan_button.click(
fn=manual_scan,
outputs=[llm_dataframe, xgb_dataframe, log_output, stats_display]
)
# Click handlers for notifications
def llm_click_handler(selected_index: gr.SelectData):
try:
row = selected_index.index[0]
if row < len(agent_framework.llm_memory):
opportunity = agent_framework.llm_memory[row]
agent_framework.messenger.alert(opportunity)
logging.info(f"Manual alert sent for LLM opportunity: {opportunity.deal.destination}")
except Exception as e:
logging.error(f"Error sending LLM notification: {e}")
def xgb_click_handler(selected_index: gr.SelectData):
try:
row = selected_index.index[0]
if row < len(agent_framework.xgb_memory):
opportunity = agent_framework.xgb_memory[row]
agent_framework.messenger.alert(opportunity)
logging.info(f"Manual alert sent for XGBoost opportunity: {opportunity.deal.destination}")
except Exception as e:
logging.error(f"Error sending XGBoost notification: {e}")
llm_dataframe.select(fn=llm_click_handler)
xgb_dataframe.select(fn=xgb_click_handler)
gr.Timer(5).tick(
fn=update_ui,
outputs=[llm_dataframe, xgb_dataframe, log_output, stats_display]
)
if __name__ == "__main__":
ui.launch(inbrowser=True, share=False)