IFX-sandbox / tools /game_recap.py
aliss77777's picture
Upload folder using huggingface_hub
06cb2a3 verified
"""
Game Recap - LangChain tool for retrieving and generating game recaps
This module provides functions to:
1. Search for games in Neo4j based on natural language queries
2. Generate game recaps from the structured data
3. Return both text summaries and data for UI components
"""
# Import Gradio-specific modules directly
import sys
import os
# Add parent directory to path to access gradio modules
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from gradio_llm import llm
from gradio_graph import graph
from langchain_neo4j import GraphCypherQAChain
from langchain_core.prompts import PromptTemplate, ChatPromptTemplate
# Create a global variable to store the last retrieved game data
# This is a workaround for LangChain dropping structured data
LAST_GAME_DATA = None
# Function to get the cached game data
def get_last_game_data():
global LAST_GAME_DATA
return LAST_GAME_DATA
# Function to set the cached game data
def set_last_game_data(game_data):
global LAST_GAME_DATA
LAST_GAME_DATA = game_data
print(f"STORED GAME DATA IN CACHE: {game_data}")
# Create the Cypher generation prompt for game search
GAME_SEARCH_TEMPLATE = """
You are an expert Neo4j Developer translating user questions about NFL games into Cypher queries.
Your goal is to find a specific game in the database based on the user's description.
Convert the user's question based on the schema.
IMPORTANT NOTES:
1. Always return the FULL game node with ALL its properties.
2. Always use case-insensitive comparisons in your Cypher queries by applying toLower() to both the property and the search string.
3. If the question mentions a specific date, look for games on that date.
4. If the question mentions teams, look for games where those teams played.
5. If the question uses phrases like "last game", "most recent game", etc., you should add an ORDER BY clause.
6. NEVER use the embedding property in your queries.
7. ALWAYS include "g.game_id, g.date, g.location, g.home_team, g.away_team, g.result, g.summary, g.home_team_logo_url, g.away_team_logo_url, g.highlight_video_url" in your RETURN statement.
Example Questions and Queries:
1. "Tell me about the 49ers game against the Jets"
```
MATCH (g:Game)
WHERE (toLower(g.home_team) CONTAINS toLower("49ers") AND toLower(g.away_team) CONTAINS toLower("Jets"))
OR (toLower(g.away_team) CONTAINS toLower("49ers") AND toLower(g.home_team) CONTAINS toLower("Jets"))
RETURN g.game_id, g.date, g.location, g.home_team, g.away_team, g.result, g.summary,
g.home_team_logo_url, g.away_team_logo_url, g.highlight_video_url
```
2. "What happened in the 49ers game on October 9th?"
```
MATCH (g:Game)
WHERE (toLower(g.home_team) CONTAINS toLower("49ers") OR toLower(g.away_team) CONTAINS toLower("49ers"))
AND toLower(g.date) CONTAINS toLower("10/09")
RETURN g.game_id, g.date, g.location, g.home_team, g.away_team, g.result, g.summary,
g.home_team_logo_url, g.away_team_logo_url, g.highlight_video_url
```
3. "Show me the most recent 49ers game"
```
MATCH (g:Game)
WHERE (toLower(g.home_team) CONTAINS toLower("49ers") OR toLower(g.away_team) CONTAINS toLower("49ers"))
RETURN g.game_id, g.date, g.location, g.home_team, g.away_team, g.result, g.summary,
g.home_team_logo_url, g.away_team_logo_url, g.highlight_video_url
ORDER BY g.date DESC
LIMIT 1
```
Schema:
{schema}
Question:
{question}
"""
game_search_prompt = PromptTemplate.from_template(GAME_SEARCH_TEMPLATE)
# Create the game recap generation prompt
GAME_RECAP_TEMPLATE = """
You are a professional sports commentator for the NFL. Write an engaging and informative recap of the game described below.
Game Details:
- Date: {date}
- Location: {location}
- Home Team: {home_team}
- Away Team: {away_team}
- Final Score: {result}
- Summary: {summary}
Instructions:
1. Begin with an attention-grabbing opening that mentions both teams and the outcome.
2. Include key moments from the summary if available.
3. Mention the venue/location.
4. Conclude with what this means for the teams going forward.
5. Keep the tone professional and engaging - like an ESPN or NFL Network broadcast.
6. Write 2-3 paragraphs maximum.
7. If the 49ers are one of the teams, focus slightly more on their perspective.
8. IMPORTANT: Do NOT include any Markdown images, team logos, or links in your text response. Provide text only.
Write your recap:
"""
recap_prompt = PromptTemplate.from_template(GAME_RECAP_TEMPLATE)
# Create the Cypher QA chain for game search
game_search = GraphCypherQAChain.from_llm(
llm,
graph=graph,
verbose=True,
cypher_prompt=game_search_prompt,
return_direct=True, # Return the raw results instead of passing through LLM
allow_dangerous_requests=True # Required to enable Cypher queries
)
# Function to parse game data from Cypher result
def parse_game_data(result):
"""Parse the game data from the Cypher result into a structured format."""
if not result or not isinstance(result, list) or len(result) == 0:
return None
game = result[0]
# Extract home and away teams to determine winner
home_team = game.get('g.home_team', '')
away_team = game.get('g.away_team', '')
result_str = game.get('g.result', 'N/A')
# Parse the score if available
home_score = away_score = 'N/A'
winner = None
if result_str and result_str != 'N/A':
try:
scores = result_str.split('-')
if len(scores) == 2:
home_score = scores[0].strip()
away_score = scores[1].strip()
# Determine winner
home_score_int = int(home_score)
away_score_int = int(away_score)
winner = 'home' if home_score_int > away_score_int else 'away'
except (ValueError, IndexError):
pass
# Build the structured game data
game_data = {
'game_id': game.get('g.game_id', ''),
'date': game.get('g.date', ''),
'location': game.get('g.location', ''),
'home_team': home_team,
'away_team': away_team,
'home_score': home_score,
'away_score': away_score,
'result': result_str,
'winner': winner,
'summary': game.get('g.summary', ''),
'home_team_logo_url': game.get('g.home_team_logo_url', ''),
'away_team_logo_url': game.get('g.away_team_logo_url', ''),
'highlight_video_url': game.get('g.highlight_video_url', '')
}
return game_data
# Function to generate a game recap using LLM
def generate_game_recap(game_data):
"""Generate a natural language recap of the game using the LLM."""
if not game_data:
return "I couldn't find information about that game."
# Format the prompt with game data
formatted_prompt = recap_prompt.format(
date=game_data.get('date', 'N/A'),
location=game_data.get('location', 'N/A'),
home_team=game_data.get('home_team', 'N/A'),
away_team=game_data.get('away_team', 'N/A'),
result=game_data.get('result', 'N/A'),
summary=game_data.get('summary', 'N/A')
)
# Generate the recap using the LLM
recap = llm.invoke(formatted_prompt)
return recap.content if hasattr(recap, 'content') else str(recap)
# Main function to search for a game and generate a recap
def game_recap_qa(input_text):
"""
Search for a game based on the input text and generate a recap.
Args:
input_text (str): Natural language query about a game
Returns:
dict: Response containing text recap and structured game data
"""
try:
# Log the incoming query
print(f"Processing game recap query: {input_text}")
# Search for the game
search_result = game_search.invoke({"query": input_text})
# Check if we have a result
if not search_result or not search_result.get('result'):
return {
"output": "I couldn't find information about that game. Could you provide more details?",
"game_data": None
}
# Parse the game data
game_data = parse_game_data(search_result.get('result'))
if not game_data:
return {
"output": "I found information about the game, but couldn't process it correctly.",
"game_data": None
}
# Generate the recap
recap_text = generate_game_recap(game_data)
# CRITICAL: Store the game data in our cache so it can be retrieved later
# This is a workaround for LangChain dropping structured data
set_last_game_data(game_data)
# Return both the text and structured data
return {
"output": recap_text,
"game_data": game_data
}
except Exception as e:
print(f"Error in game_recap_qa: {str(e)}")
import traceback
traceback.print_exc()
return {
"output": "I encountered an error while searching for the game. Please try again with a different query.",
"game_data": None
}