Spaces:
Runtime error
Runtime error
| # src/services/claude_service.py | |
| import base64 | |
| from anthropic import Anthropic | |
| import streamlit as st | |
| from config.settings import ANTHROPIC_API_KEY, CLAUDE_MODEL | |
| class ClaudeService: | |
| def __init__(self): | |
| """Initialize Claude service with API key from HuggingFace secrets""" | |
| if not ANTHROPIC_API_KEY: | |
| raise ValueError("Anthropic API key not found in HuggingFace secrets. Please ensure ANTHROPIC_API_KEY is set in your space's secrets.") | |
| self.client = Anthropic(api_key=ANTHROPIC_API_KEY) | |
| self.model = CLAUDE_MODEL | |
| def analyze_image(self, image_data, prompt): | |
| """Analyze image using Claude Vision""" | |
| try: | |
| encoded_image = base64.b64encode(image_data).decode('utf-8') | |
| message = self.client.messages.create( | |
| model=self.model, | |
| max_tokens=1000, | |
| messages=[{ | |
| "role": "user", | |
| "content": [ | |
| { | |
| "type": "text", | |
| "text": prompt | |
| }, | |
| { | |
| "type": "image", | |
| "source": { | |
| "type": "base64", | |
| "media_type": "image/jpeg", | |
| "data": encoded_image | |
| } | |
| } | |
| ] | |
| }] | |
| ) | |
| return message.content[0].text | |
| except Exception as e: | |
| st.error(f"Error in image analysis: {str(e)}") | |
| return None | |
| def analyze_multiple_images(self, image_data_list, prompt): | |
| """Analyze multiple images together using Claude Vision""" | |
| try: | |
| # Create content list with prompt and all images | |
| content = [{"type": "text", "text": prompt}] | |
| # Add all images to the content | |
| for idx, image_data in enumerate(image_data_list): | |
| encoded_image = base64.b64encode(image_data).decode('utf-8') | |
| content.append({ | |
| "type": "image", | |
| "source": { | |
| "type": "base64", | |
| "media_type": "image/jpeg", | |
| "data": encoded_image | |
| } | |
| }) | |
| message = self.client.messages.create( | |
| model=self.model, | |
| max_tokens=1500, # Increased for multiple image analysis | |
| messages=[{ | |
| "role": "user", | |
| "content": content | |
| }] | |
| ) | |
| return message.content[0].text | |
| except Exception as e: | |
| st.error(f"Error in multiple image analysis: {str(e)}") | |
| return None | |
| def detect_chart_type(self, image_data): | |
| """Detect chart type from image""" | |
| prompt = """What type of financial chart is this? | |
| Choose from: Candlestick, Line, OHLC, Area, or Other. | |
| Just respond with one word.""" | |
| result = self.analyze_image(image_data, prompt) | |
| return result.strip() if result else "Other" | |
| def generate_diagram(self, prompt): | |
| """Generate an SVG diagram using Claude""" | |
| try: | |
| message = self.client.messages.create( | |
| model=self.model, | |
| max_tokens=1000, | |
| messages=[{ | |
| "role": "user", | |
| "content": f"""Please create an SVG diagram based on this request: {prompt} | |
| Make the diagram clean, professional, and educational. | |
| Use standard SVG elements and ensure the viewBox is properly set. | |
| Keep colors accessible and include clear labels.""" | |
| }] | |
| ) | |
| response = message.content[0].text | |
| # Extract SVG content if present | |
| if '<svg' in response and '</svg>' in response: | |
| svg_start = response.find('<svg') | |
| svg_end = response.find('</svg>') + 6 | |
| return response[svg_start:svg_end] | |
| return None | |
| except Exception as e: | |
| st.error(f"Error generating diagram: {str(e)}") | |
| return None | |
| def generate_educational_content(self, prompt): | |
| """Generate educational content using Claude""" | |
| try: | |
| message = self.client.messages.create( | |
| model=self.model, | |
| max_tokens=1500, | |
| messages=[{ | |
| "role": "user", | |
| "content": prompt | |
| }] | |
| ) | |
| return message.content[0].text | |
| except Exception as e: | |
| st.error(f"Error generating educational content: {str(e)}") | |
| return None | |
| def get_educational_content(self, concept): | |
| """Get educational content about trading concepts""" | |
| try: | |
| message = self.client.messages.create( | |
| model=self.model, | |
| max_tokens=1000, | |
| messages=[{ | |
| "role": "user", | |
| "content": f"""Please explain the trading concept '{concept}' | |
| in a clear, educational way. Include: | |
| 1. Basic Definition | |
| 2. How it Works | |
| 3. Key Characteristics | |
| 4. When to Look for It | |
| 5. Trading Implications | |
| 6. Common Mistakes to Avoid | |
| 7. Real-World Example""" | |
| }] | |
| ) | |
| return message.content[0].text | |
| except Exception as e: | |
| st.error(f"Error getting educational content: {str(e)}") | |
| return None | |
| def continue_analysis(self, question, previous_analysis, image_data=None): | |
| """Continue analysis based on follow-up question""" | |
| try: | |
| content = [ | |
| { | |
| "type": "text", | |
| "text": f"""Previous analysis: {previous_analysis} | |
| User's follow-up question: {question} | |
| Please provide a detailed answer to the follow-up question, | |
| maintaining the context of the previous analysis.""" | |
| } | |
| ] | |
| if image_data: | |
| encoded_image = base64.b64encode(image_data).decode('utf-8') | |
| content.append({ | |
| "type": "image", | |
| "source": { | |
| "type": "base64", | |
| "media_type": "image/jpeg", | |
| "data": encoded_image | |
| } | |
| }) | |
| message = self.client.messages.create( | |
| model=self.model, | |
| max_tokens=1000, | |
| messages=[{"role": "user", "content": content}] | |
| ) | |
| return message.content[0].text | |
| except Exception as e: | |
| st.error(f"Error in follow-up analysis: {str(e)}") | |
| return None |