# utils/learning_module.py from datetime import datetime import json from pathlib import Path import streamlit as st import base64 from PIL import Image import io TRADING_COURSES = { "Trading 101": { "title": "Introduction to Trading", "description": "Foundation course for beginners", "modules": [ { "title": "Understanding Markets", "topics": [ {"name": "What are Financial Markets", "requires_visuals": True}, {"name": "Types of Markets (Stocks, Forex, Crypto)", "requires_visuals": True}, {"name": "Market Participants", "requires_visuals": False}, {"name": "Basic Market Mechanics", "requires_visuals": True} ] }, { "title": "Trading Basics", "topics": [ {"name": "What is Trading", "requires_visuals": False}, {"name": "Different Trading Styles", "requires_visuals": False}, {"name": "Basic Chart Reading", "requires_visuals": True}, {"name": "Understanding Price Action", "requires_visuals": True} ] }, { "title": "Risk Management", "topics": [ {"name": "Importance of Risk Management", "requires_visuals": True}, {"name": "Position Sizing", "requires_visuals": True}, {"name": "Stop Loss Basics", "requires_visuals": True}, {"name": "Risk-Reward Ratio", "requires_visuals": True} ] } ] }, # Similar structure for Trading 201 and 301... } class LearningContent: def __init__(self, text_content, diagrams=None, examples=None): self.text_content = text_content self.diagrams = diagrams or [] self.examples = examples or [] class LearningModule: def __init__(self, claude_service): self.claude_service = claude_service self.data_dir = Path("data") self.learning_dir = self.data_dir / "learning" self.content_dir = self.learning_dir / "content" self.images_dir = self.learning_dir / "images" self.setup_directories() def setup_directories(self): """Create necessary directories""" for directory in [self.data_dir, self.learning_dir, self.content_dir, self.images_dir]: directory.mkdir(parents=True, exist_ok=True) def get_diagram_prompt(self, topic, concept): """Create a prompt for generating a diagram""" return f"""Create a clear, educational diagram to explain '{concept}' for {topic}. Make the diagram simple yet informative, suitable for learning purposes. Focus on key visual elements that help explain the concept. Use clear labels and annotations. Include a brief title and legend if necessary.""" def get_course_content(self, course_name, topic_data): """Get or generate detailed content for a specific topic""" topic = topic_data["name"] try: # Create unique identifier for content content_id = f"{course_name}_{topic}".replace(" ", "_").lower() content_file = self.content_dir / f"{content_id}.json" # Check if content is cached if content_file.exists(): with open(content_file, 'r') as f: stored_content = json.load(f) return LearningContent(**stored_content) # Generate new content base_prompt = f"""Create a comprehensive lesson for the topic '{topic}' in the {course_name} course. Structure the content as follows: 1. Overview 2. Key Concepts 3. Practical Examples 4. Common Mistakes to Avoid 5. Practice Exercises 6. Additional Resources Make this suitable for the course level: - Trading 101: Basic concepts, simple language - Trading 201: Intermediate concepts, some technical terms - Trading 301: Advanced concepts, technical language """ text_content = self.claude_service.generate_educational_content(base_prompt) diagrams = [] examples = [] # Generate diagrams if needed if topic_data.get("requires_visuals", False): # Extract key concepts for visualization concepts_prompt = f"List the 3 most important concepts from '{topic}' that would benefit from visual representation." concepts = self.claude_service.generate_educational_content(concepts_prompt).split('\n') for concept in concepts: # Generate diagram for each concept diagram_prompt = self.get_diagram_prompt(topic, concept) diagram = self.claude_service.generate_diagram(diagram_prompt) if diagram: # Save diagram diagram_filename = f"{content_id}_{len(diagrams)}.svg" diagram_path = self.images_dir / diagram_filename with open(diagram_path, 'w') as f: f.write(diagram) diagrams.append(diagram_filename) # Generate an example using the diagram example_prompt = f"Create a practical example explaining {concept} using the diagram." example = self.claude_service.generate_educational_content(example_prompt) examples.append({ 'concept': concept, 'example': example, 'diagram': diagram_filename }) # Create and cache content content = LearningContent( text_content=text_content, diagrams=diagrams, examples=examples ) with open(content_file, 'w') as f: json.dump(vars(content), f) return content except Exception as e: st.error(f"Error generating course content: {str(e)}") return None def display_content(self, content): """Display multi-modal content in the UI""" if not content: return # Display main content st.markdown(content.text_content) # Display examples with diagrams if content.examples: st.subheader("Interactive Examples") for example in content.examples: with st.expander(f"Example: {example['concept']}"): # Display diagram diagram_path = self.images_dir / example['diagram'] if diagram_path.exists(): with open(diagram_path, 'r') as f: svg_content = f.read() st.image(svg_content, use_container_width=True) # Display explanation st.markdown(example['example']) # Add interactive elements st.markdown("---") st.write("Try it yourself:") user_input = st.text_area("Practice your understanding:", key=f"practice_{example['concept']}") if st.button("Check Understanding", key=f"check_{example['concept']}"): feedback = self.claude_service.generate_educational_content( f"Provide constructive feedback on this understanding of {example['concept']}: {user_input}" ) st.write(feedback) def display_course_selection(self): """Display course selection interface""" st.subheader("Trading Courses") # Course selection selected_course = st.selectbox( "Select a Course", list(TRADING_COURSES.keys()), key="course_selector" ) course_data = TRADING_COURSES[selected_course] st.write(course_data["description"]) # Module selection selected_module = st.selectbox( "Select a Module", [module["title"] for module in course_data["modules"]], key="module_selector" ) # Find selected module data module_data = next(m for m in course_data["modules"] if m["title"] == selected_module) # Topic selection selected_topic_name = st.selectbox( "Select a Topic", [topic["name"] for topic in module_data["topics"]], key="topic_selector" ) selected_topic = next(t for t in module_data["topics"] if t["name"] == selected_topic_name) if st.button("Start Learning", key="start_learning"): with st.spinner("Loading content..."): content = self.get_course_content(selected_course, selected_topic) if content: self.display_content(content) def display_custom_learning(self): """Display custom learning interface""" st.subheader("Ask Any Trading Question") question = st.text_input( "What would you like to learn about?", key="custom_question" ) needs_visual = st.checkbox("Include visual explanation", value=True) if st.button("Get Answer", key="custom_answer"): if question: with st.spinner("Generating response..."): # Generate text response response = self.claude_service.generate_educational_content(question) if needs_visual: # Generate diagram diagram = self.claude_service.generate_diagram( self.get_diagram_prompt("Custom Learning", question) ) if diagram: # Save diagram diagram_filename = f"custom_{datetime.now().strftime('%Y%m%d_%H%M%S')}.svg" diagram_path = self.images_dir / diagram_filename with open(diagram_path, 'w') as f: f.write(diagram) # Display content st.markdown(response) with open(diagram_path, 'r') as f: svg_content = f.read() st.image(svg_content, use_container_width=True) else: st.markdown(response)