Spaces:
Running
Running
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 |