import streamlit as st import anthropic import json import os # Initialize the Claude client with API key from environment (Huggingface secrets) api_key = os.getenv("ANTHROPIC_API_KEY") if not api_key: st.sidebar.error("ANTHROPIC_API_KEY not found in environment variables") client = None else: # Create the client try: client = anthropic.Anthropic(api_key=api_key) except Exception as e: st.sidebar.error(f"Error initializing Anthropic API: {str(e)}") client = None def enhance_slide_component(slide, component, instruction=None): """Enhance a specific component of a slide using Claude API""" if component == "title": return enhance_title(slide, instruction) elif component == "content": return enhance_content(slide, instruction) elif component == "visuals": return enhance_visuals(slide, instruction) elif component == "notes": return enhance_notes(slide, instruction) elif component == "structure": return enhance_structure(slide, instruction) else: return slide, {"error": f"Unknown component: {component}"} def enhance_title(slide, instruction=None): """Enhance the slide title using Claude""" prompt = f""" You are an expert presentation title specialist. Current slide title: "{slide.get('title', '')}" Slide context: - Purpose: {slide.get('purpose', 'N/A')} - Content: {slide.get('content', [])} {f"Special instruction: {instruction}" if instruction else ""} Please revise the title to be more engaging, clear, and aligned with the slide's purpose. Respond with only the new title text. """ try: response = client.messages.create( model="claude-3-7-sonnet-20250219", max_tokens=100, temperature=0.7, system="You are an expert presentation title specialist. Respond only with the revised title.", messages=[ {"role": "user", "content": prompt} ] ) result = response.content[0].text.strip() slide['title'] = result return slide, {"result": result} except Exception as e: return slide, {"error": str(e)} def enhance_content(slide, instruction=None): """Enhance slide content using Claude""" # Format current content if isinstance(slide.get('content', []), list): formatted_content = "\n".join([f"- {item}" for item in slide.get('content', [])]) else: formatted_content = str(slide.get('content', '')) prompt = f""" You are an expert presentation content specialist. Current slide content: {formatted_content} Slide context: - Title: {slide.get('title', 'N/A')} - Purpose: {slide.get('purpose', 'N/A')} {f"Special instruction: {instruction}" if instruction else ""} Please revise the content to be more effective and impactful. Format your response as a JSON array of bullet points like this: ["Point 1", "Point 2", "More detailed point 3"] Keep the presentation concise yet informative. Each bullet point should be 1-2 sentences maximum. """ try: response = client.messages.create( model="claude-3-7-sonnet-20250219", max_tokens=500, temperature=0.7, system="You are an expert presentation content specialist. Respond with a JSON array of bullet points.", messages=[ {"role": "user", "content": prompt} ] ) # Extract JSON from response content_text = response.content[0].text json_start = content_text.find("[") json_end = content_text.rfind("]") + 1 if json_start >= 0 and json_end > 0: json_str = content_text[json_start:json_end] result = json.loads(json_str) else: # Fallback if JSON parsing fails result = [line.strip().lstrip('- ') for line in content_text.split('\n') if line.strip() and not line.strip().startswith('```')] slide['content'] = result return slide, {"result": result} except Exception as e: return slide, {"error": str(e)} def enhance_visuals(slide, instruction=None): """Recommend visual elements for a slide using Claude""" # Format current content for context if isinstance(slide.get('content', []), list): content_text = "\n".join([f"- {item}" for item in slide.get('content', [])]) else: content_text = str(slide.get('content', '')) prompt = f""" You are an expert presentation visual designer. Slide title: {slide.get('title', 'N/A')} Slide content: {content_text} {f"Special instruction: {instruction}" if instruction else ""} Please recommend specific visual elements that would enhance this slide. Consider charts, diagrams, images, icons, and layout suggestions. Format as a JSON array of specific recommendations like: ["Bar chart comparing quarterly revenue", "Icon representing customer satisfaction", "Split-screen layout with image on left"] """ try: response = client.messages.create( model="claude-3-7-sonnet-20250219", max_tokens=300, temperature=0.7, system="You are an expert presentation visual designer. Respond with a JSON array of visual element recommendations.", messages=[ {"role": "user", "content": prompt} ] ) # Extract JSON from response content_text = response.content[0].text json_start = content_text.find("[") json_end = content_text.rfind("]") + 1 if json_start >= 0 and json_end > 0: json_str = content_text[json_start:json_end] result = json.loads(json_str) else: # Fallback if JSON parsing fails result = [line.strip().lstrip('- ') for line in content_text.split('\n') if line.strip() and not line.strip().startswith('```')] slide['visual_elements'] = result return slide, {"result": result} except Exception as e: return slide, {"error": str(e)} def enhance_notes(slide, instruction=None): """Generate presenter notes for a slide using Claude""" # Format content for context if isinstance(slide.get('content', []), list): content_text = "\n".join([f"- {item}" for item in slide.get('content', [])]) else: content_text = str(slide.get('content', '')) prompt = f""" You are an expert presentation coach and speech writer. Slide title: {slide.get('title', 'N/A')} Slide content: {content_text} Current presenter notes: {slide.get('notes', 'None')} {f"Special instruction: {instruction}" if instruction else ""} Please generate comprehensive presenter notes for this slide that will help the speaker deliver it effectively. Include talking points, emphasis guidance, and transitions. """ try: response = client.messages.create( model="claude-3-7-sonnet-20250219", max_tokens=500, temperature=0.7, system="You are an expert presentation coach. Provide comprehensive presenter notes.", messages=[ {"role": "user", "content": prompt} ] ) result = response.content[0].text.strip() slide['notes'] = result return slide, {"result": result} except Exception as e: return slide, {"error": str(e)} def enhance_structure(slide, instruction=None): """Optimize slide structure and layout using Claude""" # Format content for context if isinstance(slide.get('content', []), list): content_text = "\n".join([f"- {item}" for item in slide.get('content', [])]) else: content_text = str(slide.get('content', '')) prompt = f""" You are an expert presentation structure specialist. Slide title: {slide.get('title', 'N/A')} Slide content: {content_text} {f"Special instruction: {instruction}" if instruction else ""} Please analyze this slide's content and recommend the optimal structure and layout. Consider layout type, content organization, and visual hierarchy. Format your response as a JSON object with this structure: {{ "recommended_layout": "Layout name", "layout_rationale": "Why this layout works best", "content_structure": ["How content should be structured"], "emphasis": "What should be emphasized" }} """ try: response = client.messages.create( model="claude-3-7-sonnet-20250219", max_tokens=400, temperature=0.7, system="You are an expert presentation structure specialist. Respond with a JSON object containing layout recommendations.", messages=[ {"role": "user", "content": prompt} ] ) # Extract JSON from response content_text = response.content[0].text json_start = content_text.find("{") json_end = content_text.rfind("}") + 1 if json_start >= 0 and json_end > 0: json_str = content_text[json_start:json_end] result = json.loads(json_str) else: # Fallback result = { "recommended_layout": "Standard", "layout_rationale": "Standard layout suitable for most content", "content_structure": ["Use bullet points for clarity"], "emphasis": "Highlight key message in title" } if "design" not in slide: slide["design"] = {} slide["design"]["layout"] = result.get("recommended_layout") slide["structure_recommendations"] = result return slide, {"result": result} except Exception as e: return slide, {"error": str(e)}