ShubhamSetia commited on
Commit
b1ec794
ยท
1 Parent(s): 2e86bf2

add beautifulsoup4 dependency and update output formatting for research mcp

Browse files
mcp_servers/research/provider.py CHANGED
@@ -460,31 +460,48 @@ class MessageGeneratorTool(BaseTool):
460
  def _generate_template_message(
461
  self, occasion: str, recipient: str, tone: str, details: str
462
  ) -> str:
463
- """Generate message using templates."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
464
  templates = {
465
  "birthday": [
466
- f"๐ŸŽ‚ Happy Birthday, {recipient}! ๐ŸŽ‰\n\nWishing you a day filled with joy, laughter, and all your favorite things. May this year bring you endless happiness and amazing adventures!\n\nCheers to you! ๐Ÿฅณ",
467
- f"๐ŸŽˆ Happy Birthday, {recipient}!\n\nAnother year older, another year wiser, and definitely another year more awesome! Hope your special day is as wonderful as you are.\n\nEnjoy your day! ๐ŸŽ",
468
- ],
469
- "party invitation": [
470
- f"๐ŸŽ‰ You're Invited!\n\nHey {recipient}!\n\nWe're throwing a celebration and it wouldn't be the same without you! Join us for an unforgettable time.\n\n{details if details else 'Details to follow!'}\n\nHope to see you there! ๐Ÿฅณ",
471
  ],
472
  "thank you": [
473
  f"Dear {recipient},\n\nThank you so much for being part of our celebration! Your presence made the day even more special.\n\nWith gratitude,\nโค๏ธ",
474
  ],
475
  }
476
 
477
- occasion_lower = occasion.lower()
478
  for key, msgs in templates.items():
479
  if key in occasion_lower:
480
  return msgs[0]
481
 
482
- # Default template
483
  return (
 
484
  f"Dear {recipient},\n\n"
485
- f"You're invited to celebrate with us! "
486
- f"{'Details: ' + details if details else 'More details coming soon.'}\n\n"
487
- f"Looking forward to seeing you!\n๐ŸŽ‰"
 
488
  )
489
 
490
  def get_schema(self) -> Dict[str, Any]:
@@ -746,16 +763,9 @@ Maximum 3 tool calls per response."""
746
  "params": {"query": f"how to plan {state.idea} party ideas activities guide"}
747
  })
748
 
749
- # Search for specific supplies based on highlights
750
- amazon_terms = [idea_themes]
751
- if idea_highlights:
752
- # Extract shopping-related terms from highlights
753
- for highlight in idea_highlights[:2]:
754
- highlight_lower = highlight.lower()
755
- if any(word in highlight_lower for word in ["station", "kit", "supplies", "decor", "activity"]):
756
- amazon_terms.append(highlight[:30])
757
-
758
- amazon_query = " ".join(amazon_terms[:3]) + " party supplies"
759
  calls.append({
760
  "tool": "amazon_search",
761
  "params": {"query": amazon_query}
@@ -763,20 +773,20 @@ Maximum 3 tool calls per response."""
763
 
764
  # Generate invitation message with more context
765
  invite_details = []
766
- if state.context.get("location"):
767
- invite_details.append(f"Location: {state.context['location']}")
768
  if state.context.get("event_date"):
769
  invite_details.append(f"Date: {state.context['event_date']}")
770
- if state.occasion:
771
- invite_details.append(f"Occasion: {state.occasion}")
 
 
772
 
773
  calls.append({
774
  "tool": "generate_message",
775
  "params": {
776
- "occasion": f"{state.occasion or 'party'} invitation for {state.idea}",
777
- "recipient": "Guest",
778
  "tone": "fun and exciting",
779
- "details": ". ".join(invite_details) if invite_details else "at my place"
780
  }
781
  })
782
 
@@ -1136,12 +1146,8 @@ Be specific, practical, and enthusiastic!"""
1136
  # Extract overview from synthesized text
1137
  overview = final_text[:800] if len(final_text) > 800 else final_text
1138
 
1139
- # Build steps - prefer idea's next_steps if available
1140
- steps = []
1141
- if state.idea_details and state.idea_details.get("next_steps"):
1142
- steps = state.idea_details["next_steps"]
1143
- else:
1144
- steps = self._extract_steps_from_text(final_text)
1145
 
1146
  # Build references (combined sources and links)
1147
  references = [
@@ -1218,6 +1224,56 @@ Be specific, practical, and enthusiastic!"""
1218
 
1219
  return "Completed"
1220
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1221
  def _extract_steps_from_text(self, text: str) -> List[str]:
1222
  """Extract actionable steps from synthesized text."""
1223
  steps = []
@@ -1232,17 +1288,7 @@ Be specific, practical, and enthusiastic!"""
1232
  if clean_line and len(clean_line) > 10:
1233
  steps.append(clean_line[:100])
1234
 
1235
- # If no steps found, create default ones
1236
- if not steps:
1237
- steps = [
1238
- "Review the plan and customize for your needs",
1239
- "Purchase necessary supplies and decorations",
1240
- "Send invitations to guests",
1241
- "Prepare the venue and activities",
1242
- "Enjoy the celebration!"
1243
- ]
1244
-
1245
- return steps[:8] # Limit to 8 steps
1246
 
1247
  def _get_web_sources(self, state: AgentState) -> List[Dict[str, str]]:
1248
  """Extract web sources from tool results."""
 
460
  def _generate_template_message(
461
  self, occasion: str, recipient: str, tone: str, details: str
462
  ) -> str:
463
+ """Generate message using templates - always creates INVITATIONS for parties."""
464
+ occasion_lower = occasion.lower()
465
+
466
+ # For party invitations, always use invitation template
467
+ if "invitation" in occasion_lower or "party" in occasion_lower:
468
+ # Extract the party theme from occasion
469
+ theme = occasion.replace("invitation", "").replace("party", "").replace("for", "").strip()
470
+ if not theme:
471
+ theme = "our special celebration"
472
+
473
+ return (
474
+ f"๐ŸŽ‰ You're Invited to {theme}! ๐ŸŽ‰\n\n"
475
+ f"Dear {recipient},\n\n"
476
+ f"Get ready for an amazing celebration! We're hosting {theme} and it wouldn't be "
477
+ f"the same without you.\n\n"
478
+ f"๐Ÿ“… {details if details else 'Date & Time: TBD'}\n\n"
479
+ f"Please RSVP by [date] so we can plan accordingly.\n\n"
480
+ f"Can't wait to celebrate with you!\n"
481
+ f"๐Ÿฅณ See you there!"
482
+ )
483
+
484
  templates = {
485
  "birthday": [
486
+ f"๐ŸŽ‚ Happy Birthday Celebration! ๐ŸŽ‰\n\nDear {recipient},\n\nYou're invited to a special birthday celebration!\n\n{details if details else 'Details coming soon!'}\n\nJoin us for fun, food, and festivities!\n\nRSVP: [contact]\n๐ŸŽˆ Hope to see you there!",
 
 
 
 
487
  ],
488
  "thank you": [
489
  f"Dear {recipient},\n\nThank you so much for being part of our celebration! Your presence made the day even more special.\n\nWith gratitude,\nโค๏ธ",
490
  ],
491
  }
492
 
 
493
  for key, msgs in templates.items():
494
  if key in occasion_lower:
495
  return msgs[0]
496
 
497
+ # Default invitation template
498
  return (
499
+ f"๐ŸŽ‰ You're Invited!\n\n"
500
  f"Dear {recipient},\n\n"
501
+ f"We're hosting a special celebration and would love for you to join us!\n\n"
502
+ f"{'๐Ÿ“… ' + details if details else '๐Ÿ“… Details to follow!'}\n\n"
503
+ f"Please let us know if you can make it.\n\n"
504
+ f"Looking forward to celebrating with you!\n๐Ÿฅณ"
505
  )
506
 
507
  def get_schema(self) -> Dict[str, Any]:
 
763
  "params": {"query": f"how to plan {state.idea} party ideas activities guide"}
764
  })
765
 
766
+ # Search for specific supplies based on idea title and highlights
767
+ # Use the full idea name for more specific results
768
+ amazon_query = f"{state.idea} party supplies decorations"
 
 
 
 
 
 
 
769
  calls.append({
770
  "tool": "amazon_search",
771
  "params": {"query": amazon_query}
 
773
 
774
  # Generate invitation message with more context
775
  invite_details = []
 
 
776
  if state.context.get("event_date"):
777
  invite_details.append(f"Date: {state.context['event_date']}")
778
+ if state.context.get("location"):
779
+ invite_details.append(f"Location: {state.context['location']}")
780
+ if state.honoree and state.honoree.get("guest_count"):
781
+ invite_details.append(f"Expected guests: {state.honoree['guest_count']}")
782
 
783
  calls.append({
784
  "tool": "generate_message",
785
  "params": {
786
+ "occasion": f"party invitation for {state.idea}",
787
+ "recipient": "Friend",
788
  "tone": "fun and exciting",
789
+ "details": "\n".join(invite_details) if invite_details else "Details to be announced"
790
  }
791
  })
792
 
 
1146
  # Extract overview from synthesized text
1147
  overview = final_text[:800] if len(final_text) > 800 else final_text
1148
 
1149
+ # Build detailed, actionable steps
1150
+ steps = self._build_actionable_steps(state, final_text)
 
 
 
 
1151
 
1152
  # Build references (combined sources and links)
1153
  references = [
 
1224
 
1225
  return "Completed"
1226
 
1227
+ def _build_actionable_steps(self, state: AgentState, synthesis_text: str) -> List[str]:
1228
+ """Build detailed, actionable steps with timing and specific guidance."""
1229
+ idea_name = state.idea
1230
+
1231
+ # Get idea-specific steps if available
1232
+ idea_steps = []
1233
+ if state.idea_details and state.idea_details.get("next_steps"):
1234
+ idea_steps = state.idea_details["next_steps"]
1235
+
1236
+ # Extract any steps from synthesis text
1237
+ extracted_steps = self._extract_steps_from_text(synthesis_text)
1238
+
1239
+ # Build comprehensive action plan - mix generic timeline with specific tasks
1240
+ planning_steps = []
1241
+
1242
+ # Phase 1: Planning (2 weeks before)
1243
+ planning_steps.append(f"๐Ÿ“‹ **2 weeks before**: Create your guest list and budget for {idea_name}")
1244
+ if idea_steps and len(idea_steps) > 0:
1245
+ planning_steps.append(f"โœ‰๏ธ **2 weeks before**: {idea_steps[0]}")
1246
+ else:
1247
+ planning_steps.append(f"โœ‰๏ธ **2 weeks before**: Design and send themed invitations")
1248
+
1249
+ # Phase 2: Preparation (1 week before)
1250
+ planning_steps.append(f"๐Ÿ›’ **1 week before**: Order supplies from the shopping list below")
1251
+ if idea_steps and len(idea_steps) > 1:
1252
+ planning_steps.append(f"๐Ÿฝ๏ธ **1 week before**: {idea_steps[1]}")
1253
+ else:
1254
+ planning_steps.append(f"๐Ÿฝ๏ธ **1 week before**: Plan themed menu and drinks")
1255
+
1256
+ # Phase 3: Final prep (3-4 days before)
1257
+ if idea_steps and len(idea_steps) > 2:
1258
+ planning_steps.append(f"๐ŸŽฎ **3-4 days before**: {idea_steps[2]}")
1259
+ else:
1260
+ planning_steps.append(f"๐ŸŽฎ **3-4 days before**: Prepare games, activities, and entertainment")
1261
+
1262
+ # Phase 4: Setup and event
1263
+ planning_steps.append(f"๐Ÿ  **1 day before**: Set up decorations and prepare the venue")
1264
+ planning_steps.append(f"โœ… **Day of event**: Final walkthrough, welcome guests, and enjoy!")
1265
+
1266
+ # Add tips from web research
1267
+ if extracted_steps:
1268
+ for step in extracted_steps[:2]:
1269
+ if step and len(step) > 15:
1270
+ # Only add if it's genuinely new info
1271
+ step_lower = step.lower()
1272
+ if not any(kw in step_lower for kw in ["guest list", "invitation", "decoration", "menu"]):
1273
+ planning_steps.append(f"๐Ÿ’ก **Pro tip**: {step[:80]}")
1274
+
1275
+ return planning_steps[:9] # Limit to 9 steps
1276
+
1277
  def _extract_steps_from_text(self, text: str) -> List[str]:
1278
  """Extract actionable steps from synthesized text."""
1279
  steps = []
 
1288
  if clean_line and len(clean_line) > 10:
1289
  steps.append(clean_line[:100])
1290
 
1291
+ return steps[:5]
 
 
 
 
 
 
 
 
 
 
1292
 
1293
  def _get_web_sources(self, state: AgentState) -> List[Dict[str, str]]:
1294
  """Extract web sources from tool results."""
requirements.txt CHANGED
@@ -6,3 +6,4 @@ httpx
6
  ddgs
7
  langgraph>=1.0.0
8
  langchain-core>=1.1.0
 
 
6
  ddgs
7
  langgraph>=1.0.0
8
  langchain-core>=1.1.0
9
+ beautifulsoup4