""" Claude Haiku service for content generation. """ import json import logging from typing import Optional, List, Dict, Any from anthropic import Anthropic from ..config import get_settings from ..models.schemas import HaikuTagsResponse, HaikuContentResponse, TagCategory logger = logging.getLogger(__name__) class HaikuService: """Service for AI content generation using Claude Haiku.""" def __init__(self): """Initialize Anthropic client.""" settings = get_settings() self.client = Anthropic(api_key=settings.anthropic_api_key) self.model = "claude-3-5-haiku-20241022" def _call_haiku( self, system_prompt: str, user_prompt: str, max_tokens: int = 4096, ) -> str: """ Make a call to Claude Haiku. Args: system_prompt: System instructions user_prompt: User message max_tokens: Maximum response tokens Returns: Response text """ response = self.client.messages.create( model=self.model, max_tokens=max_tokens, system=system_prompt, messages=[{"role": "user", "content": user_prompt}], ) return response.content[0].text def extract_tags( self, company_name: str, website_markdown: Optional[str], address: Optional[str] = None, ) -> HaikuTagsResponse: """ Extract tags from company information. Args: company_name: Company name website_markdown: Scraped website content address: Company address Returns: Extracted tags with confidence """ system_prompt = """You are an expert at analyzing Odoo partner companies. Extract relevant tags from the provided company information. Respond with valid JSON only, no other text. Use this exact structure: { "services": ["list of services they offer"], "industries": ["list of industries they serve"], "modules": ["list of Odoo modules they specialize in"], "partner_level": "Ready Partner|Silver Partner|Gold Partner|Platinum Partner or null", "confidence": 0.0 to 1.0 } Valid services: Implementation, Customization, Training, Support, Migration, Integration, Consulting, Hosting, Development Valid industries: Manufacturing, Retail, E-commerce, Healthcare, Education, Finance, Logistics, Construction, Food & Beverage, Professional Services Valid modules: Sales, CRM, Inventory, Accounting, Manufacturing, Website, E-commerce, HR, Project, Purchase, Point of Sale Only include tags you can confidently identify from the content.""" user_prompt = f"""Company: {company_name} Address: {address or "Not provided"} Website content: {website_markdown[:8000] if website_markdown else "No website content available"} Extract tags for this Odoo partner company.""" try: response = self._call_haiku(system_prompt, user_prompt, max_tokens=1024) # Parse JSON response data = json.loads(response) return HaikuTagsResponse(**data) except json.JSONDecodeError as e: logger.error(f"Failed to parse tags response: {e}") return HaikuTagsResponse(confidence=0.0) except Exception as e: logger.error(f"Tag extraction failed: {e}") return HaikuTagsResponse(confidence=0.0) def generate_company_content( self, company_name: str, city_name: str, country_name: str, website_markdown: Optional[str], services: List[str], industries: List[str], modules: List[str], partner_level: Optional[str] = None, language: str = "de", ) -> HaikuContentResponse: """ Generate SEO-optimized company page content. Args: company_name: Company name city_name: City name country_name: Country name website_markdown: Scraped website content services: List of service tags industries: List of industry tags modules: List of module tags partner_level: Partner certification level language: Output language code Returns: Generated content """ lang_instructions = { "de": "Write all content in German (Deutsch).", "en": "Write all content in English.", "es": "Write all content in Spanish (Español).", "fr": "Write all content in French (Français).", "pt": "Write all content in Portuguese (Português).", "ar": "Write all content in Arabic (العربية).", } system_prompt = f"""You are an expert SEO content writer for Odoo partner directories. {lang_instructions.get(language, lang_instructions["en"])} Create engaging, informative content about an Odoo partner company. The content should be at least 800 words and SEO-optimized. Respond with valid JSON only: {{ "description": "2-3 sentence company description", "content_html": "Full HTML content with headings, paragraphs, lists", "meta_title": "SEO title (50-60 chars)", "meta_description": "SEO meta description (150-160 chars)" }} Include: - Company overview - Services offered - Industries served - Odoo modules expertise - Why choose this partner - Location information Use semantic HTML:
,
{company_name} ist ein zertifizierter Odoo Partner mit Sitz in {city_name}. Das Unternehmen bietet professionelle Odoo-Dienstleistungen für Unternehmen in der Region.
Als Odoo Partner bietet {company_name} folgende Leistungen: {services_text}.
{company_name} befindet sich in {city_name}, {country_name} und betreut Kunden in der gesamten Region.
""" meta_title = f"{company_name} - Odoo Partner in {city_name}" meta_desc = f"{company_name} ist Ihr Odoo Partner in {city_name}. Professionelle ERP-Beratung und Implementierung." else: description = f"{company_name} is an Odoo partner located in {city_name}, {country_name}." content = f"""{company_name} is a certified Odoo partner based in {city_name}. The company provides professional Odoo services for businesses in the region.
As an Odoo partner, {company_name} offers: {services_text}.
{company_name} is located in {city_name}, {country_name} and serves clients throughout the region.
""" meta_title = f"{company_name} - Odoo Partner in {city_name}" meta_desc = f"{company_name} is your Odoo partner in {city_name}. Professional ERP consulting and implementation." return HaikuContentResponse( description=description, content_html=content, meta_title=meta_title[:60], meta_description=meta_desc[:160], ) def generate_city_hub_content( self, city_name: str, country_name: str, company_count: int, top_services: List[str], language: str = "de", ) -> Dict[str, str]: """ Generate city hub page content. Args: city_name: City name country_name: Country name company_count: Number of companies in city top_services: Most common services language: Output language Returns: Dictionary with content sections """ lang_instructions = { "de": "Write in German.", "en": "Write in English.", } system_prompt = f"""You are an SEO expert writing city hub pages for an Odoo partner directory. {lang_instructions.get(language, "Write in English.")} Create compelling content (1000+ words) about finding Odoo partners in this city. Return valid JSON: {{ "intro": "Introduction paragraph about Odoo partners in this city", "content_html": "Full HTML content about Odoo services in this city", "meta_title": "SEO title (50-60 chars)", "meta_description": "Meta description (150-160 chars)" }}""" user_prompt = f"""City: {city_name}, {country_name} Number of Odoo Partners: {company_count} Top Services: {", ".join(top_services)} Create engaging city hub content for this Odoo partner directory.""" try: response = self._call_haiku(system_prompt, user_prompt) return json.loads(response) except Exception as e: logger.error(f"City hub content generation failed: {e}") return { "intro": f"Find Odoo partners in {city_name}.", "content_html": f"Discover {company_count} Odoo partners in {city_name}, {country_name}.
", "meta_title": f"Odoo Partners in {city_name}", "meta_description": f"Find {company_count} certified Odoo partners in {city_name}, {country_name}.", } def generate_country_hub_content( self, country_name: str, city_count: int, company_count: int, top_cities: List[str], language: str = "de", ) -> Dict[str, str]: """ Generate country hub page content. Args: country_name: Country name city_count: Number of cities with partners company_count: Total companies in country top_cities: Cities with most partners language: Output language Returns: Dictionary with content sections """ lang_instructions = { "de": "Write in German.", "en": "Write in English.", } system_prompt = f"""You are an SEO expert writing country hub pages for an Odoo partner directory. {lang_instructions.get(language, "Write in English.")} Create comprehensive content (1200+ words) about Odoo partners in this country. Return valid JSON: {{ "intro": "Introduction about Odoo partners in this country", "content_html": "Full HTML content about the Odoo ecosystem in this country", "meta_title": "SEO title (50-60 chars)", "meta_description": "Meta description (150-160 chars)" }}""" user_prompt = f"""Country: {country_name} Number of Cities: {city_count} Total Odoo Partners: {company_count} Top Cities: {", ".join(top_cities)} Create engaging country hub content for this Odoo partner directory.""" try: response = self._call_haiku(system_prompt, user_prompt) return json.loads(response) except Exception as e: logger.error(f"Country hub content generation failed: {e}") return { "intro": f"Find Odoo partners across {country_name}.", "content_html": f"Discover {company_count} Odoo partners in {city_count} cities across {country_name}.
", "meta_title": f"Odoo Partners in {country_name}", "meta_description": f"Find {company_count} certified Odoo partners in {city_count} cities across {country_name}.", }