# app.py import os, re, time, json, requests, gradio as gr from rag_utils import RAG SPORTS_KEY = os.environ["SPORTS_DATA_API_KEY"] BASE = "https://api.sportsdata.io/v3/nfl/scores/json" HEADERS = {"Ocp-Apim-Subscription-Key": SPORTS_KEY} # documented header # 1) Helper: fetch all players once & cache (fallback for name search) PLAYERS_CACHE = "/tmp/players.json" def load_players(): if os.path.exists(PLAYERS_CACHE) and (time.time()-os.path.getmtime(PLAYERS_CACHE) < 86400): return json.load(open(PLAYERS_CACHE)) # Pull active players (small enough for demo). You can also hit roster-by-team and combine. url = f"{BASE}/Players" players = requests.get(url, headers=HEADERS, timeout=30).json() json.dump(players, open(PLAYERS_CACHE, "w")) return players PLAYERS = load_players() def find_player_id(name: str): name_norm = re.sub(r"[^a-z ]", "", name.lower()).strip() best = None for p in PLAYERS: full = f"{p.get('FirstName','')} {p.get('LastName','')}".strip().lower() if name_norm in full: best = p break return (best or {}), (best or {}).get("PlayerID") def fetch_player_news(player, pid, team_fallback=True, limit=10): items = [] # Preferred: player-specific news if plan supports it if pid: url_pid = f"{BASE}/NewsByPlayerID/{pid}" resp = requests.get(url_pid, headers=HEADERS, timeout=30) if resp.status_code == 200: items = resp.json() # Fallback: team news if not items and team_fallback and player.get("Team"): url_team = f"{BASE}/NewsByTeam/{player['Team']}" resp = requests.get(url_team, headers=HEADERS, timeout=30) if resp.status_code == 200: items = resp.json() # Massage into (title, content, source, updated) docs = [] for art in (items or [])[:limit]: text = f"{art.get('Title','')}\n\n{art.get('Content','')}" docs.append({ "title": art.get("Title",""), "content": text, "source": art.get("Source",""), "updated": art.get("Updated","") }) return docs RAG_ENGINE = RAG() def pipeline(player_name): player, pid = find_player_id(player_name) if not pid and not player: return f"Couldn’t find a player matching “{player_name}”. Try full name or a team hint." docs = fetch_player_news(player, pid) if not docs: return f"No recent articles found for {player.get('FirstName','')} {player.get('LastName','')}." summary, refs = RAG_ENGINE.summarize(docs) header = f"{player.get('FirstName','')} {player.get('LastName','')} ({player.get('Team','')}, {player.get('Position','')})" bullets = "\n".join([f"• {d['title']} — {d['source']} ({d['updated']})" for d in refs]) return f"{header}\n\n{summary}\n\nSources:\n{bullets}" with gr.Blocks() as demo: gr.Markdown("# NFL Chatbot — Player Updates") name = gr.Textbox(label="Player name", placeholder="e.g., Patrick Mahomes") out = gr.Textbox(label="Summary", lines=14) btn = gr.Button("Get latest") btn.click(fn=pipeline, inputs=name, outputs=out) if __name__ == "__main__": demo.launch()