Spaces:
No application file
No application file
Liss, Alex (NYC-HUG)
commited on
Commit
·
50ab217
1
Parent(s):
bb4fc9d
added static component for UI layout
Browse files
components/game_recap_component.py
ADDED
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import pandas as pd
|
3 |
+
import os
|
4 |
+
|
5 |
+
def create_game_recap_component(game_data=None):
|
6 |
+
"""
|
7 |
+
Creates a Gradio component to display game information.
|
8 |
+
Args:
|
9 |
+
game_data (dict, optional): Game data to display. If None, loads from CSV.
|
10 |
+
Returns:
|
11 |
+
gr.Column: A Gradio component displaying the game recap.
|
12 |
+
"""
|
13 |
+
try:
|
14 |
+
# Load game schedule if no game data provided
|
15 |
+
if game_data is None:
|
16 |
+
current_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
17 |
+
schedule_path = os.path.join(current_dir, "data", "april_11_multimedia_data_collect", "schedule_with_result_and_logo_urls.csv")
|
18 |
+
df = pd.read_csv(schedule_path)
|
19 |
+
game_data = df.iloc[0].to_dict() # Get first game
|
20 |
+
|
21 |
+
# Extract game details
|
22 |
+
match_number = game_data.get('Match Number', 'N/A')
|
23 |
+
date = game_data.get('Date', 'N/A')
|
24 |
+
location = game_data.get('Location', 'N/A')
|
25 |
+
home_team = game_data.get('Home Team', 'N/A')
|
26 |
+
away_team = game_data.get('Away Team', 'N/A')
|
27 |
+
home_logo = game_data.get('home_team_logo_url', '')
|
28 |
+
away_logo = game_data.get('away_team_logo_url', '')
|
29 |
+
result = game_data.get('Result', 'N/A')
|
30 |
+
game_outcome = game_data.get('game_result', 'N/A')
|
31 |
+
|
32 |
+
# Determine winner
|
33 |
+
winner = None
|
34 |
+
if result != 'N/A':
|
35 |
+
home_score, away_score = map(int, result.split('-'))
|
36 |
+
winner = home_team if home_score > away_score else away_team
|
37 |
+
|
38 |
+
# Create the component
|
39 |
+
with gr.Column(elem_classes=["game-recap-container"]) as game_recap:
|
40 |
+
# Date and Location
|
41 |
+
gr.Markdown(f"### Game {match_number} - {date}")
|
42 |
+
gr.Markdown(f"**Location:** {location}")
|
43 |
+
|
44 |
+
# Teams and Scores
|
45 |
+
with gr.Row(elem_classes=["game-recap-row"]):
|
46 |
+
# Home Team
|
47 |
+
with gr.Column(elem_classes=["team-info"]):
|
48 |
+
if home_logo:
|
49 |
+
gr.Image(home_logo, elem_classes=["team-logo"])
|
50 |
+
gr.Markdown(f"**{home_team}**", elem_classes=["team-name"] + (["winner"] if winner == home_team else []))
|
51 |
+
gr.Markdown(result.split('-')[0], elem_classes=["team-score"])
|
52 |
+
|
53 |
+
# Away Team
|
54 |
+
with gr.Column(elem_classes=["team-info"]):
|
55 |
+
if away_logo:
|
56 |
+
gr.Image(away_logo, elem_classes=["team-logo"])
|
57 |
+
gr.Markdown(f"**{away_team}**", elem_classes=["team-name"] + (["winner"] if winner == away_team else []))
|
58 |
+
gr.Markdown(result.split('-')[1], elem_classes=["team-score"])
|
59 |
+
|
60 |
+
# Game Outcome
|
61 |
+
if game_outcome != 'N/A':
|
62 |
+
gr.Markdown(f"**{game_outcome}**")
|
63 |
+
|
64 |
+
# Video Highlights (placeholder)
|
65 |
+
with gr.Row(elem_classes=["video-preview"]):
|
66 |
+
gr.Markdown("🎥 Video highlights coming soon...")
|
67 |
+
|
68 |
+
return game_recap
|
69 |
+
|
70 |
+
except Exception as e:
|
71 |
+
print(f"Error creating game recap component: {str(e)}")
|
72 |
+
# Return a simple error message component
|
73 |
+
with gr.Column() as error_component:
|
74 |
+
gr.Markdown("⚠️ Error loading game recap. Please try again later.")
|
75 |
+
return error_component
|
76 |
+
|
77 |
+
# Test the component when run directly
|
78 |
+
if __name__ == "__main__":
|
79 |
+
demo = gr.Blocks()
|
80 |
+
with demo:
|
81 |
+
game_recap = create_game_recap_component()
|
82 |
+
demo.launch()
|
data/april_11_multimedia_data_collect/merge_schedule_logos.py
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import pandas as pd
|
2 |
+
import os
|
3 |
+
|
4 |
+
# Read the CSV files
|
5 |
+
schedule_df = pd.read_csv('data/april_11_multimedia_data_collect/nfl-2024-san-francisco-49ers-with-results.csv')
|
6 |
+
logos_df = pd.read_csv('data/april_11_multimedia_data_collect/nfl_team_logos_revised.csv')
|
7 |
+
|
8 |
+
# Create dictionaries to map team names to logo URLs
|
9 |
+
home_logos = {}
|
10 |
+
away_logos = {}
|
11 |
+
|
12 |
+
for _, row in logos_df.iterrows():
|
13 |
+
home_logos[row['team_name']] = row['logo_url']
|
14 |
+
away_logos[row['team_name']] = row['logo_url']
|
15 |
+
|
16 |
+
# Add logo URL columns to the schedule dataframe
|
17 |
+
schedule_df['home_team_logo_url'] = schedule_df['Home Team'].map(home_logos)
|
18 |
+
schedule_df['away_team_logo_url'] = schedule_df['Away Team'].map(away_logos)
|
19 |
+
|
20 |
+
# Save the merged dataframe to a new CSV file
|
21 |
+
output_path = 'data/april_11_multimedia_data_collect/schedule_with_result_and_logo_urls.csv'
|
22 |
+
schedule_df.to_csv(output_path, index=False)
|
23 |
+
|
24 |
+
print(f'CSV file created successfully at {output_path}!')
|
data/april_11_multimedia_data_collect/schedule_with_result_and_logo_urls.csv
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Match Number,Round Number,Date,Location,Home Team,Away Team,Result,game_result,home_team_logo_url,away_team_logo_url
|
2 |
+
1,1,10/09/2024 00:15,Levi's Stadium,San Francisco 49ers,New York Jets,32 - 19,Win,https://a.espncdn.com/i/teamlogos/nfl/500/sf.png,https://a.espncdn.com/i/teamlogos/nfl/500/nyj.png
|
3 |
+
28,2,15/09/2024 17:00,U.S. Bank Stadium,Minnesota Vikings,San Francisco 49ers,23 - 17,Loss,https://a.espncdn.com/i/teamlogos/nfl/500/min.png,https://a.espncdn.com/i/teamlogos/nfl/500/sf.png
|
4 |
+
38,3,22/09/2024 20:25,SoFi Stadium,Los Angeles Rams,San Francisco 49ers,27 - 24,Loss,https://a.espncdn.com/i/teamlogos/nfl/500/lar.png,https://a.espncdn.com/i/teamlogos/nfl/500/sf.png
|
5 |
+
55,4,29/09/2024 20:05,Levi's Stadium,San Francisco 49ers,New England Patriots,30 - 13,Win,https://a.espncdn.com/i/teamlogos/nfl/500/sf.png,https://a.espncdn.com/i/teamlogos/nfl/500/ne.png
|
6 |
+
70,5,06/10/2024 20:05,Levi's Stadium,San Francisco 49ers,Arizona Cardinals,23 - 24,Loss,https://a.espncdn.com/i/teamlogos/nfl/500/sf.png,https://a.espncdn.com/i/teamlogos/nfl/500/ari.png
|
7 |
+
92,6,11/10/2024 00:15,Lumen Field,Seattle Seahawks,San Francisco 49ers,24 - 36,Win,https://a.espncdn.com/i/teamlogos/nfl/500/sea.png,https://a.espncdn.com/i/teamlogos/nfl/500/sf.png
|
8 |
+
96,7,20/10/2024 20:25,Levi's Stadium,San Francisco 49ers,Kansas City Chiefs,18 - 28,Loss,https://a.espncdn.com/i/teamlogos/nfl/500/sf.png,https://a.espncdn.com/i/teamlogos/nfl/500/kc.png
|
9 |
+
109,8,28/10/2024 00:20,Levi's Stadium,San Francisco 49ers,Dallas Cowboys,30 - 24,Win,https://a.espncdn.com/i/teamlogos/nfl/500/sf.png,https://a.espncdn.com/i/teamlogos/nfl/500/dal.png
|
10 |
+
149,10,10/11/2024 18:00,Raymond James Stadium,Tampa Bay Buccaneers,San Francisco 49ers,20 - 23,Win,https://a.espncdn.com/i/teamlogos/nfl/500/tb.png,https://a.espncdn.com/i/teamlogos/nfl/500/sf.png
|
11 |
+
158,11,17/11/2024 21:05,Levi's Stadium,San Francisco 49ers,Seattle Seahawks,17 - 20,Loss,https://a.espncdn.com/i/teamlogos/nfl/500/sf.png,https://a.espncdn.com/i/teamlogos/nfl/500/sea.png
|
12 |
+
169,12,24/11/2024 21:25,Lambeau Field,Green Bay Packers,San Francisco 49ers,38 - 10,Loss,https://a.espncdn.com/i/teamlogos/nfl/500/gb.png,https://a.espncdn.com/i/teamlogos/nfl/500/sf.png
|
13 |
+
181,13,02/12/2024 01:20,Highmark Stadium,Buffalo Bills,San Francisco 49ers,35 - 10,Loss,https://a.espncdn.com/i/teamlogos/nfl/500/buf.png,https://a.espncdn.com/i/teamlogos/nfl/500/sf.png
|
14 |
+
199,14,08/12/2024 21:25,Levi's Stadium,San Francisco 49ers,Chicago Bears,38 - 13,Win,https://a.espncdn.com/i/teamlogos/nfl/500/sf.png,https://a.espncdn.com/i/teamlogos/nfl/500/chi.png
|
15 |
+
224,15,13/12/2024 01:15,Levi's Stadium,San Francisco 49ers,Los Angeles Rams,6 - 12,Loss,https://a.espncdn.com/i/teamlogos/nfl/500/sf.png,https://a.espncdn.com/i/teamlogos/nfl/500/lar.png
|
16 |
+
228,16,22/12/2024 21:25,Hard Rock Stadium,Miami Dolphins,San Francisco 49ers,29 - 17,Loss,https://a.espncdn.com/i/teamlogos/nfl/500/mia.png,https://a.espncdn.com/i/teamlogos/nfl/500/sf.png
|
17 |
+
246,17,31/12/2024 01:15,Levi's Stadium,San Francisco 49ers,Detroit Lions,34 - 40,Loss,https://a.espncdn.com/i/teamlogos/nfl/500/sf.png,https://a.espncdn.com/i/teamlogos/nfl/500/det.png
|
18 |
+
257,18,05/01/2025 21:25,State Farm Stadium,Arizona Cardinals,San Francisco 49ers,47 - 24,Loss,https://a.espncdn.com/i/teamlogos/nfl/500/ari.png,https://a.espncdn.com/i/teamlogos/nfl/500/sf.png
|
docs/requirements.md
CHANGED
@@ -359,7 +359,7 @@ Based on a review of the existing codebase and requirements, here's a structured
|
|
359 |
|
360 |
## 11. Feature Work Log
|
361 |
|
362 |
-
### Step 1.2: Team Search Feature Implementation
|
363 |
|
364 |
#### Objective
|
365 |
Implement the Team Search feature (Feature 1 from Feature Overview) with focus on game recap display functionality.
|
@@ -373,26 +373,29 @@ Implement the Team Search feature (Feature 1 from Feature Overview) with focus o
|
|
373 |
|
374 |
#### Implementation Steps
|
375 |
|
376 |
-
1. **CSS Integration
|
377 |
- Add required CSS styles to the Gradio app
|
378 |
- Ensure styles support responsive layout
|
379 |
- Implement 49ers theme colors from Design System section
|
|
|
380 |
|
381 |
-
2. **Data Requirements Enhancement
|
382 |
- Review existing game score & result data
|
383 |
- Identify home team name and logo source
|
384 |
- Identify away team name and logo source
|
385 |
- Document data structure requirements
|
|
|
386 |
|
387 |
-
3. **CSV File Update
|
388 |
- Open `schedule_with_result_april_11.csv`
|
389 |
- Add columns for home team logo
|
390 |
- Add columns for away team logo
|
391 |
- Merge data from `nfl_team_logos_revised.csv`
|
392 |
- Validate data integrity
|
393 |
- Save as new version
|
|
|
394 |
|
395 |
-
4. **Static Gradio Component Development
|
396 |
- Create new component file
|
397 |
- Implement layout matching `game recap layout example.png`:
|
398 |
- Top row: away team elements
|
@@ -401,6 +404,7 @@ Implement the Team Search feature (Feature 1 from Feature Overview) with focus o
|
|
401 |
- Video preview box
|
402 |
- Use static assets for 49ers first game
|
403 |
- Implement responsive design
|
|
|
404 |
|
405 |
5. **Component Testing**
|
406 |
- Add component as first element in Gradio app
|
|
|
359 |
|
360 |
## 11. Feature Work Log
|
361 |
|
362 |
+
### Phase 1, Step 1.2: Team Search Feature Implementation
|
363 |
|
364 |
#### Objective
|
365 |
Implement the Team Search feature (Feature 1 from Feature Overview) with focus on game recap display functionality.
|
|
|
373 |
|
374 |
#### Implementation Steps
|
375 |
|
376 |
+
1. **CSS Integration ✅**
|
377 |
- Add required CSS styles to the Gradio app
|
378 |
- Ensure styles support responsive layout
|
379 |
- Implement 49ers theme colors from Design System section
|
380 |
+
- **Implementation:** CSS styles were embedded directly in the Gradio app as a string variable, ensuring compatibility with both local development and Hugging Face Spaces deployment. The implementation includes comprehensive styling for all UI components with the 49ers theme colors.
|
381 |
|
382 |
+
2. **Data Requirements Enhancement ✅**
|
383 |
- Review existing game score & result data
|
384 |
- Identify home team name and logo source
|
385 |
- Identify away team name and logo source
|
386 |
- Document data structure requirements
|
387 |
+
- **Implementation:** Analyzed the schedule CSV file and identified that home team names are in the "Home Team" column and away team names are in the "Away Team" column. Logo sources were identified in the "logo_url" column of the team logos CSV file, which provides direct URLs to team logos from ESPN's CDN.
|
388 |
|
389 |
+
3. **CSV File Update ✅**
|
390 |
- Open `schedule_with_result_april_11.csv`
|
391 |
- Add columns for home team logo
|
392 |
- Add columns for away team logo
|
393 |
- Merge data from `nfl_team_logos_revised.csv`
|
394 |
- Validate data integrity
|
395 |
- Save as new version
|
396 |
+
- **Implementation:** Created a Python script to merge the schedule data with team logo URLs. The script maps team names to their corresponding logo URLs and adds two new columns to the schedule CSV: 'home_team_logo_url' and 'away_team_logo_url'. The merged data was saved as 'schedule_with_result_and_logo_urls.csv'.
|
397 |
|
398 |
+
4. **Static Gradio Component Development ✅**
|
399 |
- Create new component file
|
400 |
- Implement layout matching `game recap layout example.png`:
|
401 |
- Top row: away team elements
|
|
|
404 |
- Video preview box
|
405 |
- Use static assets for 49ers first game
|
406 |
- Implement responsive design
|
407 |
+
- **Implementation:** Created a reusable game recap component in `components/game_recap_component.py` that displays team logos, names, scores, and highlights the winning team. The component uses the data from the merged CSV file and applies the 49ers theme styling. The component was integrated into the main Gradio app and tested independently.
|
408 |
|
409 |
5. **Component Testing**
|
410 |
- Add component as first element in Gradio app
|
gradio_app.py
CHANGED
@@ -6,11 +6,10 @@ from zep_cloud.client import AsyncZep
|
|
6 |
from zep_cloud.types import Message
|
7 |
|
8 |
# Import our components
|
9 |
-
# We need to modify the agent import to use our Gradio-compatible modules
|
10 |
-
# But we can't modify agent.py directly, so we'll import it and patch it
|
11 |
import agent
|
12 |
from gradio_graph import graph
|
13 |
import gradio_utils
|
|
|
14 |
|
15 |
# Patch the agent module to use our Gradio-compatible modules
|
16 |
import sys
|
@@ -21,6 +20,113 @@ sys.modules['llm'] = importlib.import_module('gradio_llm')
|
|
21 |
# Now we can safely import generate_response
|
22 |
from agent import generate_response
|
23 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
# Initialize Zep client
|
25 |
zep_api_key = os.environ.get("ZEP_API_KEY")
|
26 |
if not zep_api_key:
|
@@ -29,15 +135,25 @@ if not zep_api_key:
|
|
29 |
else:
|
30 |
zep = AsyncZep(api_key=zep_api_key)
|
31 |
|
32 |
-
# Global state management (replacing Streamlit's session_state)
|
33 |
class AppState:
|
34 |
def __init__(self):
|
35 |
-
self.
|
|
|
36 |
self.initialized = False
|
37 |
self.user_id = None
|
38 |
self.session_id = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
|
40 |
-
#
|
41 |
state = AppState()
|
42 |
|
43 |
# Add welcome message to state
|
@@ -52,9 +168,9 @@ I can help you with:
|
|
52 |
What would you like to know about today?
|
53 |
"""
|
54 |
|
55 |
-
#
|
56 |
async def initialize_chat():
|
57 |
-
"""
|
58 |
try:
|
59 |
# Generate unique identifiers for the user and session
|
60 |
state.user_id = gradio_utils.get_user_id()
|
@@ -77,8 +193,8 @@ async def initialize_chat():
|
|
77 |
user_id=state.user_id,
|
78 |
)
|
79 |
|
80 |
-
|
81 |
-
state.
|
82 |
state.initialized = True
|
83 |
|
84 |
return welcome_message
|
@@ -88,14 +204,12 @@ async def initialize_chat():
|
|
88 |
print(f"Error in initialize_chat: {str(e)}")
|
89 |
print(f"Traceback: {traceback.format_exc()}")
|
90 |
error_message = "There was an error starting the chat. Please refresh the page and try again."
|
91 |
-
state.
|
92 |
return error_message
|
93 |
|
94 |
-
#
|
95 |
async def process_message(message):
|
96 |
-
"""Process
|
97 |
-
print("Starting message processing...")
|
98 |
-
|
99 |
try:
|
100 |
# Store user message in Zep memory if available
|
101 |
if zep:
|
@@ -106,7 +220,7 @@ async def process_message(message):
|
|
106 |
)
|
107 |
|
108 |
# Add user message to state
|
109 |
-
state.
|
110 |
|
111 |
# Process with the agent
|
112 |
print('Calling generate_response function...')
|
@@ -120,7 +234,7 @@ async def process_message(message):
|
|
120 |
print(f"Extracted metadata: {metadata}")
|
121 |
|
122 |
# Add assistant response to state
|
123 |
-
state.
|
124 |
|
125 |
# Store assistant's response in Zep memory if available
|
126 |
if zep:
|
@@ -138,53 +252,53 @@ async def process_message(message):
|
|
138 |
print(f"Error in process_message: {str(e)}")
|
139 |
print(f"Traceback: {traceback.format_exc()}")
|
140 |
error_message = "I apologize, but I encountered an error. Could you please try again?"
|
141 |
-
state.
|
142 |
return error_message
|
143 |
|
144 |
# Function to handle user input in Gradio
|
145 |
def user_input(message, history):
|
146 |
-
"""Handle user input and update chat history"""
|
147 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
148 |
history.append({"role": "user", "content": message})
|
|
|
|
|
149 |
return "", history
|
150 |
|
151 |
# Function to generate bot response in Gradio
|
152 |
def bot_response(history):
|
153 |
-
"""Generate
|
154 |
# Get the last user message
|
155 |
user_message = history[-1]["content"]
|
156 |
|
157 |
-
# Process the message
|
158 |
response = asyncio.run(process_message(user_message))
|
159 |
|
160 |
-
# Add the
|
161 |
history.append({"role": "assistant", "content": response})
|
162 |
|
163 |
return history
|
164 |
|
165 |
-
# Function to initialize the chat when the app starts
|
166 |
-
#async def on_app_start():
|
167 |
-
"""Initialize the chat when the app starts"""
|
168 |
-
#if not state.initialized:
|
169 |
-
# welcome_message = await initialize_chat()
|
170 |
-
# return [{"role": "assistant", "content": welcome_message}]
|
171 |
-
#return []
|
172 |
-
|
173 |
-
# Initialize the chat before creating the interface
|
174 |
-
#initial_messages = asyncio.run(on_app_start())
|
175 |
-
initial_messages = [{"role": "assistant", "content": welcome_message}]
|
176 |
-
|
177 |
# Create the Gradio interface
|
178 |
-
with gr.Blocks(title="49ers FanAI Hub", theme=gr.themes.Soft()) as demo:
|
179 |
gr.Markdown("# 🏈 49ers FanAI Hub")
|
180 |
|
|
|
|
|
|
|
|
|
181 |
# Chat interface
|
182 |
chatbot = gr.Chatbot(
|
183 |
-
value=
|
184 |
height=500,
|
185 |
show_label=False,
|
186 |
elem_id="chatbot",
|
187 |
-
type="messages"
|
188 |
)
|
189 |
|
190 |
# Input components
|
@@ -210,8 +324,6 @@ with gr.Blocks(title="49ers FanAI Hub", theme=gr.themes.Soft()) as demo:
|
|
210 |
history.append({"role": "assistant", "content": response})
|
211 |
|
212 |
return "", history
|
213 |
-
|
214 |
-
|
215 |
|
216 |
# Set up event handlers with the combined function - explicitly disable queue
|
217 |
msg.submit(process_and_respond, [msg, chatbot], [msg, chatbot], queue=False)
|
@@ -223,6 +335,4 @@ with gr.Blocks(title="49ers FanAI Hub", theme=gr.themes.Soft()) as demo:
|
|
223 |
|
224 |
# Launch the app
|
225 |
if __name__ == "__main__":
|
226 |
-
# Disable the queue completely
|
227 |
-
#demo.queue(enabled=False)
|
228 |
demo.launch(share=True)
|
|
|
6 |
from zep_cloud.types import Message
|
7 |
|
8 |
# Import our components
|
|
|
|
|
9 |
import agent
|
10 |
from gradio_graph import graph
|
11 |
import gradio_utils
|
12 |
+
from components.game_recap_component import create_game_recap_component
|
13 |
|
14 |
# Patch the agent module to use our Gradio-compatible modules
|
15 |
import sys
|
|
|
20 |
# Now we can safely import generate_response
|
21 |
from agent import generate_response
|
22 |
|
23 |
+
# Define CSS directly
|
24 |
+
css = """
|
25 |
+
/* Base styles */
|
26 |
+
body {
|
27 |
+
font-family: 'Arial', sans-serif;
|
28 |
+
background-color: #111111;
|
29 |
+
color: #E6E6E6;
|
30 |
+
}
|
31 |
+
|
32 |
+
/* Headings */
|
33 |
+
h1, h2, h3 {
|
34 |
+
color: #AA0000;
|
35 |
+
}
|
36 |
+
|
37 |
+
/* Buttons */
|
38 |
+
button {
|
39 |
+
background-color: #AA0000;
|
40 |
+
color: #FFFFFF;
|
41 |
+
border: none;
|
42 |
+
padding: 10px 20px;
|
43 |
+
border-radius: 5px;
|
44 |
+
cursor: pointer;
|
45 |
+
}
|
46 |
+
|
47 |
+
button:hover {
|
48 |
+
background-color: #B3995D;
|
49 |
+
}
|
50 |
+
|
51 |
+
/* Game Recap Component */
|
52 |
+
.game-recap-container {
|
53 |
+
background-color: #111111;
|
54 |
+
padding: 20px;
|
55 |
+
margin: 20px 0;
|
56 |
+
border-radius: 10px;
|
57 |
+
}
|
58 |
+
|
59 |
+
.game-recap-row {
|
60 |
+
display: flex;
|
61 |
+
justify-content: space-between;
|
62 |
+
align-items: center;
|
63 |
+
margin: 20px 0;
|
64 |
+
}
|
65 |
+
|
66 |
+
.team-info {
|
67 |
+
text-align: center;
|
68 |
+
}
|
69 |
+
|
70 |
+
.team-logo {
|
71 |
+
width: 100px;
|
72 |
+
height: 100px;
|
73 |
+
margin-bottom: 10px;
|
74 |
+
}
|
75 |
+
|
76 |
+
.team-name {
|
77 |
+
font-size: 1.2em;
|
78 |
+
color: #E6E6E6;
|
79 |
+
}
|
80 |
+
|
81 |
+
.team-score {
|
82 |
+
font-size: 2em;
|
83 |
+
color: #FFFFFF;
|
84 |
+
font-weight: bold;
|
85 |
+
}
|
86 |
+
|
87 |
+
.winner {
|
88 |
+
color: #B3995D;
|
89 |
+
}
|
90 |
+
|
91 |
+
.video-preview {
|
92 |
+
background-color: #222222;
|
93 |
+
padding: 15px;
|
94 |
+
border-radius: 5px;
|
95 |
+
margin-top: 20px;
|
96 |
+
}
|
97 |
+
|
98 |
+
/* Chat Interface */
|
99 |
+
.chatbot {
|
100 |
+
background-color: #111111;
|
101 |
+
border: 1px solid #333333;
|
102 |
+
border-radius: 10px;
|
103 |
+
padding: 20px;
|
104 |
+
margin: 20px 0;
|
105 |
+
}
|
106 |
+
|
107 |
+
.message-input {
|
108 |
+
background-color: #222222;
|
109 |
+
color: #E6E6E6;
|
110 |
+
border: 1px solid #333333;
|
111 |
+
border-radius: 5px;
|
112 |
+
padding: 10px;
|
113 |
+
}
|
114 |
+
|
115 |
+
.clear-button {
|
116 |
+
background-color: #AA0000;
|
117 |
+
color: #FFFFFF;
|
118 |
+
border: none;
|
119 |
+
padding: 10px 20px;
|
120 |
+
border-radius: 5px;
|
121 |
+
cursor: pointer;
|
122 |
+
margin-top: 10px;
|
123 |
+
}
|
124 |
+
|
125 |
+
.clear-button:hover {
|
126 |
+
background-color: #B3995D;
|
127 |
+
}
|
128 |
+
"""
|
129 |
+
|
130 |
# Initialize Zep client
|
131 |
zep_api_key = os.environ.get("ZEP_API_KEY")
|
132 |
if not zep_api_key:
|
|
|
135 |
else:
|
136 |
zep = AsyncZep(api_key=zep_api_key)
|
137 |
|
|
|
138 |
class AppState:
|
139 |
def __init__(self):
|
140 |
+
self.chat_history = []
|
141 |
+
self.current_game = None
|
142 |
self.initialized = False
|
143 |
self.user_id = None
|
144 |
self.session_id = None
|
145 |
+
self.zep_client = None
|
146 |
+
|
147 |
+
def add_message(self, role, content):
|
148 |
+
self.chat_history.append({"role": role, "content": content})
|
149 |
+
|
150 |
+
def get_chat_history(self):
|
151 |
+
return self.chat_history
|
152 |
+
|
153 |
+
def set_current_game(self, game_data):
|
154 |
+
self.current_game = game_data
|
155 |
|
156 |
+
# Initialize global state
|
157 |
state = AppState()
|
158 |
|
159 |
# Add welcome message to state
|
|
|
168 |
What would you like to know about today?
|
169 |
"""
|
170 |
|
171 |
+
# Initialize the chat session
|
172 |
async def initialize_chat():
|
173 |
+
"""Initialize the chat session with Zep and return a welcome message."""
|
174 |
try:
|
175 |
# Generate unique identifiers for the user and session
|
176 |
state.user_id = gradio_utils.get_user_id()
|
|
|
193 |
user_id=state.user_id,
|
194 |
)
|
195 |
|
196 |
+
# Add welcome message to state
|
197 |
+
state.add_message("assistant", welcome_message)
|
198 |
state.initialized = True
|
199 |
|
200 |
return welcome_message
|
|
|
204 |
print(f"Error in initialize_chat: {str(e)}")
|
205 |
print(f"Traceback: {traceback.format_exc()}")
|
206 |
error_message = "There was an error starting the chat. Please refresh the page and try again."
|
207 |
+
state.add_message("system", error_message)
|
208 |
return error_message
|
209 |
|
210 |
+
# Process a message and return a response
|
211 |
async def process_message(message):
|
212 |
+
"""Process a message and return a response."""
|
|
|
|
|
213 |
try:
|
214 |
# Store user message in Zep memory if available
|
215 |
if zep:
|
|
|
220 |
)
|
221 |
|
222 |
# Add user message to state
|
223 |
+
state.add_message("user", message)
|
224 |
|
225 |
# Process with the agent
|
226 |
print('Calling generate_response function...')
|
|
|
234 |
print(f"Extracted metadata: {metadata}")
|
235 |
|
236 |
# Add assistant response to state
|
237 |
+
state.add_message("assistant", output)
|
238 |
|
239 |
# Store assistant's response in Zep memory if available
|
240 |
if zep:
|
|
|
252 |
print(f"Error in process_message: {str(e)}")
|
253 |
print(f"Traceback: {traceback.format_exc()}")
|
254 |
error_message = "I apologize, but I encountered an error. Could you please try again?"
|
255 |
+
state.add_message("assistant", error_message)
|
256 |
return error_message
|
257 |
|
258 |
# Function to handle user input in Gradio
|
259 |
def user_input(message, history):
|
260 |
+
"""Handle user input and update the chat history."""
|
261 |
+
# Check if this is the first message (initialization)
|
262 |
+
if not state.initialized:
|
263 |
+
# Initialize the chat session
|
264 |
+
asyncio.run(initialize_chat())
|
265 |
+
state.initialized = True
|
266 |
+
|
267 |
+
# Add the user message to the history
|
268 |
history.append({"role": "user", "content": message})
|
269 |
+
|
270 |
+
# Clear the input field
|
271 |
return "", history
|
272 |
|
273 |
# Function to generate bot response in Gradio
|
274 |
def bot_response(history):
|
275 |
+
"""Generate a response from the bot and update the chat history."""
|
276 |
# Get the last user message
|
277 |
user_message = history[-1]["content"]
|
278 |
|
279 |
+
# Process the message and get a response
|
280 |
response = asyncio.run(process_message(user_message))
|
281 |
|
282 |
+
# Add the bot response to the history
|
283 |
history.append({"role": "assistant", "content": response})
|
284 |
|
285 |
return history
|
286 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
287 |
# Create the Gradio interface
|
288 |
+
with gr.Blocks(title="49ers FanAI Hub", theme=gr.themes.Soft(), css=css) as demo:
|
289 |
gr.Markdown("# 🏈 49ers FanAI Hub")
|
290 |
|
291 |
+
# Game Recap Component
|
292 |
+
with gr.Row():
|
293 |
+
game_recap = create_game_recap_component(state.current_game)
|
294 |
+
|
295 |
# Chat interface
|
296 |
chatbot = gr.Chatbot(
|
297 |
+
value=state.get_chat_history(),
|
298 |
height=500,
|
299 |
show_label=False,
|
300 |
elem_id="chatbot",
|
301 |
+
type="messages"
|
302 |
)
|
303 |
|
304 |
# Input components
|
|
|
324 |
history.append({"role": "assistant", "content": response})
|
325 |
|
326 |
return "", history
|
|
|
|
|
327 |
|
328 |
# Set up event handlers with the combined function - explicitly disable queue
|
329 |
msg.submit(process_and_respond, [msg, chatbot], [msg, chatbot], queue=False)
|
|
|
335 |
|
336 |
# Launch the app
|
337 |
if __name__ == "__main__":
|
|
|
|
|
338 |
demo.launch(share=True)
|