1616from dotenv import load_dotenv
1717from openai import OpenAI
1818
19+ from shared .constants .emojis import EMOJI_CATEGORIES
20+
1921logger = logging .getLogger (__name__ )
2022
2123
@@ -224,8 +226,11 @@ def extract_events_from_caption(
224226 # Return default structure if API call fails
225227 return [_get_default_event_structure (source_image_url )]
226228
227- def generate_recommended_filters (self , events_data : list [dict ]) -> list [str ]:
228- """Generate recommended filter keywords from upcoming events data using GPT"""
229+ def generate_recommended_filters (self , events_data : list [dict ]) -> list [list [str ]]:
230+ """Generate recommended filter keywords with emojis from upcoming events data using GPT
231+
232+ Returns a list of 3-element arrays: [category, emoji_string, filter_name]
233+ """
229234 if not events_data :
230235 logger .warning ("No events data provided for filter generation" )
231236 return []
@@ -240,21 +245,44 @@ def generate_recommended_filters(self, events_data: list[dict]) -> list[str]:
240245 summary += f" [type: { event .get ('club_type' )} ]"
241246 event_summaries .append (summary )
242247
248+ # Get the categorized emoji list for the prompt
249+ emoji_categories = EMOJI_CATEGORIES
250+ emoji_list_str = ""
251+ for category , emojis in emoji_categories .items ():
252+ emoji_list_str += f"\n { category } :\n "
253+ emoji_list_str += ", " .join (emojis ) + "\n "
254+
243255 prompt = f"""
244- Analyze the following list of { len (event_summaries )} upcoming student events and generate 20-25 search filter keywords.
256+ Analyze the following list of { len (event_summaries )} upcoming student events and generate 20-25 search filter keywords with matching emojis .
245257
246258Events:
247259{ chr (10 ).join (event_summaries )}
248260
261+ Available emojis organized by category (select the most fitting one for each filter):
262+ { emoji_list_str }
263+
249264Generate filter keywords that:
2502651. Capture the most common themes students care about (networking, meeting people, large events, food, professional development, etc.)
2512662. Are SHORT (1-3 words max) and SPECIFIC
2522673. Reflect actual patterns in the event data above
2532684. Focus on: event types, activities, professional topics, food/drinks, social aspects, clubs/organizations
2542695. Are diverse enough to cover different student interests
255270
256- Return ONLY a JSON array of 20-25 keyword strings, like:
257- ["networking", "free food", "career fair", "live music", "workshop", ...]
271+ For each filter, select the MOST FITTING emoji from the available list above.
272+
273+ Return ONLY a JSON array of arrays, where each inner array has exactly 3 elements:
274+ - Index 0: The category name (exactly as it appears in the categories above)
275+ - Index 1: The emoji name (exactly as it appears in the available list above)
276+ - Index 2: The filter name (string)
277+
278+ Example format:
279+ [
280+ ["Smileys", "Grinning%20Face", "networking"],
281+ ["Food%20and%20Drink", "Pizza", "free food"],
282+ ["Objects", "Graduation%20Cap", "career fair"],
283+ ["Objects", "Musical%20Note", "live music"],
284+ ["Objects", "Books", "workshop"]
285+ ]
258286
259287NO explanations, NO additional text, JUST the JSON array.
260288"""
@@ -269,12 +297,12 @@ def generate_recommended_filters(self, events_data: list[dict]) -> list[str]:
269297 messages = [
270298 {
271299 "role" : "system" ,
272- "content" : "You are a helpful assistant that generates search keywords. Always return valid JSON arrays." ,
300+ "content" : "You are a helpful assistant that generates search keywords with emojis . Always return valid JSON arrays with the exact structure requested ." ,
273301 },
274302 {"role" : "user" , "content" : prompt },
275303 ],
276304 temperature = 0.3 ,
277- max_tokens = 300 ,
305+ max_tokens = 15000 ,
278306 )
279307
280308 response_text = response .choices [0 ].message .content .strip ()
@@ -292,14 +320,24 @@ def generate_recommended_filters(self, events_data: list[dict]) -> list[str]:
292320 return []
293321
294322 # Clean and validate filters
295- cleaned_filters = [
296- str (f ).strip ()
297- for f in filters
298- if f and isinstance (f , str ) and len (str (f ).strip ()) > 0
299- ]
300-
301- logger .info (f"Generated { len (cleaned_filters )} recommended filters" )
302- return list (set (cleaned_filters ))[:25 ]
323+ cleaned_filters = []
324+ for filter_item in filters :
325+ if (isinstance (filter_item , list ) and
326+ len (filter_item ) == 3 and
327+ isinstance (filter_item [0 ], str ) and
328+ isinstance (filter_item [1 ], str ) and
329+ isinstance (filter_item [2 ], str ) and
330+ filter_item [0 ].strip () and
331+ filter_item [1 ].strip () and
332+ filter_item [2 ].strip ()):
333+ cleaned_filters .append ([
334+ filter_item [0 ].strip (), # category
335+ filter_item [1 ].strip (), # emoji_string
336+ filter_item [2 ].strip () # filter_name
337+ ])
338+
339+ logger .info (f"Generated { len (cleaned_filters )} recommended filters with emojis" )
340+ return cleaned_filters [:15 ]
303341
304342 except json .JSONDecodeError :
305343 logger .exception ("Error parsing JSON response for filters" )
0 commit comments