import os import json import openai import google.generativeai as genai import requests import logging from app.core.config import settings # Configure logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # ANSI color codes RED = "\033[91m" GREEN = "\033[92m" BLUE = "\033[94m" RESET = "\033[0m" class OpenAIClient: def __init__(self): self.api_key = settings.OPENAI_API_KEY openai.api_key = self.api_key self.model = settings.OPENAI_MODEL logger.info(f"Initialized OpenAIClient with model: {self.model}") async def generate_text(self, prompt, system_message=None, temperature=0.7): messages = [] if system_message: messages.append({"role": "system", "content": system_message}) messages.append({"role": "user", "content": prompt}) print(f"{GREEN}[OpenAIClient] Sending prompt:{RESET}", prompt[:500]) logger.info(f"OpenAIClient: Sending request with model {self.model}") try: response = openai.chat.completions.create( model=self.model, messages=messages, temperature=temperature, ) print(f"{GREEN}[OpenAIClient] Received response:{RESET}", response.choices[0].message.content[:500]) return response.choices[0].message.content except Exception as e: error_message = f"OpenAIClient error: {str(e)}" print(f"{GREEN}[OpenAIClient] {error_message}{RESET}") logger.error(error_message) raise class PerplexityClient: def __init__(self): # Hardcoded API key self.api_key = "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" self.base_url = "https://api.perplexity.ai" self.model = "sonar" logger.info(f"Initialized PerplexityClient with model: {self.model}") async def search_market_insights(self, query): print(f"{RED}[PerplexityClient] Query:{RESET}", query) if not self.api_key: error_message = "API key is missing or empty" print(f"{RED}[PerplexityClient] {error_message}, using mock data.{RESET}") logger.warning(error_message) result = self._get_mock_competitor_data(query) print(f"{RED}[PerplexityClient] Mock response:{RESET}", result[:500]) return result try: headers = { "Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json" } data = { "model": self.model, "messages": [{"role": "user", "content": query}], "stream": False } logger.info(f"PerplexityClient: Sending request to {self.base_url}/chat/completions with model {self.model}") response = requests.post( f"{self.base_url}/chat/completions", headers=headers, json=data ) if response.status_code != 200: error_message = f"API error {response.status_code}: {response.text}" print(f"{RED}[PerplexityClient] {error_message}, using mock data.{RESET}") logger.error(error_message) result = self._get_mock_competitor_data(query) print(f"{RED}[PerplexityClient] Mock response:{RESET}", result[:500]) return result result = response.json()["choices"][0]["message"]["content"] print(f"{RED}[PerplexityClient] API response:{RESET}", result[:500]) # Extract JSON from response if present import re json_pattern = r'```json(.*?)```' json_match = re.search(json_pattern, result, re.DOTALL) if json_match: # Extract the JSON content from between the backticks json_content = json_match.group(1).strip() return json_content return result except Exception as e: error_message = f"Exception: {str(e)}" print(f"{RED}[PerplexityClient] {error_message}, using mock data.{RESET}") logger.error(error_message) result = self._get_mock_competitor_data(query) print(f"{RED}[PerplexityClient] Mock response:{RESET}", result[:500]) return result def _get_mock_competitor_data(self, query): """ Generate mock competitor data when Perplexity API is unavailable """ # Extract startup name from query import re startup_name_match = re.search(r"for ([^,]+),", query) startup_name = startup_name_match.group(1) if startup_name_match else "YourStartup" # Extract problem from query problem_match = re.search(r"that (.*?) with", query) problem = problem_match.group(1) if problem_match else "solves a unique problem" # Generate generic competitors based on the problem mock_data = [ { "name": f"Competitor 1 for {startup_name}", "description": f"An established company that partially addresses {problem}", "strengths": [ "Strong market presence", "Established customer base", "Strong funding backing" ], "weaknesses": [ "Outdated technology", "Limited feature set", "Higher price point" ] }, { "name": f"Competitor 2 for {startup_name}", "description": f"A newer entrant focusing on a specific aspect of {problem}", "strengths": [ "Modern technology stack", "User-friendly interface", "Rapid innovation" ], "weaknesses": [ "Limited market reach", "Narrow focus", "Less comprehensive solution" ] }, { "name": f"Competitor 3 for {startup_name}", "description": f"A traditional player in the {problem} space", "strengths": [ "Industry experience", "Trusted brand", "Wide distribution network" ], "weaknesses": [ "Slow to innovate", "Complex user experience", "Higher operational costs" ] } ] return json.dumps(mock_data) class GeminiClient: def __init__(self): self.api_key = settings.GEMINI_API_KEY # Get model name from settings if available, else use default self.model_name = getattr(settings, "GEMINI_MODEL", "gemini-2.0-flash") logger.info(f"Initialized GeminiClient with model: {self.model_name}") if self.api_key: genai.configure(api_key=self.api_key) try: self.model = genai.GenerativeModel(self.model_name) logger.info(f"Successfully configured Gemini model: {self.model_name}") except Exception as e: error_message = f"Failed to initialize Gemini model: {str(e)}" logger.error(error_message) print(f"{BLUE}[GeminiClient] {error_message}{RESET}") self.model = None async def refine_business_angle(self, input_text): print(f"{BLUE}[GeminiClient] Input text:{RESET}", input_text[:500]) if not self.api_key: error_message = "No Gemini API key provided in .env file" print(f"{BLUE}[GeminiClient] {error_message}, using mock data.{RESET}") logger.warning(error_message) result = self._get_mock_market_positioning() print(f"{BLUE}[GeminiClient] Mock response:{RESET}", result[:500]) return result if not self.model: error_message = "Gemini model not properly initialized" print(f"{BLUE}[GeminiClient] {error_message}, using mock data.{RESET}") logger.error(error_message) result = self._get_mock_market_positioning() print(f"{BLUE}[GeminiClient] Mock response:{RESET}", result[:500]) return result try: logger.info(f"GeminiClient: Sending request with model {self.model_name}") response = self.model.generate_content(input_text) print(f"{BLUE}[GeminiClient] API response:{RESET}", response.text[:500]) return response.text except Exception as e: error_message = f"Exception: {str(e)}" print(f"{BLUE}[GeminiClient] {error_message}, using mock data.{RESET}") logger.error(error_message) result = self._get_mock_market_positioning() print(f"{BLUE}[GeminiClient] Mock response:{RESET}", result[:500]) return result def _get_mock_market_positioning(self): """ Generate mock market positioning when Gemini API is unavailable """ return """ Based on the analysis of your startup and competitors, here is a market positioning strategy: 1. Most Compelling Unique Value Proposition: Your integrated approach combining multiple aspects of the solution creates a more comprehensive and effective result than competitors who only focus on one element. This "full-stack" approach allows you to deliver superior outcomes with less complexity for customers. 2. Most Promising Market Segments to Target First: Focus on mid-sized businesses that are large enough to have the problem at a significant scale but not so large that they have custom in-house solutions. These businesses are seeking efficiency improvements but don't have the resources to build or integrate multiple point solutions. 3. Most Strategic Competitive Advantage to Emphasize: Your technological edge that allows you to provide a unified, seamless solution rather than requiring customers to piece together multiple tools. This not only improves results but significantly reduces implementation complexity and ongoing management overhead. """