from typing import Dict, Any from pydantic import BaseModel from groq import Groq import os LLM_MODEL = os.getenv("GROQ_MODEL", "llama-3.1-8b-instant") # fast + free-tier friendly class StrategyContext(BaseModel): match_title: str phase: str # "Powerplay" | "Middle" | "Death" striker: str non_striker: str batting_team: str bowling_team: str candidate_bowlers: list # from scoreboard / last used bowlers striker_recent: Dict[str, Any] # simple summary, e.g., dots, 4s, 6s vs pace/spin innings_state: Dict[str, Any] # score, over, req rate, wickets, venue (if available) def build_prompt(ctx: StrategyContext) -> str: return f""" You are an elite T20/ODI bowling strategist and fielding coach. Match: {ctx.match_title} Phase: {ctx.phase} Batting: {ctx.batting_team} Striker: {ctx.striker}, Non-striker: {ctx.non_striker} Bowling: {ctx.bowling_team} State: {ctx.innings_state} Striker recent profile (last 2-3 overs): {ctx.striker_recent} Candidate bowlers available: {", ".join(ctx.candidate_bowlers) if ctx.candidate_bowlers else "not provided"} TASKS: 1) Recommend the next OVER BOWLER (1-2 options) with reasoning. 2) Give a BALL-BY-BALL plan for 6 balls: {phase_plan(ctx.phase)} lengths & lines (yorker, hard length, slowers, wide lines). 3) Provide FIELD PLACEMENT (11 positions) tailored to the plan. 4) Add "IF/THEN" adaptations (e.g., if batter charges, switch to ___). 5) Keep it concise and actionable. Output format: - Bowler: - Plan (Balls 1-6): - Field Setting: - If/Then: """.strip() def phase_plan(phase: str) -> str: return { "Powerplay": "attack with swing, protect square boundaries", "Middle": "mix of pace-off and tight lines, choke singles", "Death": "yorkers/slow bouncers, avoid slot" }.get(phase, "balanced plans") def call_groq(prompt: str) -> str: api_key = os.getenv("GROQ_API_KEY") if not api_key: return "[Missing GROQ_API_KEY] Please set an environment variable." client = Groq(api_key=api_key) resp = client.chat.completions.create( model=LLM_MODEL, messages=[{"role": "system", "content": "Be precise, tactical, and match-aware."}, {"role": "user", "content": prompt}], temperature=0.5, max_tokens=600 ) return resp.choices[0].message.content def suggest_strategy(ctx: StrategyContext) -> str: prompt = build_prompt(ctx) return call_groq(prompt)