PierreBrunelle's picture
Upload 6 files
4b6484b verified
raw
history blame
11.8 kB
import gradio as gr
from src.game_logic import RPGGame
from src.database import interactions
def create_interface():
game = RPGGame()
with gr.Blocks(theme=gr.themes.Base()) as demo:
# Header with title and description
gr.Markdown(
"""
<div style="margin-bottom: 20px;">
<h1 style="margin-bottom: 0.5em;">🎲 AI RPG Adventure</h1>
<p>An interactive RPG experience from Pixeltable and powered by OpenAI! Get started with an example below.</p>
</div>
"""
)
# Side-by-side accordions
with gr.Row():
with gr.Column():
with gr.Accordion("🎯 What does it do?", open=False):
gr.Markdown("""
This AI RPG Adventure demonstrates Pixeltable's capabilities:
- 🎮 Creates dynamic, AI-driven interactive stories
- 🔄 Maintains game state and history using Pixeltable tables
- 💭 Generates contextual options based on player actions
- 📝 Processes natural language inputs for custom actions
- 🤖 Uses LLMs to create engaging narratives
- 📊 Tracks and displays game progression
Perfect for understanding how Pixeltable can manage complex,
stateful applications with AI integration! ✨
""")
with gr.Column():
with gr.Accordion("🛠️ How does it work?", open=False):
gr.Markdown("""
The app leverages several Pixeltable features:
1. 📦 **Data Management**: Uses Pixeltable tables to store game state,
player actions, and AI responses
2. 🤖 **AI Integration**: Seamlessly connects with language models
for story generation and response processing
3. 🔄 **State Tracking**: Maintains session history and player
choices using Pixeltable's computed columns
4. ⚙️ **Custom Processing**: Uses Pixeltable UDFs to handle game
logic and AI prompt generation
5. 🎯 **Interactive Flow**: Processes player inputs and generates
contextual responses in real-time
""")
with gr.Row():
# Setup column
with gr.Column():
player_name = gr.Textbox(
label="👤 Your Character's Name",
placeholder="Enter your character's name..."
)
genre = gr.Dropdown(
choices=[
"🧙‍♂️ Fantasy",
"🚀 Sci-Fi",
"👻 Horror",
"🔍 Mystery",
"🌋 Post-Apocalyptic",
"🤖 Cyberpunk",
"⚙️ Steampunk"
],
label="🎭 Choose Your Genre"
)
scenario = gr.Textbox(
label="📖 Starting Scenario",
lines=3,
placeholder="Describe the initial setting and situation..."
)
start_button = gr.Button("🎮 Begin Adventure", variant="primary")
# Game interaction column
with gr.Column():
story_display = gr.Textbox(
label="📜 Story",
lines=8,
interactive=False
)
gr.Markdown("### 🎯 Choose Your Action")
with gr.Row():
with gr.Column():
action_input = gr.Radio(
choices=[],
label="🎲 Select an action or write your own below:",
interactive=True
)
custom_action = gr.Textbox(
label="✨ Custom Action",
placeholder="Write your own action here...",
lines=2
)
submit_action = gr.Button("⚡ Take Action", variant="secondary")
# History display
history_df = gr.Dataframe(
headers=["📅 Turn", "🎯 Player Action", "💬 Game Response"],
label="📚 Adventure History",
wrap=True,
row_count=5,
col_count=(3, "fixed")
)
def start_new_game(name, genre_choice, scenario_text):
if not name or not genre_choice or not scenario_text:
return "Please fill in all fields before starting.", [], "", []
try:
_, initial_response = game.start_game(name, genre_choice, scenario_text)
# Get options from the initial response
options = interactions.select(interactions.options).where(
(interactions.session_id == game.current_session_id) &
(interactions.turn_number == 0)
).collect()['options'][0]
# Get initial history
history_df = interactions.select(
turn=interactions.turn_number,
action=interactions.player_input,
response=interactions.story_text
).where(
interactions.session_id == game.current_session_id
).order_by(
interactions.turn_number
).collect().to_pandas()
history_data = [
[str(row['turn']), row['action'], row['response']]
for _, row in history_df.iterrows()
]
return initial_response, gr.Radio(choices=options, interactive=True), "", history_data
except Exception as e:
return f"Error starting game: {str(e)}", [], "", []
def process_player_action(action_choice, custom_action):
try:
# Use custom action if provided, otherwise use selected choice
action = custom_action if custom_action else action_choice
if not action:
return "Please either select an action or write your own.", [], "", []
response = game.process_action(action)
# Get new options
options = interactions.select(interactions.options).where(
(interactions.session_id == game.current_session_id) &
(interactions.turn_number == game.turn_number)
).collect()['options'][0]
# Get updated history
history_df = interactions.select(
turn=interactions.turn_number,
action=interactions.player_input,
response=interactions.story_text
).where(
interactions.session_id == game.current_session_id
).order_by(
interactions.turn_number
).collect().to_pandas()
history_data = [
[str(row['turn']), row['action'], row['response']]
for _, row in history_df.iterrows()
]
return response, gr.Radio(choices=options, interactive=True), "", history_data
except Exception as e:
return f"Error: {str(e)}", [], "", []
# Connect the start button
start_button.click(
start_new_game,
inputs=[player_name, genre, scenario],
outputs=[story_display, action_input, custom_action, history_df]
)
# Single action submit button
submit_action.click(
process_player_action,
inputs=[action_input, custom_action],
outputs=[story_display, action_input, custom_action, history_df]
)
# Example scenarios
gr.Markdown("### 💫 Example Adventures")
gr.Examples(
examples=[
["Eldric", "🧙‍♂️ Fantasy", "You find yourself in an ancient forest clearing, standing before a mysterious glowing portal. Your journey begins..."],
["Commander Nova", "🚀 Sci-Fi", "Aboard the starship Nebula, alarms blare as unknown entities approach. The fate of the crew rests in your hands..."],
["Detective Blake", "🔍 Mystery", "In the fog-shrouded streets of Victorian London, a peculiar letter arrives at your doorstep..."],
],
inputs=[player_name, genre, scenario]
)
# Footer with links
gr.HTML(
"""
<div style="margin-top: 2rem; padding-top: 1rem; border-top: 1px solid #e5e7eb;">
<div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 1rem;">
<div style="flex: 1;">
<h4 style="margin: 0; color: #374151;">🚀 Built with Pixeltable</h4>
<p style="margin: 0.5rem 0; color: #6b7280;">
AI Data infrastructure providing a declarative, incremental approach for multimodal workloads.
</p>
</div>
<div style="flex: 1;">
<h4 style="margin: 0; color: #374151;">🔗 Resources</h4>
<div style="display: flex; gap: 1.5rem; margin-top: 0.5rem;">
<a href="https://github.com/pixeltable/pixeltable" target="_blank" style="color: #4F46E5; text-decoration: none; display: flex; align-items: center; gap: 0.25rem;">
💻 GitHub
</a>
<a href="https://docs.pixeltable.com" target="_blank" style="color: #4F46E5; text-decoration: none; display: flex; align-items: center; gap: 0.25rem;">
📚 Documentation
</a>
<a href="https://huggingface.co/Pixeltable" target="_blank" style="color: #4F46E5; text-decoration: none; display: flex; align-items: center; gap: 0.25rem;">
🤗 Hugging Face
</a>
</div>
</div>
</div>
<p style="margin: 1rem 0 0; text-align: center; color: #9CA3AF; font-size: 0.875rem;">
✨ © 2024 Pixeltable. This demo is open source and available on
<a href="https://huggingface.co/spaces/Pixeltable/AI-RPG-Adventure" target="_blank" style="color: #4F46E5; text-decoration: none;">
Hugging Face Spaces 🚀
</a>
</p>
</div>
"""
)
return demo