shukdevdatta123's picture
Update app.py
731ec12 verified
import gradio as gr
import json
import re
from openai import OpenAI
from typing import List, Dict, Tuple, Optional
import time
import random
class MemoryPalaceBuilder:
def __init__(self):
self.client = None
self.current_palace = None
self.learning_sessions = []
def set_api_key(self, api_key: str) -> str:
"""Initialize OpenAI client with OpenRouter API key"""
try:
self.client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=api_key,
)
# Test the connection with a simple request
test_response = self.client.chat.completions.create(
model="deepseek/deepseek-r1-0528-qwen3-8b:free",
messages=[{"role": "user", "content": "Hello, respond with 'API connection successful'"}],
max_tokens=50
)
return "βœ… API Key validated successfully!"
except Exception as e:
return f"❌ API Key validation failed: {str(e)}"
def analyze_space(self, space_description: str, space_type: str) -> str:
"""Analyze the user's space and create a spatial map"""
if not self.client:
return "Please set your OpenRouter API key first."
prompt = f"""
Analyze this {space_type} space and create a detailed spatial map for a memory palace:
Space Description: {space_description}
Please provide a structured analysis with:
1. Key locations/rooms/areas identified
2. Natural pathways and flow between areas
3. Distinctive features that can serve as memory anchors
4. Sensory elements (lighting, textures, sounds, smells)
5. Emotional associations or significance of different areas
Format your response as a clear, organized spatial map that can be used for memory techniques. Always have a complete generated response
"""
try:
response = self.client.chat.completions.create(
model="deepseek/deepseek-r1-0528-qwen3-8b:free",
messages=[{"role": "user", "content": prompt}],
max_tokens=4000
)
return response.choices[0].message.content
except Exception as e:
return f"Error analyzing space: {str(e)}"
def create_memory_palace(self, space_analysis: str, learning_content: str, content_type: str, difficulty: str) -> str:
"""Create a memory palace mapping content to space"""
if not self.client:
return "Please set your OpenRouter API key first."
prompt = f"""
Create an intelligent memory palace using advanced spatial reasoning:
SPACE ANALYSIS:
{space_analysis}
CONTENT TO MEMORIZE:
Type: {content_type}
Difficulty: {difficulty}
Content: {learning_content}
Use chain-of-thought reasoning to:
1. Break down the content into logical chunks
2. Map each chunk to specific locations in the space
3. Create vivid, multi-sensory associations
4. Design a logical pathway that connects all information
5. Include memory triggers and retrieval cues
6. Add narrative elements to make it memorable
Provide:
- Step-by-step journey through the memory palace
- Specific visualizations for each location
- Memory techniques and mnemonics
- Practice suggestions
Make it engaging, creative, and scientifically sound for memory retention.
"""
try:
response = self.client.chat.completions.create(
model="deepseek/deepseek-r1-0528-qwen3-8b:free",
messages=[{"role": "user", "content": prompt}],
max_tokens=4000
)
palace_content = response.choices[0].message.content
self.current_palace = {
'space_analysis': space_analysis,
'content': learning_content,
'content_type': content_type,
'difficulty': difficulty,
'palace_design': palace_content,
'created_at': time.strftime("%Y-%m-%d %H:%M:%S")
}
return palace_content
except Exception as e:
return f"Error creating memory palace: {str(e)}"
def generate_quiz(self, quiz_type: str) -> Tuple[str, str]:
"""Generate quiz questions based on the current memory palace"""
if not self.client or not self.current_palace:
return "Please create a memory palace first.", ""
prompt = f"""
Based on this memory palace, create a {quiz_type} quiz:
MEMORY PALACE:
{self.current_palace['palace_design']}
ORIGINAL CONTENT:
{self.current_palace['content']}
Create 5 questions that test:
- Recall of specific information
- Understanding of spatial relationships
- Application of learned concepts
- Memory pathway navigation
Format as clear questions with multiple choice or fill-in-the-blank.
Provide the answer key separately.
"""
try:
response = self.client.chat.completions.create(
model="deepseek/deepseek-r1-0528-qwen3-8b:free",
messages=[{"role": "user", "content": prompt}],
max_tokens=4000
)
quiz_content = response.choices[0].message.content
# Try to separate questions and answers
if "ANSWER KEY" in quiz_content or "ANSWERS" in quiz_content:
parts = re.split(r"ANSWER[S]?\s*KEY|ANSWERS", quiz_content, flags=re.IGNORECASE)
questions = parts[0].strip()
answers = parts[1].strip() if len(parts) > 1 else "Answers included in response above."
else:
questions = quiz_content
answers = "Answers are integrated with questions above."
return questions, answers
except Exception as e:
return f"Error generating quiz: {str(e)}", ""
def get_study_tips(self) -> str:
"""Get personalized study tips and techniques"""
if not self.client or not self.current_palace:
return "Please create a memory palace first."
prompt = f"""
Provide advanced study tips and memory techniques for this memory palace:
PALACE INFO:
Content Type: {self.current_palace['content_type']}
Difficulty: {self.current_palace['difficulty']}
PALACE DESIGN:
{self.current_palace['palace_design'][:500]}...
Provide:
1. Optimal review schedule using spaced repetition
2. Advanced memory techniques to strengthen associations
3. Ways to expand and connect this palace to other knowledge
4. Troubleshooting common memory issues
5. Progressive difficulty adjustments
6. Multi-sensory enhancement techniques
"""
try:
response = self.client.chat.completions.create(
model="deepseek/deepseek-r1-0528-qwen3-8b:free",
messages=[{"role": "user", "content": prompt}],
max_tokens=4000
)
return response.choices[0].message.content
except Exception as e:
return f"Error getting study tips: {str(e)}"
def export_palace(self) -> str:
"""Export current memory palace as JSON"""
if not self.current_palace:
return "No memory palace to export."
return json.dumps(self.current_palace, indent=2)
# Initialize the Memory Palace Builder
palace_builder = MemoryPalaceBuilder()
# Custom CSS for better styling
custom_css = """
.gradio-container {
max-width: 1200px !important;
}
.palace-header {
text-align: center;
color: #2c5aa0;
margin: 20px 0;
}
.section-header {
background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 10px;
border-radius: 5px;
margin: 10px 0;
}
"""
def create_sample_inputs_accordion():
"""Create a Gradio accordion with all sample inputs for testing"""
with gr.Accordion("πŸ“‹ Sample Test Inputs & Examples", open=False):
gr.HTML("""
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px; border-radius: 10px; margin-bottom: 20px;">
<h2 style="margin: 0; text-align: center;">🏰 Memory Palace Builder - Test Guide</h2>
<p style="margin: 10px 0 0 0; text-align: center;">Copy these examples to test each feature</p>
</div>
""")
# API Setup Section
with gr.Accordion("πŸ”‘ API Setup", open=False):
gr.HTML("""
<div style="padding: 10px; background-color: #f8f9fa; border-radius: 5px;">
<h4>OpenRouter API Key:</h4>
<ul>
<li>Get your free API key from: <a href="https://openrouter.ai/" target="_blank">https://openrouter.ai/</a></li>
<li>Paste it in the password field and click "Validate API Key"</li>
</ul>
</div>
""")
# Space Analysis Section
with gr.Accordion("πŸ—ΊοΈ Space Analysis Examples", open=False):
with gr.Tab("🏠 Home/Apartment"):
gr.HTML("<h4>Space Type: Home/Apartment</h4>")
sample_home = gr.Textbox(
label="Sample Home Description",
value="""My studio apartment has a single main room with distinct areas. When you enter through the front door, there's a small entryway with a coat closet on the left. The living area has a comfortable blue sofa facing a 55-inch TV mounted on the white wall. Behind the sofa is a small dining table with two wooden chairs next to a large window that faces east and gets bright morning sunlight.
The kitchen area is along the right wall with white cabinets, a black granite countertop, a stainless steel refrigerator, and a small microwave. There's a distinctive red coffee maker on the counter that I use every morning.
The bedroom area is separated by a tall bookshelf filled with novels and textbooks. My bed has a navy blue comforter and sits against the far wall next to a wooden nightstand with a lamp that has a green shade.
The bathroom is compact with white tiles, a shower with a clear glass door, and a mirror with Hollywood-style lights around it. There's always a lavender scent from the candle on the sink counter.""",
lines=8,
max_lines=12
)
with gr.Tab("🏒 Office/Workplace"):
gr.HTML("<h4>Space Type: Office/Workplace</h4>")
sample_office = gr.Textbox(
label="Sample Office Description",
value="""My office is a rectangular room on the 5th floor with a large window overlooking the city park. My desk is positioned diagonally in the corner near the window - it's a modern white desk with a dual monitor setup and a mechanical keyboard that makes a satisfying clicking sound.
Behind my chair is a tall filing cabinet with a small cactus plant on top. To my left is a comfortable reading chair with a grey fabric cover next to a small side table where I keep my coffee mug.
The opposite wall has a whiteboard covered in colorful sticky notes and project timelines. Below it is a long credenza with three drawers where I store supplies. On top of the credenza are several awards and a photo of my family.
Near the door is a coat rack and a small waste basket. The lighting comes from overhead fluorescent lights and a warm desk lamp with an adjustable arm. The carpet is industrial grey, and there's always a faint smell of coffee from the break room down the hall.""",
lines=8,
max_lines=12
)
with gr.Tab("🚢 Neighborhood Route"):
gr.HTML("<h4>Space Type: Neighborhood Route</h4>")
sample_route = gr.Textbox(
label="Sample Walking Route Description",
value="""My daily walking route starts at my house with the red mailbox and proceeds down Maple Street. I pass the old oak tree with the tire swing, then the yellow house with the garden gnomes in the front yard.
At the first intersection, there's a stop sign and Mrs. Johnson's house with the purple door and wind chimes. I turn right onto Pine Avenue and walk past the small park with the blue playground and the memorial bench dedicated to local veterans.
Continuing straight, I pass the corner grocery store with the neon "OPEN" sign and the barber shop with the classic spinning pole. The route curves left at the fire station with its bright red trucks visible through the glass doors.
The final stretch goes past the community center with basketball courts where teenagers often play loud music, then the old church with the tall bell tower and beautiful stained glass windows, before ending back at my street near the bus stop with the green bench and newspaper stand.""",
lines=8,
max_lines=12
)
# Learning Content Section
with gr.Accordion("🏰 Learning Content Examples", open=False):
with gr.Tab("πŸ—£οΈ Language Vocabulary"):
gr.HTML("<h4>Content Type: Language Vocabulary | Difficulty: Intermediate</h4>")
sample_language = gr.Textbox(
label="Spanish Kitchen Vocabulary",
value="""Spanish Kitchen Vocabulary:
- cocina (kitchen) - koh-SEE-nah
- refrigerador (refrigerator) - reh-free-heh-rah-DOHR
- estufa (stove) - es-TOO-fah
- microondas (microwave) - mee-kroh-ON-dahs
- fregadero (sink) - freh-gah-DEH-roh
- mesa (table) - MEH-sah
- silla (chair) - SEE-yah
- plato (plate) - PLAH-toh
- vaso (glass) - VAH-soh
- cuchillo (knife) - koo-CHEE-yoh
- tenedor (fork) - teh-neh-DOHR
- cuchara (spoon) - koo-CHAH-rah""",
lines=8,
max_lines=15
)
with gr.Tab("πŸ“š Historical Facts"):
gr.HTML("<h4>Content Type: Historical Facts | Difficulty: Advanced</h4>")
sample_history = gr.Textbox(
label="World War II Pacific Theater Timeline",
value="""World War II Pacific Theater Timeline:
- December 7, 1941: Pearl Harbor attack - Japan surprises US naval base
- April 18, 1942: Doolittle Raid - First US bombing of Japanese mainland
- June 4-7, 1942: Battle of Midway - Decisive US naval victory
- August 7, 1942: Guadalcanal Campaign begins - First major Allied offensive
- October 20, 1944: MacArthur returns to Philippines - Battle of Leyte Gulf
- February 19, 1945: Iwo Jima invasion - Iconic flag raising photo
- April 1, 1945: Okinawa invasion - Largest Pacific campaign
- August 6, 1945: Hiroshima atomic bomb - "Little Boy"
- August 9, 1945: Nagasaki atomic bomb - "Fat Man"
- August 15, 1945: Japan surrenders - Emperor's radio broadcast""",
lines=8,
max_lines=12
)
with gr.Tab("πŸ’» Programming Concepts"):
gr.HTML("<h4>Content Type: Programming Code | Difficulty: Beginner</h4>")
sample_programming = gr.Textbox(
label="Python Data Types and Operations",
value="""Python Data Types and Operations:
- int: Whole numbers (5, -3, 0) - Use type(5)
- float: Decimal numbers (3.14, -2.5) - Use type(3.14)
- str: Text in quotes ("hello", 'world') - Use len("hello")
- bool: True or False values - Use type(True)
- list: Ordered collection [1, 2, 3] - Use append(), remove()
- dict: Key-value pairs {"name": "John"} - Use keys(), values()
- tuple: Immutable sequence (1, 2, 3) - Cannot change after creation
- set: Unique values {1, 2, 3} - Use add(), remove()
Common Operations:
- len() - Get length of object
- print() - Display output
- input() - Get user input
- range() - Generate number sequence""",
lines=10,
max_lines=15
)
with gr.Tab("πŸ”¬ Scientific Concepts"):
gr.HTML("<h4>Content Type: Scientific Concepts | Difficulty: Intermediate</h4>")
sample_science = gr.Textbox(
label="Periodic Table First 20 Elements",
value="""Periodic Table First 20 Elements:
1. Hydrogen (H) - Lightest element, fuel for stars
2. Helium (He) - Noble gas, makes balloons float
3. Lithium (Li) - Soft metal, used in batteries
4. Beryllium (Be) - Light metal, toxic to humans
5. Boron (B) - Metalloid, used in glass and ceramics
6. Carbon (C) - Basis of organic chemistry, diamond/graphite
7. Nitrogen (N) - 78% of atmosphere, inert gas
8. Oxygen (O) - 21% of atmosphere, essential for life
9. Fluorine (F) - Most reactive element, in toothpaste
10. Neon (Ne) - Noble gas, glows orange-red in tubes
11. Sodium (Na) - Reactive metal, table salt component
12. Magnesium (Mg) - Light metal, burns with bright white flame
13. Aluminum (Al) - Lightweight metal, common in foil/cans
14. Silicon (Si) - Metalloid, major component of computer chips
15. Phosphorus (P) - Essential for DNA, glows in dark
16. Sulfur (S) - Yellow nonmetal, rotten egg smell
17. Chlorine (Cl) - Green gas, table salt component
18. Argon (Ar) - Noble gas, used in light bulbs
19. Potassium (K) - Soft metal, essential nutrient
20. Calcium (Ca) - Metal, essential for bones and teeth""",
lines=12,
max_lines=20
)
# Testing Combinations Section
with gr.Accordion("🎯 Recommended Testing Combinations", open=False):
gr.HTML("""
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 15px; margin: 20px 0;">
<div style="background: #e8f5e8; padding: 15px; border-radius: 10px; border-left: 4px solid #28a745;">
<h4 style="color: #155724; margin-top: 0;">🟒 Easy Test</h4>
<ul style="margin: 0;">
<li><strong>Space:</strong> Home/Apartment</li>
<li><strong>Content:</strong> Programming Concepts</li>
<li><strong>Difficulty:</strong> Beginner</li>
</ul>
</div>
<div style="background: #fff3cd; padding: 15px; border-radius: 10px; border-left: 4px solid #ffc107;">
<h4 style="color: #856404; margin-top: 0;">🟑 Medium Test</h4>
<ul style="margin: 0;">
<li><strong>Space:</strong> Office/Workplace</li>
<li><strong>Content:</strong> Language Vocabulary</li>
<li><strong>Difficulty:</strong> Intermediate</li>
</ul>
</div>
<div style="background: #f8d7da; padding: 15px; border-radius: 10px; border-left: 4px solid #dc3545;">
<h4 style="color: #721c24; margin-top: 0;">πŸ”΄ Hard Test</h4>
<ul style="margin: 0;">
<li><strong>Space:</strong> Neighborhood Route</li>
<li><strong>Content:</strong> Historical Facts</li>
<li><strong>Difficulty:</strong> Advanced</li>
</ul>
</div>
<div style="background: #d1ecf1; padding: 15px; border-radius: 10px; border-left: 4px solid #17a2b8;">
<h4 style="color: #0c5460; margin-top: 0;">πŸš€ Expert Test</h4>
<ul style="margin: 0;">
<li><strong>Space:</strong> Custom detailed description</li>
<li><strong>Content:</strong> Scientific Concepts</li>
<li><strong>Difficulty:</strong> Expert</li>
</ul>
</div>
</div>
""")
# Quiz and Features Section
with gr.Accordion("πŸ“ Quiz Types & Features", open=False):
gr.HTML("""
<div style="background-color: #f8f9fa; padding: 15px; border-radius: 8px;">
<h4>Quiz Types to Test:</h4>
<ul>
<li><strong>Quick Review:</strong> 3-5 basic recall questions</li>
<li><strong>Comprehensive Test:</strong> 8-10 detailed questions covering all content</li>
<li><strong>Spatial Navigation:</strong> Questions about the palace journey and locations</li>
<li><strong>Random Recall:</strong> Mixed difficulty questions in random order</li>
</ul>
<h4>Other Features:</h4>
<ul>
<li><strong>Study Tips:</strong> Click after creating a palace for personalized strategies</li>
<li><strong>Export:</strong> Save your palace as JSON for later use</li>
</ul>
</div>
""")
# Step-by-step Testing Guide
with gr.Accordion("πŸ”„ Step-by-Step Testing Guide", open=False):
gr.HTML("""
<div style="background: linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%); padding: 20px; border-radius: 10px;">
<h4 style="margin-top: 0;">🎯 Quick 5-Minute Test:</h4>
<ol style="line-height: 1.6;">
<li><strong>Setup:</strong> Add your OpenRouter API key</li>
<li><strong>Space:</strong> Copy the studio apartment description</li>
<li><strong>Content:</strong> Use Spanish kitchen vocabulary</li>
<li><strong>Build:</strong> Set difficulty to "Intermediate" and create palace</li>
<li><strong>Test:</strong> Generate a "Quick Review" quiz</li>
<li><strong>Tips:</strong> Get personalized study recommendations</li>
<li><strong>Export:</strong> Save your first palace</li>
</ol>
<div style="margin-top: 15px; padding: 10px; background-color: rgba(255,255,255,0.7); border-radius: 5px;">
<strong>πŸ’‘ Pro Tip:</strong> Try different combinations to see how the AI adapts its spatial reasoning to different content types and difficulty levels!
</div>
</div>
""")
# Create the enhanced Gradio interface
with gr.Blocks(css=custom_css, title="Memory Palace Builder Enhanced", theme=gr.themes.Soft()) as app:
gr.HTML("""
<div class="palace-header">
<h1>🏰 Memory Palace Builder</h1>
<p>Transform any space into a powerful learning tool using AI-powered spatial mnemonics</p>
</div>
""")
# Add the sample inputs accordion at the top
create_sample_inputs_accordion()
with gr.Tab("πŸ”‘ Setup"):
gr.HTML("<div class='section-header'><h3>API Configuration</h3></div>")
with gr.Row():
api_key_input = gr.Textbox(
label="OpenRouter API Key",
placeholder="Enter your OpenRouter API key here...",
type="password",
info="Get your free API key from https://openrouter.ai/"
)
api_status = gr.Textbox(
label="API Status",
value="Not connected",
interactive=False
)
validate_btn = gr.Button("πŸ”— Validate API Key", variant="primary")
validate_btn.click(
palace_builder.set_api_key,
inputs=[api_key_input],
outputs=[api_status]
)
with gr.Tab("πŸ—ΊοΈ Space Analysis"):
gr.HTML("<div class='section-header'><h3>Describe Your Space</h3></div>")
with gr.Row():
with gr.Column():
space_type = gr.Dropdown(
choices=["Home/Apartment", "Office/Workplace", "School/University", "Neighborhood Route", "Park/Outdoor Space", "Other"],
label="Space Type",
value="Home/Apartment"
)
space_description = gr.Textbox(
lines=8,
label="Space Description",
placeholder="""Describe your space in detail. For example:
'My apartment has a front door that opens to a small hallway. To the left is the living room with a big window, couch, and TV. Straight ahead is the kitchen with white cabinets and a small dining table. The bedroom is to the right with a bed, dresser, and closet. The bathroom is next to the bedroom with a blue shower curtain.'
Include layouts, colors, furniture, lighting, and any distinctive features.""",
info="The more detail you provide, the better your memory palace will be!"
)
with gr.Column():
space_analysis_output = gr.Textbox(
lines=12,
label="Space Analysis",
placeholder="Your space analysis will appear here...",
interactive=False
)
analyze_btn = gr.Button("πŸ” Analyze Space", variant="primary", size="lg")
analyze_btn.click(
palace_builder.analyze_space,
inputs=[space_description, space_type],
outputs=[space_analysis_output]
)
with gr.Tab("🏰 Build Palace"):
gr.HTML("<div class='section-header'><h3>Create Your Memory Palace</h3></div>")
with gr.Row():
with gr.Column():
content_type = gr.Dropdown(
choices=["Language Vocabulary", "Historical Facts", "Scientific Concepts", "Programming Code", "Mathematical Formulas", "Medical Terms", "Literature/Poetry", "Business Concepts", "Other"],
label="Content Type",
value="Language Vocabulary"
)
difficulty = gr.Dropdown(
choices=["Beginner", "Intermediate", "Advanced", "Expert"],
label="Difficulty Level",
value="Intermediate"
)
learning_content = gr.Textbox(
lines=8,
label="Content to Memorize",
placeholder="""Enter the information you want to memorize. Examples:
For Language: 'French words: maison (house), chat (cat), livre (book), eau (water), rouge (red)'
For History: 'World War II timeline: 1939 - Germany invades Poland, 1941 - Pearl Harbor attack, 1944 - D-Day landings, 1945 - End of war'
For Programming: 'Python list methods: append(), remove(), pop(), insert(), index(), count()'""",
info="Be specific and organized - this will be mapped to your space!"
)
with gr.Column():
palace_output = gr.Textbox(
lines=15,
label="Your Memory Palace",
placeholder="Your custom memory palace will be generated here...",
interactive=False
)
create_btn = gr.Button("πŸ—οΈ Build Memory Palace", variant="primary", size="lg")
create_btn.click(
palace_builder.create_memory_palace,
inputs=[space_analysis_output, learning_content, content_type, difficulty],
outputs=[palace_output]
)
with gr.Tab("πŸ“ Practice & Quiz"):
gr.HTML("<div class='section-header'><h3>Test Your Memory Palace</h3></div>")
with gr.Row():
quiz_type = gr.Dropdown(
choices=["Quick Review", "Comprehensive Test", "Spatial Navigation", "Random Recall"],
label="Quiz Type",
value="Quick Review"
)
generate_quiz_btn = gr.Button("πŸ“‹ Generate Quiz", variant="secondary")
with gr.Row():
with gr.Column():
quiz_questions = gr.Textbox(
lines=10,
label="Quiz Questions",
placeholder="Quiz questions will appear here...",
interactive=False
)
with gr.Column():
quiz_answers = gr.Textbox(
lines=10,
label="Answer Key",
placeholder="Answer key will appear here...",
interactive=False
)
generate_quiz_btn.click(
palace_builder.generate_quiz,
inputs=[quiz_type],
outputs=[quiz_questions, quiz_answers]
)
with gr.Tab("πŸ’‘ Study Tips"):
gr.HTML("<div class='section-header'><h3>Personalized Learning Strategies</h3></div>")
get_tips_btn = gr.Button("🧠 Get Study Tips", variant="secondary", size="lg")
study_tips_output = gr.Textbox(
lines=15,
label="Personalized Study Tips",
placeholder="Personalized study strategies will appear here...",
interactive=False
)
get_tips_btn.click(
palace_builder.get_study_tips,
outputs=[study_tips_output]
)
with gr.Tab("πŸ’Ύ Export"):
gr.HTML("<div class='section-header'><h3>Save Your Memory Palace</h3></div>")
export_btn = gr.Button("πŸ“€ Export Palace as JSON", variant="secondary")
export_output = gr.Code(
label="Memory Palace Export",
language="json",
interactive=False
)
gr.HTML("""
<div style="margin-top: 20px; padding: 15px; background-color: #f0f0f0; border-radius: 5px;">
<h4>πŸ’‘ Tips for Using Your Memory Palace:</h4>
<ul>
<li><strong>Practice regularly:</strong> Walk through your palace daily for best retention</li>
<li><strong>Use multiple senses:</strong> Visualize, hear, and feel the associations</li>
<li><strong>Start simple:</strong> Master one palace before creating complex ones</li>
<li><strong>Be consistent:</strong> Always follow the same path through your space</li>
<li><strong>Make it personal:</strong> Use meaningful locations and vivid imagery</li>
</ul>
</div>
""")
export_btn.click(
palace_builder.export_palace,
outputs=[export_output]
)
# Launch the app
if __name__ == "__main__":
app.launch(
share=True
)