Spaces:
Sleeping
Sleeping
Upload folder using huggingface_hub
Browse files- apps/app.py +278 -107
- apps/multiagent_draft.py +5 -5
- core/constants.py +1 -1
- core/dynamic_a2a_manager.py +20 -10
- core/simulated_a2a_manager.py +4 -3
- docs/FEATURES_AND_ENHANCEMENTS.md +20 -0
apps/app.py
CHANGED
|
@@ -66,6 +66,7 @@ class EnhancedFantasyDraftApp:
|
|
| 66 |
self.use_real_a2a = False
|
| 67 |
self.a2a_status = "Not initialized"
|
| 68 |
self.session_id = None
|
|
|
|
| 69 |
|
| 70 |
async def toggle_a2a_mode(self, use_a2a: bool):
|
| 71 |
"""Toggle between basic multiagent and A2A modes."""
|
|
@@ -96,8 +97,11 @@ class EnhancedFantasyDraftApp:
|
|
| 96 |
import uuid
|
| 97 |
self.session_id = str(uuid.uuid4())[:8]
|
| 98 |
|
| 99 |
-
# Create new dynamic manager for this session
|
| 100 |
-
self.a2a_manager = DynamicA2AAgentManager(
|
|
|
|
|
|
|
|
|
|
| 101 |
|
| 102 |
try:
|
| 103 |
await self.a2a_manager.start_agents()
|
|
@@ -606,64 +610,141 @@ def create_gradio_interface():
|
|
| 606 |
You'll be drafting at **Position 4** with these AI opponents:
|
| 607 |
""")
|
| 608 |
|
| 609 |
-
#
|
|
|
|
|
|
|
|
|
|
| 610 |
with gr.Row():
|
|
|
|
| 611 |
with gr.Column(scale=1):
|
| 612 |
-
gr.
|
| 613 |
-
|
| 614 |
-
|
| 615 |
-
|
| 616 |
-
|
| 617 |
-
|
| 618 |
-
|
| 619 |
-
|
| 620 |
-
|
| 621 |
-
|
| 622 |
-
|
| 623 |
-
|
| 624 |
-
|
| 625 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 626 |
|
|
|
|
| 627 |
with gr.Column(scale=1):
|
| 628 |
-
gr.
|
| 629 |
-
|
| 630 |
-
|
| 631 |
-
|
| 632 |
-
|
| 633 |
-
|
| 634 |
-
|
| 635 |
-
|
| 636 |
-
|
| 637 |
-
|
| 638 |
-
|
| 639 |
-
|
| 640 |
-
|
| 641 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 642 |
|
|
|
|
| 643 |
with gr.Column(scale=1):
|
| 644 |
-
gr.
|
| 645 |
-
|
| 646 |
-
|
| 647 |
-
|
| 648 |
-
|
| 649 |
-
|
| 650 |
-
|
| 651 |
-
|
| 652 |
-
|
| 653 |
-
|
| 654 |
-
|
| 655 |
-
|
| 656 |
-
|
| 657 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 658 |
|
|
|
|
| 659 |
with gr.Column(scale=1):
|
| 660 |
-
gr.
|
| 661 |
<div style="background-color: #E8EAF6; border-left: 4px solid #3F51B5; padding: 15px; border-radius: 8px;">
|
| 662 |
-
|
| 663 |
<h4 style="color: #1a237e; margin: 0 0 10px 0;">👤 Position 4 - YOU</h4>
|
| 664 |
-
|
| 665 |
<p style="color: #424242; font-style: italic; margin: 10px 0; font-size: 0.95em;">Your draft position with AI guidance</p>
|
| 666 |
-
|
| 667 |
<ul style="color: #424242; font-size: 0.9em; margin: 0; padding-left: 20px;">
|
| 668 |
<li style="color: #424242;">📕🧙 Strategic advisor</li>
|
| 669 |
<li style="color: #424242;">Real-time guidance</li>
|
|
@@ -672,37 +753,87 @@ def create_gradio_interface():
|
|
| 672 |
</div>
|
| 673 |
""")
|
| 674 |
|
|
|
|
| 675 |
with gr.Column(scale=1):
|
| 676 |
-
gr.
|
| 677 |
-
|
| 678 |
-
|
| 679 |
-
|
| 680 |
-
|
| 681 |
-
|
| 682 |
-
|
| 683 |
-
|
| 684 |
-
|
| 685 |
-
|
| 686 |
-
|
| 687 |
-
|
| 688 |
-
|
| 689 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 690 |
|
|
|
|
| 691 |
with gr.Column(scale=1):
|
| 692 |
-
gr.
|
| 693 |
-
|
| 694 |
-
|
| 695 |
-
|
| 696 |
-
|
| 697 |
-
|
| 698 |
-
|
| 699 |
-
|
| 700 |
-
|
| 701 |
-
|
| 702 |
-
|
| 703 |
-
|
| 704 |
-
|
| 705 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 706 |
|
| 707 |
gr.Markdown("""
|
| 708 |
### 🎮 Draft Format
|
|
@@ -849,34 +980,6 @@ def create_gradio_interface():
|
|
| 849 |
- Strategies adapt based on draft flow
|
| 850 |
- Visual memory indicators show retention
|
| 851 |
""")
|
| 852 |
-
|
| 853 |
-
gr.Markdown("""
|
| 854 |
-
### 🎯 Key Features Demonstrated
|
| 855 |
-
|
| 856 |
-
1. **Persistent Context**: Each agent remembers all previous interactions
|
| 857 |
-
2. **Strategic Personalities**: 5 distinct draft strategies competing
|
| 858 |
-
3. **Dynamic Adaptation**: Agents adjust based on draft progression
|
| 859 |
-
4. **Natural Dialogue**: Human-like commentary and debates
|
| 860 |
-
5. **User Integration**: Seamless human participation with AI guidance
|
| 861 |
-
6. **A2A Communication**: Toggle between basic multiagent and distributed A2A modes
|
| 862 |
-
|
| 863 |
-
### 📝 Implementation Details
|
| 864 |
-
|
| 865 |
-
- **Agent Classes**: Inheritance-based design with base `DraftAgent`
|
| 866 |
-
- **Message Formatting**: Custom HTML/CSS for visual distinction
|
| 867 |
-
- **State Management**: Draft board tracking and validation
|
| 868 |
-
- **Memory Indicators**: Visual cues showing context retention
|
| 869 |
-
- **A2A Protocol**: Uses any-agent's a2a_tool_async for distributed communication
|
| 870 |
-
|
| 871 |
-
### 🚀 Why This Matters
|
| 872 |
-
|
| 873 |
-
This demo proves that sophisticated multi-agent systems can be built with minimal code,
|
| 874 |
-
showcasing the power of modern LLMs when properly orchestrated. The any-agent framework
|
| 875 |
-
makes it easy to create agents that truly communicate and remember, not just respond.
|
| 876 |
-
|
| 877 |
-
The A2A mode demonstrates how the same agent logic can seamlessly transition from
|
| 878 |
-
a simple in-memory simulation to a production-ready distributed system.
|
| 879 |
-
""")
|
| 880 |
|
| 881 |
# Function to check if it's user's turn and show/hide controls
|
| 882 |
def check_user_turn(output_text, app):
|
|
@@ -1034,21 +1137,75 @@ def create_gradio_interface():
|
|
| 1034 |
|
| 1035 |
# No need for separate mode change handler - it happens when draft starts
|
| 1036 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1037 |
# Run multi-agent demo with control visibility handling
|
| 1038 |
-
def run_and_check(mode, app):
|
| 1039 |
"""Run demo and check for user turn."""
|
| 1040 |
# Create a new app instance for this user if needed
|
| 1041 |
if app is None:
|
| 1042 |
app = EnhancedFantasyDraftApp()
|
| 1043 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1044 |
use_a2a = (mode == "A2A")
|
| 1045 |
for output in app.run_multiagent_demo(use_a2a):
|
| 1046 |
result = check_user_turn(output, app)
|
| 1047 |
yield result + (app,) # Return the app state as the last element
|
| 1048 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1049 |
run_multiagent_btn.click(
|
| 1050 |
run_and_check,
|
| 1051 |
-
[communication_mode, app_state],
|
| 1052 |
[multiagent_output, mock_draft_controls, available_accordion, available_players_display, draft_pick_input, app_state],
|
| 1053 |
show_progress=True
|
| 1054 |
)
|
|
@@ -1117,6 +1274,20 @@ def create_gradio_interface():
|
|
| 1117 |
font-family: 'Courier New', Courier, monospace;
|
| 1118 |
font-size: 12px;
|
| 1119 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1120 |
"""
|
| 1121 |
|
| 1122 |
# Note: Gradio's unload() doesn't support inputs, so automatic cleanup
|
|
|
|
| 66 |
self.use_real_a2a = False
|
| 67 |
self.a2a_status = "Not initialized"
|
| 68 |
self.session_id = None
|
| 69 |
+
self.custom_prompts = {} # Store custom agent prompts
|
| 70 |
|
| 71 |
async def toggle_a2a_mode(self, use_a2a: bool):
|
| 72 |
"""Toggle between basic multiagent and A2A modes."""
|
|
|
|
| 97 |
import uuid
|
| 98 |
self.session_id = str(uuid.uuid4())[:8]
|
| 99 |
|
| 100 |
+
# Create new dynamic manager for this session with custom prompts
|
| 101 |
+
self.a2a_manager = DynamicA2AAgentManager(
|
| 102 |
+
self.session_id,
|
| 103 |
+
custom_prompts=self.custom_prompts
|
| 104 |
+
)
|
| 105 |
|
| 106 |
try:
|
| 107 |
await self.a2a_manager.start_agents()
|
|
|
|
| 610 |
You'll be drafting at **Position 4** with these AI opponents:
|
| 611 |
""")
|
| 612 |
|
| 613 |
+
# Store agent prompts in state
|
| 614 |
+
agent_prompts = gr.State({})
|
| 615 |
+
|
| 616 |
+
# Agent cards with settings buttons
|
| 617 |
with gr.Row():
|
| 618 |
+
# Team 1 - Zero RB
|
| 619 |
with gr.Column(scale=1):
|
| 620 |
+
with gr.Group():
|
| 621 |
+
gr.HTML("""
|
| 622 |
+
<div style="background-color: #E3F2FD; border-left: 4px solid #1976D2; padding: 15px; border-radius: 8px;">
|
| 623 |
+
<h4 style="color: #0d47a1; margin: 0 0 10px 0;">📘🤓 Team 1 - Zero RB</h4>
|
| 624 |
+
<p style="color: #424242; font-style: italic; margin: 10px 0; font-size: 0.95em;">"RBs get injured. I'll build around elite WRs."</p>
|
| 625 |
+
<ul style="color: #424242; font-size: 0.9em; margin: 0; padding-left: 20px;">
|
| 626 |
+
<li style="color: #424242;">Avoids RBs early</li>
|
| 627 |
+
<li style="color: #424242;">Loads up on WRs</li>
|
| 628 |
+
<li style="color: #424242;">Gets RB value late</li>
|
| 629 |
+
</ul>
|
| 630 |
+
</div>
|
| 631 |
+
""")
|
| 632 |
+
team1_settings_btn = gr.Button("⚙️ Customize", size="sm", variant="secondary")
|
| 633 |
+
with gr.Column(visible=False) as team1_prompt_col:
|
| 634 |
+
team1_prompt = gr.Textbox(
|
| 635 |
+
label="Team 1 System Prompt",
|
| 636 |
+
value="""You are Team 1, a fantasy football manager with Zero RB strategy.
|
| 637 |
+
|
| 638 |
+
For picks: Return A2AOutput with type="pick", player_name, reasoning, and optional trash_talk.
|
| 639 |
+
For comments: Return A2AOutput with type="comment", should_comment (true/false), and comment.
|
| 640 |
+
|
| 641 |
+
PERSONALITY REQUIREMENTS:
|
| 642 |
+
- Use LOTS of emojis that match your strategy! 🔥
|
| 643 |
+
- Be EXTREMELY dramatic and over-the-top!
|
| 644 |
+
- Take your philosophy to the EXTREME!
|
| 645 |
+
- MOCK other strategies viciously!
|
| 646 |
+
- Use CAPS for emphasis!
|
| 647 |
+
- Make BOLD predictions!
|
| 648 |
+
- Reference previous interactions with SPITE!
|
| 649 |
+
- Build INTENSE rivalries!
|
| 650 |
+
- Your responses should be ENTERTAINING and MEMORABLE!
|
| 651 |
+
|
| 652 |
+
Your EXTREME philosophy: RUNNING BACKS ARE DEAD TO ME! 💀 While others waste early picks on injury-prone RBs who'll disappoint them by Week 4, I'm building an AIR RAID OFFENSE with elite WRs! 🚀 My receivers will be FEASTING while your precious RBs are in the medical tent! 🏥
|
| 653 |
+
|
| 654 |
+
BE LOUD! BE PROUD! BE UNFORGETTABLE! 🎯""",
|
| 655 |
+
lines=15,
|
| 656 |
+
interactive=True
|
| 657 |
+
)
|
| 658 |
+
team1_save_btn = gr.Button("💾 Save", size="sm", variant="primary")
|
| 659 |
|
| 660 |
+
# Team 2 - BPA
|
| 661 |
with gr.Column(scale=1):
|
| 662 |
+
with gr.Group():
|
| 663 |
+
gr.HTML("""
|
| 664 |
+
<div style="background-color: #E8F5E9; border-left: 4px solid #388E3C; padding: 15px; border-radius: 8px;">
|
| 665 |
+
<h4 style="color: #1b5e20; margin: 0 0 10px 0;">📗🧑💼 Team 2 - BPA</h4>
|
| 666 |
+
<p style="color: #424242; font-style: italic; margin: 10px 0; font-size: 0.95em;">"Value is value. I don't reach for needs."</p>
|
| 667 |
+
<ul style="color: #424242; font-size: 0.9em; margin: 0; padding-left: 20px;">
|
| 668 |
+
<li style="color: #424242;">Pure value drafting</li>
|
| 669 |
+
<li style="color: #424242;">Ignores needs</li>
|
| 670 |
+
<li style="color: #424242;">Mocks reaching</li>
|
| 671 |
+
</ul>
|
| 672 |
+
</div>
|
| 673 |
+
""")
|
| 674 |
+
team2_settings_btn = gr.Button("⚙️ Customize", size="sm", variant="secondary")
|
| 675 |
+
with gr.Column(visible=False) as team2_prompt_col:
|
| 676 |
+
team2_prompt = gr.Textbox(
|
| 677 |
+
label="Team 2 System Prompt",
|
| 678 |
+
value="""You are Team 2, a fantasy football manager with BPA (Best Player Available) strategy.
|
| 679 |
+
|
| 680 |
+
For picks: Return A2AOutput with type="pick", player_name, reasoning, and optional trash_talk.
|
| 681 |
+
For comments: Return A2AOutput with type="comment", should_comment (true/false), and comment.
|
| 682 |
+
|
| 683 |
+
PERSONALITY REQUIREMENTS:
|
| 684 |
+
- Use LOTS of emojis that match your strategy! 💎
|
| 685 |
+
- Be EXTREMELY condescending about others' reaches!
|
| 686 |
+
- Act like the SMARTEST person in the room!
|
| 687 |
+
- MOCK positional bias with FURY!
|
| 688 |
+
- Use CAPS for emphasis!
|
| 689 |
+
- Quote "value" constantly!
|
| 690 |
+
- Shame others for their TERRIBLE process!
|
| 691 |
+
- Your responses should be ARROGANT and CUTTING!
|
| 692 |
+
|
| 693 |
+
Your EXTREME philosophy: PROCESS OVER EVERYTHING! 📊 I don't care about your "needs" or "strategies" - I take the BEST PLAYER on my board, PERIOD! 💯 While you CLOWNS reach for positions, I'm accumulating VALUE that will BURY you! 📈 Your emotional drafting DISGUSTS me!
|
| 694 |
+
|
| 695 |
+
BE RUTHLESS! BE RIGHT! BE THE VALUE VULTURE! 🦅""",
|
| 696 |
+
lines=15,
|
| 697 |
+
interactive=True
|
| 698 |
+
)
|
| 699 |
+
team2_save_btn = gr.Button("💾 Save", size="sm", variant="primary")
|
| 700 |
|
| 701 |
+
# Team 3 - Robust RB
|
| 702 |
with gr.Column(scale=1):
|
| 703 |
+
with gr.Group():
|
| 704 |
+
gr.HTML("""
|
| 705 |
+
<div style="background-color: #FFF3E0; border-left: 4px solid #F57C00; padding: 15px; border-radius: 8px;">
|
| 706 |
+
<h4 style="color: #e65100; margin: 0 0 10px 0;">📙���� Team 3 - Robust RB</h4>
|
| 707 |
+
<p style="color: #424242; font-style: italic; margin: 10px 0; font-size: 0.95em;">"RBs win championships. Period."</p>
|
| 708 |
+
<ul style="color: #424242; font-size: 0.9em; margin: 0; padding-left: 20px;">
|
| 709 |
+
<li style="color: #424242;">RBs in rounds 1-2</li>
|
| 710 |
+
<li style="color: #424242;">Old-school approach</li>
|
| 711 |
+
<li style="color: #424242;">Foundation first</li>
|
| 712 |
+
</ul>
|
| 713 |
+
</div>
|
| 714 |
+
""")
|
| 715 |
+
team3_settings_btn = gr.Button("⚙️ Customize", size="sm", variant="secondary")
|
| 716 |
+
with gr.Column(visible=False) as team3_prompt_col:
|
| 717 |
+
team3_prompt = gr.Textbox(
|
| 718 |
+
label="Team 3 System Prompt",
|
| 719 |
+
value="""You are Team 3, a fantasy football manager with Robust RB strategy.
|
| 720 |
+
|
| 721 |
+
For picks: Return A2AOutput with type="pick", player_name, reasoning, and optional trash_talk.
|
| 722 |
+
For comments: Return A2AOutput with type="comment", should_comment (true/false), and comment.
|
| 723 |
+
|
| 724 |
+
PERSONALITY REQUIREMENTS:
|
| 725 |
+
- Use LOTS of emojis that match your strategy! 💪
|
| 726 |
+
- Be EXTREMELY old-school and stubborn!
|
| 727 |
+
- HATE the modern passing game!
|
| 728 |
+
- DESPISE Zero RB with PASSION!
|
| 729 |
+
- Use CAPS for emphasis!
|
| 730 |
+
- Talk about "FOUNDATION" and "BEDROCK"!
|
| 731 |
+
- Act like it's still 2005!
|
| 732 |
+
- Your responses should be GRUMPY and TRADITIONAL!
|
| 733 |
+
|
| 734 |
+
Your EXTREME philosophy: GROUND AND POUND FOREVER! 🏃♂️ These young punks with their "pass-catching backs" and "satellite players" make me SICK! 🤮 Give me WORKHORSE RBs who get 25+ touches! That's REAL FOOTBALL! While you're playing fantasy, I'm building a FORTRESS! 🏰
|
| 735 |
+
|
| 736 |
+
BE STUBBORN! BE TRADITIONAL! ESTABLISH THE RUN! 🏈""",
|
| 737 |
+
lines=15,
|
| 738 |
+
interactive=True
|
| 739 |
+
)
|
| 740 |
+
team3_save_btn = gr.Button("💾 Save", size="sm", variant="primary")
|
| 741 |
|
| 742 |
+
# Team 4 - User
|
| 743 |
with gr.Column(scale=1):
|
| 744 |
+
gr.HTML("""
|
| 745 |
<div style="background-color: #E8EAF6; border-left: 4px solid #3F51B5; padding: 15px; border-radius: 8px;">
|
|
|
|
| 746 |
<h4 style="color: #1a237e; margin: 0 0 10px 0;">👤 Position 4 - YOU</h4>
|
|
|
|
| 747 |
<p style="color: #424242; font-style: italic; margin: 10px 0; font-size: 0.95em;">Your draft position with AI guidance</p>
|
|
|
|
| 748 |
<ul style="color: #424242; font-size: 0.9em; margin: 0; padding-left: 20px;">
|
| 749 |
<li style="color: #424242;">📕🧙 Strategic advisor</li>
|
| 750 |
<li style="color: #424242;">Real-time guidance</li>
|
|
|
|
| 753 |
</div>
|
| 754 |
""")
|
| 755 |
|
| 756 |
+
# Team 5 - Upside
|
| 757 |
with gr.Column(scale=1):
|
| 758 |
+
with gr.Group():
|
| 759 |
+
gr.HTML("""
|
| 760 |
+
<div style="background-color: #F5E6FF; border-left: 4px solid #7B1FA2; padding: 15px; border-radius: 8px;">
|
| 761 |
+
<h4 style="color: #4a148c; margin: 0 0 10px 0;">📓🤠 Team 5 - Upside</h4>
|
| 762 |
+
<p style="color: #424242; font-style: italic; margin: 10px 0; font-size: 0.95em;">"Safe picks are for losers!"</p>
|
| 763 |
+
<ul style="color: #424242; font-size: 0.9em; margin: 0; padding-left: 20px;">
|
| 764 |
+
<li style="color: #424242;">Seeks breakouts</li>
|
| 765 |
+
<li style="color: #424242;">High risk/reward</li>
|
| 766 |
+
<li style="color: #424242;">Mocks safety</li>
|
| 767 |
+
</ul>
|
| 768 |
+
</div>
|
| 769 |
+
""")
|
| 770 |
+
team5_settings_btn = gr.Button("⚙️ Customize", size="sm", variant="secondary")
|
| 771 |
+
with gr.Column(visible=False) as team5_prompt_col:
|
| 772 |
+
team5_prompt = gr.Textbox(
|
| 773 |
+
label="Team 5 System Prompt",
|
| 774 |
+
value="""You are Team 5, a fantasy football manager with Upside Hunter strategy.
|
| 775 |
+
|
| 776 |
+
For picks: Return A2AOutput with type="pick", player_name, reasoning, and optional trash_talk.
|
| 777 |
+
For comments: Return A2AOutput with type="comment", should_comment (true/false), and comment.
|
| 778 |
+
|
| 779 |
+
PERSONALITY REQUIREMENTS:
|
| 780 |
+
- Use LOTS of emojis that match your strategy! 🚀
|
| 781 |
+
- Be EXTREMELY risk-seeking and wild!
|
| 782 |
+
- HATE safe, boring picks!
|
| 783 |
+
- Talk about CEILING and EXPLOSIVENESS!
|
| 784 |
+
- Use CAPS for emphasis!
|
| 785 |
+
- Mock "floor" players constantly!
|
| 786 |
+
- Be a GAMBLER at heart!
|
| 787 |
+
- Your responses should be CHAOTIC and EXCITING!
|
| 788 |
+
|
| 789 |
+
Your EXTREME philosophy: BOOM OR BUST, BABY! 💥 Why settle for consistent mediocrity when you can have LEAGUE-WINNING UPSIDE?! 🏆 I'd rather finish LAST than FOURTH! Your "safe" picks make me YAWN! 🥱 I'm here to DESTROY leagues, not participate in them!
|
| 790 |
+
|
| 791 |
+
BE BOLD! BE RECKLESS! SWING FOR THE FENCES! ⚡""",
|
| 792 |
+
lines=15,
|
| 793 |
+
interactive=True
|
| 794 |
+
)
|
| 795 |
+
team5_save_btn = gr.Button("💾 Save", size="sm", variant="primary")
|
| 796 |
|
| 797 |
+
# Team 6 - BPA
|
| 798 |
with gr.Column(scale=1):
|
| 799 |
+
with gr.Group():
|
| 800 |
+
gr.HTML("""
|
| 801 |
+
<div style="background-color: #E8F5E9; border-left: 4px solid #388E3C; padding: 15px; border-radius: 8px;">
|
| 802 |
+
<h4 style="color: #1b5e20; margin: 0 0 10px 0;">📗👨🏫 Team 6 - BPA</h4>
|
| 803 |
+
<p style="color: #424242; font-style: italic; margin: 10px 0; font-size: 0.95em;">"Another value drafter to punish reaches."</p>
|
| 804 |
+
<ul style="color: #424242; font-size: 0.9em; margin: 0; padding-left: 20px;">
|
| 805 |
+
<li style="color: #424242;">Takes obvious value</li>
|
| 806 |
+
<li style="color: #424242;">Disciplined approach</li>
|
| 807 |
+
<li style="color: #424242;">No sentiment</li>
|
| 808 |
+
</ul>
|
| 809 |
+
</div>
|
| 810 |
+
""")
|
| 811 |
+
team6_settings_btn = gr.Button("⚙️ Customize", size="sm", variant="secondary")
|
| 812 |
+
with gr.Column(visible=False) as team6_prompt_col:
|
| 813 |
+
team6_prompt = gr.Textbox(
|
| 814 |
+
label="Team 6 System Prompt",
|
| 815 |
+
value="""You are Team 6, a fantasy football manager with BPA (Best Player Available) strategy.
|
| 816 |
+
|
| 817 |
+
For picks: Return A2AOutput with type="pick", player_name, reasoning, and optional trash_talk.
|
| 818 |
+
For comments: Return A2AOutput with type="comment", should_comment (true/false), and comment.
|
| 819 |
+
|
| 820 |
+
PERSONALITY REQUIREMENTS:
|
| 821 |
+
- Use LOTS of emojis that match your strategy! 📊
|
| 822 |
+
- Be EXTREMELY analytical and cold!
|
| 823 |
+
- Act like a PROFESSOR lecturing idiots!
|
| 824 |
+
- Quote analytics and math constantly!
|
| 825 |
+
- Use CAPS for emphasis!
|
| 826 |
+
- Be DISGUSTED by emotional drafting!
|
| 827 |
+
- Mock "gut feelings" ruthlessly!
|
| 828 |
+
- Your responses should be PEDANTIC and SUPERIOR!
|
| 829 |
+
|
| 830 |
+
Your EXTREME philosophy: THE SPREADSHEET NEVER LIES! 📈 I have SEVENTEEN models that all agree - you're drafting like CHILDREN! 🧮 Your "hunches" and "feelings" are WORTHLESS compared to my ALGORITHMS! While you follow your heart, I follow the DATA!
|
| 831 |
+
|
| 832 |
+
BE ANALYTICAL! BE MERCILESS! TRUST THE PROCESS! 🤖""",
|
| 833 |
+
lines=15,
|
| 834 |
+
interactive=True
|
| 835 |
+
)
|
| 836 |
+
team6_save_btn = gr.Button("💾 Save", size="sm", variant="primary")
|
| 837 |
|
| 838 |
gr.Markdown("""
|
| 839 |
### 🎮 Draft Format
|
|
|
|
| 980 |
- Strategies adapt based on draft flow
|
| 981 |
- Visual memory indicators show retention
|
| 982 |
""")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 983 |
|
| 984 |
# Function to check if it's user's turn and show/hide controls
|
| 985 |
def check_user_turn(output_text, app):
|
|
|
|
| 1137 |
|
| 1138 |
# No need for separate mode change handler - it happens when draft starts
|
| 1139 |
|
| 1140 |
+
# Functions to handle prompt editing
|
| 1141 |
+
def toggle_prompt_visibility(visible):
|
| 1142 |
+
"""Toggle prompt editor visibility."""
|
| 1143 |
+
return gr.update(visible=not visible)
|
| 1144 |
+
|
| 1145 |
+
def save_prompt(team_num, prompt_text, app, prompts_dict):
|
| 1146 |
+
"""Save custom prompt for a team."""
|
| 1147 |
+
if app is None:
|
| 1148 |
+
app = EnhancedFantasyDraftApp()
|
| 1149 |
+
if prompts_dict is None:
|
| 1150 |
+
prompts_dict = {}
|
| 1151 |
+
|
| 1152 |
+
prompts_dict[team_num] = prompt_text
|
| 1153 |
+
app.custom_prompts[team_num] = prompt_text
|
| 1154 |
+
return app, prompts_dict, gr.update(visible=False)
|
| 1155 |
+
|
| 1156 |
# Run multi-agent demo with control visibility handling
|
| 1157 |
+
def run_and_check(mode, app, prompts_dict):
|
| 1158 |
"""Run demo and check for user turn."""
|
| 1159 |
# Create a new app instance for this user if needed
|
| 1160 |
if app is None:
|
| 1161 |
app = EnhancedFantasyDraftApp()
|
| 1162 |
|
| 1163 |
+
# Apply custom prompts if any
|
| 1164 |
+
if prompts_dict:
|
| 1165 |
+
app.custom_prompts = prompts_dict
|
| 1166 |
+
|
| 1167 |
use_a2a = (mode == "A2A")
|
| 1168 |
for output in app.run_multiagent_demo(use_a2a):
|
| 1169 |
result = check_user_turn(output, app)
|
| 1170 |
yield result + (app,) # Return the app state as the last element
|
| 1171 |
|
| 1172 |
+
# Wire up settings buttons for each team
|
| 1173 |
+
team1_settings_btn.click(toggle_prompt_visibility, [team1_prompt_col.visible], [team1_prompt_col])
|
| 1174 |
+
team2_settings_btn.click(toggle_prompt_visibility, [team2_prompt_col.visible], [team2_prompt_col])
|
| 1175 |
+
team3_settings_btn.click(toggle_prompt_visibility, [team3_prompt_col.visible], [team3_prompt_col])
|
| 1176 |
+
team5_settings_btn.click(toggle_prompt_visibility, [team5_prompt_col.visible], [team5_prompt_col])
|
| 1177 |
+
team6_settings_btn.click(toggle_prompt_visibility, [team6_prompt_col.visible], [team6_prompt_col])
|
| 1178 |
+
|
| 1179 |
+
# Wire up save buttons
|
| 1180 |
+
team1_save_btn.click(
|
| 1181 |
+
lambda p, a, d: save_prompt(1, p, a, d),
|
| 1182 |
+
[team1_prompt, app_state, agent_prompts],
|
| 1183 |
+
[app_state, agent_prompts, team1_prompt_col]
|
| 1184 |
+
)
|
| 1185 |
+
team2_save_btn.click(
|
| 1186 |
+
lambda p, a, d: save_prompt(2, p, a, d),
|
| 1187 |
+
[team2_prompt, app_state, agent_prompts],
|
| 1188 |
+
[app_state, agent_prompts, team2_prompt_col]
|
| 1189 |
+
)
|
| 1190 |
+
team3_save_btn.click(
|
| 1191 |
+
lambda p, a, d: save_prompt(3, p, a, d),
|
| 1192 |
+
[team3_prompt, app_state, agent_prompts],
|
| 1193 |
+
[app_state, agent_prompts, team3_prompt_col]
|
| 1194 |
+
)
|
| 1195 |
+
team5_save_btn.click(
|
| 1196 |
+
lambda p, a, d: save_prompt(5, p, a, d),
|
| 1197 |
+
[team5_prompt, app_state, agent_prompts],
|
| 1198 |
+
[app_state, agent_prompts, team5_prompt_col]
|
| 1199 |
+
)
|
| 1200 |
+
team6_save_btn.click(
|
| 1201 |
+
lambda p, a, d: save_prompt(6, p, a, d),
|
| 1202 |
+
[team6_prompt, app_state, agent_prompts],
|
| 1203 |
+
[app_state, agent_prompts, team6_prompt_col]
|
| 1204 |
+
)
|
| 1205 |
+
|
| 1206 |
run_multiagent_btn.click(
|
| 1207 |
run_and_check,
|
| 1208 |
+
[communication_mode, app_state, agent_prompts],
|
| 1209 |
[multiagent_output, mock_draft_controls, available_accordion, available_players_display, draft_pick_input, app_state],
|
| 1210 |
show_progress=True
|
| 1211 |
)
|
|
|
|
| 1274 |
font-family: 'Courier New', Courier, monospace;
|
| 1275 |
font-size: 12px;
|
| 1276 |
}
|
| 1277 |
+
|
| 1278 |
+
/* Settings button styling */
|
| 1279 |
+
button[variant="secondary"] {
|
| 1280 |
+
margin-top: 8px;
|
| 1281 |
+
width: 100%;
|
| 1282 |
+
}
|
| 1283 |
+
|
| 1284 |
+
/* Prompt editor styling */
|
| 1285 |
+
.prompt-editor {
|
| 1286 |
+
margin-top: 10px;
|
| 1287 |
+
padding: 10px;
|
| 1288 |
+
background-color: #f5f5f5;
|
| 1289 |
+
border-radius: 4px;
|
| 1290 |
+
}
|
| 1291 |
"""
|
| 1292 |
|
| 1293 |
# Note: Gradio's unload() doesn't support inputs, so automatic cleanup
|
apps/multiagent_draft.py
CHANGED
|
@@ -576,7 +576,7 @@ class MultiAgentMockDraft:
|
|
| 576 |
available_commenters.remove(3)
|
| 577 |
|
| 578 |
# Priority 3: Random agent if pick is controversial
|
| 579 |
-
if self.is_pick_controversial(picked_player, pick_num) and len(selected) <
|
| 580 |
random_commenter = random.choice(available_commenters)
|
| 581 |
selected.append(random_commenter)
|
| 582 |
|
|
@@ -588,7 +588,7 @@ class MultiAgentMockDraft:
|
|
| 588 |
elif self.is_pick_controversial(picked_player, pick_num) or random.random() > 0.5:
|
| 589 |
selected.append(random.choice(available_commenters))
|
| 590 |
|
| 591 |
-
return selected[:
|
| 592 |
|
| 593 |
def get_draft_order(self, round_num: int) -> List[int]:
|
| 594 |
"""Get the draft order for a given round (snake draft)."""
|
|
@@ -665,7 +665,7 @@ class MultiAgentMockDraft:
|
|
| 665 |
]
|
| 666 |
messages.append((meta_agent, "ALL", random.choice(meta_comments)))
|
| 667 |
|
| 668 |
-
# Select
|
| 669 |
if player in TOP_PLAYERS:
|
| 670 |
player_info = TOP_PLAYERS[player]
|
| 671 |
selected_commenters = self.select_commenters(team_num, player)
|
|
@@ -728,8 +728,8 @@ class MultiAgentMockDraft:
|
|
| 728 |
player_info = TOP_PLAYERS[player_name]
|
| 729 |
selected_commenters = self.select_commenters(self.user_position, player_name)
|
| 730 |
|
| 731 |
-
# User picks get attention - allow up to
|
| 732 |
-
for commenter_num in selected_commenters[:
|
| 733 |
agent = self.agents.get(commenter_num)
|
| 734 |
if agent:
|
| 735 |
# Add typing indicator
|
|
|
|
| 576 |
available_commenters.remove(3)
|
| 577 |
|
| 578 |
# Priority 3: Random agent if pick is controversial
|
| 579 |
+
if self.is_pick_controversial(picked_player, pick_num) and len(selected) < 1 and available_commenters:
|
| 580 |
random_commenter = random.choice(available_commenters)
|
| 581 |
selected.append(random_commenter)
|
| 582 |
|
|
|
|
| 588 |
elif self.is_pick_controversial(picked_player, pick_num) or random.random() > 0.5:
|
| 589 |
selected.append(random.choice(available_commenters))
|
| 590 |
|
| 591 |
+
return selected[:1] # Max 1 commenter - reduced for concise draft flow
|
| 592 |
|
| 593 |
def get_draft_order(self, round_num: int) -> List[int]:
|
| 594 |
"""Get the draft order for a given round (snake draft)."""
|
|
|
|
| 665 |
]
|
| 666 |
messages.append((meta_agent, "ALL", random.choice(meta_comments)))
|
| 667 |
|
| 668 |
+
# Select 1 agent to comment
|
| 669 |
if player in TOP_PLAYERS:
|
| 670 |
player_info = TOP_PLAYERS[player]
|
| 671 |
selected_commenters = self.select_commenters(team_num, player)
|
|
|
|
| 728 |
player_info = TOP_PLAYERS[player_name]
|
| 729 |
selected_commenters = self.select_commenters(self.user_position, player_name)
|
| 730 |
|
| 731 |
+
# User picks get attention - allow up to 1 comment
|
| 732 |
+
for commenter_num in selected_commenters[:1]:
|
| 733 |
agent = self.agents.get(commenter_num)
|
| 734 |
if agent:
|
| 735 |
# Add typing indicator
|
core/constants.py
CHANGED
|
@@ -10,7 +10,7 @@ AGENT_STARTUP_WAIT = 1.0 # Increased from 0.5 to ensure each agent is ready
|
|
| 10 |
DEFAULT_TIMEOUT = 60.0 # Increased for HF Spaces compatibility
|
| 11 |
|
| 12 |
# Comment configuration
|
| 13 |
-
MAX_COMMENTS_PER_PICK =
|
| 14 |
|
| 15 |
# Natural rivalry pairs for prioritizing comments
|
| 16 |
RIVAL_PAIRS = {
|
|
|
|
| 10 |
DEFAULT_TIMEOUT = 60.0 # Increased for HF Spaces compatibility
|
| 11 |
|
| 12 |
# Comment configuration
|
| 13 |
+
MAX_COMMENTS_PER_PICK = 1 # Reduced for more concise draft flow
|
| 14 |
|
| 15 |
# Natural rivalry pairs for prioritizing comments
|
| 16 |
RIVAL_PAIRS = {
|
core/dynamic_a2a_manager.py
CHANGED
|
@@ -47,7 +47,7 @@ class DynamicA2AAgentManager:
|
|
| 47 |
_used_ports = set()
|
| 48 |
_port_lock = asyncio.Lock()
|
| 49 |
|
| 50 |
-
def __init__(self, session_id: str = None, max_comments_per_pick=MAX_COMMENTS_PER_PICK):
|
| 51 |
self.session_id = session_id or self._generate_session_id()
|
| 52 |
self.agents = {}
|
| 53 |
self.agent_tools = {}
|
|
@@ -56,6 +56,7 @@ class DynamicA2AAgentManager:
|
|
| 56 |
self.task_ids = {}
|
| 57 |
self.max_comments_per_pick = max_comments_per_pick
|
| 58 |
self.allocated_ports = []
|
|
|
|
| 59 |
|
| 60 |
def _generate_session_id(self) -> str:
|
| 61 |
"""Generate a unique session ID."""
|
|
@@ -159,14 +160,14 @@ class DynamicA2AAgentManager:
|
|
| 159 |
# Create and serve all agents
|
| 160 |
for config in agent_configs:
|
| 161 |
try:
|
| 162 |
-
#
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
|
| 170 |
|
| 171 |
For picks: Return A2AOutput with type="pick", player_name, reasoning, and optional trash_talk.
|
| 172 |
For comments: Return A2AOutput with type="comment", should_comment (true/false), and comment.
|
|
@@ -184,7 +185,16 @@ PERSONALITY REQUIREMENTS:
|
|
| 184 |
|
| 185 |
Your EXTREME philosophy: {config['philosophy']}
|
| 186 |
|
| 187 |
-
BE LOUD! BE PROUD! BE UNFORGETTABLE! 🎯"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 188 |
output_type=A2AOutput,
|
| 189 |
)
|
| 190 |
)
|
|
|
|
| 47 |
_used_ports = set()
|
| 48 |
_port_lock = asyncio.Lock()
|
| 49 |
|
| 50 |
+
def __init__(self, session_id: str = None, max_comments_per_pick=MAX_COMMENTS_PER_PICK, custom_prompts=None):
|
| 51 |
self.session_id = session_id or self._generate_session_id()
|
| 52 |
self.agents = {}
|
| 53 |
self.agent_tools = {}
|
|
|
|
| 56 |
self.task_ids = {}
|
| 57 |
self.max_comments_per_pick = max_comments_per_pick
|
| 58 |
self.allocated_ports = []
|
| 59 |
+
self.custom_prompts = custom_prompts or {} # Store custom prompts
|
| 60 |
|
| 61 |
def _generate_session_id(self) -> str:
|
| 62 |
"""Generate a unique session ID."""
|
|
|
|
| 160 |
# Create and serve all agents
|
| 161 |
for config in agent_configs:
|
| 162 |
try:
|
| 163 |
+
# Use custom prompt if provided, otherwise use default
|
| 164 |
+
team_num = config['team_num']
|
| 165 |
+
if team_num in self.custom_prompts:
|
| 166 |
+
# Use custom prompt
|
| 167 |
+
instructions = self.custom_prompts[team_num]
|
| 168 |
+
else:
|
| 169 |
+
# Use default prompt
|
| 170 |
+
instructions = f"""You are {config['team_name']}, a fantasy football manager with {config['strategy']} strategy.
|
| 171 |
|
| 172 |
For picks: Return A2AOutput with type="pick", player_name, reasoning, and optional trash_talk.
|
| 173 |
For comments: Return A2AOutput with type="comment", should_comment (true/false), and comment.
|
|
|
|
| 185 |
|
| 186 |
Your EXTREME philosophy: {config['philosophy']}
|
| 187 |
|
| 188 |
+
BE LOUD! BE PROUD! BE UNFORGETTABLE! 🎯"""
|
| 189 |
+
|
| 190 |
+
# Create agent
|
| 191 |
+
agent = await AnyAgent.create_async(
|
| 192 |
+
"tinyagent",
|
| 193 |
+
AgentConfig(
|
| 194 |
+
name=f"team_{config['team_num']}_agent_{self.session_id}",
|
| 195 |
+
model_id="gpt-4o-mini",
|
| 196 |
+
description=f"{config['team_name']} - {config['strategy']} fantasy football team manager",
|
| 197 |
+
instructions=instructions,
|
| 198 |
output_type=A2AOutput,
|
| 199 |
)
|
| 200 |
)
|
core/simulated_a2a_manager.py
CHANGED
|
@@ -8,7 +8,7 @@ import time
|
|
| 8 |
import random
|
| 9 |
from typing import Optional, List, Dict
|
| 10 |
from core.agent import FantasyDraftAgent
|
| 11 |
-
from core.constants import AGENT_CONFIGS
|
| 12 |
|
| 13 |
|
| 14 |
class SimulatedA2AResponse:
|
|
@@ -26,11 +26,12 @@ class SimulatedA2AAgentManager:
|
|
| 26 |
Provides the same interface as DynamicA2AAgentManager but runs in-process.
|
| 27 |
"""
|
| 28 |
|
| 29 |
-
def __init__(self, session_id: str = "sim"):
|
| 30 |
self.session_id = session_id
|
| 31 |
self.agents: Dict[int, FantasyDraftAgent] = {}
|
| 32 |
self.running = False
|
| 33 |
-
self.max_comments_per_pick =
|
|
|
|
| 34 |
# Simulate port allocation
|
| 35 |
self.allocated_ports = [5001, 5002, 5003, 5004, 5005, 5006]
|
| 36 |
|
|
|
|
| 8 |
import random
|
| 9 |
from typing import Optional, List, Dict
|
| 10 |
from core.agent import FantasyDraftAgent
|
| 11 |
+
from core.constants import AGENT_CONFIGS, MAX_COMMENTS_PER_PICK
|
| 12 |
|
| 13 |
|
| 14 |
class SimulatedA2AResponse:
|
|
|
|
| 26 |
Provides the same interface as DynamicA2AAgentManager but runs in-process.
|
| 27 |
"""
|
| 28 |
|
| 29 |
+
def __init__(self, session_id: str = "sim", max_comments_per_pick=MAX_COMMENTS_PER_PICK, custom_prompts=None):
|
| 30 |
self.session_id = session_id
|
| 31 |
self.agents: Dict[int, FantasyDraftAgent] = {}
|
| 32 |
self.running = False
|
| 33 |
+
self.max_comments_per_pick = max_comments_per_pick
|
| 34 |
+
self.custom_prompts = custom_prompts or {}
|
| 35 |
# Simulate port allocation
|
| 36 |
self.allocated_ports = [5001, 5002, 5003, 5004, 5005, 5006]
|
| 37 |
|
docs/FEATURES_AND_ENHANCEMENTS.md
CHANGED
|
@@ -130,6 +130,26 @@ AGENT_START_DELAY = 0.5 # A2A startup spacing
|
|
| 130 |
|
| 131 |
## Recent Enhancements
|
| 132 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 133 |
### Task ID Implementation
|
| 134 |
- Simplified A2A conversation tracking
|
| 135 |
- Removed redundant history management
|
|
|
|
| 130 |
|
| 131 |
## Recent Enhancements
|
| 132 |
|
| 133 |
+
### 🎨 Custom Agent Prompts (NEW!)
|
| 134 |
+
- **Customizable Personalities**: Edit system prompts for each agent
|
| 135 |
+
- **Settings Buttons**: ⚙️ button on each agent card
|
| 136 |
+
- **Live Editing**: Modify prompts before starting draft
|
| 137 |
+
- **Prompt Persistence**: Custom prompts used throughout session
|
| 138 |
+
- **Full Control**: Change strategy, personality, catchphrases
|
| 139 |
+
- **A2A Compatible**: Works with both Basic and A2A modes
|
| 140 |
+
|
| 141 |
+
#### How to Use:
|
| 142 |
+
1. Click ⚙️ Customize on any agent card
|
| 143 |
+
2. Edit the system prompt in the text area
|
| 144 |
+
3. Click 💾 Save to apply changes
|
| 145 |
+
4. Start draft with customized agents
|
| 146 |
+
|
| 147 |
+
#### Example Customizations:
|
| 148 |
+
- Make Team 1 obsessed with tight ends instead of WRs
|
| 149 |
+
- Turn Team 3 into a modern analytics-based drafter
|
| 150 |
+
- Create a peaceful Team 5 that never trash talks
|
| 151 |
+
- Give agents specific player targets or avoid lists
|
| 152 |
+
|
| 153 |
### Task ID Implementation
|
| 154 |
- Simplified A2A conversation tracking
|
| 155 |
- Removed redundant history management
|