hockey-mind-db / app.py
talhasideline's picture
Update app.py
8ea01ce verified
#!/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
)