Spaces:
Sleeping
Sleeping
API
Browse files
app.py
CHANGED
@@ -43,6 +43,10 @@ try:
|
|
43 |
excel_content.seek(0) # Reset buffer position
|
44 |
customer_profiles = pd.read_excel(excel_content, sheet_name='Customer Profile (Individual)')
|
45 |
|
|
|
|
|
|
|
|
|
46 |
logger.info("Successfully downloaded and loaded Excel file")
|
47 |
|
48 |
# Process the data
|
@@ -59,6 +63,13 @@ try:
|
|
59 |
numerical_features = ['Age', 'Income per year (in dollars)'] # Add or modify based on your actual columns
|
60 |
scaler = StandardScaler()
|
61 |
customer_profiles[numerical_features] = scaler.fit_transform(customer_profiles[numerical_features])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
|
63 |
logger.info("Data processing completed successfully")
|
64 |
|
@@ -353,4 +364,163 @@ async def get_customer_content_recommendations(customer_id: str, n: int = 5):
|
|
353 |
raise HTTPException(
|
354 |
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
355 |
detail=f"Error processing request: {str(e)}"
|
356 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
excel_content.seek(0) # Reset buffer position
|
44 |
customer_profiles = pd.read_excel(excel_content, sheet_name='Customer Profile (Individual)')
|
45 |
|
46 |
+
# Read Social Media Sentiment
|
47 |
+
excel_content.seek(0) # Reset buffer position
|
48 |
+
customer_Media = pd.read_excel(excel_content, sheet_name='Social Media Sentiment',parse_dates=['Timestamp'])
|
49 |
+
|
50 |
logger.info("Successfully downloaded and loaded Excel file")
|
51 |
|
52 |
# Process the data
|
|
|
63 |
numerical_features = ['Age', 'Income per year (in dollars)'] # Add or modify based on your actual columns
|
64 |
scaler = StandardScaler()
|
65 |
customer_profiles[numerical_features] = scaler.fit_transform(customer_profiles[numerical_features])
|
66 |
+
|
67 |
+
# Process the data media
|
68 |
+
customer_Media['Customer_Id'] = customer_Media['Customer_Id'].astype(str)
|
69 |
+
tweet_categories = customer_Media[['Post_Id', 'Platform']].drop_duplicates().set_index('Post_Id')['Platform'].to_dict()
|
70 |
+
tweet_counts = customer_Media.groupby(['Customer_Id', 'Post_Id']).size().unstack(fill_value=0)
|
71 |
+
sparse_tweet_counts = sparse.csr_matrix(tweet_counts)
|
72 |
+
cosine_similarities_tweet = cosine_similarity(sparse_tweet_counts.T)
|
73 |
|
74 |
logger.info("Data processing completed successfully")
|
75 |
|
|
|
364 |
raise HTTPException(
|
365 |
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
366 |
detail=f"Error processing request: {str(e)}"
|
367 |
+
)
|
368 |
+
|
369 |
+
@app.get("/social-sentiment/{customer_id}")
|
370 |
+
async def get_social_sentiment(customer_id: str):
|
371 |
+
"""
|
372 |
+
Get social media sentiment analysis for a customer
|
373 |
+
|
374 |
+
Parameters:
|
375 |
+
- customer_id: The ID of the customer
|
376 |
+
|
377 |
+
Returns:
|
378 |
+
- JSON object containing sentiment analysis and insights
|
379 |
+
"""
|
380 |
+
try:
|
381 |
+
# Validate customer
|
382 |
+
if customer_id not in customer_Media['Customer_Id'].unique():
|
383 |
+
raise HTTPException(
|
384 |
+
status_code=status.HTTP_404_NOT_FOUND,
|
385 |
+
detail="No social media data found for this customer"
|
386 |
+
)
|
387 |
+
|
388 |
+
# Get customer's social media data
|
389 |
+
customer_posts = customer_Media[customer_Media['Customer_Id'] == customer_id]
|
390 |
+
|
391 |
+
# Calculate sentiment metrics
|
392 |
+
avg_sentiment = customer_posts['Sentiment_Score'].mean()
|
393 |
+
recent_sentiment = customer_posts.sort_values('Timestamp', ascending=False)['Sentiment_Score'].iloc[0]
|
394 |
+
|
395 |
+
# Calculate sentiment trend
|
396 |
+
customer_posts['Timestamp'] = pd.to_datetime(customer_posts['Timestamp'])
|
397 |
+
sentiment_trend = customer_posts.sort_values('Timestamp')
|
398 |
+
|
399 |
+
# Platform breakdown
|
400 |
+
platform_stats = customer_posts.groupby('Platform').agg({
|
401 |
+
'Post_Id': 'count',
|
402 |
+
'Sentiment_Score': 'mean'
|
403 |
+
}).round(2)
|
404 |
+
|
405 |
+
platform_breakdown = [
|
406 |
+
{
|
407 |
+
"platform": platform,
|
408 |
+
"post_count": int(stats['Post_Id']),
|
409 |
+
"avg_sentiment": float(stats['Sentiment_Score'])
|
410 |
+
}
|
411 |
+
for platform, stats in platform_stats.iterrows()
|
412 |
+
]
|
413 |
+
|
414 |
+
# Intent analysis
|
415 |
+
intent_distribution = customer_posts['Intent'].value_counts().to_dict()
|
416 |
+
|
417 |
+
# Get most recent posts with sentiments
|
418 |
+
recent_posts = customer_posts.sort_values('Timestamp', ascending=False).head(5)
|
419 |
+
recent_activities = [
|
420 |
+
{
|
421 |
+
"timestamp": post['Timestamp'].strftime('%Y-%m-%d %H:%M:%S'),
|
422 |
+
"platform": post['Platform'],
|
423 |
+
"content": post['Content'],
|
424 |
+
"sentiment_score": float(post['Sentiment_Score']),
|
425 |
+
"intent": post['Intent']
|
426 |
+
}
|
427 |
+
for _, post in recent_posts.iterrows()
|
428 |
+
]
|
429 |
+
|
430 |
+
# Calculate sentiment categories
|
431 |
+
sentiment_categories = {
|
432 |
+
"positive": len(customer_posts[customer_posts['Sentiment_Score'] > 0.5]),
|
433 |
+
"neutral": len(customer_posts[(customer_posts['Sentiment_Score'] >= -0.5) &
|
434 |
+
(customer_posts['Sentiment_Score'] <= 0.5)]),
|
435 |
+
"negative": len(customer_posts[customer_posts['Sentiment_Score'] < -0.5])
|
436 |
+
}
|
437 |
+
|
438 |
+
# Determine overall mood
|
439 |
+
if avg_sentiment > 0.5:
|
440 |
+
overall_mood = "Positive"
|
441 |
+
elif avg_sentiment < -0.5:
|
442 |
+
overall_mood = "Negative"
|
443 |
+
else:
|
444 |
+
overall_mood = "Neutral"
|
445 |
+
|
446 |
+
# Generate insights
|
447 |
+
insights = []
|
448 |
+
|
449 |
+
# Trend insight
|
450 |
+
sentiment_change = recent_sentiment - customer_posts['Sentiment_Score'].iloc[0]
|
451 |
+
if abs(sentiment_change) > 0.3:
|
452 |
+
trend_direction = "improved" if sentiment_change > 0 else "declined"
|
453 |
+
insights.append(f"Customer sentiment has {trend_direction} over time")
|
454 |
+
|
455 |
+
# Platform insight
|
456 |
+
if len(platform_stats) > 1:
|
457 |
+
best_platform = platform_stats['Sentiment_Score'].idxmax()
|
458 |
+
insights.append(f"Customer shows most positive engagement on {best_platform}")
|
459 |
+
|
460 |
+
# Engagement insight
|
461 |
+
if len(recent_activities) > 0:
|
462 |
+
recent_avg = sum(post['sentiment_score'] for post in recent_activities) / len(recent_activities)
|
463 |
+
if abs(recent_avg - avg_sentiment) > 0.3:
|
464 |
+
trend = "improving" if recent_avg > avg_sentiment else "declining"
|
465 |
+
insights.append(f"Recent sentiment is {trend} compared to overall average")
|
466 |
+
|
467 |
+
return {
|
468 |
+
"customer_id": customer_id,
|
469 |
+
"overall_sentiment": {
|
470 |
+
"average_score": float(avg_sentiment),
|
471 |
+
"recent_score": float(recent_sentiment),
|
472 |
+
"overall_mood": overall_mood
|
473 |
+
},
|
474 |
+
"sentiment_distribution": sentiment_categories,
|
475 |
+
"platform_analysis": platform_breakdown,
|
476 |
+
"intent_analysis": intent_distribution,
|
477 |
+
"recent_activities": recent_activities,
|
478 |
+
"insights": insights,
|
479 |
+
"analysis_timestamp": datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
480 |
+
}
|
481 |
+
|
482 |
+
except HTTPException:
|
483 |
+
raise
|
484 |
+
except Exception as e:
|
485 |
+
logger.error(f"Error processing social sentiment for customer {customer_id}: {str(e)}")
|
486 |
+
raise HTTPException(
|
487 |
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
488 |
+
detail=f"Error processing request: {str(e)}"
|
489 |
+
)
|
490 |
+
|
491 |
+
# Add a combined endpoint for full customer analysis
|
492 |
+
@app.get("/customer-analysis/{customer_id}")
|
493 |
+
async def get_customer_analysis(customer_id: str):
|
494 |
+
"""
|
495 |
+
Get comprehensive customer analysis including recommendations and sentiment
|
496 |
+
|
497 |
+
Parameters:
|
498 |
+
- customer_id: The ID of the customer
|
499 |
+
|
500 |
+
Returns:
|
501 |
+
- JSON object containing full customer analysis
|
502 |
+
"""
|
503 |
+
try:
|
504 |
+
# Get content recommendations
|
505 |
+
content_recs = await get_customer_content_recommendations(customer_id)
|
506 |
+
|
507 |
+
# Get social sentiment
|
508 |
+
sentiment_analysis = await get_social_sentiment(customer_id)
|
509 |
+
|
510 |
+
# Get purchase recommendations
|
511 |
+
purchase_recs = await get_recommendations(customer_id)
|
512 |
+
|
513 |
+
return {
|
514 |
+
"customer_id": customer_id,
|
515 |
+
"sentiment_analysis": sentiment_analysis,
|
516 |
+
"content_recommendations": content_recs,
|
517 |
+
"purchase_recommendations": purchase_recs,
|
518 |
+
"analysis_timestamp": datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
519 |
+
}
|
520 |
+
|
521 |
+
except Exception as e:
|
522 |
+
logger.error(f"Error processing customer analysis for {customer_id}: {str(e)}")
|
523 |
+
raise HTTPException(
|
524 |
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
525 |
+
detail=f"Error processing request: {str(e)}"
|
526 |
+
)
|