Add ai_tic_tac_toe_agent folder

This commit is contained in:
Madhu 2025-01-02 04:06:48 +05:30
parent abb2cffa62
commit aba8da2c78
3 changed files with 345 additions and 0 deletions

View file

@ -0,0 +1,68 @@
# AI vs AI Tic-Tac-Toe Game 🎮
An interactive Tic-Tac-Toe game where two AI agents powered by different language models compete against each other built on phidata Agent Framework and Streamlit as UI. Watch as GPT-4O battles against either DeepSeek V3 or Google's Gemini 1.5 Flash in this classic game!
## Features 🌟
- Player X: Powered by OpenAI's GPT-4o (o1 models as api is yet to roll out for tier)
- Player O: Choice between DeepSeek AI or Google's Gemini
- Interactive game board using Streamlit
- Real-time move visualization
- AI Judge to determine game outcomes
- Clean and intuitive user interface
## Prerequisites 📋
- Python 3.8+
- OpenAI API key
- Either DeepSeek API key or Google API key (for Player O)
## How to Run 🚀
1. **Setup Environment**
```bash
# Clone the repository
git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git
cd ai_agent_tutorials/ai_tic_tac_toe_agent
# Install dependencies
pip install -r requirements.txt
```
2. **Configure API Keys**
- Get OpenAI API key from [OpenAI Platform](https://platform.openai.com)
- Get Google API key from [Google AI Studio](https://aistudio.google.com) (if using Gemini)
- Get DeepSeek API key from DeepSeek platform [Deepseek platform](https://www.deepseek.com) (if using DeepSeek v3 model)
4. **Run the Application**
```bash
streamlit run ai_tic_tac_toe_agent.py
```
5. **Using the Interface**
- Enter your API keys in the sidebar
- Click "Start Game" to begin
- Watch as the AI agents battle it out!
- Monitor the game progress and final results
## Game Components 🎯
- **Game Board**
- 3x3 interactive grid
- Real-time move visualization
- Clear symbol placement (X/O)
- **AI Players**
- Player X (GPT-4o): Strategic offensive moves
- Player O (DeepSeek/Gemini): Defensive countermoves since this agent started later
- AI Judge: Game outcome validation
- **Game Flow**
- Alternating turns between AIs
- Move validation and error handling
- Winner determination
- Draw detection
## Disclaimer ⚠️
This is a demonstration project showcasing AI capabilities in game playing. API costs will apply based on your usage of the OpenAI, DeepSeek, or Google APIs.

View file

@ -0,0 +1,273 @@
import re
import streamlit as st
from phi.agent import Agent
from phi.model.openai import OpenAIChat
from phi.model.deepseek import DeepSeekChat
from phi.model.google import Gemini
# Streamlit App Title
st.title("🤖 Tic-Tac-Toe: AI vs AI")
# Enhanced Welcome Message
with st.chat_message("assistant"):
st.markdown("""
**Welcome to the Tic-Tac-Toe AI Battle!** 🎮
This project pits two advanced AI agents against each other in a classic game of Tic-Tac-Toe.
Here's what you need to know:
""")
st.info("""
- **Player X**: Powered by OpenAI's GPT-4.
- **Player O**: Powered by DeepSeek's AI or Google's Gemini (if DeepSeek API key is not provided).
- **How to Play**: Enter your API keys in the sidebar, click **Start Game**, and watch the AI battle it out!
- **Goal**: The first player to get three of their symbols in a row (horizontally, vertically, or diagonally) wins.
- **Draw**: If the board fills up without a winner, the game ends in a draw.
""")
st.markdown("Ready to see who wins? Click the **Start Game** button below! 🚀")
# Initialize the game board in session state
if 'board' not in st.session_state:
st.session_state.board = [[None, None, None],
[None, None, None],
[None, None, None]]
# Function to display the board with better styling
def display_board(board):
st.markdown("""
<style>
.board {
display: grid;
grid-template-columns: repeat(3, 50px);
grid-template-rows: repeat(3, 50px);
gap: 5px;
margin-bottom: 20px;
}
.cell {
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #ccc;
font-size: 20px;
font-weight: bold;
}
</style>
""", unsafe_allow_html=True)
st.write("Current Board:")
board_html = '<div class="board">'
for row in board:
for cell in row:
cell_value = cell if cell is not None else "&nbsp;"
board_html += f'<div class="cell">{cell_value}</div>'
board_html += '</div>'
st.markdown(board_html, unsafe_allow_html=True)
# Function to get the board state as a string
def get_board_state(board):
rows = []
for i, row in enumerate(board):
row_str = " | ".join([f"({i},{j}) {cell or ' '}" for j, cell in enumerate(row)])
rows.append(f"Row {i}: {row_str}")
return "\n".join(rows)
# Function to check for a winner
def check_winner(board):
# Check rows
for row in board:
if row[0] == row[1] == row[2] and row[0] is not None:
return row[0]
# Check columns
for col in range(3):
if board[0][col] == board[1][col] == board[2][col] and board[0][col] is not None:
return board[0][col]
# Check diagonals
if board[0][0] == board[1][1] == board[2][2] and board[0][0] is not None:
return board[0][0]
if board[0][2] == board[1][1] == board[2][0] and board[0][2] is not None:
return board[0][2]
# Check for draw
if all(cell is not None for row in board for cell in row):
return "Draw"
return None
# Sidebar for API keys
st.sidebar.header("API Keys")
openai_api_key = st.sidebar.text_input("Enter your OpenAI API Key", type="password")
deepseek_api_key = st.sidebar.text_input("Enter your DeepSeek API Key", type="password")
google_api_key = st.sidebar.text_input("Enter your Google API Key (for Gemini)", type="password")
if openai_api_key:
st.session_state.openai_api_key = openai_api_key
if deepseek_api_key:
st.session_state.deepseek_api_key = deepseek_api_key
if google_api_key:
st.session_state.google_api_key = google_api_key
# Initialize agents if API keys are provided
if 'openai_api_key' in st.session_state:
player_x = Agent(
name="Player X",
model=OpenAIChat(id="gpt-4o", temperature=0.1, api_key=st.session_state.openai_api_key),
instructions=[
"You are a Tic-Tac-Toe player using the symbol 'X'.",
"Your opponent is using the symbol 'O'. Block their potential winning moves.",
"Make your move in the format 'row, col' based on the current board state.",
"Strategize to win by placing your symbol in a way that blocks your opponent from forming a straight line.",
"Do not include any explanations or extra text. Only provide the move.",
"Row and column indices start from 0.",
],
markdown=True,
)
# Initialize Player O with DeepSeek or Google Gemini
if 'deepseek_api_key' in st.session_state:
player_o = Agent(
name="Player O",
model=DeepSeekChat(api_key=st.session_state.deepseek_api_key),
instructions=[
"You are a Tic-Tac-Toe player using the symbol 'O'.",
"Your opponent is using the symbol 'X'. Block their potential winning moves.",
"Make your move in the format 'row, col' based on the current board state.",
"Strategize to win by placing your symbol in a way that blocks your opponent from forming a straight line.",
"Do not include any explanations or extra text. Only provide the move.",
"Row and column indices start from 0.",
],
markdown=True,
)
elif 'google_api_key' in st.session_state:
player_o = Agent(
name="Player O",
model=Gemini(id="gemini-1.5-flash", api_key=st.session_state.google_api_key),
instructions=[
"You are a Tic-Tac-Toe player using the symbol 'O'.",
"Your opponent is using the symbol 'X'. Block their potential winning moves.",
"Make your move in the format 'row, col' based on the current board state.",
"Strategize to win by placing your symbol in a way that blocks your opponent from forming a straight line.",
"Do not include any explanations or extra text. Only provide the move.",
"Row and column indices start from 0.",
],
markdown=True,
)
else:
st.warning("Please provide either a DeepSeek API key or a Google API key for Player O.")
judge = Agent(
name="Judge",
model=OpenAIChat(id="gpt-4o", temperature=0.1, api_key=st.session_state.openai_api_key),
instructions=[
"You are the judge of a Tic-Tac-Toe game.",
"The board is presented as rows with positions separated by '|'.",
"Rows are labeled from 0 to 2, and columns from 0 to 2.",
"Example board state:",
"Row 0: (0,0) X | (0,1) | (0,2) O",
"Row 1: (1,0) O | (1,1) X | (1,2) X",
"Row 2: (2,0) X | (2,1) O | (2,2) O",
"Determine the winner based on this board state.",
"The winner is the player with three of their symbols in a straight line (row, column, or diagonal).",
"If the board is full and there is no winner, declare a draw.",
"Provide only the result (e.g., 'Player X wins', 'Player O wins', 'Draw').",
],
markdown=True,
)
# Function to extract the move from the agent's response
def extract_move(response):
content = response.content.strip()
match = re.search(r'\d\s*,\s*\d', content)
if match:
move = match.group().replace(' ', '')
return move
numbers = re.findall(r'\d+', content)
if len(numbers) >= 2:
row = int(numbers[0])
col = int(numbers[1])
return f"{row},{col}"
return None
# Game loop
def play_game():
if 'current_player' not in st.session_state:
st.session_state.current_player = player_x
if 'symbol' not in st.session_state:
st.session_state.symbol = "X"
if 'move_count' not in st.session_state:
st.session_state.move_count = 0
max_moves = 9
winner = None # Initialize winner variable
while st.session_state.move_count < max_moves:
# Display the board
display_board(st.session_state.board)
# Prepare the board state for the agent
board_state = get_board_state(st.session_state.board)
move_prompt = (
f"Current board state:\n{board_state}\n"
f"{st.session_state.current_player.name}'s turn. Make your move in the format 'row, col'."
)
# Get the current player's move
with st.chat_message("assistant"):
st.write(f"**{st.session_state.current_player.name}'s turn:**")
move_response = st.session_state.current_player.run(move_prompt)
st.code(f"Agent {st.session_state.current_player.name} response:\n{move_response.content}", language="markdown")
move = extract_move(move_response)
st.write(f"**Extracted move:** {move}")
if move is None:
st.error("Invalid move! Please use the format 'row, col'.")
continue
try:
row, col = map(int, move.split(','))
if st.session_state.board[row][col] is not None:
st.error("Invalid move! Cell already occupied.")
continue
st.session_state.board[row][col] = st.session_state.symbol
except (ValueError, IndexError):
st.error("Invalid move! Please use the format 'row, col'.")
continue
# Check for a winner or draw
winner = check_winner(st.session_state.board)
if winner:
break # Exit the loop if there's a winner
# Switch players
st.session_state.current_player = player_o if st.session_state.current_player == player_x else player_x
st.session_state.symbol = "O" if st.session_state.symbol == "X" else "X"
st.session_state.move_count += 1
# After the game loop, display the final board and involve the judge agent
st.write("**Final Board:**")
display_board(st.session_state.board)
if winner:
st.success(f"**Result:** {winner}")
else:
st.success("**Result:** Draw")
# Judge's announcement
st.write("\n**Game Over. Judge is determining the result...**")
st.write("**Final board state passed to judge:**")
st.code(get_board_state(st.session_state.board), language="markdown")
judge_prompt = (
f"Final board state:\n{get_board_state(st.session_state.board)}\n"
f"Determine the winner and announce the result."
)
judge_response = judge.run(judge_prompt)
st.code(f"Judge's raw response:\n{judge_response.content}", language="markdown")
announcement = judge_response.content.strip()
st.success(f"**Judge's Announcement:** {announcement}")
# Start Game Button
if st.button("Start Game"):
st.session_state.board = [[None, None, None],
[None, None, None],
[None, None, None]]
st.session_state.current_player = player_x
st.session_state.symbol = "X"
st.session_state.move_count = 0
play_game()
else:
st.warning("Please enter your OpenAI API key and either Deepseek/Gemini API key to start the game.")

View file

@ -0,0 +1,4 @@
streamlit==1.41.1
phidata==2.7.3
openai==1.58.1
google-generativeai==0.8.3