File size: 6,097 Bytes
4f92a9b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c5e5f2b
 
 
 
 
 
 
 
4f92a9b
c5e5f2b
7dfabe3
4f92a9b
 
 
7dfabe3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
from flask import Flask, request, jsonify
from flask_cors import CORS
import pickle
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import json

app = Flask(__name__)
CORS(app)


import os
similarity_matrix = None
model_path = 'model/events_similarity.pkl'
if os.path.exists(model_path):
    try:
        with open(model_path, 'rb') as f:
            similarity_matrix = pickle.load(f)
        print("Loaded pre-trained similarity matrix")
    except Exception as e:
        similarity_matrix = None
        print(f"Error loading similarity matrix: {e}")
else:
    print("No pre-trained model found, using dynamic calculation")

@app.route('/recommend', methods=['POST'])
def recommend_events():
    try:
        data = request.json
        
        user_profile = data.get('userProfile', {})
        available_events = data.get('availableEvents', [])
        limit = data.get('limit', 10)
        
        if not available_events:
            return jsonify({
                'recommendations': [],
                'message': 'No events available for recommendation'
            })
        
        # Extract user interests and event features
        user_interests = user_profile.get('interests', [])
        user_skills = user_profile.get('skills', [])
        attended_events = user_profile.get('attendedEvents', [])
        
        # Create user profile vector
        user_profile_text = ' '.join(user_interests + user_skills)
        
        # Create event feature vectors
        event_features = []
        for event in available_events:
            event_text = f"{event.get('title', '')} {event.get('description', '')} {' '.join(event.get('tags', []))} {event.get('type', '')} {event.get('organizer', '')}"
            event_features.append(event_text)
        
        # Calculate similarity using TF-IDF and cosine similarity
        if event_features:
            vectorizer = TfidfVectorizer(stop_words='english', max_features=1000)
            event_vectors = vectorizer.fit_transform(event_features)
            
            # Add user profile to the vector space
            user_vector = vectorizer.transform([user_profile_text])
            
            # Calculate similarities
            similarities = cosine_similarity(user_vector, event_vectors).flatten()
            
            # Create recommendations
            recommendations = []
            for i, event in enumerate(available_events):
                similarity_score = float(similarities[i])
                
                # Boost score based on user history
                if event.get('organizer') in [e.get('organizer') for e in attended_events]:
                    similarity_score += 0.2
                
                if event.get('type') in user_interests:
                    similarity_score += 0.3
                
                # Add common tags bonus
                event_tags = set(event.get('tags', []))
                user_interest_tags = set(user_interests)
                common_tags = event_tags.intersection(user_interest_tags)
                similarity_score += len(common_tags) * 0.1
                
                recommendations.append({
                    'eventId': event.get('eventId'),
                    'similarityScore': round(similarity_score, 3),
                    'reason': _get_recommendation_reason(event, user_profile, similarity_score)
                })
            
            # Sort by similarity score and return top recommendations
            recommendations.sort(key=lambda x: x['similarityScore'], reverse=True)
            recommendations = recommendations[:limit]
            
            return jsonify({
                'recommendations': recommendations,
                'message': 'Recommendations generated successfully'
            })
        else:
            return jsonify({
                'recommendations': [],
                'message': 'No event features available'
            })
            
    except Exception as e:
        return jsonify({
            'error': f'Error generating recommendations: {str(e)}',
            'recommendations': []
        }), 500

def _get_recommendation_reason(event, user_profile, similarity_score):
    reasons = []
    
    user_interests = user_profile.get('interests', [])
    attended_events = user_profile.get('attendedEvents', [])
    
    # Check for interest matches
    event_tags = set(event.get('tags', []))
    user_interest_tags = set(user_interests)
    common_tags = event_tags.intersection(user_interest_tags)
    
    if common_tags:
        reasons.append(f"Matches your interests: {', '.join(common_tags)}")
    
    if event.get('type') in user_interests:
        reasons.append(f"Matches your preferred event type: {event.get('type')}")
    
    # Check for organizer preference
    if event.get('organizer') in [e.get('organizer') for e in attended_events]:
        reasons.append(f"From organizer you've attended before: {event.get('organizer')}")
    
    if similarity_score > 0.5:
        reasons.append("High similarity to your profile")
    elif similarity_score > 0.2:
        reasons.append("Moderate similarity to your profile")
    else:
        reasons.append("Popular event")
    
    return '; '.join(reasons) if reasons else "Recommended for you"

@app.route('/health', methods=['GET'])
def health_check():
    return jsonify({
        'status': 'healthy',
        'service': 'ML Recommendation API',
        'model_loaded': similarity_matrix is not None
    })

@app.route('/', methods=['GET'])
def root():
    return jsonify({
        'message': 'ML Recommendation API',
        'version': '1.0.0',
        'status': 'healthy'
    })

if __name__ == '__main__':
    port = int(os.environ.get('PORT', 7860))
    print(f"Starting ML Recommendation API server on port {port}...")
    print("Available endpoints:")
    print("- POST /recommend: Generate event recommendations")
    print("- GET /health: Health check")
    app.run(host='0.0.0.0', port=port, debug=False)