Spaces:
Sleeping
Sleeping
File size: 8,219 Bytes
699d672 9c848ec d54daef 699d672 d54daef 9c848ec 699d672 d54daef 699d672 9c848ec 699d672 9c848ec 699d672 9c848ec 699d672 9c848ec 699d672 9c848ec 699d672 9c848ec 699d672 d54daef 9c848ec d54daef 9c848ec 699d672 9c848ec 699d672 9c848ec 699d672 9c848ec 699d672 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
import gradio as gr
import json
import collections
from transformers import AutoModelForCausalLM, AutoTokenizer
# Define model name - use a very small model
MODEL_NAME = "TinyLlama/TinyLlama-1.1B-Chat-v1.0" # Chat-tuned 1.1B parameter model
print(f"Loading model {MODEL_NAME}...")
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
model = AutoModelForCausalLM.from_pretrained(
MODEL_NAME,
low_cpu_mem_usage=True, # CPU-friendly settings
device_map="cpu" # Force CPU usage
)
print("Model loaded successfully!")
def analyze_patterns(player_history, opponent_history):
"""Perform basic pattern analysis on the game history"""
analysis = {}
# Count frequencies of each move
move_counts = collections.Counter(opponent_history)
total_moves = len(opponent_history)
analysis["move_frequencies"] = {
"Rock": f"{move_counts.get('Rock', 0)}/{total_moves} ({move_counts.get('Rock', 0)*100/total_moves:.1f}%)",
"Paper": f"{move_counts.get('Paper', 0)}/{total_moves} ({move_counts.get('Paper', 0)*100/total_moves:.1f}%)",
"Scissors": f"{move_counts.get('Scissors', 0)}/{total_moves} ({move_counts.get('Scissors', 0)*100/total_moves:.1f}%)"
}
# Check response patterns (what opponent plays after player's moves)
response_patterns = {
"After_Rock": collections.Counter(),
"After_Paper": collections.Counter(),
"After_Scissors": collections.Counter()
}
for i in range(len(player_history) - 1):
player_move = player_history[i]
opponent_next = opponent_history[i + 1]
response_patterns[f"After_{player_move}"][opponent_next] += 1
analysis["response_patterns"] = {}
for pattern, counter in response_patterns.items():
if sum(counter.values()) > 0:
most_common = counter.most_common(1)[0]
analysis["response_patterns"][pattern] = f"{most_common[0]} ({most_common[1]}/{sum(counter.values())})"
# Check for repeating sequences
last_moves = opponent_history[-3:]
repeated_sequences = []
# Look for this sequence in history
for i in range(len(opponent_history) - 3):
if opponent_history[i:i+3] == last_moves:
if i+3 < len(opponent_history):
repeated_sequences.append(opponent_history[i+3])
if repeated_sequences:
counter = collections.Counter(repeated_sequences)
most_common = counter.most_common(1)[0]
analysis["sequence_prediction"] = f"After sequence {' → '.join(last_moves)}, opponent most often plays {most_common[0]} ({most_common[1]}/{len(repeated_sequences)} times)"
return analysis
def format_rps_game_prompt(game_data):
"""Format Rock-Paper-Scissors game data into a prompt for the LLM with pattern analysis"""
try:
# Parse the JSON game data
if isinstance(game_data, str):
game_data = json.loads(game_data)
# Extract key game information
player_history = game_data.get("player_history", [])
opponent_history = game_data.get("opponent_history", [])
rounds_played = len(player_history)
player_score = game_data.get("player_score", 0)
opponent_score = game_data.get("opponent_score", 0)
draws = game_data.get("draws", 0)
# Perform pattern analysis
pattern_analysis = analyze_patterns(player_history, opponent_history)
# Format analysis for prompt
move_frequencies = pattern_analysis.get("move_frequencies", {})
response_patterns = pattern_analysis.get("response_patterns", {})
sequence_prediction = pattern_analysis.get("sequence_prediction", "No clear sequence pattern detected")
# Create a more specific prompt with the analysis
prompt = f"""You are an expert Rock-Paper-Scissors strategy advisor helping a player win.
Game State:
- Rounds played: {rounds_played}
- Player score: {player_score}
- Opponent score: {opponent_score}
- Draws: {draws}
- Player's last 5 moves: {', '.join(player_history[-5:])}
- Opponent's last 5 moves: {', '.join(opponent_history[-5:])}
Pattern Analysis:
- Opponent's move frequencies:
* Rock: {move_frequencies.get('Rock', 'N/A')}
* Paper: {move_frequencies.get('Paper', 'N/A')}
* Scissors: {move_frequencies.get('Scissors', 'N/A')}
- Opponent's response patterns:
* After player's Rock: {response_patterns.get('After_Rock', 'No clear pattern')}
* After player's Paper: {response_patterns.get('After_Paper', 'No clear pattern')}
* After player's Scissors: {response_patterns.get('After_Scissors', 'No clear pattern')}
- Sequence analysis: {sequence_prediction}
Based on this pattern analysis, what should the player choose next (Rock, Paper, or Scissors)?
Explain your reasoning step-by-step, then end with: "Recommendation: [Rock/Paper/Scissors]"
"""
return prompt
except Exception as e:
return f"Error formatting prompt: {str(e)}\n\nPlease provide game data in a valid JSON format."
def generate_advice(game_data):
"""Generate advice based on game data using the LLM"""
try:
# Format the prompt
prompt = format_rps_game_prompt(game_data)
# Generate response from LLM (with CPU-only settings)
inputs = tokenizer(prompt, return_tensors="pt")
# Set max_length to avoid excessive generation
outputs = model.generate(
inputs["input_ids"],
max_new_tokens=150, # Allow more tokens for a more detailed response
do_sample=True,
temperature=0.7,
top_p=0.9
)
full_response = tokenizer.decode(outputs[0], skip_special_tokens=True)
# Extract just the model's response (remove the prompt)
if full_response.startswith(prompt):
response = full_response[len(prompt):].strip()
else:
response = full_response
# If model response is too short, add fallback advice
if len(response) < 30:
pattern_analysis = analyze_patterns(
json.loads(game_data)["player_history"] if isinstance(game_data, str) else game_data["player_history"],
json.loads(game_data)["opponent_history"] if isinstance(game_data, str) else game_data["opponent_history"]
)
# Simple fallback strategy based on pattern analysis
move_freqs = pattern_analysis.get("move_frequencies", {})
max_move = max(["Rock", "Paper", "Scissors"],
key=lambda m: float(move_freqs.get(m, "0/0 (0%)").split("(")[1].split("%")[0]))
# Choose counter to opponent's most frequent move
if max_move == "Rock":
suggestion = "Paper"
elif max_move == "Paper":
suggestion = "Scissors"
else:
suggestion = "Rock"
response += f"\n\nBased on opponent's move frequencies, they play {max_move} most often. \nRecommendation: {suggestion}"
return response
except Exception as e:
return f"Error generating advice: {str(e)}"
# Sample game data for the example
sample_game_data = {
"player_history": ["Rock", "Paper", "Scissors", "Rock", "Paper"],
"opponent_history": ["Scissors", "Rock", "Paper", "Scissors", "Rock"],
"player_score": 3,
"opponent_score": 2,
"draws": 0
}
# Create Gradio interface
with gr.Blocks(title="Rock-Paper-Scissors AI Assistant") as demo:
gr.Markdown("# Rock-Paper-Scissors AI Assistant")
gr.Markdown("Enter your game data to get advice on your next move.")
with gr.Row():
with gr.Column():
game_data_input = gr.Textbox(
label="Game State (JSON)",
placeholder=json.dumps(sample_game_data, indent=2),
lines=10
)
submit_btn = gr.Button("Get Advice")
with gr.Column():
output = gr.Textbox(label="AI Advice", lines=10)
submit_btn.click(generate_advice, inputs=[game_data_input], outputs=[output])
# Launch the app
demo.launch() |