Spaces:
Running
Running
#!/usr/bin/env python3 | |
""" | |
Hockey Mind AI Chatbot - HuggingFace Spaces Deployment | |
Optimized for HuggingFace Spaces with database integration | |
""" | |
import gradio as gr | |
import asyncio | |
import os | |
from dotenv import load_dotenv | |
from Original_OpenAPI_DB import agentic_hockey_chat | |
# Load environment variables | |
load_dotenv() | |
# Global variable to track if resources are loaded | |
resources_loaded = False | |
async def chat_interface(user_role, user_team, user_prompt): | |
"""Interface function for Gradio with HockeyFood database integration""" | |
global resources_loaded | |
try: | |
# Validate inputs - allow greetings through | |
if not user_prompt or (len(user_prompt.strip()) < 3 and user_prompt.lower().strip() not in ["hi", "hey", "hello", "hoi", "hallo"]): | |
return "Please enter a hockey question (minimum 3 characters).", "" | |
# Load resources on first use to save memory | |
if not resources_loaded: | |
try: | |
from Original_OpenAPI_DB import load_resources | |
load_resources() | |
resources_loaded = True | |
except ImportError as import_err: | |
# Fallback for HuggingFace without full database | |
return f"Hockey AI: I can help with general hockey advice.\n\nYour question: {user_prompt}\n\nThis appears to be a hockey-related question. I'd recommend focusing on basic hockey fundamentals, practice drills, and asking specific technique questions.", "Limited mode - no database" | |
except Exception as load_err: | |
return f"System initializing... Please try again in a moment.", "Loading resources" | |
# Call the main chat function with timeout | |
try: | |
# Reasonable prompt length limits for HuggingFace | |
if len(user_prompt) > 200: | |
user_prompt = user_prompt[:200] + "..." | |
result = await asyncio.wait_for( | |
agentic_hockey_chat(user_role, user_team, user_prompt), | |
timeout=25.0 | |
) | |
except asyncio.TimeoutError: | |
return "Request timed out. Please try a shorter question.", "" | |
# Format response for Gradio with length limits | |
ai_response = result.get('ai_response', 'Sorry, no response generated.') | |
# Reasonable limits for HuggingFace deployment | |
if len(ai_response) > 600: | |
ai_response = ai_response[:600] + "..." | |
recommendations = result.get('recommended_content_details', []) | |
# Format recommendations with limits | |
rec_text = "" | |
if recommendations and len(recommendations) > 0: | |
try: | |
rec_list = [] | |
for i, rec in enumerate(recommendations[:3]): # Limit to 3 items | |
if i >= 3: # Double check | |
break | |
title = str(rec.get('title', 'No title'))[:60] # Limit title length | |
content_type = str(rec.get('type', 'unknown')) | |
# Show URL for multimedia items, content type for others | |
if content_type == 'multimedia' and rec.get('url'): | |
url = str(rec.get('url', ''))[:50] # Limit URL length | |
item = f"{i+1}. [{content_type}] {title}\n π {url}" | |
else: | |
item = f"{i+1}. [{content_type}] {title}" | |
rec_list.append(item) | |
if rec_list: | |
rec_text = "Recommended Content:\n" + "\n".join(rec_list) | |
if len(rec_text) > 300: | |
rec_text = rec_text[:300] + "..." | |
except Exception as rec_err: | |
rec_text = f"Recommendations unavailable" | |
return ai_response, rec_text | |
except Exception as e: | |
# Simplified error for HuggingFace | |
return "Sorry, there was an issue processing your request. Please try again with a simpler question.", "" | |
def sync_chat_interface(user_role, user_team, user_prompt): | |
"""Synchronous wrapper for Gradio""" | |
return asyncio.run(chat_interface(user_role, user_team, user_prompt)) | |
# Gradio Interface | |
with gr.Blocks( | |
title="π Hockey Mind AI Chatbot", | |
theme=gr.themes.Soft(), | |
css=""" | |
.gradio-container {max-width: 900px !important; margin: auto !important;} | |
.main-header {text-align: center; margin-bottom: 2rem;} | |
.feature-badge { | |
background: linear-gradient(45deg, #FF6B6B, #4ECDC4); | |
color: white; | |
padding: 5px 10px; | |
border-radius: 15px; | |
font-size: 0.8em; | |
font-weight: bold; | |
margin: 5px; | |
display: inline-block; | |
} | |
""" | |
) as demo: | |
gr.HTML(""" | |
<div class="main-header"> | |
<h1>π Hockey Mind AI Chatbot</h1> | |
<div class="feature-badge">ποΈ Hockey Database</div> | |
<div class="feature-badge">π― Smart Content Search</div> | |
<div class="feature-badge">π Multi-language</div> | |
<p>Get personalized hockey advice with training content and drills!</p> | |
</div> | |
""") | |
with gr.Row(): | |
with gr.Column(): | |
user_role = gr.Dropdown( | |
choices=["le Trainer", "le Coach", "Speler"], | |
label="Your Role π€", | |
value="Speler" | |
) | |
user_team = gr.Textbox( | |
label="Team/Level π", | |
placeholder="e.g., U10, Beginner, Advanced", | |
value="U10" | |
) | |
user_prompt = gr.Textbox( | |
label="Your Question β", | |
placeholder="Ask about drills, techniques, strategies, rules...", | |
lines=3 | |
) | |
submit_btn = gr.Button("Get Hockey Advice π", variant="primary", size="lg") | |
with gr.Row(): | |
ai_response = gr.Textbox( | |
label="π€ AI Response", | |
lines=8, | |
interactive=False | |
) | |
with gr.Row(): | |
recommendations = gr.Textbox( | |
label="π Recommended Content", | |
lines=6, | |
interactive=False | |
) | |
# Examples section | |
gr.HTML("<br><h3>π‘ Example Questions:</h3>") | |
examples = gr.Examples( | |
examples=[ | |
["Speler", "U8", "What are the best backhand shooting drills for young players?"], | |
["Speler", "Intermediate", "Show me exercises for improving stick handling"], | |
["le Coach", "U10", "What training drills help with ball control?"], | |
["Speler", "Advanced", "Find training content for penalty corners"], | |
], | |
inputs=[user_role, user_team, user_prompt], | |
outputs=[ai_response, recommendations], | |
fn=sync_chat_interface, | |
) | |
# Event handlers | |
submit_btn.click( | |
fn=sync_chat_interface, | |
inputs=[user_role, user_team, user_prompt], | |
outputs=[ai_response, recommendations], | |
api_name="chat" | |
) | |
user_prompt.submit( | |
fn=sync_chat_interface, | |
inputs=[user_role, user_team, user_prompt], | |
outputs=[ai_response, recommendations] | |
) | |
# Footer | |
gr.HTML(""" | |
<br> | |
<div style="text-align: center; color: #666; font-size: 0.9em; border-top: 1px solid #eee; padding-top: 20px;"> | |
<p>π <strong>Hockey Mind AI - Database Edition</strong></p> | |
<p>Powered by OpenRouter & Sentence Transformers</p> | |
<p>π Supports English & Dutch | Built for field hockey</p> | |
</div> | |
""") | |
# Launch for HuggingFace Spaces | |
if __name__ == "__main__": | |
print("π Launching Hockey Mind AI on HuggingFace Spaces...") | |
demo.launch( | |
server_name="0.0.0.0", | |
server_port=7860, | |
share=False, | |
show_error=True, | |
quiet=False | |
) | |