FACETS-LLM-Assistant / scripts /ensemble_agent.py
spicyavo467's picture
Upload 19 files
29c2d9b verified
Raw History Blame Contribute Delete
5.04 kB
import os
import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
import joblib
from agent import Agent
from scripts.retail_price_specialist_agent import RetailPriceSpecialistAgent
from frontier_agent import FrontierAgent
from random_forest_agent import RandomForestAgent
class EnsembleAgent(Agent):
"""
An ensemble model that combines predictions from multiple price prediction agents
"""
name = "Ensemble Agent"
color = Agent.YELLOW
def __init__(self, collection=None, model_path='./models/ensemble_model.pkl'):
"""
Create an instance of Ensemble, by creating each of the models
And loading the weights of the Ensemble
"""
self.log("Initializing Ensemble Agent")
# Initialize all component agents
self.specialist = RetailPriceSpecialistAgent()
self.frontier = FrontierAgent(collection)
self.random_forest = RandomForestAgent()
# Try to load the ensemble model
try:
self.model = joblib.load(model_path)
self.log("Loaded ensemble weights from disk")
except Exception as e:
self.log(f"Could not load ensemble model: {e}")
self.log("Using default equal weights")
self.model = None
self.log("Ensemble Agent is ready")
def _default_ensemble(self, predictions):
"""
Default ensemble method when model weights aren't available
"""
# Simple median with outlier removal
sorted_preds = sorted(predictions)
# If we have 3 or more predictions, remove the highest and lowest
if len(sorted_preds) >= 3:
sorted_preds = sorted_preds[1:-1]
# Return the average of remaining predictions
return sum(sorted_preds) / len(sorted_preds)
def price(self, description: str) -> float:
"""
Run this ensemble model
Ask each of the models to price the product
Then use the Linear Regression model to return the weighted price
:param description: the description of a product
:return: an estimate of its price
"""
self.log("Running Ensemble Agent - gathering predictions from all agents")
# Get predictions from each agent with error handling
try:
specialist_price = self.specialist.price(description)
self.log(f"Specialist Agent prediction: ${specialist_price:.2f}")
except Exception as e:
self.log(f"Error from Specialist Agent: {e}")
specialist_price = None
try:
frontier_price = self.frontier.price(description)
self.log(f"Frontier Agent prediction: ${frontier_price:.2f}")
except Exception as e:
self.log(f"Error from Frontier Agent: {e}")
frontier_price = None
try:
random_forest_price = self.random_forest.price(description)
self.log(f"Random Forest Agent prediction: ${random_forest_price:.2f}")
except Exception as e:
self.log(f"Error from Random Forest Agent: {e}")
random_forest_price = None
# Collect all valid predictions
valid_predictions = [p for p in [specialist_price, frontier_price, random_forest_price] if p is not None]
if not valid_predictions:
self.log("No valid predictions from any agent - using fallback")
# Very basic fallback
return 9.99
# If we have the ensemble model, use it
if self.model is not None:
# Fill in missing values with the mean of valid predictions
mean_price = sum(valid_predictions) / len(valid_predictions)
specialist_price = specialist_price if specialist_price is not None else mean_price
frontier_price = frontier_price if frontier_price is not None else mean_price
random_forest_price = random_forest_price if random_forest_price is not None else mean_price
# Create features for the ensemble model
X = pd.DataFrame({
'Specialist': [specialist_price],
'Frontier': [frontier_price],
'RandomForest': [random_forest_price],
'Min': [min(specialist_price, frontier_price, random_forest_price)],
'Max': [max(specialist_price, frontier_price, random_forest_price)],
})
# Make prediction and ensure it's positive
prediction = max(0, self.model.predict(X)[0])
self.log(f"Ensemble Agent (weighted model) - predicting ${prediction:.2f}")
return prediction
else:
# Use default ensemble method
prediction = self._default_ensemble(valid_predictions)
self.log(f"Ensemble Agent (default average) - predicting ${prediction:.2f}")
return prediction