# ai_interpreter.py """ AI interpretation module using Claude API. Handles astrological interpretations and user interactions. """ from typing import Dict, Any import streamlit as st import os from anthropic import Anthropic class AstroAI: """Handles AI-powered astrological interpretations""" def __init__(self): # Try multiple methods to get the API key api_key = None # Method 1: Try Streamlit secrets try: api_key = st.secrets["CLAUDE_API_KEY"] except Exception: pass # Method 2: Try environment variable if not api_key: api_key = os.getenv("CLAUDE_API_KEY") # Method 3: Try direct input if in development if not api_key and not os.getenv('PRODUCTION'): api_key = st.text_input("Enter your Claude API key:", type="password") if api_key: os.environ["CLAUDE_API_KEY"] = api_key if not api_key: raise ValueError(""" CLAUDE_API_KEY not found. Please set it using one of these methods: 1. Add to .streamlit/secrets.toml: CLAUDE_API_KEY = "your-key-here" 2. Set environment variable: export CLAUDE_API_KEY="your-key-here" 3. Enter it directly in the app (development mode only) """) self.client = Anthropic(api_key=api_key) st.session_state['api_initialized'] = True def _format_chart_data(self, chart_data: Dict[str, Any]) -> str: """Convert chart data to a readable format for the AI""" formatted = "Birth Chart Analysis:\n\n" # Format planetary positions formatted += "Planetary Positions:\n" for planet, data in chart_data['planets'].items(): if 'error' not in data: retrograde = data.get('retrograde', False) house = data.get('house', 'Unknown') formatted += (f"{planet}: {data['degrees']:.1f}° {data['sign']} " f"in House {house}" f"{' (Retrograde)' if retrograde else ''}\n") # Format aspects if 'aspects' in chart_data and chart_data['aspects']: formatted += "\nMajor Aspects:\n" for aspect in chart_data['aspects']: formatted += (f"{aspect['planet1']} {aspect['aspect']} {aspect['planet2']} " f"(Orb: {aspect['orb']}°)\n") # Format element and modality balances if 'patterns' in chart_data: if 'elements' in chart_data['patterns']: formatted += "\nElement Balance:\n" for element, count in chart_data['patterns']['elements'].items(): formatted += f"{element}: {count} planets\n" if 'modalities' in chart_data['patterns']: formatted += "\nModality Balance:\n" for modality, count in chart_data['patterns']['modalities'].items(): formatted += f"{modality}: {count} planets\n" return formatted def get_interpretation(self, chart_data: Dict[str, Any], question: str) -> str: """Generate an astrological interpretation based on the chart and user's question""" try: formatted_chart = self._format_chart_data(chart_data) system_prompt = """You are an expert astrologer with deep knowledge of both modern and traditional astrology. When interpreting charts: - Focus on the specific question asked while considering the whole chart context - Provide practical, actionable insights - Balance technical astrological terms with clear explanations - Consider aspect patterns, dignities, and dispositors - Include both challenging and supportive elements - Be honest but constructive in your interpretations """ # Print debug information st.write("Sending request to Claude API...") response = self.client.messages.create( model="claude-3-sonnet-20240229", max_tokens=1000, system=system_prompt, messages=[{ "role": "user", "content": f"""Based on the following birth chart data: {formatted_chart} Question: {question} Please provide an insightful astrological interpretation focusing specifically on the question asked.""" }] ) return response.content[0].text except Exception as e: error_message = f"Error generating interpretation: {str(e)}" st.error(error_message) return f"I apologize, but I encountered an error: {error_message}" def get_initial_analysis(self, chart_data: Dict[str, Any]) -> str: """Generate an initial overview analysis of the birth chart""" try: formatted_chart = self._format_chart_data(chart_data) system_prompt = """You are a skilled astrologer providing initial birth chart readings. In your analysis: - Start with the most prominent features of the chart - Highlight significant patterns and configurations - Discuss the balance of elements and modalities - Note any particularly strong or challenged planets - Keep the tone informative and encouraging - Use clear language while preserving astrological accuracy Structure your response with clear sections and insights. """ # Print debug information st.write("Generating initial analysis...") response = self.client.messages.create( model="claude-3-sonnet-20240229", max_tokens=1500, system=system_prompt, messages=[{ "role": "user", "content": f"""Please provide an initial overview analysis of this birth chart: {formatted_chart} Focus on the most significant patterns and features that form the core themes of this chart.""" }] ) return response.content[0].text except Exception as e: error_message = f"Error generating initial analysis: {str(e)}" st.error(error_message) return f"I apologize, but I encountered an error: {error_message}"