|
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_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 |
|
|
|
|
|
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) |
|
|
|
|
|
palace_builder = MemoryPalaceBuilder() |
|
|
|
|
|
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; |
|
} |
|
""" |
|
|
|
|
|
with gr.Blocks(css=custom_css, title="Memory Palace Builder", 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> |
|
""") |
|
|
|
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] |
|
) |
|
|
|
|
|
if __name__ == "__main__": |
|
app.launch( |
|
share=True |
|
) |