Spaces:
Sleeping
Sleeping
Delete app.py
Browse files
app.py
DELETED
|
@@ -1,272 +0,0 @@
|
|
| 1 |
-
"""
|
| 2 |
-
AUTOMATION 2 — Hugging Face Spaces App
|
| 3 |
-
=======================================
|
| 4 |
-
AI-Enhanced interface for Amazon & Spotify analysis
|
| 5 |
-
Deploy this on Hugging Face Spaces (SDK: Gradio)
|
| 6 |
-
|
| 7 |
-
Instructions:
|
| 8 |
-
1. Go to huggingface.co/spaces → Create new Space
|
| 9 |
-
2. Select Gradio as SDK
|
| 10 |
-
3. Upload this file as app.py
|
| 11 |
-
4. Upload amazon_synthetic.csv and spotify_synthetic.csv
|
| 12 |
-
5. Add requirements.txt with: pandas, scikit-learn, matplotlib, vaderSentiment
|
| 13 |
-
"""
|
| 14 |
-
|
| 15 |
-
import gradio as gr
|
| 16 |
-
import pandas as pd
|
| 17 |
-
import numpy as np
|
| 18 |
-
import matplotlib
|
| 19 |
-
matplotlib.use('Agg')
|
| 20 |
-
import matplotlib.pyplot as plt
|
| 21 |
-
import io
|
| 22 |
-
import tempfile
|
| 23 |
-
import os
|
| 24 |
-
import warnings
|
| 25 |
-
warnings.filterwarnings('ignore')
|
| 26 |
-
|
| 27 |
-
from sklearn.ensemble import RandomForestRegressor, RandomForestClassifier
|
| 28 |
-
from sklearn.model_selection import train_test_split
|
| 29 |
-
from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
|
| 30 |
-
|
| 31 |
-
# ── TRAIN MODELS ON STARTUP ─────────────────────────────────
|
| 32 |
-
|
| 33 |
-
print("Loading data and training models...")
|
| 34 |
-
|
| 35 |
-
# Amazon model
|
| 36 |
-
try:
|
| 37 |
-
df_amz = pd.read_csv('amazon_synthetic.csv')
|
| 38 |
-
features_amz = ['actual_price','discounted_price','discount_pct','rating','sentiment_score']
|
| 39 |
-
df_amz['log_sales'] = np.log1p(df_amz['rating_count'])
|
| 40 |
-
X_amz = df_amz[features_amz].dropna()
|
| 41 |
-
y_amz = df_amz.loc[X_amz.index, 'log_sales']
|
| 42 |
-
rf_amz = RandomForestRegressor(n_estimators=100, random_state=42)
|
| 43 |
-
rf_amz.fit(X_amz, y_amz)
|
| 44 |
-
AMZ_LOADED = True
|
| 45 |
-
print("✓ Amazon model ready")
|
| 46 |
-
except Exception as e:
|
| 47 |
-
AMZ_LOADED = False
|
| 48 |
-
print(f"Amazon model failed: {e}")
|
| 49 |
-
|
| 50 |
-
# Spotify model
|
| 51 |
-
try:
|
| 52 |
-
df_spot = pd.read_csv('spotify_synthetic.csv')
|
| 53 |
-
features_spot = ['danceability','energy','loudness','speechiness','acousticness',
|
| 54 |
-
'instrumentalness','valence','tempo','explicit']
|
| 55 |
-
df_spot['explicit'] = df_spot['explicit'].astype(int)
|
| 56 |
-
X_spot = df_spot[features_spot].dropna()
|
| 57 |
-
y_spot = df_spot.loc[X_spot.index, 'popularity']
|
| 58 |
-
rf_spot = RandomForestRegressor(n_estimators=100, random_state=42)
|
| 59 |
-
rf_spot.fit(X_spot, y_spot)
|
| 60 |
-
SPOT_LOADED = True
|
| 61 |
-
print("✓ Spotify model ready")
|
| 62 |
-
except Exception as e:
|
| 63 |
-
SPOT_LOADED = False
|
| 64 |
-
print(f"Spotify model failed: {e}")
|
| 65 |
-
|
| 66 |
-
analyzer = SentimentIntensityAnalyzer()
|
| 67 |
-
|
| 68 |
-
# ── AMAZON TAB ───────────────────────────────────────────────
|
| 69 |
-
|
| 70 |
-
def analyze_amazon(category, actual_price, discount_pct, rating, review_text):
|
| 71 |
-
discounted_price = actual_price * (1 - discount_pct / 100)
|
| 72 |
-
sentiment_score = analyzer.polarity_scores(review_text)['compound'] if review_text else 0.0
|
| 73 |
-
sentiment_label = 'Positive' if sentiment_score >= 0.05 else ('Negative' if sentiment_score <= -0.05 else 'Neutral')
|
| 74 |
-
|
| 75 |
-
if AMZ_LOADED:
|
| 76 |
-
X = np.array([[actual_price, discounted_price, discount_pct, rating, sentiment_score]])
|
| 77 |
-
log_sales_pred = rf_amz.predict(X)[0]
|
| 78 |
-
sales_pred = int(np.expm1(log_sales_pred))
|
| 79 |
-
else:
|
| 80 |
-
sales_pred = int(rating * 1000 * (1 + sentiment_score))
|
| 81 |
-
|
| 82 |
-
# Score 0-100
|
| 83 |
-
score = min(100, int(
|
| 84 |
-
25 * (rating / 5) +
|
| 85 |
-
25 * ((sentiment_score + 1) / 2) +
|
| 86 |
-
25 * min(sales_pred / 50000, 1) +
|
| 87 |
-
25 * min(discount_pct / 70, 1)
|
| 88 |
-
))
|
| 89 |
-
tier = 'Top Performer' if score >= 75 else 'Average' if score >= 45 else 'Underperformer'
|
| 90 |
-
|
| 91 |
-
# Plot
|
| 92 |
-
fig, axes = plt.subplots(1, 2, figsize=(10, 4))
|
| 93 |
-
fig.suptitle('Amazon Product Analysis', fontsize=13, fontweight='bold')
|
| 94 |
-
|
| 95 |
-
metrics = ['Rating\n(/5)', 'Sentiment\n(scaled)', 'Discount\n(%/100)', 'Score\n(/100)']
|
| 96 |
-
values = [rating/5, (sentiment_score+1)/2, discount_pct/100, score/100]
|
| 97 |
-
colors = ['#2E86AB','#A23B72','#F18F01','#44BBA4']
|
| 98 |
-
bars = axes[0].bar(metrics, values, color=colors, edgecolor='white')
|
| 99 |
-
axes[0].set_ylim(0, 1.1)
|
| 100 |
-
axes[0].set_title('Performance Breakdown', fontweight='bold')
|
| 101 |
-
for bar, val in zip(bars, values):
|
| 102 |
-
axes[0].text(bar.get_x()+bar.get_width()/2, bar.get_height()+0.02,
|
| 103 |
-
f'{val:.2f}', ha='center', fontsize=10)
|
| 104 |
-
|
| 105 |
-
axes[1].pie([score, 100-score], labels=[f'Score: {score}', ''],
|
| 106 |
-
colors=['#2E86AB','#eee'], startangle=90,
|
| 107 |
-
wedgeprops={'edgecolor':'white'})
|
| 108 |
-
axes[1].set_title(f'Overall: {tier}', fontweight='bold')
|
| 109 |
-
|
| 110 |
-
plt.tight_layout()
|
| 111 |
-
tmp = tempfile.NamedTemporaryFile(delete=False, suffix='.png')
|
| 112 |
-
plt.savefig(tmp.name, format='png', dpi=120, bbox_inches='tight')
|
| 113 |
-
plt.close()
|
| 114 |
-
|
| 115 |
-
report = f"""
|
| 116 |
-
📦 AMAZON PRODUCT ANALYSIS REPORT
|
| 117 |
-
{'='*40}
|
| 118 |
-
Category: {category}
|
| 119 |
-
Actual Price: ₹{actual_price:.2f}
|
| 120 |
-
Discounted Price: ₹{discounted_price:.2f}
|
| 121 |
-
Discount: {discount_pct}%
|
| 122 |
-
Rating: {rating}/5
|
| 123 |
-
{'─'*40}
|
| 124 |
-
SENTIMENT
|
| 125 |
-
Score: {sentiment_score:.3f}
|
| 126 |
-
Label: {sentiment_label}
|
| 127 |
-
{'─'*40}
|
| 128 |
-
PREDICTED SALES VOLUME
|
| 129 |
-
Est. Review Count: ~{sales_pred:,}
|
| 130 |
-
{'─'*40}
|
| 131 |
-
PERFORMANCE SCORE
|
| 132 |
-
Score: {score}/100
|
| 133 |
-
Tier: {tier}
|
| 134 |
-
{'─'*40}
|
| 135 |
-
RECOMMENDATIONS
|
| 136 |
-
{' ✓ Maintain pricing — good balance' if discount_pct < 50 else ' ⚠ High discount may hurt margins'}
|
| 137 |
-
{' ✓ Leverage positive reviews in ads' if sentiment_label == 'Positive' else ' ⚠ Address negative customer feedback'}
|
| 138 |
-
{' ✓ Strong rating — invest in visibility' if rating >= 4 else ' ⚠ Focus on quality improvement'}
|
| 139 |
-
"""
|
| 140 |
-
return report.strip(), tmp.name
|
| 141 |
-
|
| 142 |
-
# ── SPOTIFY TAB ──────────────────────────────────────────────
|
| 143 |
-
|
| 144 |
-
def analyze_spotify(genre, danceability, energy, loudness, tempo, valence,
|
| 145 |
-
acousticness, speechiness, instrumentalness, explicit):
|
| 146 |
-
exp = 1 if explicit else 0
|
| 147 |
-
|
| 148 |
-
if SPOT_LOADED:
|
| 149 |
-
X = np.array([[danceability, energy, loudness, speechiness, acousticness,
|
| 150 |
-
instrumentalness, valence, tempo, exp]])
|
| 151 |
-
pop_pred = float(np.clip(rf_spot.predict(X)[0], 0, 100))
|
| 152 |
-
else:
|
| 153 |
-
pop_pred = float(np.clip(20 + 30*danceability + 15*energy + 0.5*(loudness+20), 0, 100))
|
| 154 |
-
|
| 155 |
-
is_hit = pop_pred >= 60
|
| 156 |
-
tier = 'Hit 🔥' if pop_pred >= 70 else 'Popular' if pop_pred >= 50 else 'Mid-tier' if pop_pred >= 30 else 'Niche'
|
| 157 |
-
|
| 158 |
-
# Radar-style bar chart
|
| 159 |
-
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
|
| 160 |
-
fig.suptitle('Spotify Track Analysis', fontsize=13, fontweight='bold')
|
| 161 |
-
|
| 162 |
-
feats = ['Dance', 'Energy', 'Valence', 'Acoustic', 'Speech']
|
| 163 |
-
values = [danceability, energy, valence, acousticness, speechiness]
|
| 164 |
-
axes[0].bar(feats, values, color='#2E86AB', edgecolor='white')
|
| 165 |
-
axes[0].set_ylim(0, 1.1)
|
| 166 |
-
axes[0].set_title('Audio Feature Profile', fontweight='bold')
|
| 167 |
-
for i, (f, v) in enumerate(zip(feats, values)):
|
| 168 |
-
axes[0].text(i, v+0.02, f'{v:.2f}', ha='center', fontsize=9)
|
| 169 |
-
|
| 170 |
-
pop_normalized = pop_pred / 100
|
| 171 |
-
axes[1].pie([pop_normalized, 1-pop_normalized],
|
| 172 |
-
labels=[f'{pop_pred:.0f}/100', ''],
|
| 173 |
-
colors=['#A23B72','#eee'], startangle=90,
|
| 174 |
-
wedgeprops={'edgecolor':'white'})
|
| 175 |
-
axes[1].set_title(f'Predicted Popularity: {tier}', fontweight='bold')
|
| 176 |
-
|
| 177 |
-
plt.tight_layout()
|
| 178 |
-
tmp2 = tempfile.NamedTemporaryFile(delete=False, suffix='.png')
|
| 179 |
-
plt.savefig(tmp2.name, format='png', dpi=120, bbox_inches='tight')
|
| 180 |
-
plt.close()
|
| 181 |
-
|
| 182 |
-
report = f"""
|
| 183 |
-
🎵 SPOTIFY TRACK ANALYSIS REPORT
|
| 184 |
-
{'='*40}
|
| 185 |
-
Genre: {genre}
|
| 186 |
-
Tempo: {tempo:.1f} BPM
|
| 187 |
-
Explicit: {'Yes' if explicit else 'No'}
|
| 188 |
-
{'─'*40}
|
| 189 |
-
AUDIO FEATURES
|
| 190 |
-
Danceability: {danceability:.3f}
|
| 191 |
-
Energy: {energy:.3f}
|
| 192 |
-
Loudness: {loudness:.1f} dB
|
| 193 |
-
Valence: {valence:.3f}
|
| 194 |
-
Acousticness: {acousticness:.3f}
|
| 195 |
-
Speechiness: {speechiness:.3f}
|
| 196 |
-
{'─'*40}
|
| 197 |
-
PREDICTED PERFORMANCE
|
| 198 |
-
Popularity Score: {pop_pred:.1f}/100
|
| 199 |
-
Commercial Tier: {tier}
|
| 200 |
-
Hit Potential: {'Yes 🔥' if is_hit else 'Not quite yet'}
|
| 201 |
-
{'─'*40}
|
| 202 |
-
RECOMMENDATIONS
|
| 203 |
-
{' ✓ Strong commercial profile — pitch to playlists' if pop_pred >= 60 else ' → Consider boosting danceability'}
|
| 204 |
-
{' ✓ High energy suits live events & promo' if energy >= 0.7 else ' → Lower energy may limit mainstream appeal'}
|
| 205 |
-
{' ✓ Positive mood boosts streaming' if valence >= 0.5 else ' → Consider a more upbeat arrangement'}
|
| 206 |
-
"""
|
| 207 |
-
return report.strip(), tmp2.name
|
| 208 |
-
|
| 209 |
-
# ── GRADIO INTERFACE ─────────────────────────────────────────
|
| 210 |
-
|
| 211 |
-
with gr.Blocks(title="AI Music & E-Commerce Analyzer", theme=gr.themes.Soft()) as demo:
|
| 212 |
-
|
| 213 |
-
gr.Markdown("""
|
| 214 |
-
# 🤖 AI Performance Analyzer
|
| 215 |
-
### Amazon Products × Spotify Tracks
|
| 216 |
-
*Predicting commercial success using Machine Learning & Sentiment Analysis*
|
| 217 |
-
""")
|
| 218 |
-
|
| 219 |
-
with gr.Tabs():
|
| 220 |
-
|
| 221 |
-
# ── AMAZON TAB
|
| 222 |
-
with gr.TabItem("🛒 Amazon Product"):
|
| 223 |
-
gr.Markdown("### Analyze an Amazon product's performance potential")
|
| 224 |
-
with gr.Row():
|
| 225 |
-
with gr.Column():
|
| 226 |
-
amz_category = gr.Dropdown(
|
| 227 |
-
['Electronics','Clothing','HomeKitchen','Books','Sports','Beauty','Toys'],
|
| 228 |
-
label="Category", value="Electronics")
|
| 229 |
-
amz_actual = gr.Slider(50, 50000, value=999, label="Actual Price (₹)")
|
| 230 |
-
amz_discount = gr.Slider(0, 80, value=30, label="Discount %")
|
| 231 |
-
amz_rating = gr.Slider(1.0, 5.0, value=4.2, step=0.1, label="Rating (/5)")
|
| 232 |
-
amz_review = gr.Textbox(label="Sample Review Text",
|
| 233 |
-
value="Great product, works perfectly and fast delivery!",
|
| 234 |
-
lines=2)
|
| 235 |
-
amz_btn = gr.Button("Analyze Product", variant="primary")
|
| 236 |
-
with gr.Column():
|
| 237 |
-
amz_output = gr.Textbox(label="Analysis Report", lines=20)
|
| 238 |
-
amz_plot = gr.Image(label="Performance Chart", type="filepath")
|
| 239 |
-
|
| 240 |
-
amz_btn.click(analyze_amazon,
|
| 241 |
-
inputs=[amz_category, amz_actual, amz_discount, amz_rating, amz_review],
|
| 242 |
-
outputs=[amz_output, amz_plot])
|
| 243 |
-
|
| 244 |
-
# ── SPOTIFY TAB
|
| 245 |
-
with gr.TabItem("🎵 Spotify Track"):
|
| 246 |
-
gr.Markdown("### Predict a track's commercial success on Spotify")
|
| 247 |
-
with gr.Row():
|
| 248 |
-
with gr.Column():
|
| 249 |
-
sp_genre = gr.Dropdown(
|
| 250 |
-
['pop','hip-hop','rock','electronic','jazz','r-n-b','country','latin','indie','classical'],
|
| 251 |
-
label="Genre", value="pop")
|
| 252 |
-
sp_dance = gr.Slider(0.0, 1.0, value=0.7, step=0.01, label="Danceability")
|
| 253 |
-
sp_energy = gr.Slider(0.0, 1.0, value=0.8, step=0.01, label="Energy")
|
| 254 |
-
sp_loud = gr.Slider(-40, 0, value=-7, step=0.5, label="Loudness (dB)")
|
| 255 |
-
sp_tempo = gr.Slider(60, 200, value=120, step=1, label="Tempo (BPM)")
|
| 256 |
-
sp_val = gr.Slider(0.0, 1.0, value=0.6, step=0.01, label="Valence (positivity)")
|
| 257 |
-
sp_acou = gr.Slider(0.0, 1.0, value=0.1, step=0.01, label="Acousticness")
|
| 258 |
-
sp_speech = gr.Slider(0.0, 1.0, value=0.05, step=0.01, label="Speechiness")
|
| 259 |
-
sp_instr = gr.Slider(0.0, 1.0, value=0.0, step=0.01, label="Instrumentalness")
|
| 260 |
-
sp_exp = gr.Checkbox(label="Explicit content", value=False)
|
| 261 |
-
sp_btn = gr.Button("Analyze Track", variant="primary")
|
| 262 |
-
with gr.Column():
|
| 263 |
-
sp_output = gr.Textbox(label="Analysis Report", lines=20)
|
| 264 |
-
sp_plot = gr.Image(label="Track Performance Chart", type="filepath")
|
| 265 |
-
|
| 266 |
-
sp_btn.click(analyze_spotify,
|
| 267 |
-
inputs=[sp_genre, sp_dance, sp_energy, sp_loud, sp_tempo,
|
| 268 |
-
sp_val, sp_acou, sp_speech, sp_instr, sp_exp],
|
| 269 |
-
outputs=[sp_output, sp_plot])
|
| 270 |
-
|
| 271 |
-
if __name__ == "__main__":
|
| 272 |
-
demo.launch(share=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|