From c1a894ad506e97d38eaaddde390675c0517452c2 Mon Sep 17 00:00:00 2001 From: Michael Ikehi Date: Mon, 21 Apr 2025 17:32:33 +0100 Subject: [PATCH] feat(feedback): Add content improvement feedback system Frontend (frontend/app.js): - Add textarea for improvement feedback - Add submit button with loading state - Handle API response and display improved content Backend (backend/copywriter.py): - Add improve_copy() method using Cohere API - Integrate retry mechanism for API calls Backend (backend/main.py): - Add /improve-content POST endpoint - Implement error handling and return improved content with metadata Testing: - Verified feedback submission flow - Confirmed improved content generation - Tested error scenarios and loading states --- backend/brand_style.py | 74 +- backend/config.py | 23 +- backend/copywriter.py | 139 ++- backend/vector_store.py | 213 +++-- data/training_data.db | Bin 8192 -> 8192 bytes data/vector_store/faiss_index.bin | Bin 12333 -> 127021 bytes data/vector_store/metadata.pkl | Bin 3917 -> 45291 bytes frontend/app.js | 493 ++++------ frontend/index.html | 43 +- frontend/styles.css | 97 +- logs/app.log | 1390 +++++++++-------------------- 11 files changed, 1001 insertions(+), 1471 deletions(-) diff --git a/backend/brand_style.py b/backend/brand_style.py index 3104434..7a25e22 100644 --- a/backend/brand_style.py +++ b/backend/brand_style.py @@ -13,7 +13,7 @@ import config class BrandStyleManager: """Manages brand style guidelines and ensures content consistency.""" - + def __init__(self): """Initialize the BrandStyleManager with default or stored style guidelines.""" self.style_path = Path(config.DATA_DIR) / "style_guidelines" / "brand_style.json" @@ -117,7 +117,7 @@ class BrandStyleManager: """ } logger.info("BrandStyleManager initialized successfully") - + def _load_or_create_style(self) -> Dict[str, Any]: """Load existing style guidelines or create new ones with defaults.""" try: @@ -129,37 +129,37 @@ class BrandStyleManager: else: # Create directory if it doesn't exist self.style_path.parent.mkdir(exist_ok=True) - + # Use default style guidelines style = config.DEFAULT_BRAND_STYLE - + # Save default style with open(self.style_path, 'w') as f: json.dump(style, f, indent=2) - + logger.info("Created default brand style guidelines") return style except Exception as e: logger.error(f"Error loading or creating style guidelines: {str(e)}") # Fall back to default style return config.DEFAULT_BRAND_STYLE - + def get_style_guidelines(self) -> Dict[str, Any]: """ Get current brand style guidelines. - + Returns: Dictionary of style guidelines """ return self.style_guidelines - + def update_style_guidelines(self, new_style: Dict[str, Any]) -> Dict[str, Any]: """ Update brand style guidelines. - + Args: new_style: Dictionary with new style guidelines - + Returns: Updated style guidelines dictionary """ @@ -167,37 +167,41 @@ class BrandStyleManager: # Merge new style with existing for key, value in new_style.items(): self.style_guidelines[key] = value - + # Ensure brand name is preserved self.style_guidelines['brand_name'] = config.BRAND_NAME - + # Save updated style with open(self.style_path, 'w') as f: json.dump(self.style_guidelines, f, indent=2) - + logger.info("Updated brand style guidelines") return self.style_guidelines except Exception as e: logger.error(f"Error updating style guidelines: {str(e)}") raise - + def format_prompt_with_brand_style(self, user_prompt: str, content_type: Optional[str] = None) -> str: - """Format user prompt to match the established writing style.""" - + """Format user prompt to match the distinctive communication style.""" + style_instructions = [ - "Follow these writing style guidelines:", - "- Use direct commands that empower the reader", - "- Address the reader directly using 'you' and 'your'", - "- Create rhythmic, repetitive patterns in key messages", - "- Maintain a clear, confident, and authoritative tone", - "- Use simple, practical language without jargon", - "- Acknowledge challenges while focusing on solutions", - "- Include empowering phrases that emphasize reader's control and choice" + "Follow these distinctive communication style guidelines:", + "- Use empowering, assertive language that inspires action", + "- Address the reader directly using 'you' and 'your' with conviction", + "- Create rhythmic, repetitive patterns in key messages for emphasis", + "- Maintain a clear, confident, and conversational teaching tone", + "- Use simple, practical language that communicates profound ideas", + "- Use embedded commands (e.g., 'Decide now to change your thinking')", + "- Include cause-effect statements (e.g., 'Because you understand this, you will now take action')", + "- Speak with conviction and clarity rather than hesitation", + "- Replace tentative phrases with confident declarations", + "- Use a motivational coach-like clarity in all communications", + "- IMPORTANT: Do not mention any specific person's name in the content" ] # Content type specific formatting content_format = self._get_content_format(content_type) if content_type else "" - + return "\n".join([ f"Generate content based on this request:", f"\"{user_prompt}\"", @@ -205,37 +209,37 @@ class BrandStyleManager: "\n".join(style_instructions), content_format ]) - + def check_content_alignment(self, content: str) -> Dict[str, Any]: """ Check if generated content aligns with brand style guidelines. - + Args: content: Generated marketing content - + Returns: Dictionary with alignment metrics and suggestions """ style = self.style_guidelines taboo_words = style.get('taboo_words', []) preferred_terms = style.get('preferred_terms', {}) - + # Check for taboo words found_taboo_words = [] for word in taboo_words: if word.lower() in content.lower(): found_taboo_words.append(word) - + # Check for preferred terminology terminology_issues = [] for avoid, use in preferred_terms.items(): if avoid.lower() in content.lower(): terminology_issues.append(f"Found '{avoid}', should use '{use}' instead") - + # Calculate an overall alignment score (simple implementation) issues_count = len(found_taboo_words) + len(terminology_issues) alignment_score = max(0, 100 - (issues_count * 10)) # Reduce score for each issue - + return { 'alignment_score': alignment_score, 'taboo_words_found': found_taboo_words, @@ -246,16 +250,16 @@ class BrandStyleManager: def _get_content_format(self, content_type: str) -> str: """ Get formatting instructions for specific content type. - + Args: content_type: Type of content to generate - + Returns: Formatting instructions as string """ if not content_type: return "" - + format_instructions = self.content_formats.get(content_type, "") if format_instructions: return f"\nContent type specific instructions:\n{format_instructions.strip()}" diff --git a/backend/config.py b/backend/config.py index a1ef94f..a04a292 100644 --- a/backend/config.py +++ b/backend/config.py @@ -52,12 +52,12 @@ CONTENT_TYPES = [ "newsletter" ] -# Tone options - simplified to match the core style +# Tone options - specifically matching Adriana James' communication style TONE_OPTIONS = [ - "direct", "empowering", - "confident", - "practical" + "assertive", + "inspirational", + "direct" ] # Content length options @@ -67,19 +67,22 @@ LENGTH_OPTIONS = [ "long", # > 300 words ] -# Default brand style guidelines +# Default brand style guidelines - fixed to match Adriana James' distinct communication style DEFAULT_BRAND_STYLE = { - "tone": ["direct", "empowering", "confident", "practical"], - "voice_characteristics": ["clear", "authoritative", "steady", "rhythmic"], - "writing_patterns": ["direct commands", "personal pronouns", "repetitive rhythms"], - "taboo_words": ["cheap", "discount", "bargain", "failure", "impossible", "difficult"], + "tone": ["empowering", "assertive", "inspirational", "direct"], + "voice_characteristics": ["clear", "confident", "conversational", "teaching"], + "writing_patterns": ["direct commands", "personal pronouns", "repetitive rhythms", "embedded commands", "cause-effect statements"], + "taboo_words": ["cheap", "discount", "bargain", "failure", "impossible", "difficult", "might", "try", "consider"], "preferred_terms": { "problems": "challenges", "try": "take action", "difficult": "ready for growth", "failure": "learning opportunity", "hope": "know", - "maybe": "will" + "maybe": "will", + "might help you": "you can do this", + "consider doing this": "decide now to change your thinking", + "this could work": "this works because" } } diff --git a/backend/copywriter.py b/backend/copywriter.py index 4014c87..52e0c24 100644 --- a/backend/copywriter.py +++ b/backend/copywriter.py @@ -16,13 +16,13 @@ from vector_store import vector_store class Copywriter: """Generates marketing copy using a fine-tuned LLM.""" - + def __init__(self): """Initialize the Copywriter with Cohere LLM client.""" self.model = "command" # Cohere's generation model self.api_key = config.COHERE_API_KEY logger.info("Copywriter initialized with Cohere API successfully") - + @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10)) async def generate_copy( self, @@ -40,34 +40,43 @@ class Copywriter: try: # Step 1: Format prompt with brand style guidelines branded_prompt = brand_style_manager.format_prompt_with_brand_style(prompt, content_type) - + # Step 2: Find similar content for reference (if enabled) reference_content = [] if reference_similar_content: + logger.info(f"Searching for similar content to reference for prompt: {prompt[:50]}...") search_results = await vector_store.search(prompt, top_k=3) if search_results: reference_content = [result['text'] for result in search_results] - + logger.info(f"Found {len(reference_content)} similar content items to reference") + for i, content in enumerate(reference_content): + logger.debug(f"Reference content {i+1}: {content[:100]}...") + else: + logger.warning("No similar content found in vector store for reference") + # Step 3: Add length and CTA instructions if needed if length: branded_prompt += f"\n- Generate {length} content" if include_cta: branded_prompt += "\n- Include a direct, empowering call to action" - + # Step 4: Add reference content if available if reference_content: branded_prompt += "\n\nReference these successful examples for tone and style:\n" branded_prompt += "\n---\n".join(reference_content) - + # Step 5: Generate content using the LLM generated_content = await self._call_llm_api(branded_prompt, max_tokens) - - # Step 6: Check content alignment with brand style + + # Step 6: Post-process to remove any mentions of Adriana James + generated_content = self._remove_name_mentions(generated_content) + + # Step 7: Check content alignment with brand style alignment_check = brand_style_manager.check_content_alignment(generated_content) - + # Step 7: Generate alternative headline suggestions headline_suggestions = await self._generate_headline_suggestions(prompt, generated_content) - + # Step 8: Return the generated content with metadata result = { "content": generated_content, @@ -79,21 +88,21 @@ class Copywriter: "generated_at": None # Will be added by the API } } - + # Add alignment issues if any if alignment_check['taboo_words_found'] or alignment_check['terminology_issues']: result["alignment_issues"] = { "taboo_words_found": alignment_check['taboo_words_found'], "terminology_issues": alignment_check['terminology_issues'] } - + logger.info(f"Generated content with {len(generated_content)} characters") return result - + except Exception as e: logger.error(f"Error generating copy: {str(e)}") raise - + @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10)) async def _call_llm_api(self, prompt: str, max_tokens: int = 1000) -> str: """ @@ -102,12 +111,11 @@ class Copywriter: Args: prompt: The formatted prompt for the LLM max_tokens: Maximum tokens for the generated response - + Returns: - Generated content as a string + Generated content as a string with preserved formatting """ try: - # Use Cohere's generate API with the API key from config cohere_api_key = config.COHERE_API_KEY async with httpx.AsyncClient() as client: @@ -118,19 +126,30 @@ class Copywriter: "Content-Type": "application/json" }, json={ - "model": "command", # Cohere's generation model - "prompt": prompt, + "model": "command", + "prompt": f"{prompt}\n\nNote: Please preserve formatting with proper paragraphs, line breaks, and bullet points where appropriate.", "max_tokens": max_tokens, "temperature": 0.7, "k": 0, - "p": 0.75 + "p": 0.75, + "return_likelihoods": "NONE" }, timeout=30.0 ) if response.status_code == 200: result = response.json() - return result["generations"][0]["text"].strip() + generated_text = result["generations"][0]["text"].strip() + + # Preserve paragraph breaks and formatting + formatted_text = ( + generated_text + .replace("\n\n", "") # Preserve paragraph breaks + .replace("\n- ", "\n• ") # Convert hyphens to bullets + .replace("", "\n\n") # Restore paragraph breaks + ) + + return formatted_text else: logger.error(f"Cohere API error: {response.status_code}, {response.text}") raise Exception(f"Cohere API error: {response.status_code}") @@ -138,24 +157,25 @@ class Copywriter: except Exception as e: logger.error(f"Error calling Cohere API: {str(e)}") raise - + async def _generate_headline_suggestions(self, original_prompt: str, generated_content: str) -> List[str]: """ Generate alternative headline suggestions based on the content. - + Args: original_prompt: The original user prompt generated_content: The generated marketing content - + Returns: List of headline suggestions """ try: # Create a prompt for headline generation headline_prompt = f""" - Generate 3 alternative marketing headlines for the following content. + Generate 3 alternative marketing headlines for the following content. Make headlines compelling, concise, and aligned with the content's message. Each headline should be unique and capture attention. + IMPORTANT: Do not mention any specific person's name in the headlines. ORIGINAL PROMPT: {original_prompt} @@ -179,6 +199,9 @@ class Copywriter: if headline.strip() and not headline.lower().startswith(('headline', 'title', '-', '*', '•')) ] + # Remove any mentions of Adriana James from headlines + headlines = [self._remove_name_mentions(headline) for headline in headlines] + # Ensure we have exactly 3 headlines if len(headlines) > 3: headlines = headlines[:3] @@ -192,15 +215,15 @@ class Copywriter: logger.error(f"Error generating headline suggestions: {str(e)}") # Return empty list instead of mock response on error return [] - + async def improve_copy(self, content: str, feedback: str) -> str: """ Improve content based on user feedback. - + Args: content: Original generated content feedback: User feedback for improvement - + Returns: Improved content """ @@ -208,53 +231,57 @@ class Copywriter: # Format prompt for improvement improve_prompt = f""" Please improve the following marketing content based on the feedback provided: - + IMPORTANT: Do not mention any specific person's name in the content. + ORIGINAL CONTENT: {content} - + FEEDBACK: {feedback} - + IMPROVED CONTENT: """ - + # Call LLM to improve content improved_content = await self._call_llm_api(improve_prompt, max_tokens=1200) - + + # Remove any mentions of Adriana James from improved content + improved_content = self._remove_name_mentions(improved_content) + logger.info(f"Improved content based on feedback") return improved_content - + except Exception as e: logger.error(f"Error improving content: {str(e)}") raise - + async def analyze_content_performance(self, content: str) -> Dict[str, Any]: """ Analyze marketing content for performance prediction. - + Args: content: Marketing content to analyze - + Returns: Dictionary with analysis results """ try: # This would be enhanced with actual ML models in production # Simplified mock response for demonstration - + # Very basic analysis using length and keyword presence word_count = len(content.split()) has_cta = any(phrase in content.lower() for phrase in ["call", "contact", "get started", "try", "buy", "sign up"]) sentence_count = len([s for s in content.split(".") if s.strip()]) avg_words_per_sentence = word_count / max(1, sentence_count) - + # Simple scoring system readability_score = 100 - min(100, max(0, abs(avg_words_per_sentence - 15) * 5)) cta_score = 90 if has_cta else 60 length_score = min(100, max(0, word_count / 3)) - + overall_score = (readability_score + cta_score + length_score) / 3 - + return { "overall_score": round(overall_score, 1), "readability_score": round(readability_score, 1), @@ -272,10 +299,38 @@ class Copywriter: "Consider adding more content for better engagement" if word_count < 100 else "Your content length is appropriate" ] } - + except Exception as e: logger.error(f"Error analyzing content: {str(e)}") raise + def _remove_name_mentions(self, content: str) -> str: + """ + Remove any mentions of specific names from the generated content. + + Args: + content: The generated content to process + + Returns: + Content with name mentions removed + """ + try: + # Remove any mentions of "Adriana James" (case insensitive) + import re + pattern = re.compile(r'\bAdriana\s+James\b', re.IGNORECASE) + content = pattern.sub('', content) + + # Clean up any double spaces that might result from the removal + content = re.sub(r'\s+', ' ', content) + + # Clean up any lines that might now be empty + content = '\n'.join([line for line in content.split('\n') if line.strip()]) + + logger.info("Removed any name mentions from generated content") + return content + except Exception as e: + logger.error(f"Error removing name mentions: {str(e)}") + return content + # Create a singleton instance copywriter = Copywriter() diff --git a/backend/vector_store.py b/backend/vector_store.py index 7ab68d9..3c35621 100644 --- a/backend/vector_store.py +++ b/backend/vector_store.py @@ -18,22 +18,27 @@ from embeddings import embeddings_manager class VectorStore: """Manages vector database operations for content retrieval.""" - + def __init__(self): """Initialize the VectorStore with FAISS index.""" self.store_path = Path(config.VECTOR_DB_PATH) self.store_path.mkdir(exist_ok=True) - + self.index_path = self.store_path / "faiss_index.bin" self.metadata_path = self.store_path / "metadata.pkl" - + self.dimension = None self.index = None self.metadata = [] - + self._load_or_create_index() logger.info("VectorStore initialized successfully") - + + # Check if the index is empty and load sample data if needed + if self.index.ntotal == 0: + logger.warning("Vector store is empty. Loading sample data...") + self._load_sample_data() + def _load_or_create_index(self) -> None: """Load existing index or create new one if it doesn't exist.""" try: @@ -46,17 +51,17 @@ class VectorStore: logger.info(f"Loaded existing vector index with {self.index.ntotal} vectors") else: # Default dimension for Cohere embeddings - self.dimension = 1024 + self.dimension = 1024 self.index = faiss.IndexFlatL2(self.dimension) self.metadata = [] logger.info(f"Created new vector index with dimension {self.dimension}") - + # Save the empty index and metadata self._save_index() except Exception as e: logger.error(f"Error loading or creating index: {str(e)}") raise - + def _save_index(self) -> None: """Save the index and metadata to disk.""" try: @@ -67,19 +72,19 @@ class VectorStore: except Exception as e: logger.error(f"Error saving index: {str(e)}") raise - + async def add_documents( - self, - texts: List[str], + self, + texts: List[str], metadata_list: Optional[List[Dict[str, Any]]] = None ) -> List[int]: """ Add documents to the vector store. - + Args: texts: List of text documents to add metadata_list: List of metadata dictionaries for each document - + Returns: List of document IDs (vector indices) """ @@ -87,16 +92,16 @@ class VectorStore: if not texts: logger.warning("No texts provided to add to vector store") return [] - + if metadata_list is None: metadata_list = [{} for _ in texts] - + if len(texts) != len(metadata_list): raise ValueError("Number of texts and metadata entries must match") - + # Generate embeddings embeddings = await embeddings_manager.get_embeddings(texts) - + # Check if embeddings match our dimension if embeddings.shape[1] != self.dimension: logger.warning(f"Embedding dimension mismatch: expected {self.dimension}, got {embeddings.shape[1]}") @@ -107,93 +112,97 @@ class VectorStore: logger.info(f"Adapted to new dimension: {self.dimension}") else: raise ValueError(f"Embedding dimension mismatch: expected {self.dimension}, got {embeddings.shape[1]}") - + # Add timestamp to metadata timestamp = datetime.now().isoformat() for meta in metadata_list: meta['timestamp'] = timestamp meta['document_id'] = len(self.metadata) + len(metadata_list) - + # Store texts in metadata for i, (text, meta) in enumerate(zip(texts, metadata_list)): meta['text'] = text - + # Add vectors to index start_idx = self.index.ntotal self.index.add(embeddings.astype(np.float32)) self.metadata.extend(metadata_list) - + # Save updated index self._save_index() - + # Return document IDs doc_ids = list(range(start_idx, start_idx + len(texts))) logger.info(f"Added {len(texts)} documents to vector store") return doc_ids - + except Exception as e: logger.error(f"Error adding documents to vector store: {str(e)}") raise - + async def search( - self, - query: str, + self, + query: str, top_k: int = 5, filters: Optional[Dict[str, Any]] = None, rerank: bool = True ) -> List[Dict[str, Any]]: """ Search for similar documents. - + Args: query: The search query top_k: Number of results to return filters: Dictionary of metadata filters rerank: Whether to use Cohere's reranking - + Returns: List of result dictionaries with document content and metadata """ try: + logger.info(f"Searching vector store with query: {query[:50]}... (top_k={top_k})") + if self.index.ntotal == 0: logger.warning("Empty vector store, no results to return") return [] - + + logger.info(f"Vector store contains {self.index.ntotal} documents") + # Generate query embedding query_embedding = await embeddings_manager.get_query_embedding(query) query_embedding = query_embedding.reshape(1, -1).astype(np.float32) - + # First pass: find more candidates than needed for reranking search_k = top_k * 3 if rerank else top_k search_k = min(search_k, self.index.ntotal) # Don't request more than we have - + distances, indices = self.index.search(query_embedding, search_k) - + # Get metadata and texts for matching indices results = [] for i, idx in enumerate(indices[0]): if idx < 0 or idx >= len(self.metadata): continue # Skip invalid indices - + metadata = self.metadata[idx] text = metadata.get('text', '') - + # Apply filters if any if filters and not self._matches_filters(metadata, filters): continue - + results.append({ 'document_id': idx, 'text': text, 'metadata': {k: v for k, v in metadata.items() if k != 'text'}, 'distance': float(distances[0][i]) }) - + # Apply reranking if requested if rerank and results: texts = [r['text'] for r in results] reranked = await embeddings_manager.rerank_results(query, texts, top_n=top_k) - + # Map reranked results back to our original results reranked_results = [] for item in reranked: @@ -203,41 +212,41 @@ class VectorStore: **results[orig_idx], 'relevance_score': item['relevance_score'] }) - + results = reranked_results else: # Just take the top_k results results = results[:top_k] - + logger.info(f"Found {len(results)} matching documents for query") return results - + except Exception as e: logger.error(f"Error searching vector store: {str(e)}") raise - + def _matches_filters(self, metadata: Dict[str, Any], filters: Dict[str, Any]) -> bool: """Check if metadata matches the specified filters.""" for key, value in filters.items(): if key not in metadata: return False - + if isinstance(value, list): # Check if metadata value is in the list if metadata[key] not in value: return False elif metadata[key] != value: return False - + return True - + async def delete_document(self, document_id: int) -> bool: """ Delete a document from the vector store. - + Args: document_id: ID of the document to delete - + Returns: Boolean indicating success """ @@ -245,28 +254,28 @@ class VectorStore: if document_id < 0 or document_id >= len(self.metadata): logger.warning(f"Invalid document ID: {document_id}") return False - + # FAISS doesn't support direct deletion, so we need to rebuild the index # Mark the document as deleted in metadata self.metadata[document_id]['deleted'] = True - + # Save updated metadata self._save_index() - + logger.info(f"Marked document {document_id} as deleted") return True - + except Exception as e: logger.error(f"Error deleting document: {str(e)}") raise - + async def get_document(self, document_id: int) -> Optional[Dict[str, Any]]: """ Retrieve a document by ID. - + Args: document_id: ID of the document to retrieve - + Returns: Document with metadata or None if not found """ @@ -274,35 +283,35 @@ class VectorStore: if document_id < 0 or document_id >= len(self.metadata): logger.warning(f"Invalid document ID: {document_id}") return None - + metadata = self.metadata[document_id] - + # Check if document is marked as deleted if metadata.get('deleted', False): logger.warning(f"Document {document_id} is marked as deleted") return None - + text = metadata.get('text', '') - + return { 'document_id': document_id, 'text': text, 'metadata': {k: v for k, v in metadata.items() if k != 'text' and k != 'deleted'} } - + except Exception as e: logger.error(f"Error retrieving document: {str(e)}") raise - + async def update_document(self, document_id: int, text: str, metadata: Optional[Dict[str, Any]] = None) -> bool: """ Update a document in the vector store. - + Args: document_id: ID of the document to update text: New document text metadata: New metadata (will be merged with existing) - + Returns: Boolean indicating success """ @@ -310,38 +319,102 @@ class VectorStore: if document_id < 0 or document_id >= len(self.metadata): logger.warning(f"Invalid document ID: {document_id}") return False - + # Get existing metadata existing_metadata = self.metadata[document_id] - + # Check if document is marked as deleted if existing_metadata.get('deleted', False): logger.warning(f"Cannot update deleted document {document_id}") return False - + # Generate new embedding embeddings = await embeddings_manager.get_embeddings([text]) - + # Update the vector in the index faiss.IndexFlatL2_update_vectors(self.index, embeddings.astype(np.float32), np.array([document_id], dtype=np.int64)) - + # Update metadata if metadata: for key, value in metadata.items(): existing_metadata[key] = value - + existing_metadata['text'] = text existing_metadata['updated_at'] = datetime.now().isoformat() - + # Save updated index self._save_index() - + logger.info(f"Updated document {document_id}") return True - + except Exception as e: logger.error(f"Error updating document: {str(e)}") raise + def _load_sample_data(self) -> None: + """Load sample data from past campaigns into the vector store.""" + try: + # Path to past campaigns directory + campaigns_dir = Path(config.DATA_DIR) / "past_campaigns" + + if not campaigns_dir.exists() or not campaigns_dir.is_dir(): + logger.warning(f"Past campaigns directory not found: {campaigns_dir}") + return + + # Find all JSON files in the directory + campaign_files = list(campaigns_dir.glob("*.json")) + if not campaign_files: + logger.warning("No campaign files found in past_campaigns directory") + return + + # Load and process each campaign file + texts = [] + metadata_list = [] + + for file_path in campaign_files: + try: + with open(file_path, 'r') as f: + campaign_data = json.load(f) + + # Extract content and metadata + if 'content' in campaign_data: + texts.append(campaign_data['content']) + + # Create metadata entry + metadata = { + 'content_type': campaign_data.get('content_type', 'unknown'), + 'campaign_name': campaign_data.get('metadata', {}).get('campaign_name', file_path.stem), + 'source': 'past_campaign', + 'file_path': str(file_path) + } + + # Add performance metrics if available + if 'metadata' in campaign_data and 'performance_metrics' in campaign_data['metadata']: + metadata['performance_metrics'] = campaign_data['metadata']['performance_metrics'] + + metadata_list.append(metadata) + logger.debug(f"Loaded campaign from {file_path.name}") + except Exception as e: + logger.error(f"Error loading campaign file {file_path}: {str(e)}") + continue + + if not texts: + logger.warning("No valid campaign content found in files") + return + + # Add documents to vector store + import asyncio + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + try: + doc_ids = loop.run_until_complete(self.add_documents(texts, metadata_list)) + logger.info(f"Added {len(doc_ids)} past campaigns to vector store") + finally: + loop.close() + + except Exception as e: + logger.error(f"Error loading sample data: {str(e)}") + # Create a singleton instance vector_store = VectorStore() \ No newline at end of file diff --git a/data/training_data.db b/data/training_data.db index 189ca4e8c3289db1c3df2e6ee8cad84bc845bc32..a6d05f07a39643975e7dc2cf611e2e325fea2f58 100644 GIT binary patch literal 8192 zcmeI1&u<$=6vyqVf~FFP8`q~uD6QmLiIW2L2`9B^XquGN1yvlP@$R#C$nMNCGwZFX zdMQT^`~&=(-1)v)$BESnZd}-v6WKez-hAHo`_}7y@%@PoOf%~W6==WnS*P3Wd_&af zbZ+DC7XGe|F5bwwt3y8j+i|*;>)3XVkzC1bU(cP`Yn!qN|52N#=C!-IxU4&)HAM8+YP!b1y_u}kyV_KD_ zoL=BA{V_tC96uXxv}%8`8Q?mZ8RZ7-S$E=l0bL}_bwvnr=xt^A|P!e^JvW|!AZyl|Tb27hy+Y8LT1YRZ7@P#< zGllPS7U!Jb5ljh}vT0zHWY9ukelf>W&!EqgWz`e2t5D;|zP%B%e(5ZOea zIMxO&Nh4&}>^{R#CKltHAsuDbqA^!yUWrgeTfv$YtoIZfO}gXPu8juS1XU|n#A#+uvq_OF#Hy;0S*LL? zB)eZ3WsR^GZH?VwFHs#a0tHujM2ZZRxeD?;5kfyiqP0oIzQ|kbU1#tDXc{O=G#m|f zO{Y+=b)kP<5zs}clF+AvK8?*>wj8^cl`8>a_>X498Vi7qwWqORBVNadPpp|m--*od z=o58rbB$|TDCk1T{h@55R!f>LBLY#qcmUpa@y&`9d?Opf`tdIC!_{Q7k~Wz{L0Q>C z@{gr(4++TEN{2ok_UQ%lWvpmO7|IFEVuBw6P=b=!)GtvmcODi%>;aeU(7ovF^Du^wuPFSRha zA^QMRkO7(myEsSC#gtudt?{-n>QAN-Xhb0h#3H8Zz|i-e1}VyMu=h ub`Ks5_9lB@4F`ka{$79Y;Na2zm(p|NM*wsWuHv`XLufr@u>1Ai-tOO7Wjfjb literal 8192 zcmeI1(N7yk5XNm(sl`&OzU6h`g`~1AAfcp4RceS;XbGfXicnOc1g8rCyR4=lh6NktTejQcb{Wc^NT+lc-2Qupe9fgs0q{rY63NZnm|pUCQuWo z3DgAsKLT$*YkqofW25=|X;e3cqgUE$JG#zQR7)RL4$k_$L7xV_{o_6@4blD9s?O=? zWYGVe`!>Q>*e_NPfw5gz2zmIpB+8xon6t7{VTe!^9QX5X>Z>8s)1L1)C6h* zHG!HyO`s-F6Q~K)1U?|}?!39$_~YTdx8L?w57`(;FHY2ie`&W`J?)>COR-Fi&-|um7I;n$P;R{F4<&m!W11Wm@-q|v}sb&&}+8& z8fNU5k!G@(9@0!Enmjp84q)SXBakA?vxRSRHmx;L{+8oBkeN1yvazxw#DP;cOxK@K zk33JEDWi5)`HFI$>I`1QVKTy(Ya8TeGI8oDSK3tM9SrO|r5m0nfas$yLj((4D3ryD zVzV(7morrbnkj4$@-7`kgd7a>ZJP==V?QiSJMqyrmO27Xm(Ep1wEh4hfJ0q?G0ew(W8%DN4kE{@JvoNRXfXO+OYlyOe>r{nE zU;uD{mO0}*aHEukijlnyZ3-@#X3A25r2*3D-;y#sMa~eSBmByUlZ3Fe`en%!Vuc9O zN_R%F>XMXON6H-syAd(V6_TRoH5&XQQz6ZP_+_b!0^pMZ12%Kqal;PGI?6}LQ^nF_ zUaIOu-6FZtW~t;xM~JPoUAi2z_}9#^by^p#49p-$nB5d zr?Hx|%tZcDZ;|<2`iKqa?&6Tuiqb=u0ns^YL{ozC2BlG@6?a{vtt6z`xDx%l;SfP8 z@;cmhhMq-rS{Wg)9enj)$r;-uVy0hRC3Op|CWb>0Ay`K0Q^|YYk%jUQ02}awY5GN2 ztP@KR`J1@b=n5S_R#3HdaV#mIyhaow%ONl{x9qN^Hj6I6gb}vd0^;1Y(d0V2g|?wk zF=gc~O`Pae*hqO)K1Hjjx#pzp_!aI90evygAEk7t3GO9xNiFLigSo1tK}0dB!DN0a zJfkG&a`YCKxfSLC5f2S(|M2=ZTWba{e1!t3=+AzAd&wZ*-0 zeUH|Qv(u*+2Lm#_i<5)H^){}&hkK3PzSmj6#Mf^yw0Lrmo(_m{T2yTA_Wp8ldvklI tv-zmA^?0!LcyDKSZ)>OfaQmCDcOS{jrH25Rj(ZWmd2d1=n(Xdu{sj_SW6uBp diff --git a/data/vector_store/faiss_index.bin b/data/vector_store/faiss_index.bin index ea6344d4515cfae5635801ae5a9cab3e89ebf0fe..85d0da3e9fb0c2c8939296c9bf21d794a6f81f5b 100644 GIT binary patch literal 127021 zcmXus1-KSP`#;_Z3= z*Om;eh2)}o$d_pi`39{a%xnt9vGq{SpBKvMwUFKD`kFx@*|9a02cjM1yjnekFPlO& zqBT@k);h4Q9)C?3Uo5WZ_#LYk7fT`g33 zE#!}o-IeZLnnSg?^M_5L9N!f3U+Mn69@16jg<=NU1@7O(zg0a{t@V(NZ3)Sm@V24* zj;0WnqU&jNOE%L-|6O!WLwiYUNFHtp)j4duzd7Uw(6dZ)$bQwwj`RoTq9tTQ=;=(y z>*Rckc3pO^i0&2`S8ol)*{<&;^9ekk4-DnCbnQt`UoyXK3fW%x=Cp>ipZl}fkJ@%*!QEfhDlgyM7h+oPFCS0C+H z@)=qA((InkmV3phTWiSH=i3*x&mkMGay_=*;kupnZuAZipB6l;h|8-FhH4wWWk10K9MUDa_TWY<+=!Pd0^gc`+S>wnpc-{C6pTcW`|;dk#mt z3_ETidu4qah|9I`ug_l>lD8SYspMQDrk!BCRo@Kf)A8OUhaP5QE36y1Uo6V5h2(yi zKi9S_y_d6PU)Q6_It8W`_?g}5`Q+ZLeFd?3=fRMi?t1tpLbi%w`ue;O zz9IKe2ftP8z_tiqb)?TZoCgD&%8i>svY;j8x6TXcTZ2N`JTK%ea6b&kPxOCA#{>A+ zgmo49u`$_X<$Rx4;wDeRT-b&>j}zbJ^)1x5GhL_CaTYm8k<*L*_v#_zm%J_icV**8 z+T~OjNA`N!RyBUc;kk^Ci`lf3oZ_FD8$}(C&EQx9?LsoT^ToP+%6DZOJkiHjqKWx^ zyZ#57!;~lBY$>p%#~yLpr?2};`&+gHzTXJ>x<>&yZGgJV(f-a ze6BWC8{nHI4ioh)t0s(6lUC*fGQ!Jh$rZ-RRdm0PZ)-+{b|I^$ zwpIDqT{~sD*SE9BY%M&L)fMHxH%qrWk09&n5%5d~f)k!Se$B*UBGxnVkunS`vD=mJj8p z?i2BSioT1)aW{t?sNNeC@}tR2YoXWzh8|=;ffj~x0)F{Zo&u+F6&|dId@TAV_nU~p z!+bgwt-28NB@85UBpu%yZ?j=}9X_!RaomoQW51BuAKoos=cl{}ng`PR^J`PW;*|%wvBWW+V-iCQ``cG6(o^X9S96Pdc3BKE*9@5E! zj92;6@87m+ZT{FpY}Mg}uAqj6>*h6TSG5>9o53K)fP;dWJX*gTdOSWOwx^e>^rQ z6lz}jJUwb_K1$7s{locj3GHv88_H+ju}xkU*OEPruWu#SxXxz4zm)40(OrgqNxo~Q zyDeFL(9Iy%nk-Yp%Q5J>>stu7x|uJ{9&wFxR`|nxFZgaEuN7TS_F4m!?fG^Nf0>uV zN@Q5uCHLb$oF85?mOo(|IcayiF}Hq}dp+rFc7G`Q_kg`$Efj;%e?~?Vzm7)t6&iVx zeF*mje8^Yns@isi`%SSqjcqew5SOqu{Qa#v)yL#-IB(#Kz0f~q98arnv6-*T6yd`QG)Oa7}{gP(EtM zmugJ53?9!CSwA*C;(jb!pOE+bS*{J!FWRmkqYW%^4i&>(yyH5xn8jD4*?(HCvBuA~ zsE2GVvQLl?)-mN2Hlxpmw}fhGzJI{|jeIS3>C5DfcJ9kRr^CelM2=K{u;nH9hmhHU zPcP;7d-+KYr{on=>EDGJpTFdMT(6bW@NcB;F1TJtqsHgr7uOo)Fm2oN z+kkpVpKWU7P4x^M>O?BP%V&(Iwq&34V8}b8Ppw<8Buo9thTyvm9o_lrY#E5}O!A|j zKb22>Tk=tmC*}1~CcfX%-v;}~Xl`}g3d?_CIFLMZW;Rn@JcJ+hXUnsFdHnpA-^~}j zT_4*TvaaMjPTo7>bfWurT(8Op52M+H4aR4=ZA&Nyk$;`>`=46KkB4s^zFEehzE|eM z>{Zv+QrVbR&x88=zd=_D(`OCf+;CrEm{D%d%lVy#3&e zvfGor2c301cd$pU6n}3Tk`d$@M`=%ad1Z5`zJ*&ZriaPJo8f0~G6s(^6~5x5q57{Q zXI?#I)9E|kc)i~Edz9XN={*GRw~lsjjevDaw5Q@dz*&t6m*TrZyYY}*Uk}Nq+W$*; zA!n^oGILWnqZU$iz1)r6o1nj@9`er|JHWR!JJx~uN&1Y9Y7|{;DtBOGKW&e*t2^Bj z(5o?VZBlvGDf{t1453NibaRN>T$Fshzx#z`h*@#~dUc@q8m4{Gn;Wum&?k=u9!l{|M*}uKjBaRLN6cUn2cjA z8HM+IHj8UvUdt}#i!IrGqU(Ov=Y8PdoBTZT*KSp#jMM$u^1X5JuJf|wM9k~a)s?P- z%%8OnjCQ#;=jPGZzoAh-LKk__ft@ql4`Jtg_p8$1m+$x^+uR}dRPd`&6~y9I_v@W*tTzed*D3JOta8 z{9`>;8Jlr^R$hny5;(tvP2QGsVc`3Op7c2WJ`Bxj>emH)vmLqu-&WT1$CEpr9V?T4 z;RAAqZ=OaQ=Zk&RxNl+Q|Kwc9e&ng^`3LCFi}uOEgIu@O$M!PTG`U^&#J?^(!s_i~<)+t@aQj2uFHG)wlyZiJH0_)XMJD85o-tj z;xzpuw9TaBeYVT_?9+P4c6FA=aZQ+fs{MB{P&2C~=vBl+7G z-*?7Oe=*(`rXRH%L&ZSxdjp=Hp8e^`M#0*PZ&!nVKeVgBa2?xULF<_%iS<|R<+tIV z3A?yw&PgY@r@H?fo?ftTC?{^=Cu_8-uK#mwJCQND9+EHM`pH?WVoj=y&&K-cc{FRt zxAUFXqoWJiXOpuV{ySouzO!rAXAU@%C18DA-|OP^KR#Sb+s5cFZL+7M?{@a64cXhS z_eW>W$&ajC7qM%mTJV~6$5!xNTMyaY_Ph?`>j%X%@DIDfVgv2b;q3y;>*78K|NF+o z6g;!Fi%0RNYxOtpL(kX7jG9%9VABA;_(H$2R#}Iai_qJP9CDMr$ZzI%dMop4c|P8s z$Y@s!;VOC$Wy>Uf+|>0Y=#0<28~oO9xf+}w3&Yj;UemuCdF^2t#80b<;db!br)jL4 znzela$4C6~9$i<#c1m+&FDAU9T~4L2WhZDihD$kKzDIY^z6*@vl&@_c=MetH8~0tp z;_SJBU2-%&_a*97`Mm34bZuJ?xq2KX)n3r~D*#)aA;uXm7-C ztW~!;KSxI4Kv&#t9dsG~nP{#<(i)xQy4lJ)Lql%;v`!%agP()cz#DjCF6ll*IL} z`8sWa1%2EvO|~?47v=Z&$UlsoJIUeRFzm-a`=cG;Z0;}ckDgXX77M_sq%;ehHuITa=IIuxTVYv*LD>R7n0 zg8N*0$HDudYqcetfq$qrYs7Fvv-L4KOY-SRSge1_r{FzUT%INee`&tRx8~Om*#4dC z9(bF`H#Qn`lG@PNN7>8$1nrBl=PGU6lO5-Y?qt;HK8QVHoup!Uo}3huaxz(+<@@Sr zR!5IF*}oR5MPZ1!vManxvvnypuE7^e@y(rRW{@?)d5ZoGYaw}AjOJ^T+i^Wz>_cE{76?mOvTob7YmujzTqI4S7~E4$yw z9P}QZd(dBvW*D3A;@fLrXfn_7Po~~vVingKWf!@XvGZZH)0@q`FEA3*e`Qz&DUM{ z_%3#S>H0@l#H>`u^Dg+mM&A|vZD`Fy*^Y3jfAN{98Y>T`%ApIyq9;G7+0~=kN0V`^ zI2`PH0XY}*%l+^TATQP-an1Rmw9j72)huWq&o2+jqgYEHg?&$W{!8a!Y@DtCB{4x) zY{rL2@{@6s{m75TS+OcvY$^6&$58ZB$eQH-o4Wm5*p^dM_C+HHvl5O3?%w+1bsP50 zexULGCpEXG$7z%Mi8>kgB@_2mJFzO+d9Sv!-Csfed-~SIy9fF+<+^=@>OgIu!7iVZ zvy5HOPN^E3&tm_f^nHwWGJM~%C(f50_-w_xXK{GGfzi0jmLuz8KI?}*#v4y4=sjFM z_U4nT(Y;E?bMr#Qk40Bw?JIQq)uO@SH)mSmjHT zCq{+w81pXu4e#ynzeSdHWgh3RH`!UB8Orwc`Fjs^H9lHRTO7aE^yT9Crn=_q_%MXr%Y|GmuVu@4eSO5^CH>#wTbHi&$y!LRu^n?D-^=kgzK6;Dj14>EU57mv zvT-Lq*$VB_{6%(SUEY_R_iG`2p-IhktuAEI_T}oKT!Al*;ZR4*kEOZ2@XjiUdzNRw zaUWUMr(twGR4b!BN1WA#^72;Wpw`HRWdFMND*x&$M$7SDQ8CSmL9>rjo93iuC>*&1_qe+rsJlXcW-EB z;(wjI|G+&_-kw59P*z{QHWtaa0Y5d4*^% zf6YhlT<~k=87FK28{FAf_)nsPz92v2`lfhskoP_K=hwa0)+g8US+E|`>irR(PHbG0 ze-^^A2sw+8e=9%3l!#rWFTKq5D(Lwt84Jguj^60Tpp*akKIoeGXd+Dg^%-mVVd!s# zSKSB`T#um(&dNMnye%$+U>L#XpV+D`jpOVGd3T91I)@%{&o2^-8_>zg@ZGmxt53dcG`bs_Y>raZFP@**;U1VO^0(jxE9J7BV#B% z2F6p3ov2?O$Xe*VLVr)|$?@{7tcPj^{!_oRI1Y{><9L2vg1uMs&qnady|5P^xt*TN zZ}(bzb>~<9EXKmEMx|Fec4Eg_aPwo@N6g?)`6F4xob-Ua_)E@g4fiydd%}Jb-Rvy) zKqo%=7VJLR{poDY;T((R8rQdw^?~;3aH&7ZI&6u#sxHPlR>bkPH2iq8d&pKV;(Sq9 zvu0buIo0*G`Zt7~-}7tTuSCvse6*k@2l#V;-w0Sg#r@&%iT*b7><@MyiLPzkIOO}= z^^KuVoywv zPt&6&$Mt0B2jA*sIA?WsKL!75aNdk}4Y51~-(GTi5)6CSLeiHHjfd(eV{|KHYPMr_ zbibfm942#7wgg)BH`!i%e?<2Z9Vr}_I-hKudCsjy!L$sX4`JC3?I^nWBi!LQ1BTt` z=|<0S?06ndc^K5J%o;thUy$j`+KaEc6zA`1HGCKUi#4vL;+iXCXSNSJhR~somL)yL zPC7>|+6BGm*n)r44fyn+rjU;#FODm54O3ei`|0tyF1|Ob%**9mvCj1^?|71p>S=xo z-DlJLKmL;|shGugb=7wA^wN4`-#3oUv@<i0{|qd{_L>{R#BPwSoJ}*sXS= zcV&Kj>;doA|J5Ikq?_H@E&Ankah*DM0RQuGz!Q#xgKfoQaPLF+`s|*-*3Zyf4%gE) zHb1Ctv+*(hJzM{Vbac@E8h_qXw{GQ+P2e%tW!uyD09>A9vnBAXOAh}P%g`U~mD9zp z_=mvq4W2#NDQ1Onp3Y|fe(-$mNMJZ$oWIe2k!$s*Sc~8O+tT<>s-&y@mM^TE%J0!n zWKV{62ED!Du`3iNbcj#_v>Fn8@;g>#%Igo zcJfzn{|EnX0sFq>%E#()?OQpop&mYfFXqZ=FCM82@pAG2-6yMKzDVZ{{DelfH1Mt#R%yZ@?dI(W1q{tDKG{4kNvhQJ`M=@0q_(9_NJlI+`ttc~>@3r8y)$MBiCublLN=Lfpi zhd=P$mh^lh1_Q`6M)G0q_tD>uUbQ1Xcworig4dcWzd@hesQA1R+iW?w`m*;*aT|&1=j$H$_iiyZ>}5@D_I`xTYEx;B%zqa5Z}g9H)Y$zuo}bCO4E-m@sdZK& z?~8j{8t-O`ujLrLiM%gfhoP7J;LChzHVt$?65Ww};X0W}URO38h5y57x3)#ZjJ&Y6 z^VR5YhwoK;g3Gbt1U_1W-f{fZNjyf#vtDTbr@bw@SNMJ^8T&hSEySD*d~=l=uo~Luybm7bxg8(>_Ag&t50qo^-KAaqDic16 zev5PHW&C1ZEgm=K7UvW7A^C@Wf8dGll~0EERQT1+u)qEl|Fu28%eB3YByom6?rVg7 z@SNm`&#dpk^8wnSuzi3o+Pr+tGadg7hvQV(cILa`?3V9gvRsu{acsorgBiJ&W{=o!^z0J8+_J%dsyjZ+%fGKbHKPuf%W0c3jWJXYS&;x_7N)zFH5-iH;}mOcD#c`3J6Zv7QdsLeJ9A5 z=9c(AG2BGfHTq`in~g`k4HM}dE)TZni~Y#&q_0AE1m5lV?mEX z>I?P2ep`7jTdyVa3OUgW%}=oPhlLNqQm{R)U%d<4YtLL?K)1DWwKLmKr_cB*N7DBZ zU(TmbU9IG4E(X~sedgz~V*3pJGu^`!%zwH0wDW@JP__n$uV!0bI2CIbT4gf z=$++#sQrcF82o37+s7@9ee`N|cAdi}K8|~EmHDN*Uo86aJsgd1C}1it*Vl(_EAo@t zm&v8Hz1&sva`_tWH+EL9c@Ig~a`S!V-dz}H$I_`j7Abja@{ioA z?lTSt;`yD-tN2dd=hu@n2G1L8kbAi~Hv5X42kBgt&R<=tnbq6QC0p;8HxHoc`(Wc+ z-Y{QV7xM3MKAc}V;`tl>Y2wFErTL*ciw@_wzZBNyo73SiHqzI{X@vgCa&5eRVw)T8T7392zB4O-t2frg*^BJiN&Az| zufWn*->UpVM$VSF=b6asoIhhNDPYdzW73v>^`^X?9plf(mO#PopH^O@raxJN1e$;~q}F z3ceHhq=cn6+W*io58s}A&IjQw{nlb}t(}Tjwg&z|^jUW$7o)!f@4kFI8tpBv+wr4Z zOa3N*qUSBo+UcTXh+Ei`j7`Pl+IjX+n*aSKdaG9ZHGFjmd<%`;M_{$)NvD(ZE_rw3 z9qQPa%x&>>G%nSGC_i`3A87JiLC0;5Q><-b&1>~Mz6T#n&y}8J~U3pk@*pv z$G|Hu8t*~3fidRIWcPQIf3taHXV{;hXJ2@KV&i#i{2I2`>fWi5F;gtL3}rJusvlZ_jT z=@W1-&o}CP@(L{SB;kk5e4WHGALw3>oZZoOfYUdm;c~Lg@#Sm!J)bq!VtruRkzL!V zv8~$Vd|}N|t&YC~8`g%Gz146sjNQif(WkaH-c{xE=)4ooz1^<}>uU7D6=POhi1u)? zw{A*zcKsf_=fZg>nb*2D_k~UA_WWOdR14KEa1KEG)~3b?esfKFyP9al=u7GG5>G#r1Wpk7-G!aT>%t zTgg4$Wp8cb6yGbB;#TBxgT7*jTuIm*=Scf)@jK64K8J(Y@iP7yWLul0|1}=2qVJEI z+<@gudD^P~OR~q)`{97b-bHeqxQ-F~J}{m`*4y~@gW1}?xRG65>H5?8YP_Et3oxb+ z<2j04b6C27yjT}kX8&o;-s8b2r@}JMZRA)#ym9>7H!3IL{mdBp7Vk`$%x4+@#b=QC zJRjn5H4KlSn?`@M_c?x8jBNF%w7w~?q;FFg*QaZ3a`s{43FK_aA7tjIu)`6*VJ&W= z>kqb_g5Q`dmLqEvng`hOD}V80YAhy)(s!6=s#(tOz_O3rM< z|Ho>`k?i`OFOG0ur++(rSJP{(X1lZX1Uyf|Kv(q`8h$D!HHne)z4CkqKHbTD+kP|e z)?gziSrV25@ehG{FL}BcTL+NwD*2!2@9De@?8blbDh%tWnZ04}!GB^BK8!vj%ieC( z6W~qadYas-z5cB{-(L^+;F|TIzDMhgHDIzCA3jNrxMXjzdn6v;fTjGKPs2BrzGz1m zc(y^SR;AnPYj(erJU0$Ab9G!>WT(?VrYU4{quN3LK=b z*{^+7%#FYJyqc~~pI8)!s8jQOPq8E)SOdoAp0G6?tHF5_`90hpjK2oQ#o{!luD-Eb z?qw(8Jw;yjX8Tv#&PJn_#J#yVk0!lfn@88R`f_-Bk@*&#SMcX!aB9z@eX(|&)f|f7 zwXcQlX}GU&oNsKv821D-V>-*p9t!t{{GyhIi^zVKkDsVnuk%4BCbQxD0_Jwc-n#s7 z2Yz{<^Fw?OT#9e@GI?T~@=tOzJZenL#h{)Q6UbQye~RyTxo9rR{~>Er_-?^B)?P$^ zy5(MJZjH}DG47STtd`j<#CJG_Jc{#e=takm;(H8Pu?|jkUaG~j4;_z)^R9Aoc{#Cf zEC1pb%VaU*A=a41*x6S5L2Mk(*Jr`>DgE|G;ycgm5xF>C-yY=d%-8a>90%8%d~rKD zC$nuu*X+r5g6CPdeiMh?U}%ziH^9~&{qyWtif{TfHQog`=869L_#oYcZ%6BwPpO)f z{s8j};$VH4K1%;=IuqAxvNhHcdmqJ{u&n@(byz;0ZAY@i|3&)4>) z-1&%qjQ3JKsg5J-ZZsP-hw^^<7lrwKwp@<)NA?_sW`BB&-}Du^HGwX1igmMmME`!; z%`3$dFdx8I#z}D%y3zW_>OT=CJ}KhZzYtv~F+B>+X6B3Y(ahijb6L2Q{ypfL#Sh!@ z(Q@K-xR{hM?E!nt$A9QO$^8!cyOOi4_SdwjG3f+0t$|#38`dL!Nf4S)bNIvYMR!fNyR=H`rke zB%R23LH|wUL>-^9L;Wetzwuo`+R-;`=Ev+Qc8){;2l|uTuLyrvvA7c7B>1k^7uT78 z$a}e*^Ii70wkyQ!KkVh-;!sE`Rh3uoqyr2K~CI4!4*V4N@ zUTdoOES|@;^zyFt<(HAow~2LB%-!@QddIuooxTa;^BH^EXuHq&=v8mbAIW26Pu6y) znjgpTuJ|6T85?!q5VA#mDcKP^JFcPQEMrXEiu+(}$1nTR{f&0A(=)aACPNIX!LY0g z>qTNWR!tm@Urj7_gSk%soAgFo_$?nw){*F!ms4s=j7<(xcE9rt=;+Q@YBHXzp(biS zrq$ZI)_C`rCgR_hpO>op-URk-T0{8A`A+!N-kd+_tAW#KhDkSN^&O}@r&P7+?*ZXZu9tc~LPf&2qlzpj}}(Z<|wgYIhf@nwAGsy=$4 zVRzi~tKccy!f^-Led&LX+~NFjF}&ZgSB}N~<4WBu#3nnMzNgTWooz+_x^PFo9>w;B z?(Jz*#%?CR!?yG;!_UTN$tT%;e03wu41PCHox#=(BgP!~7NMNeQYUj7K;1BgO%%<14&%bA9 zjMW2$t~W*0t; z?LX1^Ir(Ccc7$;vn#I{E7LC2SyV3Jqb_AYoY#c_Px=?+iU!I0}&KvRZrs94Ae{_dQ zeW_lT+au)rY3|RjH`el*x*y-U7lYYe$9FipPon>He1F1VT&4Z%jlHP&3>j7;r-dE& z=r?zj>UGsj)|sxwI)1B_^o8XzcxP*0z=pT*_rt4}7JKSjlRfaIZ?Lx~8Zk@`(*GuW zud+)#g5UW^pCmJ38A;z;Y6bk+biViPR2W46!RWpvdu9FdBwq)XnCsi}@7ru@?|OCo z(J!x~y8zvx?x*5?g`T!Cr^s!sH@@Mn__Fu`%|VV;`7hSXTa2$6^~Uca@~z}%H+;F= zB(JbG$YTAT4@Xxz4saOnaWA_%r`h+ga`HKN<63PYTVpP*H7^t!v7b$i-~UWy^Ln+$ zo_<_!X7AAXqT>^5w(ZH0p9TGKUncEDk631{e7Kf4u59hjKk3o-xMRImBl5TKibHvp zYkk?^7V&dE6`h!dudEXU~|y6A>Sy>;n zh`h&P;HRo?3|h}*1Niun7VqZRy%_sO)a=FRn`-^gPP{*bwY{Sgtmo0YET8|*_7Qxu zKAD%nx{B{E#H{SDhMq_7K-XWwYYr)&wQn{A?UDQ#>&f~sSj*)xCYx)6vsjFboy2T1 zTh#Knk6s;(<}k7Oj(`8g7w4L_bOa z#|q?#Lp4CWKV#n;XO@n)PZT57E>&du@Pwo-B8~Dtek`Ex? zdLX@k+$HH=945IKzQDheoawD?eQn|vtl8rG?YM>xN7D6*b~zr`&rx4C6n%U?xtt%= zoob{Svprh%wR#E718f%8&>7EF#$#MNT}aP52YNy5Fre_V3FZ$zO;6x|91d4C--Q<5jWt z-im(5y1K*n`)ZH=Tnn!`G(IzB>UB0wek|vHvU5K)VxM13-YxvPTdVhO@71+C1j;S%?K z===fJ9&D+xe--k?J+7(Z+!gm`^M_n_tpEF7?OuJ0G~55ha}Ycmk#{S3m*eN>&=&vJ z>|V09@%JW@1$6vQ|18H?bZT(OjrYgNRVxees5Y$`tM$gboOaUBr@8)ggf+M^mmE*- z<8a2k^cC2)x%)Ng$?5!6&1FNG(--4#hxht}=^78SIl449s$0;UAii-v++F*@=;!bk zU!<|7;>|DQbGD>vQu01Lz2vWPXQJ>P+`Aj|RWTK&o7uAg`u*g_hwg{5V{ONku8sMs zJNhT-LL1cZxLyn&z}e(}IrsDx=aMmy@7{EdnCQzk1HreLkNOrJKAu(JQ)sae3p5D-0R3QX0u!MZzcc4 zF+C0s|L30F^W)sV2IEt%?<0o~gE;4V!aUTuo8vfn)NG7g2Jbi4Pw&J34Z8OHCa=R1 z;`IbR*fLZ>)I=V>-PGzMbLjiEoV)(4DlO^aDpEUArNcQ^p&*4XFl>AZGSE%U)+qaUZ!D~&B+^X;7nr~#??*;b_Y^JNaMJ&Xr!dF3Jjm}W)Qt=M+QL!v^daj5>#l#C&)_Gyl=mPb?J#DoiKP{_`Z(@73A6%QY zHs<~EOmVkg(|CV7O~3IL*O_q-J1oZMzsk9p&I8b0%|B=`a=|^&|H=Ip$+{eGxhPk?vzTx^? za^+^R5+AZZR|Asv@Z5v8EnS1fV&|H@C^Gano_S7e4(S-jrg-qjz1_q-T`Yial5aS? zLx|5oskkSt`X;-6o6R4=Gt0F(HLkU)mmPPLy$QW)O1d9iQ>@`&%hyBGjt%@(1is%* z+eq@Svxl@g-%jDDQ}7sfRrE(rmbGsAEbK?rz2CBqRhOzu_>@nQ+46&|vMm|LPTcQ{ z`#*8bQ{2yniF~)0SP!vBbE^KCu-r)QFg)ASZ7!~2U5)eJX!L*9eZypIexj3{x^!I^ForwGK;V;-ugP**@+M!$;{%@@9$HN!%*w}3Rj$7`BA^h@( zc5CFgubphnr+xV`B~zTU_O1^X&t+?k-A4l7p0(-ZcQeDM#wJI9!! z9RP>?skR_*31|5e)XJ0%>2`I`hwd-J+l9QN`CYzOe`#Y^bp>4HSMAVFqLZEFLUL>D zTo*25sqDsH>xl9*IdF@<6ur5vI-ktd?)SH`*u>`e{Me||bLlMMc-dJEFUR0}8jac! z4%9vpj^FtBM|JbN7T?5+?*jH$`unlxQg-af&RGARkOS&YZaf9Hglo}lt$$7UMv=ph zRcXF5Ph?&7oyFhF>5FTCg^uC$wBuL#6zfQSF5dP3#h)xr-Y~g8R6gBA{)KhxHayR^ z7`x_(SIL%ZUNU%pEf>tQ*<{C4=yq>yd~cBsavy8r`(&N$d(k0$HKgXZ1Zt)llYYcpWKQr);m5e68#;FwXK?b_rPc3 z5`PmNzcnahy|<=L`p}Vx$t?1g_`kg7zw&XpKMAk3LHxcVKe}$MARb@4ztX*Lz{?Nd zmG|-Q_7u_21Ng5US+BcZo&1;RT^ZKT(M(|P$@~{{Ze_8mbg%#lIDCvi?V4Sb_}$ zofji-1#+#ei>uMb{#bVpbH0k)YmJqY_~!vQj(5EnAH2YyIo`938}UdlYWCYswr?U= z_Jn%^J?zd8Ay)*>i@-MuD?SXq%V@b!|=yxL1m`opK>o7LGkOy-j>$ji#eIoxI(gpJv-3#;w@q{n&p$eH)0A z+7j1{#on!rZ*$7ln(=5HcWd_T8Jgbgi#5s|mraI&?a9(|s+YbO=s18s{xlxVd*xMi z&&%Y;dAqZI{F!kW=di3JdGn%^&%4kG6mymByXY>n`+ zHh!;$;@^pE`I&DQWxAG+S&YM(FkU2X8?^Y%1t0g)zZbjtG`<@P&!BzNz+d9~R)UouvNOJCOC^_}qcfz28|>CO+s#r|S^oABXT zc*fNHtwp)?U-SpbGy5g!VEOp5<6(X0ICgg#R5V&rI ze{Vbqy$9C)j)2d)iT7G!_do4>pxs8Bb!pOutU&K6WFL!u1UrWD-RR~}uFr-w$Q!L5 z%)~R4y;q^x8P>8$?e5=2yNdA+2bZ4vId&2Z5-Rvr2n>Ax1m&_m) zpz7qj6RhT?_-qwA&^N#CeWMz94qpu=-&m-uspC8MT#d}dKan5d5cBPRFm8l@3>)Yw zdgGnpY)pk;>0SyR^GEKvAzRs)nT_{1wymaJT;pDNu14q0@IPiRa2R~ou<<%F{z3n- z_QT}#PR`Tn#sr(56YJ&3*{P-R_p7pZ$&q8>CH=?IbNYk6HG(}C=PR52P7wVHbbLgY z`6b^K?UsCaBOTkzyQzHHLWUTYb-Ij)a5LjNgOC zIXV3T7PT|K%^6Lcr!s5ltb?|$?hmB%B$&?E_PJPp1>2!)*n^Fyux%gtjjlKuCVwL_ zK2sF@SUykA4fM#lxb6wD|9jV+=>1Dvwm`RzHtU?^9==nLk{#F-ZTn6P9+JP$Hd%Lw z^-AQN%OCsF^O^oT#P5D`qQ9@z_aR)yaI!dmSdZns+GKpQ4X_)gIa(rhi4UuHql_eO#BMOOX@DjPaGrnXD_?xR-GPA1%*T z@17I+kd4RlI6Yg?DfW%$FMsDVJ|E^I#Hk0o?P1(mobcsqiq+%f)ya$g-VSEtHm*~W z0+u`V$?L*ct45Gt!wthZ_cx;jk$;5--i5??9a{D?(Zt(=raB) z+wgT4{m+v1t+>vnW3^f+{_D7qZoUX(oj=xo13#XHPrTxDL~;c^x6*exT0TiW;q!jl z+VIbc+9uO4&+|9_WLhqumu`4}_j&81pi?bXIPsRC|Z&ooD z*peE9@oyrQU(jhh4=KQH!gay?>alZy7QDkj`=BsW;gV zbe!*fBA>-|YB~>&IQ9=EZwz{Jsu#7Zd+A$vhQR)_Jv_FD46Sut)da&&@ERN06h1iA zF~#~P)}O(0vm^a4^U=ZdS#uOWk$xd-QQ$S`7A&)q#Z(E4gcu6>%F2 zNn8Ev*X)~;c@3XFMd$u-&=+G;T+jZ&XwP$fj<%F-9r2A9yYBXtR;A|^@*ULx`b*dF zqpeLc*dd(Sx!))VRf(Ykc8X1^~blg|7@ZQsGLHhk8R`JQsW z7e8GIi+Lma%^u3C;voLzrFi@umbgx-`qDi^ZjFTTWOAN%zdfwmp!vcxUjomfj%&nn zj2v2wkH6xlMaAL|*!FR3$gellttHiqQ80X99-2oQ3cr5|babmiWn8h)3vTNhHSYCXuL;FoFJ&;EiK5=K3;lbrLJJHM>yzSp8eF|0TXy0RI`}-9^Siy3EZn4mmqh zIau6=Up#Wp_tnkp_pNubHQSFOgU{1XP^7$(T2Mfl+jwA08R$kn*q*))uK~O(M*F=PL+3QKZK5RoVRH4 z9R<1T&=vPwhLQIjESJ;kTaUOG7~@*V^F*G;=j=xOI`HSJ@DAX=6ZNe}&*L@EfGv$$ zT-<^7Rk9CZpXcPTgIsxz?yvEmDL0qoyJPU(1H&$87tohDUZl^6<zw(Iy|_Ge=&@|CEj|_)WbGE%=S~WGgs2vqgTUbIF@e*Q5IP=KB~=^L+f) zrb%a!+BCJP4nXZ>$zqH~+ied?#G& z&aOgpCx7ME1h2xpmqTtRlbpA5c&@C}k@&X|iyZy0{5*~gay9Km=Xzp0Rlj%?U&6@$ z)ivnEv`Xlh2ipqdf1+(GzP{Hn%fa?y1}t~i8}BRgIqca6EnJBj5o>uhuWrwj%s5|l zf&XP^^(uRUKJ$Ae2FZE&*G7LK-ZjPk82ab3w{e232XKTNM%u8T+Pv4#n&yV2_d>xFD_Ri*!O6LT=ChgRI|%#`AMA0ZRwcKzg@^)+Ib~I6PHflj%T7W{Sq z*)h+*S1%&wxE`^dD)*&d?aPe6@Ve8$JhD#>XGhe_u=EZx4i+WBALZ(JrFzdh+*$qdhyK@3x`qUG#FetcC6&&f*i`3f=U1ZV$#ud5e2_ zQY^!^?&v*_RXw9_82a+jj@o{4O-E^LmnF=T^qmbHpW5BzM5f6qP@ zllVN{sJTaLKd9ASzj6A3IK{l`?RjqjpAVO-FVZuVEyh}*UQ`R{K7i~Cv~@;n{>a6( z8jRnZ(Rltp4Bvb3FKNzwAJ0cHE{C=Yye)EN2A)eC`ifrqrlP%u%x}?-Wy3Ep4}z~P zxns}_hkF=(JM;Jbd_5A+y7WEo?3t@PUM%LYIj=YVE_k+;yt$TL>Q#1s#E!<=JHJeS zKR#Za+;i1}X7k4^d_UvogY0d(&PBgAEKA~j*m#VwG9I#}9D~UnA#Wz4ec9Y{B|E$O z?)W;g?_$Fbc)O$Vo6h*2Eq)u4u0?)ZZDLaOx4&~0-3PIAoW3)y^NjiIF8bDNZv1WC z#djH-Hm)~*OB~~r zi9>O@`!8I_@i-9nyTplK8ox972%f+BaSQQ)q1>AMyWv|;ydIRxTeyyxj)r5F*v)o- za8u(ux@3R3UBi1H-EWW|b7OZH_hiqlHQ(s-%Rrd+LvtZt%H2?dTU+SlJh!>A&Ms%* zdxl)&H$B$ak;ifVC})y!G3*;SJo^OoEw|Q9N7w%Sh8BI8rfqrsBhX*o(%A24yw6iV z;{JNVKl#c0bTWJ^qraFP>or@O>e~k2({!#4$9d%6!;X_{)&`!Pn%VKDb5}GazG3|Q zFk9$~&xOIWMzuE`Z=k=2ZBuLB%b*?2hnKh?${ukpZjQS2(I3`>B{VmlL93XfYq8Hd zHeX9TSK+I9@DC#MZh3JNTz%0_R2$TTxQCqXLf-2C>dw|}wSJL1W6{(-SIe_G?xG?m&;2 zhjDa#L`Q!(?sY$*W==L951QxOMDI#x^WjMShmgA;+}rd24t#nnd7sd+w(%3|(=5Dm z`N4W3?<0n267fvh^J{#DFb}00;$M{iIyZ&lNB+A<`zP!=ioB)8^Ck6fJ9?YN<#zr1 z(eXIi@i5*&*R#%_!a{y_y)nG|fX3g=h~G7poA75217D?+(GEBMUv##A6Ap3ayW|qG z*qTmreH&T6zV6Q8Co_*wJU(?ZvpH3087uhw;`9^ZrjwW-*(bx48(67%S0dFg@rI&=KdFSli@rbwwL%}N!Po#c!qOq2-_{S#@`yKI+OJ- zo~!8eyqvX%$6OZQ4VE9Xdo!|@bNvFE)7|e#?!DqQuh#hcBxM_Y(bs!xztBSD=IN!&5RDQ(=tIMw?*l||P+K-Kkx^9N0y?ptWtR8S5i1!}; zT^fBy{Zr^%qt(74tSiBH8h<{duN|HP^{EGmxTmw!lmT?BE#VWsxx)SJuK6Q1C&%xi z;_sI$&#mPoISoVch&pAwhbivIu|r*ragEII*`P*n)PV@DeO1U%cd;m*|x^aYR(^!YahJv|5vR+ zjyP9)@zFjoy|3>^IrSGzJJ1#D5I={rVS1aK-`ux4?}_$6?Q7FzE-oIRi(kv@@py*H zH=}nuG_gi*z8*oQv6(iLzX0#UeDDrmwkLlnx<4nU7d?OD9Ux!&@!87F{wBNHm!j$6*ow^V zc;=F!CdKbU@|dFqS>4&VH{V5{#I@&Dvj6V5PegeS7Sf@$(3|Z#6xZszX#b$-w?c$?Hz1F{xNu; zLGv1WdpO?%_xbqf&KD8epIy^k-m33Ve4f#hm^a3M@`L+W`^7xYMTJ_G-p0r6^v{O% z7PgPTC$Ey5jNy5;#=dy|U;babCZE-2eof_TxvP5hjWOmqrSY4HjK9pup+?>)zKSuL zA$H=I%`?{>O?NNYQu2?5HI9=N_-KFhYz>oO?t=a){`*bcn(KaNvHK4mwW0A|ase5S zz|jXk-=}B7A@A}(w7o*cwrIsHFZ4ag*E^uwMBMqNxREb6M{_hCd>q#l;aThFm-Vkm z##d;Jx7=8cdwQXn57eG&X+C+3%u8V~->34meATtJLD&!P2KtU+x7uBaO&q%^{b8W^ z$+c8nOv%Xlkw0Hs%+~|>E#}^~d~S|S{$#Ity!*{GX}S@f}bymF%bJ znt+CXlHuAfCO`Tk`e<{0JC2-o__k>^Hrci&`KA6RQuUn;{!4} z@$(XLVxo79SK?WnKR4%(yX1v=s)*|exnF+H_rKA*J^Sl0vms2W`%az@J&K6fVEf6-~J$f z&w1Wi@c$9ojJ3e7;tqZLkuwLjm&v`6&i&!&#*Ys>A4J|QcQ{iVDHU$ayVbj`@{BdeqU?+7BqBqhADo}nO_JS zoAb9F!{{!_dz#<3pwItln%INQSJJ+2t8Yl*jq3#UGp;SmbKT43xJQy5;@-SpZ6}Z3 zqrbc35i;d`c?Aq#!?PK`u_x}smG8659!omJ{podo%g6B!pBgXW2G1qWk<-RCzsGe+ ze7~6X5<_DwlaGa3TdJ$YK)812%SHI(=Vt3AJ{;tDmF@p?K7=11!gmxq#ii=3?QOih z-LK((V=|_)VQ#bEk2-clKZ4$vZ}-8t4;$3txX%^HEO#My68{~9T9gEn<8 z+X-I#IB^{q9+R^bd(5}ha(ud2-SeumIOoP#n1+@=<9JThsW_))e4d+Usui35{r05= zzj2f<1;;;fne*zS*6PSHY|Pgcaaaiwn4lcWc%HXu9fqmaU({#mM?2)3y>n zy`$|%w*LypShD7$TZQZ=tZnh+Us@A)&@XR;e2VWnvZIWTXKRgdo{wPrW3I(Dd7N(V zf#UnN{8IA1!?Qg8fn+YA^9^Ueg|B|rUavLmC|}1TzH$Cb$JD)#f_-r~K4PyJm$1gV zo7F7jS@M;a$<@YN>d$+dD@IRA_O zNxZQ>drm07rh7f-qs8kWIoyeSHm06I!uI4&gySB#=4wBdZKL(c!SXHV#rfRWE6$*A zCi$NmTl^aL6H9d@Z{fGI*;?Z_`&n6q|1S4O(i!`ACznskC+K+%p7Y6>YF=Mg4oxR# zp<3EXmvuxsNKDp~=R+N0k>B9>0^Y0G;+ZDv$429*B0s)!$@hordvY&i$2dHddp0!o zUiiK^P@6nSUPi;_JjH*#ziat8eH)_thab1nx5T{0{&^X55 z(ag}_q2BoBEA9{Ham_YRoAqlp#u)2N_FCl4BBPtbc#ie5e3cDPIiF6ivD5f|SI)$B zac;eom>c8Y8mQ!Fat$9Yl%o&Ba5Wt_%lqiN?($9jDB?V#4&>L68OP{2{9m&1WVD`9 zV_nYFu;g&Qn!*n=<l95$`*xRYFUAln$Wm0`Hw(c|AXh1uW2BX^42Us4{ZVaYTY)`#hFZ8z#; zTV*_@x2T(*!2+MgclzlV$17qkZgDTAytgTod|G|vm`?^@W{ZefC)iuWVNvw^vr`>Q zx@uQn%AetrW7R17#3cXLng7#bUSp035u34HEP?K3_*NFj4f)_OZDL-^-|Akv)QPyB z4u8OTjqmYq#n%?i9S=0-knlU2O`99*wla>_Pu<5FbTs~}(OSnPhsw8h;&cT(eep*B zxz3HBD%Ozg(e@)B*5q#XMBhi6lh7>Cz7oDx{v6S2?$>`RpR*;-(Fs4NqxcTaY!2KR zeOHoeoQ1nxH#>js*q6`7)4e=?V>x_A_Tc7!e{0YI{YU(BfOjlMqdS|t@9^Nw_%4jA z`&++!bAQvn|CjW_7XRl}EfjJz?p4Np!_WpM@kl=-+c%8afpG6nrunV9iQWs?_(rYq zZBiQ7r}yZ;)wnv3-^aKfK*j|5*p^Mx$-juaey!Go{I(hWtCM??`uH+Amy>rEU0b_; zo*gOwSQAv&p?960Dxc(5+Le8dq9>W{ok#Iu5SxRY&-DGt<*;?f4_C6l+|iNWA9DYd z8Zn!`SU-2gcMV&2gS89%C&`~r;QdB^8q4vSC9V(S8YR71KfB{QhX8wa{UB>C?R&$u zl2|ON{{_0_Qu!D?zwrB8>d$%XSp=@B{PHfE=W31L?N)!bn9JB^UQ61+VLr}oB5ROw zF6ZOgx7eHh73uFo*77jV;=@7g8x9Abr;+Gw@shR05 zt&QI)Bo~nX0h*u4K1drZZtH55xZtJB{T^E|f7wP0n}{Sjz3l+oSgH-*Fm> z2L7VAz8~~$0nd|u-{-r+jIYYK*|Gt6swg`e0l_DUBN(80YMX+%8!65c}?OkK*7X3bjPRcBImcBlcH;`eM=pYow=mD0Mi_?s?g&_Uj%Z{j)D7S?U8__7A` z3H0Ira$h{>i1`cQzlgk_+3`VRF2bXiw$0H@VfVItFht(BNAoZ9Ly+?aUZI8`0IymW zpA8#-WE-)^N8*8f%FWn#Av^v_{%dUfExD(P$KGPq92tdYw`y=XO8aT_=uDsE)al*X zqy-)y8ao4@&0!c!M!@}YU+=k))q(6W_LE_*IsSuQTkHP|omh;=8T&duAJd_~_JF4y zY>()l%%(50w;U?vQZmf`A@uZ%PJ+$7g>+B!7qhdtDu>c5wqCm!-xJ`LFX6g12|oTw z+o!M&MEfOqcWY~+qw9~vxU{!3UGadKF`vG$2^Y@9(-cg11F70E<_=;Y$U_P7;A4b0%+l=SKzv*;| zF`JP!%b2Ip{0|;^6!I$?sedc<`_`*(zNBwiGwlQ4G31M-Tuhd47_*R0^1kdT?uOyr zvl$PzIFKEm(=Vs9akgh2U&&Sp-hPXjtAXh>@${*8=EZO#uB&(W)rhe6&98%<9nzt; zSLm=d90QD1kIG}&`9$Mqhw(7|3U_PrZfEnaZ1>bWho;jV^xF@fkV|*L&{E&oFm}Uh zV|g(Z-|_TpWfOPBtl>8|t?xTli)v5m#%wC7@K=xk_mWS~AQC%LWX22iT|Cu>1T8^Gqz&#Sr5n}5+ z@*aa_79BP*hK;K4M~#LZj-)$TBjDZxpQ-x7HEC-$3HMQU<^Q+fTnXRf`RYkLTF^&M zXCXdD>UT|FObj^Luf{fCz-ZnH?+g_WJ6^TXoWQTH0h3M18?0?NwDz%>iB@)uF1?ja zTu-Hg`S5Kzh=Fk3nqDKWA8)Ge&*TR;yJw;Q1bEiRvjcxj*0wd=cLkf!ImFv1e7GO} z>ScPQ<44JCP4`RL@)+X}VdJIz_NZ}e6TW*DJwS%|&aEfP#bVL=EAwtnx)wR7)8T0R zLM`K~@a|@`DPFDva`p(#%50lMfiwU+} z;NX+A9XV5By@2dT#lwI3#JaM41ir`hZGr!9;&NSjsE&#lkme`R)I|gPWLJi=o=&PP93D?MUWlu&D+4 zM7Zx&>qp>oEt%_}g{8nNS^?bxaW@Utm1@g=Gy9;m#NT*zpkFV?_o3gIte=fpAC5iI znJ0=#_@1b}H=LW({VOrm+qrAUgnltS<59I`|Jl29bM+g=@Sa;TMr_W<|0aCcD__kT z=Xacea+Wwk-UrF zd2BHOj}Qy$TXv=6L-4p4zb)a|A1=9?is|@xSVp6J)p=sA6!K*c^+jz;?=<#3wkco@ zIkE-pOB}OhG=q-vBHIM7P0>$p4lRVUb_1SHC z{pwcrj_<4dxJk1$w|mbw!16wQ&tmgG=-iFXH}QLli^csw@=k+sSc5eqc|&0GEGE9) z7{C7r&)(86$P)L_scgf?$=z(Z6xRRI{SoqR(EltRogb{e-4TAHQ@|eHVGh4#OT=8G(J4pUad*Y;iWtXztf67!c)wZN5Lx3 z(g5F;~SIoa{Qj29cpz4RK?=o_K`he;g_zqzRHTUnE3 z8|e%7Q%mD>#mP*1y~VcbK&lSpYtZW`KBRvvHqryp4T91AruYfi67;iRUyUwmOnQr$ zeSnSlqBy6?dYI1U-}p_mH^R@Z*&og~u+7)DiftNQ$j>9VFV+7!KlN>{t{ux=>i)|U zuLISyuFLEZ)~{tu=JL(e_n+d^jT;K@G5U{id3B3Bw#BomrTWjPdrt(v3+2iX-;H02pBN1HPg3j4Qk^I!vEx2y*)V+!y>)iF zqx}i=vaTz8vgt^+`_%D&>1d8E*D_9CRrjN>WTPe+x32roZgN`Tw?d=e*>6{^QS(l) zO(Sz<{ma3(C!Bw=g}5y;`{DS7T7Hs#bm`(+^_`PsUp44O<3fzV9oAs^3w(7u9@f5z zwL|nL+I8@6V3(um^CRqQ<9nX|Ghv#j|3Cd*V;X-I9X@h@pu6$U*8H!DynkN%)@*r& z@oTZkqwM3Fs!&hzq3{e8>%H*#yH>sT5bmqRnPc%3KO;s5lEpXKY%~{<--n;hfm0n! zcEo1`dbQE+8Y_Rt*j|m^-+}ivylPWgxU7fC1zuyl!#DDpIK#AY? zc%MzjkmqaBcSZWYhxaOIKY-&{ylzLgrfnvgd$qB7^*k{%F2w5Vo(al{Ol>ZE!2P)K zpR>zP^i?~G8^|AR3_AuNSMNGB;s2dly$y`#khun%%Y$qz3{Ua*sSUn0D(==0KYhsz zIdZn~@-x9VQ7>}7O~0Y%40d~7+Y-k^^?y$O&U}Toe4pJqll?OM+vCIM$$!W^O5ct8 z{$q2klKlvGFBo3L=Rfq^0qyg6u~oR9C>LwLoGzW%`yw_D@jM8h)_gP&&im;2lK%DO zQ5*CJ9IYny;*%5j>@WT8 z#99jX88&0Ge)bR5oi{DB*#UTN1oMgFXV^DoAMNeWAS^7oLd{K_x+>RVsLYM-NpYM><8e#zZ$i&^F7#g0vil+ zzejA9j~FACvXA)d7y4P}M91MhjLg6ATuAT#Y41e0)7kPHdazZ*uf16(otufOM_-^i8 zUgXn^o9BErbd%Y764`Ips@N|>UR?#(CB~}*p*DqgO$#-xT2~H5$3IDbI?i#d?v}UK zT_dtZ(6gicxBS_jtqwBAJ)DAF67d#dE}Bo4djQc$W519C-|^+{u#7;n4J_u*^jCeO z*=R*=IlrAxZ|lM=a{MR$8C;*+LLQ3yRK7){U}}vYTO@KOT}aT)v>f2fY`!@ljb6=Lc( z_B_p)_wf81z6aRy+92O?8#bxKb}qXQpvRi<-DBTT8@{Aw2?=+Nm(5W3>>%uV*w$b=>F?PZ-Y$ct`-O1<2a7|xW`zPDt)#Ug> zetVYuCmjF4#&Rp`P#3FoI3Ldc;VZ85>&feFf26g^Id~0c_jQe3tc`!;g6y~H{0A&Q zumj(wpBQt9{(IPAN0`1b_G{N1&(+wy!S7bY!f-MllLKq@U-tc)qqVDd`7`8R%SS8n z+xE^kqRYeV@G{;{(s4RDKjWkol4D)O}JjW?|HhLc%%?tXk_C87bTJ@YVIUSAs zinnKvb@108x3tkW)QZB~ncTr{FN@pf_3x`aC-L0=(pH7VKy}P|!QRzR@=|@x7BBk1_r#x^K^JFQDCm ztZmV3Y0L=YFLL|~ojS1f_2iGKiB++(mcBP^HyQIH+E;9E!f(BqwB^4gbX|b{675^l ze_)1dwsNV>ycV}K?hrbT#b-0|^BW%G zI-`F&!};sz-ZySz*n1m04X#Q0&UX9`d?(O#KXJ2T-Ma>k?}o)SWBw7Gr!UjJ%*k1* zejJ1M=W=Z-Y*(V4!7o?n`$o(h5OCN0ZcM!KO$kSI7|fqpE8OAuNiqks=i~UV%@`#`S~dh-O8(#I4ii(ZC&RtVNc}Fa z-PlgNr=yJdl`eO~KEZLY->GDcsk`TAe;W+H(X(}9^;?@{7CA3zyGFlp z?^XtInC}}z@E%vZ1daNT9EFGa9JhwyB)YzW*VEn~6wk@0blJuD8{s^H?cgld z&@cbWZ;jv0*eUhuowoQs@_LfD3SMW`*snoU<~!WxKV9?3H<;%Z-vii@U%zQ1GbL(N9z+O zshCW}UwIcF!;pRGd=lOHHysM+Q2ZvqB~RmR>9INleG&R4QTIUkLzLO^W-poy$Y?`5`74ZSc=-fKgQTaQcOp^X|sYlIxG)YhLk?cG>UMCc`wUUfmmsch&we9d4rUlVXs6^F{RE z&e*^BZ8v?#%G;CJ?^CqmFWwC8G4Lhyc*WdtbAz>hsJnE)H~rMOIrtB^wF-2`n7@jQ zK2Oo(D&z4j^Jk1-s_%2Q;-~6a#)^EE^T$1K zZKVG7#Y?SE_@MX#tz1kdZMW=qOlKR%KE(z2tp(cyu$(~dhHUYcF&mP%p5rs{V*65U zi5{l+a5`8Y$49gA@v!%S`6qU}ij1Mg|4Pp3u*=1K19(EsE8#QeCE>a>VEObR`Nt-G z#Njw{)trpnWEQ*pVm#ZYbK$dw%*NsG+BG{*t#@2Jjdl$oPVco8b5e zj|cEQ0_KVAwU7QQ@c164L$r0&R`(vkyXcmK=TeYL&={NN1Y+Og@9hkMTh_V{c}gPwLe-7_-&cO{nq|TX6$tGI>7%n{3qcn zHzGAVmSf2eju+X+)t3Dq#Yg&&#mBwWY>aU`81u5&m`&!r&ToKIeJ@TY!*|AFc~{=T zpKHZYvtZ(+~ZFNHL9ifJZGLg3Qcc(_9jF8M{Hk|P1U=T zk@$}~!$_BKPcffXQy=Rd6}@$1@lB>PBX zpRaj;0H#CmdlQCJ(8$O9n_Bfga(rRiimx5r!EP2Y2!$`9pK z_ndbiXN>y$D}HOiw-H|bw5`Ej9ogBnK`y5vu^K;*_jWMK&D@yqtc7W6NVG~Svy8%*Zej@Q*6Ri}lRbq$@a?)Mh$#o&Y5`LNsz zh6DIn%?)ewaua@7ML*2hJ9w7XY}b?Dg8jbMXWoxCBYRcx1b4ZrF*|AB5TA@s+~0|> zB>PzQm~3wLj61Bu3Vh2jPd?VwWS`X;;VfZyNx$%;b0 z9S);>4fk=9X8JC`^HKY2@Vp!5bDQOXcYemBxkcNhbRQ>v_8|Xq+XVb>N4GZHZQZQh zwa_zg7vwFb7oD?{>9!nwx1`^@XrI(~FI)#3uU2L=@NMaT6V-rX2>joO(FX0^&oT_g&oyPJ*@Xcmys!nAG!10XZjqS}b*&g~oww((zAEX1| z68C8@<9E}q?qxso!x8K{l%JM|^ELI64T~_x{@4Bk_}Msl8vhsB;tn=ur!c4G?)Qd! z_{j{s&t$K*V)a<(_jyJ*8bA44uA=<|^kS)OCq}F{<2UHj0M`WV)>?)7Q_jRgOy%Te z!H4Q{dKg=Zqv%2UbijLC?XHQ+&EY=Rxphc1*ZDj+A0Y1#d`@IjJo6jyxdiWZ@cp@; z`!@9PpXc!iKAY#c>g#07_i&#%zZA{(@X48CgSzJyXx+C7H9S8UpA#Gppog5zhr|6I z9HShs4MWhmzqT+hwITaXvAj24k@_)5O?rbKZ{yEr$wGQ~k1osEWo7++;eD13!+f+i znr4{(M^0z7))3KXvg>qH4-?N?^I_z!34aSdh>bZw-^;#J-nF^9&IolqYOK2!GOh{V z+iK=Kyl#T$6>W{|^`;tgopI-ocZqn4)WzlX-{gFAc-SM{tB5a`dy~<&!@F5*PoSUs z3GqvGn86&R+4On{#?guPdu6p*I+~I)BF^C>6!hToZ#=Nc)uW?)a>{Qye9D7 z^7MFKOngJPQ~A*Rk=)~$zmfs$aS5zLwf!abe%1e*Slx$wv0Pq8j{DxpcYL@p+dpeu zUo!ikSEC56?rokc7Pv4N^PtkEZxYi>p#C>nNUTgehG7`KNu-n1L zvuz%;r};H}!?oC~t|pVQ5`A`o?J%(=zKcz?AH>e1(8#%Rw0s_{?R8kT<_j|NM1L#t z+co%YGMjh7b8g@X%YNDiklD&{KmGqUc5j&b7&n)`-`Bj)*1!5M@q92m&$82-#;{X# zKl&Oy)w{F>+V_l=|Ix;LHHwT=`E&!a>)Nkn$EjlV25m4G8^fo)RBy{2v|q!PLtwDB zjmWL;g+0JNO>|h|zu(l@q9vPHd*|1~U@cT^LH5q%9A^9=W4gfV|Kh@P)OZ~_m_viy zG=Vc*8>=~SpQh?rP58gf{4D)2CE`BkpPXN_&(K~3qx{bf5;I5O`6Hd!FJHY@{by7% zslo4`+5Ss?KhWiM*cY0Y!`kqsMr(Zb$=UfN``|ONkcIi@e)@^w_+7fZq>qepFrD_o zYh$vXgU`E-g?vw}i^KiVXfWEIVr>zfZiKZ4hb=vs%wKAL`&p~*!)B9=Ijm+)PVXM* zC+mO6b_G0N@ZT2=?$eMVwu=|YSx8QIW94>Oe}-qZ@kqS8u-8toiuGs`IopUg>(SI) z6uudeo&?VUu-uCGfoO)~w+EeiiQ(<|rN4fD%U*MC-!v`OS_bB|uS{~N?E79k8eM4aANQZvx zyNms0bT|^ve_%Fmm!BFV-&1o!0Yf^IZ}%hn2sUV=eXO>X@URBRrl9FWrg@;)+St{^ zNbvQo;%!Z~k{g-4%im`EQ{deICiSaC8_TnFcHQrb=|85)?<)0^8Lrb~H8I`_-sQ-R z(7Q&>hHCo{IZx2xUOII!c2)an##~4iJaH%a@F;%ftEgjh^=;bpGv|YwtM6!~58x@! z@@>%WZrp=>HvwOM&E-qFu??Rx)R9l%X*Tw3_xfF%W^a;3*Yvkq_1q|HO~wS{{)JC} zI$KASBVd|>|7GDGG5T$^@63-kk~5a=#CFK{at}0bSnqcJzxFfOqoX|8MC{3va!vhD zqu&B849SoDGgNFnPWJtMAznNV*e@eq&c0 zjLyBA=!I>~Nf#zS@*vS-!t9`-$(m$Z2O0EzRAsp$rd#>;G=(uzdh-& z5nRhRRdJUb14|1v!9L8T(bxE&g}x_zEgb(yR;a&g!`Kpr-uTtY74vyNV;-efgtlGH zJvMw_(_fOcow2`bKUCeHNymNAh4DMHi@1+=B6k#9ye;=QmRjq?bu_t~pUbM=2o$sE|u zGv>=$^<9AI2mJ1t#=V9A-T1;& z!XK^)!km=9?|88|`_8yy^^22eWj4Av*c{LG<)1k;JYOhQVSh5B7j37YSHsft@c0zZ z{n6La1pnS&_xxY`O^&;x6-(u&biKv#GxqcNm2bluxA?u;d!07ENqdpIB71K_o_vok zHtt5)-^BM?wWueY%{A*g*u{16q&462Z0q@bA^*c#BixrvzF-GFD8pR39eanETpK38 z|H@CtQynSkp5l|SWpX%sse$2t$4m0lvD(ihYZgpoC%0H%SjUDrI$%l1iH9@TKltPT zHn9c>IKy+8Vkz7Mo2uWV=J%4ZK>K6HJ+1!EhqoKq>%)8qom;cT4)_m&>0kULehcf2 zsDTY`VB2}xZxwTDWW?9yPx@N1+mqHqE$BZU|9``4?HSKxv!&>#Xd8^rjc~09%PgB3 zQCM4~$I(x1iMqqo8(q*(9m_6+V+A}er1v+q>YikQNBO&R*FrHq`O|o`=Qr`2t2bqc zhuHrvm!bajNt+uA8Xn)Z0C*nywrq}Vo z4X`$;b1_*R@RU=DnwW{L@I8d^K3M#*7{AnUhGu~nmn-?V==dwfr#Kn?1L7an{A|7u zW9iTIIEbv>*y>LE0p!0$r<353OXV5*Pjx&5zvakH*WN23q9HLmU%IA45Bj~3c* zLO+At2-IV@k!7z!AJ>WZ^oi8SHkT!7~@2J*a zMrH%u)R6Q8GP{U@U&P&qeA5YLFWhY~cqscH=#rnfqwJ>Kzm(@LUpkG(m?&2fY zpG60JH?v=lj^{L0?{`LB;bF7l4fY5+JOKN7#&3?-`s{EpyIEsa_o8~RZ#QGbQQWGj z`t4zOHWi7XTwWFHlJyZ^$&vK!{#7hxgV^_L=eM!JduR_a{z!ZWqP6ypHVk9QIM(@2 zaJ)`F{}idcILJ>zpUD9+UUWgr=jm|z-b!C{O#CT5*QM7jY~4*MtVZJNqw3Ln==`vW3 zSl2}J=t6FIpEM57Kw36O(K;|MV!xb?=o{{_C#$mCf!eKg(zRju$Q-_>zNzH77Rk1S zcO<%t=O@!^rPMPR;pX zeWQ&XM)&RbVM{tT+uw)hd3^b&>xN7$zryxvXZWwu>|6T%g#K%`9E9#w_}-y+!1=bZ zQ}8_r|DIw`K7@On(b8q#j!*v!mwUyjnowMA+rODl*k?WZyi<3Nh>kncy{qwZE7}X5 z5St&svAN@Y&|haSmXb^OxS->e#*D@58^^Uq_pa~?^`nRVlk9#4ymBaNwzcHPKj67Y zUxvrw;^0?0CAI3_U(9FmLG;`azYXcu7v1*yo(^NIZSYF_(e-I`tCQESxq5Fd)U`-k z%C{MQ(XQz4BmVjMgCL;sK`?|MfYo)D*{IV&s}g!fqckSoWM+lKsA*kBZWzC(L) zt@?gYWKEoYiftSFQ@mR__v@RdlWs`-#%KKtwMaCVgD2!tFqA@ z;@ljNF7J3byeHTW=9`n*BiOeCOzLPknv55X>F4JPtqcmG`g@c77YS`|x>>j2VtkZd~^5qDS!G)EXenE6>)d=cwsQ?9-a8 z!F2e>+Gqt>Cb7w6a{scw3!NI98e2})cMM<8`Cwc`sRNK3+&?^KMxGhwGmFOE~sm<6YUF4a4_9vf0Lmx_E=*AK@Eqd`FnsHExFG zayaM6TlOlhB!6Q$5gC66UL(l;(|!M)V3Ggf-K%sVx(C?g3;nCGMFe9fbl>4O%>EH` z&>8x+WsgnJ&eGo9_z*+e;480kb4pkTmug7Pf0217|C=p#g@wHnb9DIsmQ;yH1>NGza8t=Sg`O%nAg*h>KdO__c7PTlW(IZ_=eAt;Ai*UB6dmN*Y`MEz?+x@ zs`r)#*QeJwKh?6qQYKgRkP*__Jf_{$j*7 z@n3A(jxXeVzB`$hvgrYQ@u=gTV&r+4&mezSa&BYS&6=%2joDAm>@H5MTausgfjeKD z9mk-%jE#D0yRBa3ak!pMpMdoQo0w0;Nb(~3<=L#sz8zT)k+B%RkR?qQ?PZxpR8ydvi^qiD?WEGH`Kd$Jh}bwxPyJ= zMAF^9OQYN*>mPk#J#fE09{CgK&ZgV>wdy}9s`>UIwQL4Hd{VGoG>_hDXtV_FAifaS zVf|9vs{MGpteL{Q8{xTBHq97$9StMXHC!&YBC%TCfB%!r51OiPRb_q1+(7>oFpJad zSh|pr{15%R?6js$Y?U{YdpH^6#LTMXZHVS}`u^K?k};>_v9;Jc9sLyjA>TrLUS6y2 z*Qe@8F@R0o|IZE)ix(JwExw20w?d=mK#pg^&=Ib`jaT!F7sOHoGhf7y!S zZC5o}rIoJ=v3%eQ=^x^*mG>)}%;!&)m+ZfAOM;g}-Ub3<& z;*WjOq59h5F<0Lxa%c0E=PD^4sdZ)kZ*8s6hdK2yV|%mFv5kHoO3#PUjAEZVYgH~L z`_ScFZ7mj=k80K(@a@!Wtw~R7q2ahn)=l|l#+Z+?_O`#+bw&1G zg^$CWeg@w*Xj5zQU9_tW;d>?dV8?PGI+w2UFIRg~xfA=IV0a!~{KIcs(f>CXmy+Ka zyj-T_Ys>zp?LxS(aQtVZXH8^_vtl?N=io0M z)0N=;z?eV0!`+zT}Y z4U7iC*BOts`A}SD<6zrT|61tGWAU^6e}VQ7;R|*b`}u16&aYSRVubI)6syBHmoDoD z8=_a2Q)8kn+2ap9w&APy`SB6wKgmmWFJGxuzi}^4BmV^Yej?UpX&-{msp#GzbNn*> zi!=2dWF4?2z5C*`GybsTE0ZC{qFMHTqd7qz+s1sGUMNo%>z+~ZN-HC z{&+t|rv=7a-(+XViS6m#O#Z-n_0CJYm2qOGv_1;&t!Fop)5+K=_^OBL5W26*Zawi) zufuy82&+$93;x^7GTi4Wh$zx_6Wt)&=SF;^i#%eGvWYj_)?+Te!x; zbQzr1P^q~(%tz(P`uH>doUG;Xxr)D*S6j^&(OWR6LD9o7%wW$~j9rP|Vl`jQ_+Q~_ zhsL@!o@3nQ>~uQ1S?bEQa`JxkU$W7PWc#L3c@g<@&~)U>5HIG@qF-G<8&1P7TD0uC z|2TGgyrKG?QMe9_TIgS|Axg~+dB|0=lVIz2$(~E!_wYZ%y1A8jKbGFl(Pa&Ed{wL` zPIiRX^+mN#In%whE@a-0??3P~qkTbMtbq44G7q;8{t;Wr4EDW?UWM423b%D@_C|yI zfS%)to%DV*50ULSdmPUT?FZ7UEqjWW>YF|nu%ny_|Cdvo&X({OYm>2GgKwhYrM9I{ z<8>lAbPD(X($Nd6XFAcwwI~VS6xpJ&`kijJ0U3M4){ng>8#f)FFSo1iN2mN!{EH2b zK^y#UO%>kB2=yupc_>En{q=PtQ++NQjLo%&yjaa~Tl2(DVrW-wH=^xMm-ggu#TP;6 z@5R6`blVl*PsNRRPF9o4zo09%UqSW(j<1FPV!C{)Urv_2@jI1_U)XF_wpipm*n!RR z)%oTiI$x!pe8xuBA;q=qGMInWo9KG{%oXW%Xs&_TTBO`i+q7C$_FDZ?0h7-_h|o}eS8-&+r;|t zXZiLf`?aRu)_5#W?nrj*U#qT{O6$j@56nODhkPj5FWrc|iD;Iysm(!V_8WU#j?W*) z?L}T(tA4*$4#V?a`iQaYOM18;5o%lbeL?y!*yxqaV=unWZfDCeaBi;e8*(7bwef&igVdRziTfm_${Qf>}OTSa}|IAh+7gq1f$7iy+I4NecF}tU8+2cw& zT_TtHBil$$T5edAwJn9dso|faD0LHs&xGip6kHVL)(`0{h2&*5$4;t9U8F|zNwIy z=aO+`yoJ|A^jwQ9F_goR(j(O8GLsL>vvDu|J;+mU;^XKxnhmdGD?ZHMU|Z{-P~ReT zF#4Xn554zrYp7A?5bMB*+;IJr-pDWW(4S=99t7(hFr5jbnwWpizIMvS9$?IvspYd!~k2&oeM10hu=mdJmxm2Bqwr#5Z2O<4RoV>=Cf;4f8lQ zkYh<}$4`^hyMOf?-SC^#cr2My@w^AN?)X~&=6~_c4d~D4@4NeCPJof$BeIhbZ2CO9 zBW$O_*izetFuzc%ey>=z<--~LGn}43yO-IC%)xld)uO5zFEEcNyx}9sCw*0<5{1t9;xI{daJ@t8Etguh~*v%Fx8Y z*YYynP1}p?v;kf{`MVd)57JF+=j3Kh=ys;#1?;*3{%dOc4;>f6uihtXz}ds`y2gJD z=bM2y+}8C;H?&t9b6rDK>yoYEoYPQ!!zG)9rY}BS*oUu!z48$AYsgFa5cEs?pxp)? zT(LaOmZ#V0j`=&hubz!%hn*cak^d0cKj8NadGaxD!&j@(IjmvN zD|?e!P9@Vkmpow1mB#LA|F>~urJaqthdy-7&%u9v7|s-%uZgMEj0rXA8a%wi7uHdU zxXOm%(Ll!a`1FOVhyH8mvnGD(ZhE2ZT{=EU?ydA0LZ400btLBj=QldwkM%=X z3q*Uc0lUTr_xH{v`SLBkhTNxM5B9wb&D!h_chS*tC;Dv)|MvQSY^Z*>k)FkGjmFL- z<3RX-T=wzonniWeU9;;I$S_+rSb0@`y2hM<3o@4r`EdOWWqKqc2*q>Bn$PbspinHrYLl zyB`0|V12#r8kSwqCe!JlCRP7I5_10qx?a&x{iZ(rwln;WAio~{?fA6TE*`Uc+2&^$ ztvAATV@$WwToS#A_Ze)n6-*?D9m)wc4G~vkx@qqfW?~HWT{($rS>ADZ! z_S60tSx1W9t=Z{8n9i@6M_}%Sb}xR7+0;FZ@H`{@2YJ2_{^RZ8N`|n{$LQv$2|e-J zi=JYxASb)g_9}bcN1v88&zNldTCIVP)wUuGkI7xOFK@#8DtNY{@3;6K1fyr@$tT(` zC3|?2?^fwU7uGc;9YRiocQImhtK8YX1DYM-o@uuYdH2Y zW&*uo$ni?qExNeoy(8y?8ms>nj@8C&E*^c@_icPmXs{-t&th`!z_U9(ci>B2z?YtZ zkN8Sq$#ygD3z!bY@7bDX7i_W=e|{;p*A{Bz-{{t9^!+%rr^B-^IqS3G8+e?L{wny? zhxkW2iOsAFxc6K``Co2~c9Fh*>gToiFE;)-GJb{gadG?z+Kc7Ir}+2RH;j!hBlnbA zH6Mrf+6(W*hIdCwv6P-@8>KBb?qq!4Lwlj)H*4l=IEIoZK4Nx`A49u7yZmVX2OW3N zHW>ysOAkQ%AKx?`P4)=qSBRG>WQ3YPkFuM+I-k#`|5vbd=C{M?_K@u-{M66ty5<#_ z*ApY1&E|Gx|l7d8~buY_1omkbwsfq`Fs^$O7^wRo6xo}cC46bAp2Q-=~Jph z<>I>kAY;E>#nw;GFF|{Qv7O=n6peLlauoh+!#M^{e#nd|zBEp)$q$D2U2Co`WPWB` zPkOG0W*y_25TwiDT27AgkVLg+>D zn$4IqoX>E)27K3$eK)%tE5EK}iw5y%t|`@|@SW2n_^Oxdu$J&|z>Y7<+1~sU*1CKU z-#`ZYl=JcLNY)fKdfz#W$w+nON!V^9W3c^0I)mPPl;cWkhcw6Ea&)3 zwXPArFZCV92GixkuK1ly?mRT~4mns_N2KyL9ql;8?MPVgNN=o(UpUz`$VktZbFMiG zxnGE*Z0~yY{{Z1VmSQZ7yBVV{W$VECKe(PYW|Fqw@LApdY3;+|cE2jTPglB*DF5qO zMz?0~$vSthEgyrn4V!L`{#-T~j_;j#jc`w4Jo{cv_x+lx{}M{bjc%sf-SDkNCpL(> zP-9= zd$D<9#WeWF>f2U)h}ZHLGF4wMZsPa8L`-@@D=j!{>HkDr%(>27;26%4*Plo?D@P7%< z#&~&0x_koNX5_62=Yec6n4BH)>5WHwIA77fD?Yo{mOVTFZ_WFcWSR@ImutRTiLbmV z{t~xK*=RhS#7t@KO|8X3T}XD3u8yY*r8+2IC+Ujln%dxXLKffl( z=l3JfhxzAX_8NiL_1e|owp6L9G|9bKYBhV&L@$R zlm9>0JhNa}!UvDCd3*EU9_T-4tiIC~o!fvvTb_?^KjW6vt9SLo92kp-cwKQYi%#bl z^KaLxAClLejm2CPY_bXazKh4rWW5{wNQb}0in%Plawb1Ue6VRMC(D+$LGYagkNGQGiU-}xSJ~h+?I+XcI((Kl?h9?3qYt%ZQnUXs z=GQG7t7jb5eYPEq&(U5?$1CAE&UPMMSJ1Yrwnj3yv%yfv&)ogS@ST=oNBs$%UxWF( zhGo~xA+}5BYD-Ffb~HJAv$q(HzH`sEGaHN9So}uj%~-8YC)4v9eBex8vL9mH_VoXi z4mat01@2k=f2IC4`0O*-PNh=U}<(KHJ+?!=np7{Q}zsFkRl{zAyZZwies_k4k)=$LFY~ z>RXAycd_ffd@GoDGS>VXejlHT>FAn&JT);=AUJ>i~j+|6Xa1fR82xF$>A!sA*r z%X$9KpVhVAOgz+q@;Nc`pti|;GD%xYeEBEyK4sR){sA#IlO6-K`^{QdAI5K>l`p0G zn)Ve3UyF?m$YGOgRkY8s2fJq-#6VZ~^ER>Wmapl!n&%I6mLp}T-|AC%hF`Qmw;cZ8 z)#RUiX^-z0c*x@nrYgsqjQf=jjzD_}d&;@uVzfK+?-JwAheQ0Qzrxnln4##*N7*LY zt%cGS@U;`8;w;!Q+&jp2sa3d>gYo;pxf+o?3(pXKQp?J@c&y8gTf@70bM*`?Iu~ zceDWA`o^{(f4cF%@Ijah-oyVa{lmq@OY~b}{Kw>mdG1p->SfGbc=1bgKbaYQl=l~PHfx?k2%Kl)V5GuL}l>|410i+;l69dg7^d{3~2^DYg(eGA7{cwFOL z+-93u7d4U70o`K0Iu329ku7c8qFVzVF_nzh-<|y4waN$K`%KC6WNA+eyyzA0%`SV@ zjX4YLM*Md(y`N^s$8CFw)l2zz zd-6_!g>6!{j@LJSL-_yHZaz-m6uV+G%t7IIlhI9Z&BDLGzTCdA_LcBn4>tSKdMyt= zy$7DJ*`=Lx>wh;xJ#%FTYudDeL&)0$ z-!_YUKSG~%M#1Nim??T1|6slPU#<9dI=tSjUh98K-EwFXvwTP_?W#}Qmn*@Xle-~%c>ge32mW_q zSh2yqTgPXLr>potEG5(MT?1WW?9O=L7p(yI&g`{-E%-Gx--TJ&FZ#oA1-{5KFa^MJg|KGi>v&AO0nzKiaL>ksq%g=Fjot2r~{yCPs;S^R8Tvrffp z5^UeWx+Xh`_wb%W@+x^_;FM$Go%>>a`tPQ#6P&ke>q^$4uC1SUe1o~^O5@qO+>}qc zqFo(^xnzz2ii^w=l{~c^RlrE<=vx~lQ^ayj#`sDLTx+bjVhj4GPlp|$Z zHoO6zo^`)xl4tx>hFbUp+V|{##6!(XUn5hD#&RrDtMVP#TJr03@2ZiV zzrYTYo0fgU0-x+wc^lRYC3%DJ;MefXD|wyF*~W>5jNEt+IOJb^9eL-`*?p7rY&37c zP~-b=(0(sI_oe44bYDp4UD(4qA?O%=MaH~kF_BC}JAv$2{|96q3G;OKQ0bGkLC^ll zeC_|M``y|?Ycbg78h@7kZ}LlAdP%OD1G2c;?}hMvTi@4?cY`sk7qrJq*yTX`-^uH% zPh6$=#A2)zw;6uPUD|u{-$vdq5pRY3kDkQOm_*G>e^AG-)!th?ylnrRz8%rGW@|B- z9!>5Las9d&+(Q3$+Cx0Zg<>6cJB1!s&`-=4A+9H~t+i})8C_?yk-Amg7j@4oc^K{K z`sT0=-;{Oy)*^2fENqkiQLp~nv|!uldA{@vv$Spqzi|lng5&mR#9V$Cxu3&5j;z^q zzTAdKJ_R2!SKLd-l^Uzx*T#3_IjCO!A5lCAzEk0t!+x9a!D zVE+mp^pCCa!t<#jtW!^CuPN+0irgl8j3?tn{P?$6fsNj9J_p~H@J)mHZ#G+{vGP|8 zUx@#54&LU=Y%|CElgU@b9eA%p#-(EQBlca{F;#5H?8W?=e?%W~oAQ4t z=HlzfX=BVHIEISFmGHhu4rJ(eYxG|l==nTi@8nkdK6swkxa@lj`_tnX7+&HBaaR6H zZ*xqzcaVtraKAO)mCVKB)O?tYQ?K#K>f&r)V}7&!NVeKn+zwNMz72lY(`BYyxK;^ z&Gyg2c05_^n7+aHYFU^=!*lucjk@oZXupiT54I1r=tTR#H_U5I`X8tFVdBHOI_k-1 z{2JEi;hX-6SWKUU?*Qi!zliZT#Zu~;F5G9# z&%;v;#e5#MwLcM$5VLLI*^2MZChs0R`@wZG9NNpr9J6u!NX`E$(q+8;es$kRse4zH z4a}qA9ggsJf8ly^HGM17p(VVV8Z!_7{n=}enw-S@7P8=vAFKOsIp5EJQ@c7+ zx_6j{>(N{2w~#;9rk~u6&*E$RV!2S=kNUmAwTR=zZ1b&snCs26**@&D*#Tg6x^wz-P`Y`+!F}YX!QvEj@v%oPO(=%Xa+fqEoQ^noN&fgC*_+}`4 z7qQ`ChWf6Uj#K(xoRN4VyKG5A05jmb=}#eXp@ zP53m6@t@&rPgZ|@C-cEfycyGlE z&gecqP@|%t&z5*x3VV=$y1017`Ko;TD?MJ*HW-f$$!@_;=fbfb8{cI76uxNz!&q{! zg)^+_TcYp7_j}M|DVi;8cx|EYgSvUwu~-ei8%eBn!n1_(J#Bv(bF{th zsiopDo@8CO4%z#|+Y#Lva`0~B+v_W>U$$kxc0p%0JP6HFvcT*uO5Dm#m_ zoPCRk-PkhtFglQbI+68_xySWib~B#0)Vv?bw~x8@>x0is{@~L%=<%oXJ?Zt9u>;s) zr{?PZYqd66WZY`{%;m{~n)ftpVSIlWdXXy+i#N1|d|-!on)B(fn_t2=T%xb))pNW2 zF@6|^*HAL<(DoU8N5Iunj4fi1*6eh>^GU|GWW#=V2HXeQ*f7i4e+RK({!c>8t-vnr zY#-ClJQjz#E+&${@EYD+eJehF8}4 zhyNVsSLx@Q^6aMSx0T_3Y?$MVdtfFjzS?#+U0rWfb6qQAU-Ms==Z1Nrs(fe z7x^KYXgwL`zwqq)>4xe*IWuds@EefiQ1;tJyd2JUx8b#${btS9InB%LbuZq1Yy;S- zi!tZG|5~kjmKwejRrX-7$u{vC4Iy)1{Kan~--{+~*V6G(`j|VjQ{{%WTI{-@Gu5_`!D9sm%n9i3+-9lD65#j)re-`m;q6@UnNgA|1E1eiRe&ljLn?e*r85@!F-ix~9zhracbp z(+lC~PbPW6--Y-}XL=X%19oU&zeix(8O=H{U&cq)@Tv7~{IvE{#Z)V@=QdQ|fDO-2 z!ZWC70o#O_?FGNJQFw+~K4>%Vm!)l0awa%G%k~dG@+SSH<{6Sau&zuWri(ZV>+tL! zHtxjseU16MzxjhbABL?v*<07WvtpbYmp)aC3j6T8w;WCM5PEr*dJi@~non*-f4vxy zQ`PtR|ANtVMYc0u;ypRvn2&6i%1RBe9QfDrY0Ls$5I|KsM?J zUmyNilbz1A$@O>~JZp-VCHx9w`WiW8gl9xy4IfQ#{vy7?j)$?+uJl@pUr+qyMYv{) zza;bQTJ=r%JYbk^>`(d!lCiP&)6o4-&AQ*czEJaK;`_9%H=O6OOP&6A!LmKyK2F|B zi>#0M|8bZm*t-VG$CCL^f8V@ki(g@I9Ut*y_=ZcqvhirE`zJf|2~6P{BfE`F04o#40&pRd?uazj)c1|Pe|+rV*Dqx(qo3$fD2xWMOrdwwf7 zhdbmeJLikEUC?MfX#a!0%NwHysr?jwSzgL8xI=$tQc4my*e4*^-3;-zY`2Qi@`t0H(!PO67h!3 zYM2-eYqHnT?T&`6;$i4VvExl}{)o>GbXtqNPsj*<8Kj;5StGmNYwU@9&UWD$Pk9bZ z`@wiIJMm?>uTZ>Z8^!()iJ=FK=?w29WVL{AUGlmZ-x<%JZQ?vz1vYZymDDY~O8B$g z*m*mB>QrKVl^sM6bMF6R>CWS~7`s1!PpeAGE|NwnQkGuKW%<*0zm;wG}L{)vN!!kN6kvzsBG23s!6l-_EHwg?f-1%h_LKI>U6GxGkWo4fze>f;~0n^7R~t>%ZQ3wT1}yH8Xh? z){^;w&CCC{p#vQ~VCw|)wI4CQrhBkK$#0&$4$u&gpxW{hMml|1yN{kd$(wfG2quzWd~vT&iL<&bcSq zR$s~+o!f`M&zrN>2^jb_gxr1l)_i`&af%D;m2@T^@Ey<8{xyux!h@UqGP(z_JD87j z=kh9@4DX5bzd5LS9+IT+O~-8u`@7_b*cLMym*?i`bjgcyQ~i(DUrmU!X3x6x$7OPW zHgj$G9#DLPwkKfRhF>K;e>ndY`|s<2t@f7m!XNI5WN(N5bPjg@5;j(JuDfjoF%$dT z^OZIRRxnP0;Z8n9xHcb#^;I-ppZ+!9PlkK0{Uf+j!?HW%%`vd3 zpW&WmDZjE0$3mi&!=huigVI^A*HSiM(PEYoLO$HrK`K;PN* z>iah3m9X$XJlBZZlCQyGtVG+fb2%S2f^QPPc4?^ow=bVVcav+ee#XQwv3LR2QSd#7 zpJ(d+<5d4CYK!NPbJOv@x3+cIl5gSrxyhDv zea>I=K()4lDZNVku5tb`ZEfibzJ~GnLsRuUD7jmn%)s*k@$AXJ9m&nHZ)1Oz^~h5G zt^<3hXJU}34=KF)8~VIetG?$EJ!-A7gIxI8cnx_n1s9?AwzlU-*_l4RXD_iYM{_kj zIu(Wu`EiE1@g#lJ&6He1AwI#d{7Qca;QH`E|)AKj^f6=`KJ-r+KPXilY z$&*|7+FLwZ(`6ildY!3l<=NUM7z1H0d77^6nms$vXHV^;ZDZv{2mGn|=@0N7FJ6OT zc^9|1h*l@lLd@TXiQVw-d43MNpOSeFH^zSAIxuN$u70;PZiQoGBGl`+vv{0mzZILA zb@Mg)1)S%@g(}De#bQ)X5#r&z&Vf3A(gsnrGt7jm^vUBYTkX1{(?NN^Pc#7Q_T9%{XT53=(jJ~%i&v9{{gsPRgA0!!h5OVS!lYB zHPMgesbA%CM#k7pM!+~(&UA!r7MriR{+d9~tJ?S)8@us%{`O|OnQr4g{2y9$xorU- z2he@KHCq?^6&n5C54oM~@57znt4}Y{caNI;`TE+D&*aW0#!$G<#aG$r^Sb;QLH=?a zj3E0EfA?l5jK$scKY@Rf^uG`uvCI#G^HTD|oj+0gTzYYvje?_({dSG!zHEgKq4vh7h>1098S>&-W2O&W ze2WevyHJ1m9@fxFXXo_I-}Lz_GK2BC0$(q3F5=^zdjR3t zK(W5@GKB8Vw*TQ^dvaIGp{1}b7KcuazOyM7JJ36wox=R{o#SrgeU9Nu`|~-};g{>) z>0-;ASd6Os&n$M-^Tb$<)Z5Hhh>y~CvUT$^`VZB2YGd_1{3vkS==cupZROMla#=h>F6YBC&-Rn=)!fML4Rzy2+^6B{S-RJ!cLM!m@G}E<^W?>3dcKBhy3dR0>BU#? z?1y{4aSwSgLEDqInfiYNi?(R!Uj+Jjjmv-ICc=1grz7)ySWGpq-) zgXvKpvWMX<>~UQjA}^1m%e)uX^`UlV&-uI+Kh@UwF>Sr%&uczE&p)}JKF2>f7}hvN zK`&nu<1O2r{s;d*7GKfvzT=OyiDkK&&tt@3t{l0>{u#c@HdbWnz#fQD{R-#b;+r*VGFohpYxK^XzQ^(LVRp>3;aWBSH{ZYI z^IrG}HDH;xeZ|0aPVo#~UFrRSuIt&hg*sl&hHaAm1L^#Z{A9AtY=!y11s)%x|5I4* z6)n!wx04lJh&_u^lYI&u8FRU4HDxmO2{NapkMx^&vb9&AW%uDZk6z^*2`* zE30vn`K#`Q94hV-%O*M>)$c>LuF!9D^1IT-hj^a2)|@ZwJwuH)gNa&e`z0yn{w09&s*erMgOhYTv+pd3xCdYPHc)k?C*o4 z?)r9v?{1iObNnzqZ>d$krxL5N;T}nN4<+22Nbs0l!|#>J@8$DW&CCBcRQ)bDGzQGk zk-0eUE;bA4yB-!kWJjLbo2u3~YDj&=S*w!E{D{97M!%C^?;2HS9UHYd|ZjOBIy3qP+~wEQpe;a!Ife8ykA3cT-XKaj2Awd(hq^S0(#^GT}a=55(-iQ^OKzq?k&H(3n_ zKi8`F8_U-E>@Jq-OWFmllW^6Sy!CGOBK;w!-j>rJk>g|d9#HwdZGAZ8adM<~JcaM; zmV+Cr@AbyRoO?>F@RYnx4;)oY$J6(LEr;nz_V1}xYvtl^&&vnNwOhsP8Mbj`v?-1NWwC z)~{^gBkHg3!*s94#-G+FYlvfKeb!+63GIj2CfBO(2bZnreF%n?+4vvMZWjmlEwb@+ z9mv)~@!FF7aCz3-d7Ol6{!9*J6ZtjYv6$yq;b%+uuMiWt6}<;TYdR;Ao5HTKUEb^6 zm<##20e!d1p9>nQ-(CzgJU>I9k{tQ+Q1i|(`2ObmvHx#lbH2cz!x`@Lrz2|k6ZhSl z{Vo>Y7PAv-+U_v!K<}E3ReeiB&fzIJL+ocee~&(g!~6l8+sjk;e@eK^3w=JteY)}L z{tWRsLjN`}K4?=j!@EdD$g#EISc$&-ag^iM_=<1UH~f}JC&%WwxHn9D;_G&J=W2V@ zekD5B!S!T$eLh|4ak?|yU40HUWjy&Yd}S+p9tXSWGsD&er|MaD1%F?`@ebrSvfU}q z#3DNYN7gCnZ;o*n?$L+uqh%M7Iml=2=~HA{!oC2f53t*ptq^ZDE}KQBzx)~I+Ugp9 zsU^`}&K;wDb@;mQrz;L?+CInKqjXupKwL4@&l2$MnR#;dcF%J*n>$F&4|PhRio2 z{~i6tWoB(u*2#|`-+^2|{ZFO)V{Mx_zo*aEbV)0|F40e(RQD&_;;1gae+WJ{T7U2* zjOqWfX$)82nI{|8QQ7wVWhb)k2+woE{fQ8lU^m-=jT8BBxLj+kZ7I9v#AF-tcdDx& z;O05}y$9bF^owb+iWqvQEt*%ux3;0|n+u~8>H0&P8W8SuTQ=f99T0 zBlD~2;cI%BKHI{x89&Vhp&rM3IPS^jg}5>wmOD0A_npIfD>9C=74Wzz-@bIb%ve|p zm!HTf@h+^@vM>$~)NfT|dk!3z;pq8#RF2aJ#_;SVmhT0Q!yKFU;|qVo?{GxsjQl=* zlDh9-;J{iq-22M6lJ`FcF1C)M>wFjFUu-OFvTh(3p5a}=hh6!*L{0ice?BE*62Hhc zZi|-kz!q&i>nU_HzDeb>KX> z{*pK5$?$A433^Y%*JSfl_h!FMq+dtt{aiBgZzRtCuywY{xVC zF@YX6tHgi!P0H}REZ<6>y7tR!)w8_pF6Y&+bkm?u4xZKE9Xx!FF=}y+wXC{2BvLEvLFqrreJ+xS@W{Z#2TKQsrh;u={*hs!y1^+odKa8(_VrD$# zPm6gszTF1Dxh)$lhm6}|K0DiyJ4@g9;O&K{Mf&fBW3{S~6NMZ}N7K{Z=O(_ip)ZWB z(QrTq~wne9RTAUgUtSKn!h^^3%^+)Y~_dVXh9z01|T>_q-sGbW31 z&4fOMDJ-Ra4XdkcB;4h5UAS*aXfn7CZ6F^-}bbcW8r*dKulu zPF!35KG=O^zcTJ4>nEIS=hUZIhD96&RakC%a2G`9g z*4%uG@Kv5fHsr}HHdbT%TiC9q=Ujabv!Bb?HT3%)zsIw`172JMXT2SFkW&-Lz2@Ay zWdFfdH{9RL=V!FPL3Up_eCH(YR;#WieE!aSYe!;TkE-#mPf#Uc{f3$n3@!nBq<8JJm*i+S<7v zToV{$C4LHXaz2&bmBe&DPL~;5>)Fe<@^Jl)+vI6J-o(bybh&mYaalmm17gv}IC)Ck%?stK zuzkV4x*u($?<^R{!F(`%``~3RpZ}&0ui>6T?l}97?n`0Jw1@Xo3xW^dYtqtq@a%XsNm9I;*zp3s%Mb@**>fNkk$b8q}dKl-%QIXR%6d$j+=e50a zD>S6t<9S2jyAQ@@kTak{i#)$ZaGx}InIH++U` z*(q#%?*Hi<`S%X_={Unvwy*nnx%}I|UcK|2Uc$Grwnn;Qy4yN_0~YI!Xa*g3+kc_| z-Y^~F{O#;6#4n$tgMI$CR$Vj4TkuWoiKjFyzqfEP{nwhWw_`J`<*)bo80Wje(*;&_ zG!c(*-=_SE-$UqnT|QjGc1!XL#b-Z#UtqUjb7$wpKRoX#ujI=Q_J8>tk@;Ewxpe*0 z)))8oWvRVA{PS$q(y@6gI|tUy|5=Ggo~a`Gy9oR5dd zBXLR1wUPWtZ+C7!8&AS;GrKVvVAicFY+y)3)?9^ zFQHSd56{-Zv!{3)KC2`7ov{7k-2cdYuI(25wrH;Y6D=Z}`|p(UUO8!8IET8=J4=ZHMOSI}6Ft^j*crebkXo_^WTe8eY2a_i}o#!P8{=df~?T{4F_VJVh;Gnqhr*xxUr~QOK9ce3B>8 zLu9|xcT;??B~I!7U>N>euYM;#5yuRN#m2BqpldGOW9V3yU*?gJFZsu6 z#mD@55B?STwuGJ3aZ5JCytSGAVRXoq^e1}X7sJEFOC1Zpcb|+l_V|*@wb(i#Ji{vA zW~aZl5%z=W!+Wmgc%n z_leriB71A&^7j|yaCkOYtV54Fnw~|zX5XRNZ+wvLr_ZtM+)3|!_<9kZ_ON`x{vPyn z)BkbuiyY5{y@U8P_&iAb%wOqIUgNf|KjiG@*;eGW^whs zr*t&VYHS|EuY`=;E+^4teN!9+<4bhH5o&kzoxU6DD;JA_eEtBwBk0_nkLNg^PwoPC zd+^;{7XKm-%xlGYbl*Y7^+|4wWsObN@@%%jo!l%o$B(s7Y@8+Eu{jTZ`Je0vdq4gj zLie?>-AbSMMK@~mTaNLrFm+>-ui@IUxP^_j&C8#k#^m1De*ryzkvo!&5%T$Xx;|!O z8XqQwW8+7x%f0#iAvyC)dZN9!q`BicbT&92YVZx(zvtI%ZGY?Ao9^*+o=M-^d|4)! z)ZXy!akxKI_9b^e`6>3BsM~TP{U04~-(Rii!*llPyIty4%EuDd>1HrnU!^bT^A>K$ zswcbYcMlr_v~2^|6u!)s^HJ45?Gu^OyRo|LP>+{d;%T+RGwXaBf917LW8{S|S|*YJ)^YVJz!#NEaEssD)_ zEuX4+MgaR>+D4L{0PjhTueNWn=VQ3$h%R`r`u(!%-sO0F`2Easa?S5gIR3`@4)WbK zMLg8;_r^#8NHuj^qPjaS$3;TkUzqbRJaY?14caGxdm6DRs+=hQt{ zvJSogC)4Hjoi*)?E_4|syLp&2~JZ;79gE)B~cZb6s)=b84cs3u_Y2lt+xIRm+rSBH~Z^7e}`okEW>4xuj=5i?A zR-b{j>i%5PkDd#)Tep^9;9w&EpOh~X;8mx}3&?iCJ>Rm~VwBh)hJ&?meueXUiH-3W zZAEYIhUNbke<|H7v3)1mkUs_gJJK_aY#0N3HM+;e<~aO~Ylej%@-yw=cSfG}c^;Vu zwT*JDCYJBAEABf+u`LA_=d1|0htyJ=3t!u!S3hUFJ-G^WA#70Wp8>9s8#n8 z!+JdH0k<5<#VOmBopJiKB2&S(x!T&flENpfJAO+IELv|kT{>&2`Wo2S>JUYPEJs$v$#`;y)cvjnoY&ZofK!a~FuwPvdw`gV zQ#B^pi{B=%-X`iv-irK*F!d*Y58Yx|-c0rk{La>PGJHqdUuDB-_%EC6?}62S!NzmQ z^dLKo4Y?ieJy!M3xXF*CcLlgJ$8sk(9!s2;j+1cj^I!J+z#{*1{1t6$)$hoM->)k7 zFka+iasZwd!kX~$H9i*KSr8=WRTKN<_)(|MEgli<6n z+4oe{g7cljSMoC5VwcTe^L)C*HN95;90&95wvF-ejhq{!pZf{n`#pttM4RGFo|opG zyfYo=!V+?B0Upe=VNFnWCHJm#gXxifW!zZ3mz{*?XA8+}#fPoL`4WBq1J5~hsn^NK z5F>H#qC97;mrm++J-@|x+O#W`KXtP9vXQ`=PI;0nC$iRU-9%Z+4HaZ^Lm-nh7r-BW6Qw~ww{*_gs^FLr+= zC(q(G`l;P1`{6x}Oul5Fkl%?97qE8&F7DD#4N2PJOpceI!RY^dBb?{I;zzC*JCNI+ zjU)NEv$iYQ{g9p;;J`ldV+0N}o_cFMy!q=zz>z76F z@F!in*?m=8%J%)vx8(0E<3QaE?@p!KvkS#yr^W7B!!Vi7;e39Aoe8$#+Ha=ia#al&mqB zhFaOJsk)z099Lid8}G*%4|i%G>io-cqJun7`1CE?qx3sK|CTrv&vIScbm#lncf!ps z_3GWqcw^`PE05c;Z%&K<_Uvk&c`oZ&#bv02pUMf(tdpI!uj2eF_2u`IKCqvv{}Q&BhigCAiSf}m6vJ?@to+!qoXRe??}>xCINhJ@ zZ}e?J&tdkb^Xu38^6yp$-^8g1_5F6+#c=%tCOVSmaJ~(0zV-aSC;QXkl;=s(;JLZ+ zyhPvE=~8#%)12#}|0Mb!hPe)lScUK9CTdslG&%R;qKP%Nmyi3wb{>Az-gssERmJia z{n#zN2N$lNvWepQl>U+PJF?%;@z;Ew0$*2g;!7mg(rJ7d4MPY0|Bail4%h)soF}d5 zJq*?@wHtH!B=YPe@;AIo5ayKJy4WJ7dPb1$PVNdd@}I_*zQtDT-b>Ff^2EFl?%9WR zLB`MOT7PH#`j<_6!9I6z^_`aVQe3XW#;#&E72YxM^11vs znRlF%m&y8kbS+i>$^Jb0KHS;UPsaz9-N2!@rgA? z`Wen=v;QE!c7uI2*mrkV0v7uh%{0jfASUe9)%ICdo-@#a8|B+_nk^jb5 zwl91gVcXs3sm5NYv*xeVd>Ymk$w73$QO)Cln^EL%fTb-Ri}@`#iaYcX_b|Vv3xXZ} zF3|rccyH8SyyB97KIiS}7$VlK$X;i^Dp@(4K4RP5`3G$BE(&8Fm+8Ka!@Zu1#BUw? z#y6`|bpJxn47M*8Cv!&mDlTrLQw}Bm4>0ab-zMVNpO0_hVkdIbwaLlMoLUZiuzF4$ zO{QZ_eXkO?p?F)9Ut*P5_k`cOEf3Nr*Tech%yF3|Z->(N3?JUH^=3njEv$(Pb4mP0L-l*?;W=S( zFWl?E(xut8lyfcUy{*ajf!WI%m;Y|se0~{k#b`2jXrBbP7!_Nvc@GZMt*kRW>T`KB ze!G%kJA9WYTzBTKYvU7qp2?Rr=#oPv-wU~&(-q&U{kMkdyVa3>Jg;&2@2XuV7Uqj^ z&5(Z24|7qqetc5DEyVR6Hb3G29Px4QCp%P48K-YAe7(pw`IH?*t_vCSX~eg1t(eTE z?{0n0B4fUdrr_*5pO15X75qK|i+U8U*`f>d-vItI9j|ZC$KrbDyTP?FT^rEB|2)j+ zA;&Jk;qkcH#QC=N>l=$}>-z*bxfy-V*S^*VYG=M?y}ExL*4gO{y5&lCobw%E7}sQN zNpEYMo`#LAFFICgjw12T&W7PKepq{lcZZUP z$eZuN_pWl-(t-Bv=|A0u+e~}7#?KnzO=16%pa0>TzR?`xf=^+cmS^e_xfIVy>GLSD zJ&#SbD%6a05dWP~3A7Ag5d)wo|eV_2IdGQ3@#zu9&=PP`4V%vJCdS@lZ(O=}`bUK_b)&=<~j`yQ; z0eu5%%j0>!bIa<>fBVb*xoSqS}iyB!?V5UJREf+uRewE!RFz6+-hNV41Ep!F;2^S^;?aNP%q?Sx)w}J z<@d+r@R|+M|2X5UFI#dlxmS#Dhj~viF)kv0Cr{ID-YQ4x*8~2iYRmrvWJ9|8;4ED4 zHt@R}zVVRbpgfJm12)+{k2{)x8`C$_`<5VeO7FU7hr?4j?i@@zO=@*wJf zhw0)QaQ(-aI7s~tc*GW`1>LotNHvqA3mV-UigQ>`%m(?EFPj~8htJJ z_J{MKR)(6e3^ymzzjJf-J@6z^AAV%Zd=ZDbDX-FD#`zum?&96`o8*gFMYqt`O!pIf zZI6pR@hU%~WuUCH$cfOVJ zG{&{t?y%gc?{)CHUJY|-vJL%z%1g0Hm)KU*zBN8t!$D_`vt%YatzdYW>`VH$()OeE zo49BHXs-U#Go7L>aIs~rdQY>IGlg^E+Aic^F;*^y_^CN9sZxHL( z_?N@o#XU#!PO2`&uhMrJ`^Hr?slof;Fl=x6|P2nNfI79G;=1)(-gtxPM0O<0!otr;pI{vfMhKZJZY` z(9u=h+DSew^DI5YZWeq4>+Ut-_gQxK<5#G6|HjW$Iie<|J+*D5&!hA|4c7_(pVQ{O zO#M!FWiPB1)%J7&d9^B=&DOT`_hS1Rx)(WK-Tn+bH`Tm{1YeV}HqKah7xqp~-b>bJ zGz_oU=q{dMOTL!!BI-{5Q~E!#UxUpFu=IfGBYnd9Vn0~cqxW2Ww}Jtu;rVmg4SyZ! zF!rKR`cBb4-1e-^xJ!2A+gRt-!*U3lx4?3^@z9!2;*e}0cQ&RcU|tp8YuSE}p40Ss z!L|`uwKe&KpFivSF+Ad3>`cbENk_1IkiK)p&i@gm!AEmi@*A12#L9e}^C^5+DTOJ& zoSydlRgcp9YSnrt?Hc;SE0?kXIQ+(EYr|-yae5oy*(&5oAy?zwVNB_^ZcXlU?%WVh z?cQ&D6&Bo7Ve4WMK)!Hw|NpJfwMmx|q0NzKP z+Xm({wYA3az*_a4plG!wYc9CuX!)788T_O_tYM;$e1A+Vu#^=rW`Lg})_JirXsAisG|0f$>vODPFZ{gn za%-UDe(bN!Z|Bq7*l$a&puamz3Hyz7h8i${{A~CS6yK-W+nc`!($7}7ADNpoOKY=G zKXTVT#fI!w_ZI2inhrIjI9X>`ItNK<< z`+FJR!h2l#X!^{PMR(Z#R`+%h=b_qmfJJVmFYx7H{&wdhAF{c&mtp&wA6II-$LF?W zx8(a`95>+pWXGXC1-z^B;ZC3XI3Cql)se*bNgkv3Au`Kq)o(UcwW7|~N$_4!H;0IY z{775U{fIWPOg3@chQIDnMm^|^#PTFEC*mWsJ&Cu#;nbRSu0DIf0&jAtZC9VmS`=ST zW+I$NvhhCN)P=AHjnAVmteI95(^A_#a6M1wQuaQzmuKm8`m~3AnW^34n1>Y~F1K3!DPu4WyU8MX{Tc)jS2g@t4-0fJcjke?CKb_mwu{f4=C7Zz_-@|u2%1$tL z#mPFx)CIVdhecOD!x66aQvM~K>F*`qV2sxzJApq9j@RMan(Q2cuL<(j{GYdLs@@Ta zLhVzd%JExG^59`DB ze0Y_<-*GWnpR4rQ65dE2$@}a(*jmH1ILK@N2ialu>V8Nx+5QOU4yA8k$bZ-_XJ5?^ z&loeglAI{Mfy?Lk_W}FHMYbxAUJ>h&`fMi_u^f4sY%hAwwAVLZNbWXr%NnZxSB?jZ z=hn8x&dK?Z6NP?Z?Vp_iM`#=5+{J7>O^2}&Z-t+k+9%`kZ8#5cZd|>3UJ;o~<36yx zYpsR*_;B{CwH@Fo(a!PvX{ty?XxA~P?B?>wa4V0=yve@^aUK537;;3UL&sQ!B!M=4&+ zTiGbQ?nv(hvepRYNBX*V5$=nYvvhTzJW4EOSjE9~W9={?f?5&DP1 zv!yL(vkk7S+shO5xzO{;zod`>=}2vN661_~BG<$FUg`73gEd*qR=B5_7Vvxo z%O1A1W9^*x`S zo_PNOfAh%PZj7{r`z>~Yj&@}BA+r&Fmb$zGi0?_Ls?X`a?{MHOXzS?QYkA@+3T4D>8X= zk@kbM57FmyTW>jbAuP|+*^I-}?6u|FlMnq*u9;Kl9gOQte2v|>r#53F-3?E_*Q^8O z1{|q#;aNx2%AA|pAFkht_)woSYo_9Q*j{JLadeOOdZys82Mi0usV~f@%YQsYo%r8@ zzk9PIAL1+I+zqg=OTGbL{a}%&*?QtWRUYBF>_+!X`tC^PUG}Gl(Ot03BHM?}(APC} z{w2T8Y_9HA#dyfS(C2%9%xHm)Q7=YQi>ohs!+ST~2- z8J$T-?%Y*A-!!=5DK?kHkKunTeDlQvuc^E%)tWfmW890*;MdM@z?8j1@AE#pzZ>-p zc>ufhL!ws1c&^?>JswA!>er9lA#$*-bH-0G$obX8;1d|y@%K@ie2ymJ$aTF%$@1Tc zRXYmj;*(+chHNwcyWwUG`B#Fk&Ts2ou<4HP(Z4I-hT^+3?t<)0{aV_3^QCLucTKhZ ztI2opaB&tKKf@pvxxVQreP3yEk5J$B_$EhlwV-SzroGq*`M4qsN5J>U1J!f>xECDH zkTZYhr_`5!7bIfq0J=x%w}`!<=i4Ut_HZC3`I|m}?RZtWJKJ0)j^%Fha**~bv{`Q@ z;+OA$t6TB9J?_Kx{Z9Ir*TPyNW+U96kDh~hD!ZTRw+;ElYR74Ox&nrl_V?F3UxncS z{nnI2;diDM@|7=P{A6S!v57v{ubCe8IL1X{4W1cqWdkl=b&uzDeDu<pV#2uSNbpDO9%GNXUW;P@cvPFHk9v0wxMpU;dx}Ox|T1+BD|lK zt)*Qol6&==#TRpW(i#sNH=B3a{*&!)OV=mG+T^~lmxu9|^d3w8VZQ8)haNcj#^-lzAqN`tnQNbEH;*Kto`-RV zr#RGi{DfyC*?!H&A|CjjZ?8|nKX}7$`IjsBY>bBaJi$qEo3%%K`OsMN8#OqyrMHU7 zp6-*pYcJQ+FXh#zYfY`@Oe&2dCF{7!wCKT6{xc}A}KeU{YRpC2TrgRl4CqrZ4u zf81LpZRraEKN;)&629skB=T|H26s$8xz_%art1Gdi_75f3?{@hSq+!%*t*&n zcpWEK(Zly}ZC!|U@gTc{>ec|DB2cHXD|I{m_WB*w)=xnjO5$Fd=3Grt!STgOBv;dKsM#!7x3*)!_?yGCyA z$i^60+sLDUZC5e5oBgfe7^J^ik?(?={`KlRP}%Ern+N0D#74}k?;7$qaGiC-_11J8 ztj~Rms_*=V?W%P^iM)~nw*DEiRZ2CjRZKZd=QbX{U>c7-j+#i8uCz^i#7 z{kp;Lak0@%PfxO;em%#|=KR^0Y)d-CxNJ-3%XQBdwC&>a6gBG`{Z8h`ApBhc<4f#J z;mcF@#!7rHT>nu6ucq%WF`S|QfpDG)+c@?vvRCJmZT0U6+pG8vu{YO+`kVE7LoZ*(rALyU_ja0O>IZ(BE}o!HuquBmcqA^p#? zIn?KS^!bRdH;ctG+%3Tm-gE8Ac>DSMJPNnJ`o7wGWWLePe#ow8@p;l(h;Txw#{|r z<$Sfi&9`Aw-15`-$5vSTmGY)o#FsJ7E#l7)Fs(^uW%jNSZ?z|F&8D%JJw$JqOAZsq zw;fN$(Jk8Lc{)M6F%-$!BBQT|OHT1H3Ec^*C2!XZcU&*~m`@Z~Sqy5jjl=g*|$V7|$v;%uKcAY&b#wjlq# z-xD%Fgt}YEyJ#hT^umj|CUBmuQTM+$I9P#wzLu}*%l8!L;oe`a?v&O|CI7?!&Lna+ znT*qq*}9_cJ}5n1#7R!YeH>4=*6d2}m+E#6KgT%^Ii+v)OyQsOo&ZPgUfdx4-(}xe zO`NZO7b(n_;v4Sw#Bb0U;(CPfw5b@Y(eVb>pM%*6IPb3c4J>|jU<3E*v-A$6Pfn&! zIDad-y0P{qJ#}*03-`pcm_MJ9{e;h*^%cL0JM(?CBTOyyJ6QV}l1 z^IgtnQ*B>5SI5WU&ac=UMgNm`xXE^<4`1=WZP)Na9;djf)-hX>+qtF|!7vo3N0J?{ z#$JrCO~}fX@+EeM)cwCS%y04WdGaC7yTMz+-cI6&)Wa*2BpdGj2?J7T8!l zM@&zma|QhL$MK3VJ!1bLz5I+0X1kI8S8(2r4`Xrh1^?PQZlbraZLjSucJLRjvGQK< ztM##Xrv3QVS%0}*gyT)b{9xF7%HIuPx{=J!IFskm#`0$#Os%c$!ug}cb5G}2hsXRA zf}dyt<>Uzn>h{Wf=eEIr%NJsyKi&CYZi!#fZk(4R z$i3H8U0bF-aX6&G8r8Xea2w}w2ezLf^QioKh}{% zYZ5jNl`mhwbq5_d${yx(J9~3eu|eR%c*JQ^)4q(YL$&Wl$2>J?gL<|04{MduIyt*X zj34C7USccfBegoZn~hue)0O{^!Zm`OMUBIXKZKC-PCS8K-d{aqLC^ zG`P(@`4MvGUA~Ni!CVsFiz|;OGm5?OWY%j|k6afFaUREEjK&8zuP)^c&YN#bex>i> z+B}_YM7MQTvI?6c#P~aH1Js6YKDWZfKlKmuagckOjlcQ!9G^li-NN=rc`~2gOZj9z ziq*VgeK?S_|`>NQ;sicK=wjx}WTe3G? z+jKk}La+Qv#XmJy$1B2g7MpML>nZ2?65bDp+R@iq?v3)fr{j<_*N|yXPY-SCcDf$! z3%aL;ScE-a!aD9b_+NwBm@<0d$cZ}y!?GOx3oPmSUD9{L}HS1v@4dB?}PCS63wWVpmHX~l=7 z&fR8gyh?xIMJ>qh7mr=-H-WV?UiN}W7vl>6lz1jMFlAF=r^bdfyJKTSohjynQ zZ{hv4cq%-%!9ce9ol*G`o_mCKTe-Hp+kk$xw7dtdC+YcA`@a193_okZcPIY0WApJQ z_hp@rV7Wwl>*gr`iJWWks5hCF;dzSR+psN`#q65v8an5~cS_Updk1@vyGfrT=ni8- zUd6}26TbWKxOQ9>BjMZu_Fc^DgYCmS`XhU7aq+m^n5<1*h|R~zo9e??u>VG1H*r_* zLR^z(c-5Oo{)B6S)L4sWz}KDqL)cx}xwXiwNte8eb|QB@+t(R4OX>U{{MH6Ze{Cy= z_~13v*XjD)sBZ@2u0GF$!TZtWH2gl|xS{5Gi9DLZ#-nsvKZox=Bsb#dV)%Q|xi-1O z<;y$lyaUf1+o^E3Wa~V7Kcr(^WA$D`9`Xu~^f2dc({B@4I@25GHGUTVs8`pD(ZI%P z9iKl1f2hy)k!#&}N5|jMzm?Ay>N}vZx{na!ES{(Ted2R29eeT1_zY|R>}-5&rk}AA ztWcH+9#F#?qnWXSpZQNnFF6Ys?k<;IM`KggqH6 z|8N%cC%d!r0Q@_WxgW;o?f)QS&JNE!!}If`BfK}kw#@m>;l086&it28`J42#h4bfH z^;{%}CEW8*z9Z8Tj{kT*F^vB1e0mbj@9UmJlfMZU*U7IBjP-@~u04`AVz+*iF-yjO zC&dlUeI;Mt=i}G(iAUPbcnEb*9t1waoKncY@c%%?-o9H_@c%M$9ocGt^%VGil!GTU z!J};-Yr8G^(Mq2u_FM`#}-#+fzJ3Jul&U{v1|x`A)c(P@4v@5Bv^c_TdA^64iSaFkqw%V&&-)@4rgJ$G(Mtt$s4E1oTlo2W!e{(uDBKRuucrWbrFU5kEY`!`uUS@ zK*vmd_Qv62W91^Bf5Aa-e2i!J0$8T-5g*YWcz?#Zar%zu^RH^t26U;*#oBVfS}Gq% z&p-5S%U&3(h4$X;%lkCUgD*M1y?Cet*&Fn@o-Xx`?k8_tM@QoBQCz%5b}jwXm#~J7 zj@2IGq)+)J+ui6P69vDgIsXz)@R_L3>E&c*+WPQ)iGHVw!x%Da;mVlFSE+kPTHiHb zpF`(9&DC$)6p!jZMNICr_0o1EzmC+W4{XQL@rZu^rS~;`_o8Qi_%^7!f1@pdeHDED zPWB->&*8&|gN0Y{4JC zyO^lwG5yH}=GD#Vo6n~o*BHTG>EkekL!tLEyvF4^Z~c7<^&pPqED;$(Sw zB7N)AbDg%igZ+m99PH=Aa6)e+m$E+OK9?WCzWNYimtII-z7*^@8q#^y(`u0U6N zdcF#}$j`LiZO7)VFl5GY3-%uO*;q`6iIs7e@-f_BP1hmw6rH#5=MZw^`F4psxXu{q z?lWwK-vG)wkdwRR5dHeWauAN$jCX|P3Ea3>Rjv=ur}An>y_%n@`ON$puTK7~`tt7_ zT%_h^j?d$#d9eI9-oqMymgBP0gZhx)kEfl)Vt_v0X~}Jx!v0_C^rHi--(^o0hNX68|9_55>W`_?PdQdY%L>7QkZtSG~)bH2Tj@pHH{#LRKyppWt_O zSgqTV9bvnM{h4yr+NOMv{y)im3ByIOs-K0N3C~5Mp)hqN3r}>9m_1wby+*jsAm5hE z6?pznt@{7xd^j9ei%DPYGvK>fzh(M$)^;SHcZEkRin?)l1MI!onOwKNR=qzIh5X}lxug6%AGdIX z=PBX7T{(!pE$HK4crF~Sf3q2IJmGi|-nZtRr5~Ew1Q|To>lg;`JDM=EJv?-5+6i-2Pf~#WV0G@LH2aBb+x5vq#yLAMrS~W$pU% z-z8rY=4sCF>HKZ_{-j<0m0}*9vrYAX^7-$U9l?j&iegXQzhh zcMPT6qV~PEkW1CbucOb^R{G$?@{w5*XxgBu3>f&K5|L4`|PJHW(kG<*a$?q^HzYm+Z=O6jJk+}ADyq_4wuD0^qeO* zHYU3&9f#Na_7)q~>f!fbv#0s@U-*oPJcV^I8z;dt5iYeUT;C+tw)p`4T8cAF(bx6r zec|YC`MM$=Tk}~gQ}WrV@$qTnmAE^k|*uk@vj5?;uXbL2$h-6JOP^oE^(HlQfWA}onP`JC z<#+r798L0JDqHSBWpXvTTHBfYnXS({?CM_{_t}NoKDSweRsVC;P5Wwioey73SIC2d z>z?1yXRHRB)$awHchlRQw^m6GpuY{Qzu@NuIrIh_A3GMaXn+0xmX9CO;W%9Xmrd+% zTEB4#Uiz)EWg3c zsbo7C8|J|B5}zMnk6(Es**lD7zJzfW-^WKaG2Baza2;KWr-A(V%K4MzQ(3Q`%_isL zR$I0%`Rmv`9flLdd>^>KHIBt4d4}w|>WSJ{s5AK~)_iYipP1AZ84lZ_%r~&$KvWUa!c{zbGk3C9w9fF{~htQ1=(90TwBAjBi;Cj z&n5c}K7O$+!lmDa3GX_lZOE?GU>ykCsr<6eE!2m6HT`a4XA;}$S{laQLE6X2*PneJ z3V##daTTsBqM2d`SM^*X*R~|Y7ye;5YGXb710KF0w>CY4`9FlrQg(;2PiHiiy=!1z zz{elid8_XCN#uL)=4x$QbcOp4K8Cn&=bU;G=Am$(D;g%2D>i#K%yrzJa^p_=#j;#m zE)BwOYrJd(&mq=xVv=3q+)89tf$uze)`DH_N{_HDA%7v8KZ~`Ro153t(RdWcFs{oT z`LGLo-@-Z){$|@cArD+HekD&@z_C63Pw$h0{_ux?P(+2wbvi~MK@-W`2 z$-PQg+wsE~N)kRk21iG2$HF^}zFus+M&}&_%WOqukmcT5PoZjOgs|4()Oe_ zbt;xWp*EJ2>H8m_0$+W^ZdDP%Lhcs8er5nGeznYYO zL+>p$|F5Huv7HUl_MDiEk~81h<2(AuKIGT^Fm{KrQ?0rORYv4n@hxp|?-8bN*qKvX z{!X7YWVrr|AM^QYHqWGI562-l_!8cSC>zMX3h&dnQ#Zmrj!2H=HGEEB1KwhFwnLoo z5bf*u4>uB1lQ|3*OPzN@MTzg zJS0!WI{k^AJ7E76R^vO|&q(^QHw)%)FMf`9yR1tRV=ViWEm*@l*Hw;PXfI#$PW0w{ zp3Kf&__|7e_tIig^Nwu5QFRyx>n}b*0t(4M+(;k zrFv7v$=HlvW$!Gys<58`)nurzOu&Qb1uh= zj;;xhz;kE5|9`D3XF2}M`D^{==m6)Q(T|Z8`hE7+S8%OCOZHXP>a@Y^KGUHYH1JjcU&Icvp#^F($D9XHyZg5xiG zo~7@6xYV*-%nM^F8teQ{@P~0f)iYo5DL<6Ya;Ln<9Or&V+Lf%DRi38bq2f7>jYsKU zMc`#T~E_mJ%hu7F^<@~vg%iqVk0R9c}a2wxFB4_M{HEOz@vE2dw;M+LZ z)YW_v-d9r})Pdw?y5w0os%~s*59`AzY@aM%|IsE7L(Pju;PF0s&*#%lWOjo21#&mx zC5)Bp;M+#K98cdPcZYLKh2t^Y;!YJHfU0fRMF zB43hM_$SWcSyVnvEYSaw<>PpI46K7%( z@1osUExyvXomypml1!&t?2=LNxIbE`vEdp!X$ObAh<0;)5{_~utJH8C2?qb1y-bK6dTHFqYH9#6_$i}vv;nXLS)9EMt>P+_B zPy=w3iAi_wZrkC*ktX+?GCP*^&W z-4*tm_;i)?d*Je2eJ8OM_P?JnBaQj1&aCobhu z_{PECP2BEbXR`Bke6_HRfJtr^YIv1HpVG6)cAM=6T?%oH+JAV{fAYsR9BD7DNq#6|7h&=hLXzdl`F)WgH8Z z8G9S=ZwH-c?tPy7N1i0Rto5#Ut-bc%IXUN)d=}&H#5!zv{S1yLT+b%seAjp3i~adb z{fv`nfb$sk8GCUI)46!PTOPf;<{e%4Cy`ZyZ53F8&9C5SsvI;L&PnRTPrjeNv+;1T zvhFaNd*e6hv)__&m3SAw5XhtJ*#a$G_<`Z)VM4*co4S<7_AT7n#E!s4xGFHQ?+m zfA_`LU2yVYJQ5E>tl^KxKm76K`X9-U!}Yn1{Nu>($cERnzd`-Z@a&@OS953Z(_pcA zepB_%RrZ*2`7-;~v7)})vX}12{yE)+Ee|W}j;HNmHz!1gH+WBx-f`sgcYa>Kp6Vyy zs>ySJrR0XSb89jd=(917j>b=0*I^F4TC8oxhF8fMqTJdbtQ)fHVYNpI@0C@bv34VW zA{ilveD2KFh|VJDZ9zw8cF8G~3}ZZb7S4|Po=48p0aKIrYH|LCzOkd9@(uOnpJ=}O zLvi(^K7WUA1if1;8w!`-}&_5mz|wBMDS0qR@hZeR0FC;Tr| zf0a7x>#*-E`?2kG_>8H1J{jZc)&Fi*W9$cd&mnWJHYeiceD(53F_^rc#ltmh8;&3L zmEUR83bsug)(GMAsAOk+KjIw5x^+zSA9{_G@L6wo&L0^&=@>GvA^Q<_-!ZWITrR(t zjHP5+yGJi-A9C#^Jn==CN8^9e*-0F&1;b{1@)8Uabf7z3A;u$BpD~ zTd$r06ni^AwIoWLl&zr8Gh`gCO&DvV= zRBsL{LTGPtTY=s_WDJl`Iw;#+JZ?qS z>FlshFU3Z@CmZi2V?TZ#&E{i#KDjQNej@7&n40M0@AMhETjFv|-8|^pIw-qN-z&wx zTvvVnX|{GDoS12Vp-uQbg4{e2->uIR?qLYey7R7h8b{wvu!xCt59hnp z{gq7h(Hy$Rll_Bp@YQ8-F6M`@r}ue5x=f$&4uKpV_9fx7rbxV%;v#PkXIMM$!+x=w z<2%tmT!-~ySSv+W;p_^WuD5(H58o4u=i+dBp{c7r6 z&#!sU+M3`XF+RZ>=XRWl`Jx|xeaJrZYPyu3wOxn3xp>Lswg{KyF8bjj9o1BQ=AVg= zy!HJ)XLP@b^+#-h+v@X+)U&PZOZ~U!=XdJf z7bN>`M{|7si41k+j?RCk{{S5FagbY1QLjyScO;#x|2p=G-;sY>gY^~;eh~AkYJW70 zexaacgJo1*((~+&lW_p~uxiG;N9mcP0ijNbcct{s3d!bhSr(?7h+ppC&jF$u9 z-x4ot;BGZ`$ulWm<>I0^pZ*>BsRP}uaC9wf=kQrUj$B?$;2Rv}x3J@9K08$mZ9&Ec zWVNO{hTFVUG}O%b?oWVe3>)^PZxgXJQn~MY#8o*Gi)_l67vJb`E zNpK%R&zkt8KfFI2ePIptEPaFc**u&sU{eQpj&^?|{Or#jaO_J)bLIE)`8F_qf#=i7 z;e&J_T(4+v{)yHj)3{7wul9OR!~M5LdnbJ!(Poexvh7xaEf8D(xQNv*+}`LEHVcdzdYk(7!o9oBOKIaldxo z3!bHpW3BD+SIYHae--!%|3wnsaSY#sij}3uC^HVz3+dtC@SHiuZP}CkA)dPEf4s9b zWZ3h>dy^CPBj*3`J7M{W>}r&Yp2S&E_y3UY)u&>nXo-h5a=}?-oF`AakH)GWPnSGW z%v8UKT{G*|?_J~rwDVb1e3<*2={yG>dw_J3cKj1^cpQ8`7k4>3`7gg8AI!rVQVKXd*)LBF->vPMbXV#8+m*jT$48_eb8 zi|b@{{dX7Ze4RfY+B89 z_`$dg?^37cuIL%^tqsa+tz$Rlo4@1cpj!2Rujv8oi15BK9n>`Sc; z!v8MDQ{cO!R{b7(8OF^4dcJg*6_k6azMb6*IV_WsznQ7#G zg~L|#$o=6rVzR(@TioBI-OA$qC-#pMFUsS&${r+_t?9ZjUTq95fM*r`;ZBZJe-E8| zs1Gqbf!}w*#SHN>6y`6;sI%SpF7BcC4Z3_6KN|{9cRax#U5dYN)wd<%1F~VrN3-uP z*t^hiE1XLlz3EzmtPlBbsJ3{lp84}{SmzdDE?b6=`(T(t#+TagNA@Ba#$)+cy80-S zAG5#0bq6_XJ6jJ#!Oz!gcMu!D@J#JW`oq}Yjtz7tW0&}iMKVg)8;iRwao^41xj=X? zJw6kzJIPp;ys!os2wN}p%G2q%Xv^o@z$U)ZjO?k}nH$pW=@i$=zS^xx_V=)*)_eRI z{u3=9tWW2r>e*LeU6!m4(<}HgF5*t`tPhK4+sPf?jb2Rd3}q+6I?{SyT@uFQ;pCf3 z^J(f2bKi@+H}qdXhk2yr*JMBa__)HyU!^#YdNi2>_<1Ys#7wkl&Hqv9&zBMYbK^UH zA=n}w$CEjj-6yl@HSK!B+1A*DA!`Nqy?p2SXw;g_gO!ce-rA`c>fU-Qe0Es*=W{$5 zx5-5Du#_J8E7=alS=vm1;}Qq{!*hzHe~>{p-zH)1lLym@K@V&>4)~}%0^aLzG{^yC zx*KdGYq*Ac4z9yodj@`{u=hguzH1U03*qzs@N6_a6xY8gJ6^vx_^ux;tH5$D{YTTa zKV3JApJwD~pLAziM>z17jAu({xk()7Ps34z_hfC1z36;>U#wT}`xLhurx!IWe@=Eb zJtwJ~quoo+t;x&P&4y_%OnyHzxxKzTuN)*tzeVqZa2qe>m+=0e?oo#vlnt)?t^TkDE#rz3RTw~u9 zyuec&>o|ejC*j)F`4}9p2=ndgzhl3=m;AG#djC4_%kGcrRlH?&x?oGgn0rT?18~~U zxHC?Y$6&vVzjko!uT2|R_r?*sip|J;o4lzo)s|HMqnqqF(D$nK>#S`{htIjHc~~sP z=E_`*r{?zTAbz;6<~OsHy~Sp8QgH!W_&~^o|TWI%z*lyZ$h&&xh94F)pG@V4hA+FZu@PJ45{a zs{C4QhACeihQply%D-#Djn8y7-0^2AhopaBQhinttxCT5u09LCB*=jghv~-b`rNU= z{YdwtwCTcz!0$>;o?FAVi8?;aM%JtM@zany%!OshwYRb1L+6msE_Qxge1tLdrtxT6Q;b*pfSd6aa^IfDXIK0#FmC3! z7Qdx+UABcXahcsHp7tQGn>b-__AD6-lyAf@a%IB*$>wyNh^OxKybJF#eSgvBBb=<_ zeo~|NA?cEDqkf)Wbil)=Y@MVXUBz4avM>6rUj6??{(QJ^^85_v8`P_POv*1|O`Nym zLvoTy#>i9ZX6f@SU!6kUwoCjc40$);X$X8L>eGQO*TU7$AzsVR+1O4$`LvJ&vrcTg z0G_?*+KSwc_``d6mR!iE`NR6%4bND8t$EAq$$LckN3gG=@4ecFd9X{pD$9nzvxwf5 ztoP)@&F~IKGLqi?!gyEKg}#ntok_>txV+W*67q-Z zFGjK(>E5bVz55-;ZFx1F=7l({FQ(x@jE2vY!}n&=2jOF9EFVN+9)K-6lukJ+n?~ja zaNTP!JD=WXwSCDMrm}@T^VGM4Gl8p7yD$&WmqWk6$J^>g^H~Yoed^ER-`(_kn9f7= z-IWcF;Dcnbb7%M-UReD{TzUf=dZ@n#4sjLD!+m%41>H;8JHR1_N8}gwe#H@Db_|=Z z!F!1J9r);coIkDX9Ccybeg)Gi@R5;ziu23a@(5dv`Gh~ye%h0p4{of!4sBlSflSMz!S6UHvMnov-WVaHGUorb8mR2Q+B1lgpuwzakf`14tC7Y z*Zw8(d1PX4&enEs%!l9SjyBQvL~_j`DXxos$$S;oF66DM-JNyc>D1feV-z2#5sLoZ5xMuncwV-GI-2!@%3z-slB|K zcc*_#n5<>u9q{^uK9kL>)~+FblXvV1tOIhnFz!U(&t%9~(ZS?~obaV*ewWMrr|{oY zGFF9ubN!Ad2d2W>sa%6SLmUyk@=O-ikrTCDjeQpzn}<2eZ2jc!d7zDH{OCX!eMS+kheq?Wx-j+!k=tHu+@iiO`!=HE zC4OK>aR7NgC|~S6I?Tb^p5ElSB5du*-B9cdr2BZbu0!8`Z2W+2<2*0xK!p>mxrb@rm(6?f;o-(!82iV-@pt-$(6tkM z3&@g3(tpEj9A{UP^$y-fHu^pv99^^<1;dqakH*o;PRNOY}66YrS91`Ohd@Qm=j| zG+jN&f#nnRWA&eizfO4kLfK+C7pZS>zK1=#=(9R(&p2atF=k-Z~6;7 zhB0Ft6e}Aq*D5ofqn%)UN7+I+C+YhexxeW5EL(nZALi7j@VYgAH^R+M^oO~2CeE7U z{$?@`gtZ+Ruc_bMc@ACAk<*-w=Fe*V-O_mtI>I=)49*5VdQQ3R z!18y0*b(0S3IA0c_G|g-_&JU(fv+Fg(TQ*R=|8Y3O7DmBOZL2^Y#13Q!*w4HjivDH zBAuW=dEs53KT5jHshOuvkx|yyAiH(i)FX_1k|1Xn^t8!~O zcq=mB*Y|ks-qwCR-4D4wL9VdR$<2YW7^?QGd)Ga)C+mCnFKP3pvH2^TUnO&?_E*)a z|9B~XazCocIvCC$>AV?c^=UWdf7fmnIUA9S_k1LsEUYzWn|I^;Eb~o-jns=VDeiZkmoSTfI;~#uJ zf?VUHJh^6#Kn_1Q#_+JC&%Aw z8}f5o*Vh=o>yx!u+jAZC=V!3Pv*GYge{3BR{tGn`!{vo|NyvUnALBJYlboaAGPdG? zE9A1jz}Sq9SBP;wO4`G520z@QpZPqjmy0uvr8ck*SN4nhceR%<(&pM9SFir3GH+G) zoPf^NacO;&<1ssnjy3iB29BEg8GLIETF95Fybzw3Cx_zuJ#`ns7RD@}rJvEUss4e# zeVvWP!gveM($degy&Pv@eYF>ko+tbMn)hLG@FDIxJ8sioZpykS7wgF>&O`ZqGFdlh zH=m3L#r%Bs9O~GM4fApO54^mteMj}Dz{kcohSmBZyb~Uu217qGIxFu@ra33%;Yi*{ z$V?Badww7W#c1}ixSy%db~v=g&s*VoJ8}oowF(*f7cY~so<8*EyDPtxoG{Zq$@&Y}4UOk&_sja+Ht_ZW-n#kFy z@teG--k6Dp!`*__$%+RTG9<1=%9c*iU3$#ZjTsed9*6p!e)H@!`GGzS)Zlr0m}=9cm)F|nkf z`Yb2Cnx0kgZaylW!R1gm?h+d-&{e`^?4*OVT>#sT{I<;VnYG9;@8r$s>dyDa(r1o~ zr`D?fVJPo&|AKx8vGo#st?S-+E$E1F9G;1VHFPFFg>_&01zCGJ52CXf3_HPY>}1=+ zAAHe^PuWwPsQ<_M90|uPWy9Fsh5l{o_C#W0v^>Ty`8YV%)Zep(@VlSMd1PO!UkBVB z(&Y1bhxKr_SUzuwvriZM-A9~kL9cODgnohh_ReyB@(G?_l{2n{b1)2aW*y0VMco&; znnTA+WkL5f#*_w*+%y=q()$eTbwj^gmxKD%mI{o@9 zi|Ml;D9?sxjQaCoKbrh5`dvo;bh1{YtC#uW7BYi>%@=WtCeP&TB`%h8CX$J_sEzjj z6nlO6ZK(f*_>`OsZ=+%BuKg&!SciX(6gPV)zgPYKIK7O$lgZr!#v$zcikz3=yLy`_TNkE( z!8E;AJ=ac8qjx3#+*#j+IJ{Q-MQof)b}v|-)i=a)FJ+IYf0d1A!aG_2UtN1Au6#!u zc{KVH9&wm&OV*+8FZ3+=5{LX!t_O=a$*isOd9Js^$M&#a9(bi|H#U!8hd3f}PWqpx&$uiKF)`fr#`HetEXQTv)y$vd9PXZt$;!^w zM`cU)TE~>|=8rd4pHG#>PD*}xCA%gBzu?7uoZUp1ximayh@QnOU&awxe3HCvE)C=H zUVY`S@;7*_FN#>*XSkc@_!k==;OjTYI|ep=%ir98EFYeNgKM;TLcaxUzDzE-tyaA+ zl{^jWKz&2}27bT6(T&<3OU{)`s^62%pd%wMtRup>JVn0WuItN3*#V`%mN3nbrWSlkqLy*VgAv{#ojPJ?uf!5JU2MK7?NLN%lTD_9fY0aB?$w z18U1ZFS}nn#-R>o>xo>yWSF|oaV74GE%bj-eMh?c!_<{c^Xc4Gn-=_eF&_9U%(cbn zdi9w@wH{i+e}86gcQ$Igl=Eobnwq z2EaUsuJ7TPR>uqev`fW7z8an`hUWtJ3-NE9<`*fSMBXlZ`7V6}$$K3xxjNaAysOl0 zgufp89Yp6`N24}V=ox`Cxgr0Motc=q&6u0O#xwQ%gpVGg`wZ>Po$(kPyeFo1Age3+ z8?j4n3hVMnE-5pz{^R(btnOm48+^u5p5wwgA?okAM|<3cXN%>V)`6qc9mdwlbOm3H zg8wm`+)M^rl5NNvEDnazIbYuaINyNG8S2c*>AK_`sC{qO_7ou}ha4W!8{Vghza~%2 zh0l$X9o*lc{zY;|ildvzhCk|!%ioOiHu`Kx51r{sbc(g?6*(ARVc#C!SBvkaNA60G zF{W0(<6AgTG_4iG$(JG zv2tpo=UV1a<1Jnb_B|S-{9OJxdWp|ev>V?bpBl5PxyNmoGqXj?JY(}goM-Xyj>C!k z5Dgb#Ki>tpL9N*te^PwBJJSJ`7yagzKh6C$uWOqRSDew=#ifNDPME2b0j*U`p!iJarne6|N4_R}`ZuZJpo5{_Hk z&(bC#rz1RD!*L{??1`SCYbH6?sY&K6&&5ABF5ick1G5(TelMrtH@Zz9<1sx?{48+2 z4!h555>I#wJd5}6|7*Fn7t3eiAvW!MDAB z#&B4>C2$uPkny=3^iSt&*(Uzu)!^ixDmOlYgSE){0xuyCej}Db{ydpXb46({Q+i$$ z=I)pe@{6_o)%jrDu1V*2Y*|E?Je1x_#(>)L?_n&1*|@IW!%!|`!v(8D+4A>@S| zz96%DcjQVOwuS4`+VaoEub~g8@m{cpIQo#k`?IIB*t-KyBl!Ga*k<5D?)YQ>A5GJ~ zo%#JFeBrKm%sR#xE$sixH^|#Xd%5L*_y1x3t)A0d?|gW@+W%))!O@ysz4)%J>yGgM zq~GuR|LlES8Rscm!u~&z7gF;~E(YVCu#1a7_W${Bwg2w_qe;foaeNefaEZL%NUr=9 z`li;aVgFyQPxfN6&vnpWn0Jy<+HT4Z=Eksx`D6c|Y){wQxUv6F&t$Ltf7TBMxZ*HB z`~|;rw`}qYW;HEBhtPo$M52S#v%*R{srg-b%ke<9Q9T z!}<@8)%(6{>i3O)HSsbX2X~v7+Osd!zN3DJvgtk77m>MS$@2F-KBZ$*@&kYSI=?TD zx{ZiEirv&r*8c|W<}3Ss{~zA9 zPWPh!_x*qLy6cXPQ{WBbD6IJgGA$G(5Ki>{t+h}9Vr22>be~j}mzht{RE+xOAsoMX?&BfIlbe`+H1^%BP z^R-&_y}5#}s0~bf5wD|-IjpdUvHAV){y*z(9k*D!eYCUxk9VwB?_Or7(D64h(+!Wi zXdm=VrQ=aPInuG3>jM9Kx&D3spFU3ypa1XvzgUqitLp!wc$>`c@4>NC(|`B>$w%xH zcmMDHKf9X^n~QgApZE=!TEo*?ypCtzD|9qEc7>s@V+suWk+}uF=h1b+^8J5!S0wEJ z!{=6E{~yb%h50h<|I0dDui-TK$o{`r9oJ8bi6wlH^7Ym9uLA40&d2qkjsF57hs=|1a$Sv-a?xr;M$+ z7*C9+_*dA@*1nJX4b`6p^L1qQbG<%$PHU+4|M?i$&*%4}>0V#|%N)~TSy4OxPxasZ z|K>Pvfj4Ws!u~(Z;UNyvHo*os`|!Q@K;25QTgmV}E##0gU`&IM|6bo{Dv8veMkIeo*;)}4K`QQD2`~bV#@K}piRrtfcHJcvtz# zZ26NI2^?+B?VgDb=|M}&v;ZAo`f2i?wFwA|~dxNr< z18%XtGtNraD~PXvb0l0B(s?Ic&%0j0r-kuotYjOL`<$~Jmw(5`E8ss|yI|wW@SX%$ zOa8tFhwv7UlL>o%q&bKDKlcCe# zSHx`kjLvCf{2QMSEUEVY(J`<^Z266y%jBq2w7UkMa`qql|NJ)C$HDxxzG3Wz{PYf; z-#Bh$>v7s%!RJ%)(}%pPo#(47@ye%R|6g99-5h-2J2_px->~i-3V!H~*Q43oiY=$H z`wHXNo-F*{M7%Z}Z`P~*e+qkE=qrZuef1ea-c+*RS7uL{{{^q!14;(es`qlj_o~DG zzq}c?t?;2=JWQL1FQy+K`R>jG8?BM8JKuqE0DN+1*#8&P>ec=~ zyT(}@WWVqK^9$U|&*3@UAN&7eXYnbv(}DWE4yU;}?EllNaIz6wdgy-;Tyq_b4*RFD z|Ig)y;zMV-r10)%HUZW%;P^!S!|V>%4~h%>|D4~F9mv67#I_`i$*p0ROa9pZ7vICM zp}6WsZrC&C_=F|y&v*Cm%Y${_CFR3+lk)d^bj#sU&}+XD_WzOG6ZZe*j&$6i{zVu@io2WW zfIqyWk^e_LwxMUk#^v+SO0LCP{<8HazTyUU_glXIkL9la-Tz0Ii0>cRu@Jr+YSsQf z-vK6bRC&C<+rYN)9$sbr{;?P-T#NRYlzY8q5(b|grg4oP`s}T z>saj%z|ZMyS%>{%D>IkH8;gH)L6{@L`+4~u+6>0oUhI%fet#;$(x)66A z$S&ZYUiX_%4eaBy_1V5DyyNHy`Q;%x?EkZA>O%QS{M%VsKemeN+#HtRzHG1kd&b+J z>;K*VCvfF&(Z{CPx;j~(P3Gb7c}3X&=VvNEN13=xjw0_YZRgOx6Fk>xN7oE7-g~9ePKA4 zUDwcevh(Wd6TZRsAN&9O0=~DV3;X}%TIaj84SUZ{?0H@PrPefSvHuHt#Zk5Ymp{Yj zVX@~f)#t*$@Ba()Ul?=Yz1sL-+^z}V_qbm~_6+>pO2z>Ev!ncs4C6YyH;_(e*WrA7 zr#4?`4`0X&8D4|TbOUYdp^CO}T}oy%^6!^_@sraL*5>JR{Bj%nesjnJ<(=fL*68~= zd=$p0{Y-csoEGE-`Sw6z-yQzPGjA_WA7;zL&WG{Ked^EP<5Tgt6puscd_h0H3~S%y zHSx2nGIMhGCYBfS&Gi|m4_?zDc>2;cEYRhGuPvQDZJ$Uj=$iR=je;QLID&z{H0rR+Y74`z7pqqkhQBm z;WvcV)^C4!Lc7iQg{<7%5&2$jc4obL?3CLK*I_*z4}j}y zw)7D{+7w|dJ;NsWlT`h7`~`R3v&nizd6PDGWoy2*cGnu-`opaui03Azc(37 z=8mxSAlKXwp0mfDV0l%(J5m3)Yvv~XcIW&4BXfIxm`(28%GV?JV&g~LWQVi$8aNK3W91s1^n9efIW{~S4c~K#KCV}v6X)Al zYb9h(#-DXoauPr7NLH&QRqn~<+2TI!jj!|x{kL_V3gaiPf0Bbdv&eRFEQ3MY$XKq{ zXH)d+L6`Um&+dvU%sv*5X(z5~hF3)Tsai&EIg zsq%>I_v*|4uk} zo78y*k@HW{4+r8qtPAtq=}Od1!I}MV3`cYb-NCk*@CVL!3NqRF4(`9RmbeKfYrASc z*OH9Zj%nmvMvmAh!rbzez9Y4Hiku-e@60&5h#|Q=Gv9`}KUV7nW#INcQ|iE7ddGL zqZo+g&%$20jGZ@8|DrN;S@aM+`|L-bBaTjl;-S+PB7M>l4XG!@RFrKQcWus>@jXuk!XSlMrw7JTzU)nVm_Uzd=-7< zheS>)p7wh*Tk5l$dh39wH7woKjltm$+U*F(9P5z{`E765H>`UHl$_!E?1YzpID5Y# z^~|7<3zKc=zK_mr>b}cw-u6y=*+oC|U>G}v{Fl7OmQmV&tWAjZSIIE1C&qbLD<^}= z-5Q=f*%XnP!_}GGVeI}^`DSA2uXKp9>bvB(kU>r|bxHMK7THwtJg-h4kk1CedMW;6 zb_^sp#L-Q)>UZI?HG(YV?O=2+$K$jajvscM1KUda8XM8i@OOlH20U^^YJN)O>EafB zZ+7;6M9BBy|02@cosEU010A=})tp_=>YKRFoeyrP{!2IbKkT(*`6A5uaT~s<8}Hj# z4}HVlHf&h8=6@&1GGB&wi?W^J-%~k1#xKMA8C+qEzD(Am$~*8;t-gHzHmAl{YlE|- zh4O#0Np36G@EyG$?T5F87R%3cc8kL z@Y5(Zeseuktb~1MW3Bov%{&vwkKt%vZBkf1(DxrT@7rtJ1C}Z7joG49KZeW^d}bbx zcfgmv@oup9B#(Vj@aG0NS<$(-_G6b=+b^vCHzHn_ujGboR;~IS@oYLA=7R8UU1khL z9rXW^pQb6h6A#hpxI?pMJR-$x&c@wMT+Ao$e1T$!3vtM7hZ?S2jY zmTD`;qpR6A1}{D%OP`1F0GvId4PD7?)}McYaTl?+MBT@*{YRgT;T)*XL+m?N*$jPx zZFkdgHg3)NrC5m`^!(tT#?9aL??LCkV3!ZV`XhY)P`-9#U;JNOf?MOFdPX!T@DA_S z^6E!)ovyF(8b|DE2P;3Pmy!=x`~VqpaPkQ5t$`zXEBcX4<0qOers*vYA$M=MFC=GY zc&}7%ZJb*#=L>7*K=^~QSSG-ro#nEeNj8)?^>%%5Nulj&pb zXY2ojI9f&g7^~$F^G3IZ>OY>sbMeAHFArmI2Dzi*SQB>f7jj2DTpzhEzZX_>WO$b( z{J(vCsCpPu>wt9oCZ9Rfd`A(E!{J{b|KH2*H{?`4Om>8)jpJ}_y5L$a%RW$ls=mf? zc{CkQJHq;6BAmh3^R<7Mp10v0$zM1vUNxRPJIH6@X;nCIo3tQb4CR|@)6#Vxd3hp^ z29s^vr#InnKEE!;%@<3m-@pm|%12z^PWBFTt)UH>#br2LeZk%7+DiZRvHPBX3toD7{Uj;(rc_no8p3BO7>RyYgPSEaQ&jV9H!3)ORDE7Sy!A|Z{%T)5X+@; zm2KdeN;CHMgw^;f=}fa8;9?mrN1ne#}-$gm8ToBUEYYMDL)^luk*#WjlLH_&PV$7gY{QB z^ zJF@?K_?~2Qh}lWn-^BJ1^VhPibz>E;S;)B|Z%=Zsf3oOU1RY24SDP8zmk4W;bw+e2$;?Z6FF0DUqouM5zT5YTYkk6R3MFvocj03+TLx-Zuyr-I z48}*J_F_7Ff^6fvD72r>FCVdGK7Vbe-A%BGxu^vn#$@RmZOW#n^=lME)&kisj;r7> zuasM9^DBABlm8t%%_HIS;qXj2%)$AEux!EB3!CIwarIT*-b0LCB4OjyqLXA z=J#T2PdW8Ee1`nhhm7awF{WbI`3SjVkn5x9+1vel@V`p$HFDG5uzUi?UiyfoYP~DR zM>8FZwYdeS?co}yF7R=`_TnMGh|Uk`eyE}Pydatt{7TLkdOnAJqP}m!i=(^&ml@rU z>&Kr-C_fp_S3;~ec^;w9uG%bCH;1lU*%9KW;(*RC$;DNC8r|$DPvZ0b4p`D5#?nq? zcO`Fae0@lU&k^IfbcNXBlkyZ;_P|wmzP5t%Nas!Qw>D0n!o@!9fTLRf8K?1%Fm1`+ zKkF<1hIeOD@sz(vPO0t1d~%HP(aOCaALsN8#={ZD$yc@N8FdzNsoWlm#}E@ChQsH? z1s`M^u=O&>jg8f~NV~D|p_+XgIoInG=7AOP_7FD>muJ@PL5^g1e^?l>r!okZ@zZVhtVS61qk`*@Ot%oKS|)` zFEBl?O;=@XNv?D~1rH%F{!9NO;oq09SHMS&jYpF&Pgd_dHs`bZ>ec6P(SG`#%P)ze zh66r}kEClhyXKMoobsR9dx|yS>EtxAVJQwLvmtU^!Ji+{cdRyF(D?*=x5m@v@X;6E zlvhi>pz(#H26=8Uf&iOE}h0Cq9zlqOJqVs*ao0C67Te-2|)4WkR9nk{k zH5;u%U_F5B)75?Be3bqz^qZ|;S9Yze-ZRhQW-{jEk{yY-E^;`|g5yc;TETp#vO~nt z6nw2OUgs#oTe&Y?lW=h(zBdvV?dZ6XEbs8;3t*QE!*lInZ1sW=GF`Qwm7 zTH`F_w9Dyzh>V*Xy^qS?Jz;y>KFvHC*RlrcwH_OP{k_>XH&-m|!(VUe|XX`e~ zzs1E$^d3rX%?`jrS4t>iad}Grugn^M4|4I@dkxu*Sn-w7Pbgx=&#+ zM$!@Vwsrq2o5P$E+HT3lwfSg6XX7c%aanWEz2AW4Qu24uz6H5MJzojL)c^gk{$xjSb7iC-uFF=Z(VN-Cts)LlJFT`W_^*%H)Y`aIqmikxBVOK zF=}jt-<~JDmm1&MQ2joCegb}t$LK@(_6dC+hv8Ooc7knycz8kEgK@`4x!haYTjp#^ z#cX(oExVPEAB9=0MQz#rEnNRmE+*1f*!e8I^NrI{WbUUdJfk@nXLqsXBQlMJgr2mu z`|F%fhH)ihW(!z$ta-NM{GfjN=YN6ePWSWha~~bSr^Z3NJN>SU7Hof0pTW+j!800f z`_UC_T8sWG@Uf@9PY$S_QH0M9^6BKoFr2`5=WG8qyKdFy66ed{c#XU^czC#GA7qS7 z4!(nN9$5qRSqBEsrgC{Q+FQ=%i|`yF?bNvZH#xsz*P~>dg0nvQv}6BdvPbYqAM1|` z$l65P@5mYsr?q!H3y$CDGf!0iwf8w4uaYl^WZ66^HLS_T~fM*~+&fb1`}S^&hL= z{7^0+a|}!w`@+8DRxz}mdU-p%vrycn-8#4$;QAii{gaN{*fNAoL-m~?4t7zNl6$?f zRq5!a?@)Z;Bx(gWTgp~^y0tvB6P#n|J%cWolPk0p8`*dKMrWZcjo5XMw!v>ZlmBP< zIw;>)ALFf9gWU79*|#otDi^QiX?UhTE%ez07bJ_w!(+ac{%}T@lXbZM#&>e1``L0#@Xwy)&gJ_b$lDwb4~wZ` N+QJ$3z3HO*{{fwIEQtUB literal 12333 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 Yh6(C!-@J#L)iAlAYeYO@%U9O^e`+S4_5c6? literal 3917 zcmeHKO>Y!O5OoNUuz}>jEteGHU=Hhzu>mi>SYQ%^KoG@72BFC6ovGPr+|xaD_v|uA zNI7!YGq%5V6l&Pv#dTOa~o)lqa-ei%CYHU_^iwo1`j=X!f zxDa*4A!0|j_<3V}jkW9JgX`n%o42+%*GIR<zc}~Bpne!ST?5TXpahvYxkhvNAboPrsmJmEv75_CD+-KOO z7wOk+>nmidz1^_@09$5s_+a_nzS(Wm~9D7IR+8D}8WvB21 zkFH4Xcjyjzo;lM*?X2=Ge^fn}j~Fm6gsRT?NvHBABTV z2^au4fR;Jqyl^$ATE)oTh9L!)wq~fK8bJ^byyl8EY+F+v)xs*G z(w3a8)G>lXMW>V-9YMCnj_9ytu><2sPL8DJQYfKj&I6$zOn?fKKBY+tyd|RxR4?{? z20xXm$1>HCb5^PtO~}#&sX@~bb0dVU#HD%J3jbYE zz)3}3hvT)vv#?GpBgkt9Tfe=QC$@>iOfOw4c?+y6!yyO}ELwt|N!)!!*2;qbY=9rO z3e}bDPFQ{!-4*E_2obEdE|wAk(rbhLX87B88a}3Gwx!PVDnV@90fIa0gOHErZ&=2YPVe@L+#T05p`tI zk-No@^`B4fJ>5MZbLZ*f-TU3*@<%B=suj3pbB)6;=1H{O;@P$K&y>@m5z}czC89JiB~uW#x2AoKA_;DRDX_ zPNxL4cWU0F)ViTXf#tGb<~PoJ*oY21^iGEvoox;ar5O$lDz{WRas&7iI2XLSq^-RQ3~0 z8w1q@%TRbm1OmjX=myJ}#~w2Y@+ab-jOa8&`_YeSIpH{GOhC*~k!dn%r!uI;fa+D# ziB=Uk32_4HA!myKP6vt<)S+C;QCPv=RU8$d+T^@KC((pi4t*jQnnK49f^E6jd=xwE zoM>F!=zN;A$!(eZb106XNIHS2k3&Jt#R$=obVyQ=a%B_aGP~t=12foxoIuM|5PnG~ z$|W!@D&0JTitATR1V}+$?9MUM1%N%=MNZ^_QBYVo^hEJ2?<{lYalJ`e14^yHMNXuc ztb&@tVJU14CEcs%bVCuKd(FO+Byul!kdF6KCO8B2JQ!Tvhxhl?n>UCvJwHPJ@q_@M O*3S{%o@k1ONB;uMplXx= diff --git a/frontend/app.js b/frontend/app.js index 32444ca..ca86004 100644 --- a/frontend/app.js +++ b/frontend/app.js @@ -4,7 +4,7 @@ document.addEventListener('DOMContentLoaded', function() { // Navigation const menuItems = document.querySelectorAll('.menu li'); const pages = document.querySelectorAll('.page'); - + // Generate Content Page const generateBtn = document.getElementById('generate-btn'); const promptInput = document.getElementById('prompt'); @@ -23,12 +23,12 @@ document.addEventListener('DOMContentLoaded', function() { const improvementPanel = document.getElementById('improvement-panel'); const improvementFeedback = document.getElementById('improvement-feedback'); const submitImprovement = document.getElementById('submit-improvement'); - + // History Page const historyFilterType = document.getElementById('history-filter-type'); const historySearch = document.getElementById('history-search'); const historyList = document.querySelector('.history-list'); - + // Brand Style Page const toneSelector = document.getElementById('tone-selector'); const voiceSelector = document.getElementById('voice-selector'); @@ -40,7 +40,7 @@ document.addEventListener('DOMContentLoaded', function() { const addTermBtn = document.getElementById('add-term-btn'); const saveBrandStyleBtn = document.getElementById('save-brand-style'); const resetBrandStyleBtn = document.getElementById('reset-brand-style'); - + // Training Page const trainingTabs = document.querySelectorAll('.training-tabs .tab'); const tabContents = document.querySelectorAll('.tab-content'); @@ -54,24 +54,24 @@ document.addEventListener('DOMContentLoaded', function() { const trainingFilterType = document.getElementById('training-filter-type'); const trainingSearch = document.getElementById('training-search'); const trainingList = document.querySelector('.training-list'); - + // API Base URL const API_URL = 'http://localhost:8000'; - + // Menu Navigation menuItems.forEach(item => { item.addEventListener('click', function() { const pageName = this.getAttribute('data-page'); - + // Update active menu item menuItems.forEach(menuItem => menuItem.classList.remove('active')); this.classList.add('active'); - + // Show selected page pages.forEach(page => { if (page.id === `${pageName}-page`) { page.classList.add('active'); - + // Load data for specific pages when they're opened if (pageName === 'history') { loadUserQueries(); @@ -87,7 +87,7 @@ document.addEventListener('DOMContentLoaded', function() { }); }); }); - + // Generate Content if (generateBtn) { generateBtn.addEventListener('click', function() { @@ -95,11 +95,11 @@ document.addEventListener('DOMContentLoaded', function() { alert('Please enter a prompt for content generation.'); return; } - + // Show loading indicator loadingIndicator.classList.remove('hidden'); resultContainer.classList.add('hidden'); - + // Prepare request data const requestData = { prompt: promptInput.value, @@ -108,7 +108,7 @@ document.addEventListener('DOMContentLoaded', function() { include_cta: includeCTACheckbox.checked, reference_similar_content: referenceSimilarCheckbox.checked }; - + // Call the API fetch(`${API_URL}/generate-copy`, { method: 'POST', @@ -126,15 +126,25 @@ document.addEventListener('DOMContentLoaded', function() { .then(data => { // Hide loading indicator loadingIndicator.classList.add('hidden'); - - // Display result - resultContent.textContent = data.content; - + + // Display result with preserved formatting + resultContent.innerHTML = data.content + .split('\n') + .map(line => { + // Convert bullet points to list items + if (line.trim().startsWith('•')) { + return `
  • ${line.trim().substring(1).trim()}
  • `; + } + // Wrap non-empty lines in paragraphs + return line.trim() ? `

    ${line}

    ` : ''; + }) + .join('\n'); + // Set alignment score const score = data.metadata.alignment_score || 0; alignmentScore.style.width = `${score}%`; alignmentScore.textContent = `${Math.round(score)}%`; - + if (score < 60) { alignmentScore.style.backgroundColor = 'var(--danger-color)'; } else if (score < 80) { @@ -142,7 +152,7 @@ document.addEventListener('DOMContentLoaded', function() { } else { alignmentScore.style.backgroundColor = 'var(--success-color)'; } - + // Display suggestions if (data.suggestions && data.suggestions.length > 0) { suggestionsList.innerHTML = ''; @@ -155,7 +165,7 @@ document.addEventListener('DOMContentLoaded', function() { suggestionsList.appendChild(li); }); } - + // Show result container resultContainer.classList.remove('hidden'); }) @@ -166,7 +176,7 @@ document.addEventListener('DOMContentLoaded', function() { }); }); } - + // Copy to Clipboard if (copyBtn) { copyBtn.addEventListener('click', function() { @@ -183,53 +193,50 @@ document.addEventListener('DOMContentLoaded', function() { }); }); } - + // Toggle Improvement Panel if (improveBtn) { improveBtn.addEventListener('click', function() { improvementPanel.classList.toggle('hidden'); }); } - + // Submit Improvement Feedback if (submitImprovement) { submitImprovement.addEventListener('click', function() { - if (!improvementFeedback.value.trim()) { - alert('Please enter feedback for improvement.'); + const feedback = improvementFeedback.value.trim(); + if (!feedback) { + alert('Please provide improvement feedback.'); return; } - - // Show loading indicator + loadingIndicator.classList.remove('hidden'); - - // Prepare request data - const requestData = { - content: resultContent.textContent, - feedback: improvementFeedback.value - }; - - // Call the API + fetch(`${API_URL}/improve-content`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(requestData) - }) - .then(response => { - if (!response.ok) { - throw new Error(`HTTP error! Status: ${response.status}`); - } - return response.json(); + body: JSON.stringify({ + content: resultContent.textContent, + feedback: feedback + }) }) + .then(response => response.json()) .then(data => { - // Hide loading indicator loadingIndicator.classList.add('hidden'); - // Update result content - resultContent.textContent = data.improved_content; - - // Hide improvement panel + // Update result content with preserved formatting + resultContent.innerHTML = data.improved_content + .split('\n') + .map(line => { + if (line.trim().startsWith('•')) { + return `
  • ${line.trim().substring(1).trim()}
  • `; + } + return line.trim() ? `

    ${line}

    ` : ''; + }) + .join('\n'); + improvementPanel.classList.add('hidden'); improvementFeedback.value = ''; }) @@ -240,7 +247,7 @@ document.addEventListener('DOMContentLoaded', function() { }); }); } - + // Save Content to History if (saveBtn) { saveBtn.addEventListener('click', function() { @@ -249,17 +256,17 @@ document.addEventListener('DOMContentLoaded', function() { // so we don't need to make another API call here }); } - + // Load User Queries (History) function loadUserQueries(page = 1, contentType = '') { if (!historyList) return; - + // Show loading state historyList.innerHTML = '
    Loading history...
    '; - + // Build the query parameters let queryParams = `?page=${page}&limit=10`; - + // Call the API fetch(`${API_URL}/user-queries${queryParams}`) .then(response => { @@ -270,26 +277,26 @@ document.addEventListener('DOMContentLoaded', function() { }) .then(data => { historyList.innerHTML = ''; - + if (data.items.length === 0) { historyList.innerHTML = '
    No history found.
    '; return; } - + // Filter by content type if provided let filteredItems = data.items; if (contentType) { - filteredItems = data.items.filter(item => + filteredItems = data.items.filter(item => item.parameters && item.parameters.content_type === contentType ); } - + // Create history items filteredItems.forEach(item => { const contentType = item.parameters?.content_type || 'general'; const timestamp = item.timestamp ? new Date(item.timestamp).toLocaleDateString() : 'Unknown date'; const promptPreview = item.prompt.length > 80 ? item.prompt.substring(0, 80) + '...' : item.prompt; - + const historyItem = document.createElement('div'); historyItem.className = 'history-item'; historyItem.innerHTML = ` @@ -308,10 +315,10 @@ document.addEventListener('DOMContentLoaded', function() { `; - + historyList.appendChild(historyItem); }); - + // Add event listeners for view and delete buttons document.querySelectorAll('.view-query').forEach(btn => { btn.addEventListener('click', function() { @@ -319,7 +326,7 @@ document.addEventListener('DOMContentLoaded', function() { viewUserQuery(timestamp); }); }); - + document.querySelectorAll('.delete-query').forEach(btn => { btn.addEventListener('click', function() { const timestamp = this.getAttribute('data-timestamp'); @@ -328,7 +335,7 @@ document.addEventListener('DOMContentLoaded', function() { } }); }); - + // Add pagination if needed if (data.pagination && data.pagination.pages > 1) { // Remove existing pagination if any @@ -336,18 +343,18 @@ document.addEventListener('DOMContentLoaded', function() { if (existingPagination) { existingPagination.remove(); } - + const paginationElement = document.createElement('div'); paginationElement.className = 'pagination'; - + let paginationHTML = ''; for (let i = 1; i <= data.pagination.pages; i++) { paginationHTML += ``; } - + paginationElement.innerHTML = paginationHTML; historyList.after(paginationElement); - + // Add event listeners for pagination buttons document.querySelectorAll('.page-btn').forEach(btn => { btn.addEventListener('click', function() { @@ -362,14 +369,14 @@ document.addEventListener('DOMContentLoaded', function() { historyList.innerHTML = '
    Error loading history. Please try again.
    '; }); } - + // Helper function to extract timestamp from ISO date function getTimestampFromISODate(isoDate) { if (!isoDate) return ''; const date = new Date(isoDate); return date.toISOString().replace(/[-:T.]/g, '').slice(0, 14); } - + // Helper function to generate a title from prompt function getPromptTitle(prompt) { if (!prompt) return 'Untitled Query'; @@ -377,11 +384,11 @@ document.addEventListener('DOMContentLoaded', function() { if (words.length <= 5) return prompt; return words.slice(0, 5).join(' ') + '...'; } - + // Helper function to get display label for content type function getContentTypeLabel(contentType) { if (!contentType) return 'General'; - + const labels = { 'email': 'Email', 'social_media': 'Social', @@ -397,10 +404,10 @@ document.addEventListener('DOMContentLoaded', function() { 'newsletter': 'Newsletter', 'general': 'General' }; - + return labels[contentType] || contentType.charAt(0).toUpperCase() + contentType.slice(1); } - + // View User Query function viewUserQuery(timestamp) { fetch(`${API_URL}/user-queries/${timestamp}`) @@ -414,15 +421,15 @@ document.addEventListener('DOMContentLoaded', function() { // Create a modal to display the query details const modal = document.createElement('div'); modal.className = 'modal'; - + const modalContent = document.createElement('div'); modalContent.className = 'modal-content'; - + const parameters = data.parameters || {}; const contentType = parameters.content_type || 'Not specified'; const length = parameters.length || 'Not specified'; const includeCTA = parameters.include_cta ? 'Yes' : 'No'; - + modalContent.innerHTML = ` `; - + modal.appendChild(modalContent); document.body.appendChild(modal); - + // Close button functionality modal.querySelector('.modal-close').addEventListener('click', function() { document.body.removeChild(modal); }); - + // Close when clicking outside the modal window.addEventListener('click', function(event) { if (event.target === modal) { @@ -472,7 +479,7 @@ document.addEventListener('DOMContentLoaded', function() { alert('Error viewing query details. Please try again.'); }); } - + // Delete User Query function deleteUserQuery(timestamp) { fetch(`${API_URL}/user-queries/${timestamp}`, { @@ -486,7 +493,7 @@ document.addEventListener('DOMContentLoaded', function() { }) .then(data => { alert('Query successfully deleted.'); - + // Reload the user queries loadUserQueries(); }) @@ -495,20 +502,20 @@ document.addEventListener('DOMContentLoaded', function() { alert('Error deleting query. Please try again.'); }); } - + // History Filter Handlers if (historyFilterType) { historyFilterType.addEventListener('change', function() { loadUserQueries(1, this.value); }); } - + if (historySearch) { historySearch.addEventListener('input', function() { // Client-side filtering - this would ideally be server-side, // but we'll implement a simple client-side filter for now const searchTerm = this.value.toLowerCase(); - + document.querySelectorAll('.history-item').forEach(item => { const content = item.querySelector('.history-item-content').textContent.toLowerCase(); if (content.includes(searchTerm)) { @@ -519,185 +526,63 @@ document.addEventListener('DOMContentLoaded', function() { }); }); } - - // Brand Style Tag Selection - if (toneSelector) { - const tagElements = toneSelector.querySelectorAll('.tag'); - tagElements.forEach(tag => { - tag.addEventListener('click', function() { - this.classList.toggle('selected'); - }); - }); + + // Brand Style Tag Selection - Disabled as brand style is fixed to Adriana James' style + // Read-only display of brand style tags + + // Taboo Words - Read-only as brand style is fixed to Adriana James' style + // Disabled taboo word editing functionality + if (tabooInput) { + tabooInput.disabled = true; + tabooInput.placeholder = "Taboo words are fixed to maintain brand consistency"; } - - if (voiceSelector) { - const tagElements = voiceSelector.querySelectorAll('.tag'); - tagElements.forEach(tag => { - tag.addEventListener('click', function() { - this.classList.toggle('selected'); - }); - }); + + if (addTabooBtn) { + addTabooBtn.disabled = true; } - - // Add Taboo Word - if (addTabooBtn && tabooInput && tabooWords) { - addTabooBtn.addEventListener('click', function() { - const word = tabooInput.value.trim(); - if (word) { - const tagElement = document.createElement('span'); - tagElement.classList.add('tag', 'removable'); - tagElement.innerHTML = `${word}`; - - // Add click event to remove the tag - tagElement.querySelector('i').addEventListener('click', function() { - tagElement.remove(); - }); - - tabooWords.appendChild(tagElement); - tabooInput.value = ''; - } - }); - - // Allow pressing Enter to add a word - tabooInput.addEventListener('keypress', function(e) { - if (e.key === 'Enter') { - e.preventDefault(); - addTabooBtn.click(); - } - }); + + // Terminology - Read-only as brand style is fixed to Adriana James' style + // Disabled terminology editing functionality + if (avoidTerm) { + avoidTerm.disabled = true; + avoidTerm.placeholder = "Terminology is fixed"; } - - // Add Terminology Term - if (addTermBtn && avoidTerm && useTerm) { - addTermBtn.addEventListener('click', function() { - const avoid = avoidTerm.value.trim(); - const use = useTerm.value.trim(); - - if (avoid && use) { - const tableRow = document.createElement('div'); - tableRow.classList.add('terminology-row'); - tableRow.innerHTML = ` -
    ${avoid}
    -
    ${use}
    -
    - -
    - `; - - // Add click event to remove the row - tableRow.querySelector('.btn-icon').addEventListener('click', function() { - tableRow.remove(); - }); - - // Insert before the add row - const addRow = document.querySelector('.terminology-row.add-row'); - addRow.parentNode.insertBefore(tableRow, addRow); - - avoidTerm.value = ''; - useTerm.value = ''; - } - }); - - // Allow pressing Enter to add a term - useTerm.addEventListener('keypress', function(e) { - if (e.key === 'Enter') { - e.preventDefault(); - addTermBtn.click(); - } - }); + + if (useTerm) { + useTerm.disabled = true; + useTerm.placeholder = "Terminology is fixed"; } - - // Save Brand Style - if (saveBrandStyleBtn) { - saveBrandStyleBtn.addEventListener('click', function() { - // Collect tone tags - const selectedTones = []; - toneSelector.querySelectorAll('.tag.selected').forEach(tag => { - selectedTones.push(tag.textContent); - }); - - // Collect voice characteristics - const selectedVoice = []; - voiceSelector.querySelectorAll('.tag.selected').forEach(tag => { - selectedVoice.push(tag.textContent); - }); - - // Collect taboo words - const tabooWordsList = []; - tabooWords.querySelectorAll('.tag').forEach(tag => { - // Extract just the text without the 'x' icon - const text = tag.textContent.replace('×', '').trim(); - tabooWordsList.push(text); - }); - - // Collect preferred terms - const preferredTerms = {}; - document.querySelectorAll('.terminology-row:not(.add-row):not(.terminology-header)').forEach(row => { - const avoid = row.querySelector('.term-avoid').textContent.trim(); - const use = row.querySelector('.term-use').textContent.trim(); - if (avoid && use) { - preferredTerms[avoid] = use; - } - }); - - // Prepare request data - const requestData = { - tone: selectedTones, - voice_characteristics: selectedVoice, - taboo_words: tabooWordsList, - preferred_terms: preferredTerms - }; - - // Call the API - fetch(`${API_URL}/brand-style`, { - method: 'PUT', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(requestData) - }) - .then(response => { - if (!response.ok) { - throw new Error(`HTTP error! Status: ${response.status}`); - } - return response.json(); - }) - .then(data => { - alert('Brand style updated successfully!'); - }) - .catch(error => { - console.error('Error:', error); - alert('An error occurred while updating brand style. Please try again.'); - }); - }); + + if (addTermBtn) { + addTermBtn.disabled = true; } - - // Reset Brand Style - if (resetBrandStyleBtn) { - resetBrandStyleBtn.addEventListener('click', function() { - if (confirm('Are you sure you want to reset brand style to defaults?')) { - // In a real implementation, you would call an API to reset - // For now, just reload the page - window.location.reload(); - } - }); - } - + + // Disable remove buttons for terminology rows + document.querySelectorAll('.terminology-row:not(.add-row):not(.terminology-header) .btn-icon').forEach(btn => { + btn.disabled = true; + btn.style.opacity = '0.5'; + btn.style.cursor = 'not-allowed'; + }); + + // Brand Style is fixed - removed save functionality + + // Brand Style is fixed - removed reset functionality + // Training Tabs if (trainingTabs.length > 0) { trainingTabs.forEach(tab => { tab.addEventListener('click', function() { const tabName = this.getAttribute('data-tab'); - + // Update active tab trainingTabs.forEach(t => t.classList.remove('active')); this.classList.add('active'); - + // Show selected tab content tabContents.forEach(content => { if (content.id === `${tabName}-tab`) { content.classList.add('active'); - + // Load training data when the View tab is selected if (tabName === 'view-training') { loadTrainingData(); @@ -709,7 +594,7 @@ document.addEventListener('DOMContentLoaded', function() { }); }); } - + // Add Training Data if (addTrainingBtn) { addTrainingBtn.addEventListener('click', function() { @@ -717,12 +602,12 @@ document.addEventListener('DOMContentLoaded', function() { alert('Please select a content type.'); return; } - + if (!trainingContent.value.trim()) { alert('Please enter content for training.'); return; } - + // Prepare request data const requestData = { content_type: trainingContentType.value, @@ -732,20 +617,20 @@ document.addEventListener('DOMContentLoaded', function() { performance_metrics: {} } }; - + // Add performance metrics if provided if (openRate.value) { requestData.metadata.performance_metrics.open_rate = parseFloat(openRate.value) / 100; } - + if (clickRate.value) { requestData.metadata.performance_metrics.click_rate = parseFloat(clickRate.value) / 100; } - + if (conversionRate.value) { requestData.metadata.performance_metrics.conversion_rate = parseFloat(conversionRate.value) / 100; } - + // Call the API fetch(`${API_URL}/training-data`, { method: 'POST', @@ -762,7 +647,7 @@ document.addEventListener('DOMContentLoaded', function() { }) .then(data => { alert('Training data added successfully!'); - + // Clear form trainingContentType.value = ''; campaignName.value = ''; @@ -770,7 +655,7 @@ document.addEventListener('DOMContentLoaded', function() { openRate.value = ''; clickRate.value = ''; conversionRate.value = ''; - + // Switch to view tab document.querySelector('.tab[data-tab="view-training"]').click(); }) @@ -780,20 +665,20 @@ document.addEventListener('DOMContentLoaded', function() { }); }); } - + // Load Training Data function loadTrainingData(page = 1, contentType = '') { if (!trainingList) return; - + // Show loading state trainingList.innerHTML = '
    Loading training data...
    '; - + // Build the query parameters let queryParams = `?page=${page}&limit=10`; if (contentType) { queryParams += `&content_type=${contentType}`; } - + // Call the API fetch(`${API_URL}/training-data${queryParams}`) .then(response => { @@ -804,17 +689,17 @@ document.addEventListener('DOMContentLoaded', function() { }) .then(data => { trainingList.innerHTML = ''; - + if (data.items.length === 0) { trainingList.innerHTML = '
    No training data found.
    '; return; } - + // Create training items data.items.forEach(item => { const trainingItem = document.createElement('div'); trainingItem.className = 'training-item'; - + // Generate metrics HTML let metricsHTML = ''; if (item.metadata && item.metadata.performance_metrics) { @@ -829,13 +714,13 @@ document.addEventListener('DOMContentLoaded', function() { metricsHTML += `Conversion: ${(metrics.conversion_rate * 100).toFixed(1)}%`; } } - + if (!metricsHTML) { metricsHTML = 'No metrics available'; } - + const campaignName = item.metadata?.campaign_name || 'Untitled'; - + trainingItem.innerHTML = `
    ${getContentTypeLabel(item.content_type)}
    @@ -845,7 +730,7 @@ document.addEventListener('DOMContentLoaded', function() { ${metricsHTML}
    - +
    `; - + trainingList.appendChild(trainingItem); }); - + // Add event listeners for view and delete buttons document.querySelectorAll('.view-training').forEach(btn => { btn.addEventListener('click', function() { @@ -866,7 +751,7 @@ document.addEventListener('DOMContentLoaded', function() { viewTrainingData(id); }); }); - + document.querySelectorAll('.delete-training').forEach(btn => { btn.addEventListener('click', function() { const id = this.getAttribute('data-id'); @@ -875,7 +760,7 @@ document.addEventListener('DOMContentLoaded', function() { } }); }); - + // Add pagination for training data if (data.pagination && data.pagination.pages > 1) { // Remove existing pagination if any @@ -883,18 +768,18 @@ document.addEventListener('DOMContentLoaded', function() { if (existingPagination) { existingPagination.remove(); } - + const paginationElement = document.createElement('div'); paginationElement.className = 'pagination'; - + let paginationHTML = ''; for (let i = 1; i <= data.pagination.pages; i++) { paginationHTML += ``; } - + paginationElement.innerHTML = paginationHTML; trainingList.after(paginationElement); - + // Add event listeners for pagination buttons document.querySelectorAll('.page-btn').forEach(btn => { btn.addEventListener('click', function() { @@ -909,7 +794,7 @@ document.addEventListener('DOMContentLoaded', function() { trainingList.innerHTML = '
    Error loading training data. Please try again.
    '; }); } - + // View Training Data function viewTrainingData(id) { fetch(`${API_URL}/training-data/${id}`) @@ -923,12 +808,12 @@ document.addEventListener('DOMContentLoaded', function() { // Create a modal to display the training data details const modal = document.createElement('div'); modal.className = 'modal'; - + const modalContent = document.createElement('div'); modalContent.className = 'modal-content'; - + const campaignName = data.metadata?.campaign_name || 'Untitled'; - + let metricsHTML = ''; if (data.metadata && data.metadata.performance_metrics) { const metrics = data.metadata.performance_metrics; @@ -942,7 +827,7 @@ document.addEventListener('DOMContentLoaded', function() { metricsHTML += `
    Conversion Rate: ${(metrics.conversion_rate * 100).toFixed(1)}%
    `; } } - + modalContent.innerHTML = ` `; - + modal.appendChild(modalContent); document.body.appendChild(modal); - + // Close button functionality modal.querySelector('.modal-close').addEventListener('click', function() { document.body.removeChild(modal); }); - + // Close when clicking outside the modal window.addEventListener('click', function(event) { if (event.target === modal) { @@ -985,7 +870,7 @@ document.addEventListener('DOMContentLoaded', function() { alert('Error viewing training data details. Please try again.'); }); } - + // Delete Training Data function deleteTrainingData(id) { fetch(`${API_URL}/training-data/${id}`, { @@ -999,7 +884,7 @@ document.addEventListener('DOMContentLoaded', function() { }) .then(data => { alert('Training data successfully deleted.'); - + // Reload the training data loadTrainingData(); }) @@ -1008,19 +893,19 @@ document.addEventListener('DOMContentLoaded', function() { alert('Error deleting training data. Please try again.'); }); } - + // Training Filter Handlers if (trainingFilterType) { trainingFilterType.addEventListener('change', function() { loadTrainingData(1, this.value); }); } - + if (trainingSearch) { trainingSearch.addEventListener('input', function() { // Client-side filtering const searchTerm = this.value.toLowerCase(); - + document.querySelectorAll('.training-item').forEach(item => { const content = item.querySelector('.training-item-content').textContent.toLowerCase(); if (content.includes(searchTerm)) { @@ -1031,7 +916,7 @@ document.addEventListener('DOMContentLoaded', function() { }); }); } - + // Load Brand Style on Page Load fetch(`${API_URL}/brand-style`) .then(response => { @@ -1047,11 +932,11 @@ document.addEventListener('DOMContentLoaded', function() { .catch(error => { console.error('Error loading brand style:', error); }); - + // For demonstration purposes, let's create a mocked pre-filled content // In a real implementation, this would be loaded from the backend document.getElementById('prompt').value = 'Generate an email campaign for a product launch'; - + // Add CSS for modal const modalStyle = document.createElement('style'); modalStyle.textContent = ` @@ -1066,7 +951,7 @@ document.addEventListener('DOMContentLoaded', function() { background-color: rgba(0, 0, 0, 0.5); overflow: auto; } - + .modal-content { background-color: white; margin: 5% auto; @@ -1077,12 +962,12 @@ document.addEventListener('DOMContentLoaded', function() { max-width: 800px; animation: modalOpen 0.3s ease-out; } - + @keyframes modalOpen { from {opacity: 0; transform: translateY(-20px);} to {opacity: 1; transform: translateY(0);} } - + .modal-header { padding: 20px 25px; border-bottom: 1px solid var(--grey-200); @@ -1090,11 +975,11 @@ document.addEventListener('DOMContentLoaded', function() { justify-content: space-between; align-items: center; } - + .modal-header h3 { margin: 0; } - + .modal-close { background: transparent; border: none; @@ -1102,34 +987,34 @@ document.addEventListener('DOMContentLoaded', function() { cursor: pointer; color: var(--grey-600); } - + .modal-close:hover { color: var(--grey-800); } - + .modal-body { padding: 25px; } - + .detail-item { margin-bottom: 15px; } - + .detail-label { font-weight: 600; color: var(--grey-700); display: block; margin-bottom: 5px; } - + .detail-value { color: var(--grey-800); } - + .content-preview { margin-top: 25px; } - + .content-box { background-color: var(--grey-100); border: 1px solid var(--grey-200); @@ -1140,20 +1025,20 @@ document.addEventListener('DOMContentLoaded', function() { max-height: 300px; overflow-y: auto; } - + .loading-state, .empty-state, .error-state { text-align: center; padding: 30px; color: var(--grey-500); } - + .pagination { display: flex; justify-content: center; gap: 5px; margin-top: 20px; } - + .page-btn { padding: 8px 12px; border: 1px solid var(--grey-300); @@ -1161,7 +1046,7 @@ document.addEventListener('DOMContentLoaded', function() { border-radius: var(--radius-md); cursor: pointer; } - + .page-btn.active { background-color: var(--primary-color); color: white; diff --git a/frontend/index.html b/frontend/index.html index d349df1..4258713 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -71,7 +71,7 @@ - +
    @@ -227,38 +227,36 @@

    Brand Tone

    -

    Select the tone options that best represent the brand.

    -
    - professional - friendly - inspirational +

    Adriana James' distinctive tone is characterized by:

    +
    empowering - excited - authoritative - casual - humorous + assertive + inspirational + direct
    +

    Her tone carries a motivational coach-like clarity, using embedded commands and cause-effect statements that inspire action.

    Voice Characteristics

    -

    Define the key characteristics of the brand voice.

    -
    +

    Adriana James speaks with these distinctive characteristics:

    +
    clear - direct - empowering confident - authentic - innovative - visionary - approachable + conversational + teaching
    +

    She speaks with conviction and clarity, using simple language to communicate profound ideas. Instead of saying "This might help you," she would say "You can do this—because your unconscious mind already knows how."

    @@ -339,8 +337,7 @@
    - - +

    Brand style settings are locked to maintain Adriana James' authentic voice across all content.

    diff --git a/frontend/styles.css b/frontend/styles.css index 4661797..e90b6f0 100644 --- a/frontend/styles.css +++ b/frontend/styles.css @@ -446,9 +446,30 @@ header { } .result-content { - padding: 25px; white-space: pre-wrap; + font-family: var(--font-family); line-height: 1.6; + padding: 20px; + background: white; + border-radius: 8px; + box-shadow: var(--shadow-sm); +} + +.result-content ul, +.result-content ol { + padding-left: 20px; + margin: 1em 0; +} + +.result-content p { + margin: 1em 0; +} + +/* Style bullet points */ +.result-content • { + margin-left: 1em; + display: list-item; + list-style-type: disc; } .metadata-panel { @@ -745,6 +766,48 @@ header { margin-top: 10px; } +.tag-selector.read-only .tag { + cursor: default; +} + +.style-description { + margin-top: 15px; + font-style: italic; + color: var(--grey-600); + line-height: 1.6; +} + +.style-note { + display: flex; + align-items: center; + color: var(--grey-600); + font-style: italic; +} + +.style-note i { + margin-right: 8px; + color: var(--grey-500); +} + +.alert { + padding: 15px; + border-radius: var(--radius-md); + margin-top: 15px; + display: flex; + align-items: center; +} + +.alert i { + margin-right: 10px; + font-size: 18px; +} + +.alert-info { + background-color: rgba(98, 54, 255, 0.1); + color: var(--primary-dark); + border-left: 4px solid var(--primary-color); +} + .tag { display: inline-flex; align-items: center; @@ -885,40 +948,40 @@ header { width: 80px; padding: 15px 0; } - + .logo h2 { width: 50px; height: 50px; font-size: 20px; } - + .menu li { justify-content: center; padding: 12px; } - + .menu li i { margin-right: 0; font-size: 20px; } - + .menu li span { display: none; } - + .user-info { justify-content: center; padding: 10px; } - + .user-avatar { margin-right: 0; } - + .user-name { display: none; } - + .content { margin-left: 80px; max-width: calc(100vw - 80px); @@ -930,35 +993,35 @@ header { flex-direction: column; gap: 10px; } - + .templates-grid { grid-template-columns: 1fr; } - - .history-item, + + .history-item, .training-item { flex-direction: column; align-items: flex-start; } - + .history-item-type, .training-item-type { margin-bottom: 10px; } - + .history-item-content, .training-item-content { padding: 0; margin-bottom: 10px; } - + .history-item-date { text-align: left; margin-bottom: 10px; } - + .checkbox-group { flex-direction: column; gap: 10px; } -} \ No newline at end of file +} diff --git a/logs/app.log b/logs/app.log index 95a31a6..5342add 100644 --- a/logs/app.log +++ b/logs/app.log @@ -1,970 +1,420 @@ -2025-04-17 07:08:51.543 | WARNING | vector_store:search:159 - Empty vector store, no results to return -2025-04-17 07:08:51.543 | WARNING | vector_store:search:159 - Empty vector store, no results to return -2025-04-17 07:08:51.551 | INFO | copywriter:generate_copy:118 - Generated content with 159 characters -2025-04-17 07:08:51.551 | INFO | copywriter:generate_copy:118 - Generated content with 159 characters -2025-04-17 07:08:52.803 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 07:08:52.803 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 07:12:18.934 | INFO | vector_store:search:212 - Found 1 matching documents for query -2025-04-17 07:12:18.934 | INFO | vector_store:search:212 - Found 1 matching documents for query -2025-04-17 07:12:18.936 | INFO | copywriter:generate_copy:118 - Generated content with 159 characters -2025-04-17 07:12:18.936 | INFO | copywriter:generate_copy:118 - Generated content with 159 characters -2025-04-17 07:12:19.677 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 07:12:19.677 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 07:15:03.309 | INFO | vector_store:search:212 - Found 2 matching documents for query -2025-04-17 07:15:03.309 | INFO | vector_store:search:212 - Found 2 matching documents for query -2025-04-17 07:15:05.643 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 404, { - "error": { - "message": "The model `gpt-4` does not exist or you do not have access to it.", - "type": "invalid_request_error", - "param": null, - "code": "model_not_found" - } -} - -2025-04-17 07:15:05.643 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 404, { - "error": { - "message": "The model `gpt-4` does not exist or you do not have access to it.", - "type": "invalid_request_error", - "param": null, - "code": "model_not_found" - } -} - -2025-04-17 07:15:05.644 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 404 -2025-04-17 07:15:05.644 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 404 -2025-04-17 07:15:10.452 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 404, { - "error": { - "message": "The model `gpt-4` does not exist or you do not have access to it.", - "type": "invalid_request_error", - "param": null, - "code": "model_not_found" - } -} - -2025-04-17 07:15:10.452 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 404, { - "error": { - "message": "The model `gpt-4` does not exist or you do not have access to it.", - "type": "invalid_request_error", - "param": null, - "code": "model_not_found" - } -} - -2025-04-17 07:15:10.455 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 404 -2025-04-17 07:15:10.455 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 404 -2025-04-17 07:15:15.166 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 404, { - "error": { - "message": "The model `gpt-4` does not exist or you do not have access to it.", - "type": "invalid_request_error", - "param": null, - "code": "model_not_found" - } -} - -2025-04-17 07:15:15.166 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 404, { - "error": { - "message": "The model `gpt-4` does not exist or you do not have access to it.", - "type": "invalid_request_error", - "param": null, - "code": "model_not_found" - } -} - -2025-04-17 07:15:15.168 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 404 -2025-04-17 07:15:15.168 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 404 -2025-04-17 07:15:15.170 | ERROR | copywriter:generate_copy:122 - Error generating copy: RetryError[] -2025-04-17 07:15:15.170 | ERROR | copywriter:generate_copy:122 - Error generating copy: RetryError[] -2025-04-17 07:15:20.280 | INFO | vector_store:search:212 - Found 2 matching documents for query -2025-04-17 07:15:20.280 | INFO | vector_store:search:212 - Found 2 matching documents for query -2025-04-17 07:15:21.317 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 404, { - "error": { - "message": "The model `gpt-4` does not exist or you do not have access to it.", - "type": "invalid_request_error", - "param": null, - "code": "model_not_found" - } -} - -2025-04-17 07:15:21.317 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 404, { - "error": { - "message": "The model `gpt-4` does not exist or you do not have access to it.", - "type": "invalid_request_error", - "param": null, - "code": "model_not_found" - } -} - -2025-04-17 07:15:21.369 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 404 -2025-04-17 07:15:21.369 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 404 -2025-04-17 07:15:26.051 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 404, { - "error": { - "message": "The model `gpt-4` does not exist or you do not have access to it.", - "type": "invalid_request_error", - "param": null, - "code": "model_not_found" - } -} - -2025-04-17 07:15:26.051 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 404, { - "error": { - "message": "The model `gpt-4` does not exist or you do not have access to it.", - "type": "invalid_request_error", - "param": null, - "code": "model_not_found" - } -} - -2025-04-17 07:15:26.052 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 404 -2025-04-17 07:15:26.052 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 404 -2025-04-17 07:15:30.842 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 404, { - "error": { - "message": "The model `gpt-4` does not exist or you do not have access to it.", - "type": "invalid_request_error", - "param": null, - "code": "model_not_found" - } -} - -2025-04-17 07:15:30.842 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 404, { - "error": { - "message": "The model `gpt-4` does not exist or you do not have access to it.", - "type": "invalid_request_error", - "param": null, - "code": "model_not_found" - } -} - -2025-04-17 07:15:30.847 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 404 -2025-04-17 07:15:30.847 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 404 -2025-04-17 07:15:30.859 | ERROR | copywriter:generate_copy:122 - Error generating copy: RetryError[] -2025-04-17 07:15:30.859 | ERROR | copywriter:generate_copy:122 - Error generating copy: RetryError[] -2025-04-17 07:15:36.115 | INFO | vector_store:search:212 - Found 2 matching documents for query -2025-04-17 07:15:36.115 | INFO | vector_store:search:212 - Found 2 matching documents for query -2025-04-17 07:15:36.882 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 404, { - "error": { - "message": "The model `gpt-4` does not exist or you do not have access to it.", - "type": "invalid_request_error", - "param": null, - "code": "model_not_found" - } -} - -2025-04-17 07:15:36.882 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 404, { - "error": { - "message": "The model `gpt-4` does not exist or you do not have access to it.", - "type": "invalid_request_error", - "param": null, - "code": "model_not_found" - } -} - -2025-04-17 07:15:36.885 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 404 -2025-04-17 07:15:36.885 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 404 -2025-04-17 07:15:41.549 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 404, { - "error": { - "message": "The model `gpt-4` does not exist or you do not have access to it.", - "type": "invalid_request_error", - "param": null, - "code": "model_not_found" - } -} - -2025-04-17 07:15:41.549 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 404, { - "error": { - "message": "The model `gpt-4` does not exist or you do not have access to it.", - "type": "invalid_request_error", - "param": null, - "code": "model_not_found" - } -} - -2025-04-17 07:15:41.551 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 404 -2025-04-17 07:15:41.551 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 404 -2025-04-17 07:15:46.258 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 404, { - "error": { - "message": "The model `gpt-4` does not exist or you do not have access to it.", - "type": "invalid_request_error", - "param": null, - "code": "model_not_found" - } -} - -2025-04-17 07:15:46.258 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 404, { - "error": { - "message": "The model `gpt-4` does not exist or you do not have access to it.", - "type": "invalid_request_error", - "param": null, - "code": "model_not_found" - } -} - -2025-04-17 07:15:46.266 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 404 -2025-04-17 07:15:46.266 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 404 -2025-04-17 07:15:46.269 | ERROR | copywriter:generate_copy:122 - Error generating copy: RetryError[] -2025-04-17 07:15:46.269 | ERROR | copywriter:generate_copy:122 - Error generating copy: RetryError[] -2025-04-17 07:15:46.274 | ERROR | main:generate_copy:157 - Error generating copy: RetryError[] -2025-04-17 07:15:46.274 | ERROR | main:generate_copy:157 - Error generating copy: RetryError[] -2025-04-17 07:18:54.993 | INFO | vector_store:search:212 - Found 2 matching documents for query -2025-04-17 07:18:54.993 | INFO | vector_store:search:212 - Found 2 matching documents for query -2025-04-17 07:18:57.991 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 429, { - "error": { - "message": "You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.", - "type": "insufficient_quota", - "param": null, - "code": "insufficient_quota" - } -} - -2025-04-17 07:18:57.991 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 429, { - "error": { - "message": "You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.", - "type": "insufficient_quota", - "param": null, - "code": "insufficient_quota" - } -} - -2025-04-17 07:18:57.993 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 429 -2025-04-17 07:18:57.993 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 429 -2025-04-17 07:19:02.717 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 429, { - "error": { - "message": "You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.", - "type": "insufficient_quota", - "param": null, - "code": "insufficient_quota" - } -} - -2025-04-17 07:19:02.717 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 429, { - "error": { - "message": "You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.", - "type": "insufficient_quota", - "param": null, - "code": "insufficient_quota" - } -} - -2025-04-17 07:19:02.719 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 429 -2025-04-17 07:19:02.719 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 429 -2025-04-17 07:19:07.525 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 429, { - "error": { - "message": "You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.", - "type": "insufficient_quota", - "param": null, - "code": "insufficient_quota" - } -} - -2025-04-17 07:19:07.525 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 429, { - "error": { - "message": "You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.", - "type": "insufficient_quota", - "param": null, - "code": "insufficient_quota" - } -} - -2025-04-17 07:19:07.526 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 429 -2025-04-17 07:19:07.526 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 429 -2025-04-17 07:19:07.527 | ERROR | copywriter:generate_copy:122 - Error generating copy: RetryError[] -2025-04-17 07:19:07.527 | ERROR | copywriter:generate_copy:122 - Error generating copy: RetryError[] -2025-04-17 07:19:12.302 | INFO | vector_store:search:212 - Found 2 matching documents for query -2025-04-17 07:19:12.302 | INFO | vector_store:search:212 - Found 2 matching documents for query -2025-04-17 07:19:13.063 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 429, { - "error": { - "message": "You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.", - "type": "insufficient_quota", - "param": null, - "code": "insufficient_quota" - } -} - -2025-04-17 07:19:13.063 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 429, { - "error": { - "message": "You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.", - "type": "insufficient_quota", - "param": null, - "code": "insufficient_quota" - } -} - -2025-04-17 07:19:13.064 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 429 -2025-04-17 07:19:13.064 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 429 -2025-04-17 07:19:21.192 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 429, { - "error": { - "message": "You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.", - "type": "insufficient_quota", - "param": null, - "code": "insufficient_quota" - } -} - -2025-04-17 07:19:21.192 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 429, { - "error": { - "message": "You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.", - "type": "insufficient_quota", - "param": null, - "code": "insufficient_quota" - } -} - -2025-04-17 07:19:21.199 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 429 -2025-04-17 07:19:21.199 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 429 -2025-04-17 07:19:26.353 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 429, { - "error": { - "message": "You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.", - "type": "insufficient_quota", - "param": null, - "code": "insufficient_quota" - } -} - -2025-04-17 07:19:26.353 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 429, { - "error": { - "message": "You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.", - "type": "insufficient_quota", - "param": null, - "code": "insufficient_quota" - } -} - -2025-04-17 07:19:26.360 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 429 -2025-04-17 07:19:26.360 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 429 -2025-04-17 07:19:26.364 | ERROR | copywriter:generate_copy:122 - Error generating copy: RetryError[] -2025-04-17 07:19:26.364 | ERROR | copywriter:generate_copy:122 - Error generating copy: RetryError[] -2025-04-17 07:19:31.480 | INFO | vector_store:search:212 - Found 2 matching documents for query -2025-04-17 07:19:31.480 | INFO | vector_store:search:212 - Found 2 matching documents for query -2025-04-17 07:19:32.593 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 429, { - "error": { - "message": "You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.", - "type": "insufficient_quota", - "param": null, - "code": "insufficient_quota" - } -} - -2025-04-17 07:19:32.593 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 429, { - "error": { - "message": "You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.", - "type": "insufficient_quota", - "param": null, - "code": "insufficient_quota" - } -} - -2025-04-17 07:19:32.597 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 429 -2025-04-17 07:19:32.597 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 429 -2025-04-17 07:19:37.418 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 429, { - "error": { - "message": "You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.", - "type": "insufficient_quota", - "param": null, - "code": "insufficient_quota" - } -} - -2025-04-17 07:19:37.418 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 429, { - "error": { - "message": "You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.", - "type": "insufficient_quota", - "param": null, - "code": "insufficient_quota" - } -} - -2025-04-17 07:19:37.425 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 429 -2025-04-17 07:19:37.425 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 429 -2025-04-17 07:19:42.179 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 429, { - "error": { - "message": "You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.", - "type": "insufficient_quota", - "param": null, - "code": "insufficient_quota" - } -} - -2025-04-17 07:19:42.179 | ERROR | copywriter:_call_llm_api:161 - OpenAI API error: 429, { - "error": { - "message": "You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.", - "type": "insufficient_quota", - "param": null, - "code": "insufficient_quota" - } -} - -2025-04-17 07:19:42.180 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 429 -2025-04-17 07:19:42.180 | ERROR | copywriter:_call_llm_api:165 - Error calling OpenAI API: OpenAI API error: 429 -2025-04-17 07:19:42.181 | ERROR | copywriter:generate_copy:122 - Error generating copy: RetryError[] -2025-04-17 07:19:42.181 | ERROR | copywriter:generate_copy:122 - Error generating copy: RetryError[] -2025-04-17 07:19:42.182 | ERROR | main:generate_copy:157 - Error generating copy: RetryError[] -2025-04-17 07:19:42.182 | ERROR | main:generate_copy:157 - Error generating copy: RetryError[] -2025-04-17 07:23:26.426 | INFO | vector_store:search:212 - Found 2 matching documents for query -2025-04-17 07:23:26.426 | INFO | vector_store:search:212 - Found 2 matching documents for query -2025-04-17 07:23:41.296 | INFO | copywriter:generate_copy:118 - Generated content with 1092 characters -2025-04-17 07:23:41.296 | INFO | copywriter:generate_copy:118 - Generated content with 1092 characters -2025-04-17 07:23:41.800 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 07:23:41.800 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 07:24:54.053 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-17 07:24:54.053 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-17 07:25:04.622 | INFO | copywriter:generate_copy:118 - Generated content with 1528 characters -2025-04-17 07:25:04.622 | INFO | copywriter:generate_copy:118 - Generated content with 1528 characters -2025-04-17 07:25:05.154 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 07:25:05.154 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 07:36:21.399 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-17 07:36:21.399 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-17 07:36:38.021 | INFO | copywriter:generate_copy:118 - Generated content with 1506 characters -2025-04-17 07:36:38.021 | INFO | copywriter:generate_copy:118 - Generated content with 1506 characters -2025-04-17 07:36:38.691 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 07:36:38.691 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 07:52:38.745 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-17 07:52:38.745 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-17 07:52:43.989 | INFO | copywriter:generate_copy:118 - Generated content with 735 characters -2025-04-17 07:52:43.989 | INFO | copywriter:generate_copy:118 - Generated content with 735 characters -2025-04-17 07:52:44.389 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 07:52:44.389 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 07:53:48.816 | INFO | brand_style:update_style_guidelines:80 - Updated brand style guidelines -2025-04-17 07:53:48.816 | INFO | brand_style:update_style_guidelines:80 - Updated brand style guidelines -2025-04-17 07:53:53.715 | INFO | brand_style:update_style_guidelines:80 - Updated brand style guidelines -2025-04-17 07:53:53.715 | INFO | brand_style:update_style_guidelines:80 - Updated brand style guidelines -2025-04-17 07:57:41.845 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-17 07:57:41.845 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-17 07:57:49.623 | INFO | copywriter:generate_copy:118 - Generated content with 1037 characters -2025-04-17 07:57:49.623 | INFO | copywriter:generate_copy:118 - Generated content with 1037 characters -2025-04-17 07:57:49.997 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 07:57:49.997 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 07:58:37.795 | INFO | copywriter:generate_copy:118 - Generated content with 1229 characters -2025-04-17 07:58:37.795 | INFO | copywriter:generate_copy:118 - Generated content with 1229 characters -2025-04-17 07:58:38.334 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 07:58:38.334 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 08:00:19.501 | INFO | copywriter:improve_copy:221 - Improved content based on feedback -2025-04-17 08:00:19.501 | INFO | copywriter:improve_copy:221 - Improved content based on feedback -2025-04-17 08:02:10.367 | INFO | brand_style:update_style_guidelines:80 - Updated brand style guidelines -2025-04-17 08:02:10.367 | INFO | brand_style:update_style_guidelines:80 - Updated brand style guidelines -2025-04-17 08:03:00.533 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-17 08:03:00.533 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-17 08:03:15.382 | INFO | copywriter:generate_copy:118 - Generated content with 2057 characters -2025-04-17 08:03:15.382 | INFO | copywriter:generate_copy:118 - Generated content with 2057 characters -2025-04-17 08:03:15.964 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 08:03:15.964 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 08:04:49.387 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-17 08:04:49.387 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-17 08:05:19.792 | ERROR | copywriter:_call_llm_api:167 - Error calling Cohere API: -2025-04-17 08:05:19.792 | ERROR | copywriter:_call_llm_api:167 - Error calling Cohere API: -2025-04-17 08:05:33.019 | INFO | copywriter:generate_copy:118 - Generated content with 938 characters -2025-04-17 08:05:33.019 | INFO | copywriter:generate_copy:118 - Generated content with 938 characters -2025-04-17 08:05:33.540 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 08:05:33.540 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 08:08:22.724 | INFO | brand_style:update_style_guidelines:80 - Updated brand style guidelines -2025-04-17 08:08:22.724 | INFO | brand_style:update_style_guidelines:80 - Updated brand style guidelines -2025-04-17 08:10:36.577 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 08:10:36.577 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 09:14:52.646 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-17 09:14:52.646 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-17 09:15:06.876 | INFO | copywriter:generate_copy:118 - Generated content with 775 characters -2025-04-17 09:15:06.876 | INFO | copywriter:generate_copy:118 - Generated content with 775 characters -2025-04-17 09:15:07.331 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 09:15:07.331 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 09:15:45.897 | INFO | copywriter:improve_copy:221 - Improved content based on feedback -2025-04-17 09:15:45.897 | INFO | copywriter:improve_copy:221 - Improved content based on feedback -2025-04-17 09:21:39.757 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-17 09:21:39.757 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-17 09:21:55.770 | INFO | copywriter:generate_copy:118 - Generated content with 1778 characters -2025-04-17 09:21:55.770 | INFO | copywriter:generate_copy:118 - Generated content with 1778 characters -2025-04-17 09:21:56.229 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 09:21:56.229 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 09:23:23.199 | INFO | copywriter:improve_copy:221 - Improved content based on feedback -2025-04-17 09:23:23.199 | INFO | copywriter:improve_copy:221 - Improved content based on feedback -2025-04-17 09:24:27.186 | INFO | copywriter:generate_copy:118 - Generated content with 1353 characters -2025-04-17 09:24:27.186 | INFO | copywriter:generate_copy:118 - Generated content with 1353 characters -2025-04-17 09:24:33.304 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 09:24:33.304 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 09:25:18.277 | INFO | copywriter:improve_copy:221 - Improved content based on feedback -2025-04-17 09:25:18.277 | INFO | copywriter:improve_copy:221 - Improved content based on feedback -2025-04-17 09:27:47.580 | INFO | copywriter:generate_copy:118 - Generated content with 1316 characters -2025-04-17 09:27:47.580 | INFO | copywriter:generate_copy:118 - Generated content with 1316 characters -2025-04-17 09:27:48.175 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 09:27:48.175 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 09:28:28.798 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-17 09:28:28.798 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 00:48:00.063 | INFO | brand_style:update_style_guidelines:80 - Updated brand style guidelines -2025-04-18 00:48:00.063 | INFO | brand_style:update_style_guidelines:80 - Updated brand style guidelines -2025-04-18 01:00:14.884 | ERROR | copywriter:generate_copy:122 - Error generating copy: 'BrandStyleManager' object has no attribute '_get_content_format' -2025-04-18 01:00:14.884 | ERROR | copywriter:generate_copy:122 - Error generating copy: 'BrandStyleManager' object has no attribute '_get_content_format' -2025-04-18 01:00:18.898 | ERROR | copywriter:generate_copy:122 - Error generating copy: 'BrandStyleManager' object has no attribute '_get_content_format' -2025-04-18 01:00:18.898 | ERROR | copywriter:generate_copy:122 - Error generating copy: 'BrandStyleManager' object has no attribute '_get_content_format' -2025-04-18 01:00:22.903 | ERROR | copywriter:generate_copy:122 - Error generating copy: 'BrandStyleManager' object has no attribute '_get_content_format' -2025-04-18 01:00:22.903 | ERROR | copywriter:generate_copy:122 - Error generating copy: 'BrandStyleManager' object has no attribute '_get_content_format' -2025-04-18 01:00:22.904 | ERROR | main:generate_copy:157 - Error generating copy: RetryError[] -2025-04-18 01:00:22.904 | ERROR | main:generate_copy:157 - Error generating copy: RetryError[] -2025-04-18 01:02:05.000 | ERROR | copywriter:generate_copy:122 - Error generating copy: 'BrandStyleManager' object has no attribute '_get_content_format' -2025-04-18 01:02:05.000 | ERROR | copywriter:generate_copy:122 - Error generating copy: 'BrandStyleManager' object has no attribute '_get_content_format' -2025-04-18 01:02:09.006 | ERROR | copywriter:generate_copy:122 - Error generating copy: 'BrandStyleManager' object has no attribute '_get_content_format' -2025-04-18 01:02:09.006 | ERROR | copywriter:generate_copy:122 - Error generating copy: 'BrandStyleManager' object has no attribute '_get_content_format' -2025-04-18 01:02:13.014 | ERROR | copywriter:generate_copy:122 - Error generating copy: 'BrandStyleManager' object has no attribute '_get_content_format' -2025-04-18 01:02:13.014 | ERROR | copywriter:generate_copy:122 - Error generating copy: 'BrandStyleManager' object has no attribute '_get_content_format' -2025-04-18 01:02:13.015 | ERROR | main:generate_copy:157 - Error generating copy: RetryError[] -2025-04-18 01:02:13.015 | ERROR | main:generate_copy:157 - Error generating copy: RetryError[] -2025-04-18 01:14:27.689 | ERROR | copywriter:generate_copy:94 - Error generating copy: 'BrandStyleManager' object has no attribute '_get_content_format' -2025-04-18 01:14:27.689 | ERROR | copywriter:generate_copy:94 - Error generating copy: 'BrandStyleManager' object has no attribute '_get_content_format' -2025-04-18 01:14:31.699 | ERROR | copywriter:generate_copy:94 - Error generating copy: 'BrandStyleManager' object has no attribute '_get_content_format' -2025-04-18 01:14:31.699 | ERROR | copywriter:generate_copy:94 - Error generating copy: 'BrandStyleManager' object has no attribute '_get_content_format' -2025-04-18 01:14:35.702 | ERROR | copywriter:generate_copy:94 - Error generating copy: 'BrandStyleManager' object has no attribute '_get_content_format' -2025-04-18 01:14:35.702 | ERROR | copywriter:generate_copy:94 - Error generating copy: 'BrandStyleManager' object has no attribute '_get_content_format' -2025-04-18 01:14:35.703 | ERROR | main:generate_copy:133 - Error generating copy: RetryError[] -2025-04-18 01:14:35.703 | ERROR | main:generate_copy:133 - Error generating copy: RetryError[] -2025-04-18 01:17:10.288 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 01:17:10.288 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 01:17:16.813 | INFO | copywriter:generate_copy:90 - Generated content with 770 characters -2025-04-18 01:17:16.813 | INFO | copywriter:generate_copy:90 - Generated content with 770 characters -2025-04-18 01:17:17.285 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 01:17:17.285 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 01:18:21.877 | INFO | copywriter:generate_copy:90 - Generated content with 583 characters -2025-04-18 01:18:21.877 | INFO | copywriter:generate_copy:90 - Generated content with 583 characters -2025-04-18 01:18:22.645 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 01:18:22.645 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 01:18:52.465 | INFO | copywriter:generate_copy:90 - Generated content with 791 characters -2025-04-18 01:18:52.465 | INFO | copywriter:generate_copy:90 - Generated content with 791 characters -2025-04-18 01:18:52.905 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 01:18:52.905 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 01:20:01.008 | INFO | copywriter:generate_copy:90 - Generated content with 1695 characters -2025-04-18 01:20:01.008 | INFO | copywriter:generate_copy:90 - Generated content with 1695 characters -2025-04-18 01:20:01.566 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 01:20:01.566 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 01:20:26.004 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 01:20:26.004 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 01:34:03.153 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 01:34:03.153 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 01:34:22.102 | INFO | copywriter:generate_copy:90 - Generated content with 2004 characters -2025-04-18 01:34:22.102 | INFO | copywriter:generate_copy:90 - Generated content with 2004 characters -2025-04-18 01:34:22.524 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 01:34:22.524 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 01:35:24.984 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 01:35:24.984 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 01:35:41.564 | INFO | copywriter:generate_copy:90 - Generated content with 1635 characters -2025-04-18 01:35:41.564 | INFO | copywriter:generate_copy:90 - Generated content with 1635 characters -2025-04-18 01:35:42.025 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 01:35:42.025 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 01:36:43.029 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 01:36:43.029 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 01:36:51.487 | INFO | copywriter:generate_copy:90 - Generated content with 1163 characters -2025-04-18 01:36:51.487 | INFO | copywriter:generate_copy:90 - Generated content with 1163 characters -2025-04-18 01:36:51.866 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 01:36:51.866 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 01:37:35.913 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 01:37:35.913 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 01:38:04.403 | INFO | copywriter:generate_copy:90 - Generated content with 1374 characters -2025-04-18 01:38:04.403 | INFO | copywriter:generate_copy:90 - Generated content with 1374 characters -2025-04-18 01:38:05.011 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 01:38:05.011 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 01:38:44.318 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 01:38:44.318 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 01:39:14.512 | ERROR | copywriter:_call_llm_api:139 - Error calling Cohere API: -2025-04-18 01:39:14.512 | ERROR | copywriter:_call_llm_api:139 - Error calling Cohere API: -2025-04-18 01:39:48.781 | ERROR | copywriter:_call_llm_api:139 - Error calling Cohere API: -2025-04-18 01:39:48.781 | ERROR | copywriter:_call_llm_api:139 - Error calling Cohere API: -2025-04-18 01:40:08.963 | INFO | copywriter:generate_copy:90 - Generated content with 1831 characters -2025-04-18 01:40:08.963 | INFO | copywriter:generate_copy:90 - Generated content with 1831 characters -2025-04-18 01:40:09.921 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 01:40:09.921 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 01:44:03.287 | INFO | copywriter:improve_copy:193 - Improved content based on feedback -2025-04-18 01:44:03.287 | INFO | copywriter:improve_copy:193 - Improved content based on feedback -2025-04-18 01:44:55.624 | INFO | copywriter:improve_copy:193 - Improved content based on feedback -2025-04-18 01:44:55.624 | INFO | copywriter:improve_copy:193 - Improved content based on feedback -2025-04-18 02:07:19.823 | ERROR | copywriter:_call_llm_api:139 - Error calling Cohere API: -2025-04-18 02:07:19.823 | ERROR | copywriter:_call_llm_api:139 - Error calling Cohere API: -2025-04-18 02:07:27.541 | INFO | copywriter:generate_copy:90 - Generated content with 226 characters -2025-04-18 02:07:27.541 | INFO | copywriter:generate_copy:90 - Generated content with 226 characters -2025-04-18 02:07:28.463 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 02:07:28.463 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 02:08:38.495 | INFO | copywriter:generate_copy:90 - Generated content with 239 characters -2025-04-18 02:08:38.495 | INFO | copywriter:generate_copy:90 - Generated content with 239 characters -2025-04-18 02:08:38.965 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 02:08:38.965 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 02:09:04.045 | INFO | copywriter:generate_copy:90 - Generated content with 229 characters -2025-04-18 02:09:04.045 | INFO | copywriter:generate_copy:90 - Generated content with 229 characters -2025-04-18 02:09:04.476 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 02:09:04.476 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 02:09:33.639 | INFO | copywriter:generate_copy:90 - Generated content with 686 characters -2025-04-18 02:09:33.639 | INFO | copywriter:generate_copy:90 - Generated content with 686 characters -2025-04-18 02:09:34.290 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 02:09:34.290 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 02:10:29.627 | INFO | copywriter:generate_copy:90 - Generated content with 383 characters -2025-04-18 02:10:29.627 | INFO | copywriter:generate_copy:90 - Generated content with 383 characters -2025-04-18 02:10:30.087 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 02:10:30.087 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 02:19:13.085 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 02:19:13.085 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 02:19:22.542 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 02:19:22.542 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 02:19:22.543 | INFO | copywriter:generate_copy:90 - Generated content with 963 characters -2025-04-18 02:19:22.543 | INFO | copywriter:generate_copy:90 - Generated content with 963 characters -2025-04-18 02:20:37.281 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 02:20:37.281 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 02:20:37.283 | INFO | copywriter:generate_copy:90 - Generated content with 1278 characters -2025-04-18 02:20:37.283 | INFO | copywriter:generate_copy:90 - Generated content with 1278 characters -2025-04-18 02:21:03.210 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 02:21:03.210 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 02:21:03.212 | INFO | copywriter:generate_copy:90 - Generated content with 1099 characters -2025-04-18 02:21:03.212 | INFO | copywriter:generate_copy:90 - Generated content with 1099 characters -2025-04-18 02:26:17.803 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 02:26:17.803 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 02:26:25.385 | INFO | copywriter:generate_copy:90 - Generated content with 1128 characters -2025-04-18 02:26:25.385 | INFO | copywriter:generate_copy:90 - Generated content with 1128 characters -2025-04-18 02:26:25.823 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 02:26:25.823 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 02:28:15.335 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 02:28:15.335 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 02:28:24.861 | INFO | copywriter:generate_copy:90 - Generated content with 1197 characters -2025-04-18 02:28:24.861 | INFO | copywriter:generate_copy:90 - Generated content with 1197 characters -2025-04-18 02:28:25.253 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 02:28:25.253 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 02:29:27.025 | INFO | copywriter:generate_copy:90 - Generated content with 852 characters -2025-04-18 02:29:27.025 | INFO | copywriter:generate_copy:90 - Generated content with 852 characters -2025-04-18 02:29:27.561 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 02:29:27.561 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 02:30:18.629 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 02:30:18.629 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 02:30:31.984 | INFO | copywriter:generate_copy:90 - Generated content with 1280 characters -2025-04-18 02:30:31.984 | INFO | copywriter:generate_copy:90 - Generated content with 1280 characters -2025-04-18 02:30:32.533 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 02:30:32.533 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 02:50:52.050 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 02:50:52.050 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 02:51:08.753 | INFO | copywriter:generate_copy:90 - Generated content with 1621 characters -2025-04-18 02:51:08.753 | INFO | copywriter:generate_copy:90 - Generated content with 1621 characters -2025-04-18 02:51:09.188 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 02:51:09.188 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 02:54:25.384 | INFO | copywriter:generate_copy:90 - Generated content with 1304 characters -2025-04-18 02:54:25.384 | INFO | copywriter:generate_copy:90 - Generated content with 1304 characters -2025-04-18 02:54:26.186 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 02:54:26.186 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 02:54:46.982 | INFO | copywriter:generate_copy:90 - Generated content with 815 characters -2025-04-18 02:54:46.982 | INFO | copywriter:generate_copy:90 - Generated content with 815 characters -2025-04-18 02:54:47.508 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 02:54:47.508 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 02:55:50.883 | INFO | copywriter:generate_copy:90 - Generated content with 1827 characters -2025-04-18 02:55:50.883 | INFO | copywriter:generate_copy:90 - Generated content with 1827 characters -2025-04-18 02:55:51.314 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 02:55:51.314 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:02:34.882 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 03:02:34.882 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 03:02:55.595 | INFO | copywriter:generate_copy:90 - Generated content with 1571 characters -2025-04-18 03:02:55.595 | INFO | copywriter:generate_copy:90 - Generated content with 1571 characters -2025-04-18 03:02:57.531 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:02:57.531 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:11:46.772 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 03:11:46.772 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 03:12:00.197 | INFO | copywriter:generate_copy:90 - Generated content with 971 characters -2025-04-18 03:12:00.197 | INFO | copywriter:generate_copy:90 - Generated content with 971 characters -2025-04-18 03:12:00.621 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:12:00.621 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:14:42.619 | INFO | copywriter:generate_copy:90 - Generated content with 1146 characters -2025-04-18 03:14:42.619 | INFO | copywriter:generate_copy:90 - Generated content with 1146 characters -2025-04-18 03:14:43.225 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:14:43.225 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:29:08.562 | INFO | copywriter:generate_copy:90 - Generated content with 1423 characters -2025-04-18 03:29:08.562 | INFO | copywriter:generate_copy:90 - Generated content with 1423 characters -2025-04-18 03:29:09.128 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:29:09.128 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:30:04.797 | INFO | copywriter:generate_copy:90 - Generated content with 1475 characters -2025-04-18 03:30:04.797 | INFO | copywriter:generate_copy:90 - Generated content with 1475 characters -2025-04-18 03:30:05.244 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:30:05.244 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:43:52.883 | INFO | copywriter:generate_copy:90 - Generated content with 1123 characters -2025-04-18 03:43:52.883 | INFO | copywriter:generate_copy:90 - Generated content with 1123 characters -2025-04-18 03:44:41.387 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:44:41.387 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:45:23.813 | INFO | copywriter:generate_copy:90 - Generated content with 2004 characters -2025-04-18 03:45:23.813 | INFO | copywriter:generate_copy:90 - Generated content with 2004 characters -2025-04-18 03:45:24.224 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:45:24.224 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:46:06.815 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 03:46:06.815 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 03:46:23.745 | INFO | copywriter:generate_copy:90 - Generated content with 1750 characters -2025-04-18 03:46:23.745 | INFO | copywriter:generate_copy:90 - Generated content with 1750 characters -2025-04-18 03:46:50.243 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:46:50.243 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:49:53.371 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 03:49:53.371 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 03:50:01.024 | INFO | copywriter:generate_copy:90 - Generated content with 1182 characters -2025-04-18 03:50:01.024 | INFO | copywriter:generate_copy:90 - Generated content with 1182 characters -2025-04-18 03:50:01.557 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:50:01.557 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:52:18.453 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 03:52:18.453 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 03:52:25.589 | INFO | copywriter:generate_copy:90 - Generated content with 1040 characters -2025-04-18 03:52:25.589 | INFO | copywriter:generate_copy:90 - Generated content with 1040 characters -2025-04-18 03:52:26.378 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:52:26.378 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:53:03.190 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 03:53:03.190 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 03:53:09.327 | INFO | copywriter:generate_copy:90 - Generated content with 883 characters -2025-04-18 03:53:09.327 | INFO | copywriter:generate_copy:90 - Generated content with 883 characters -2025-04-18 03:53:09.798 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:53:09.798 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:54:12.575 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 03:54:12.575 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 03:54:29.054 | INFO | copywriter:generate_copy:90 - Generated content with 1439 characters -2025-04-18 03:54:29.054 | INFO | copywriter:generate_copy:90 - Generated content with 1439 characters -2025-04-18 03:54:29.441 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:54:29.441 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:55:16.974 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 03:55:16.974 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 03:55:26.092 | INFO | copywriter:generate_copy:90 - Generated content with 1243 characters -2025-04-18 03:55:26.092 | INFO | copywriter:generate_copy:90 - Generated content with 1243 characters -2025-04-18 03:55:26.505 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:55:26.505 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:56:15.753 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 03:56:15.753 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 03:56:24.050 | INFO | copywriter:generate_copy:90 - Generated content with 1189 characters -2025-04-18 03:56:24.050 | INFO | copywriter:generate_copy:90 - Generated content with 1189 characters -2025-04-18 03:56:53.669 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:56:53.669 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:59:44.352 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 03:59:44.352 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 03:59:44.355 | INFO | copywriter:generate_copy:90 - Generated content with 906 characters -2025-04-18 03:59:44.355 | INFO | copywriter:generate_copy:90 - Generated content with 906 characters -2025-04-18 03:59:45.100 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 03:59:45.100 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 04:00:08.827 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 04:00:08.827 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 04:00:21.413 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 04:00:21.413 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 04:00:21.413 | INFO | copywriter:generate_copy:90 - Generated content with 1350 characters -2025-04-18 04:00:21.413 | INFO | copywriter:generate_copy:90 - Generated content with 1350 characters -2025-04-18 04:00:21.848 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 04:00:21.848 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 04:01:23.133 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 04:01:23.133 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 04:01:23.138 | INFO | copywriter:generate_copy:90 - Generated content with 1525 characters -2025-04-18 04:01:23.138 | INFO | copywriter:generate_copy:90 - Generated content with 1525 characters -2025-04-18 04:01:23.727 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 04:01:23.727 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 04:02:32.346 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines -2025-04-18 04:02:32.346 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines -2025-04-18 04:03:46.372 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines -2025-04-18 04:03:46.372 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines -2025-04-18 04:05:53.862 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines -2025-04-18 04:05:53.862 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines -2025-04-18 04:06:28.073 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines -2025-04-18 04:06:28.073 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines -2025-04-18 04:10:51.448 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 04:10:51.448 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 04:11:15.704 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 04:11:15.704 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 04:11:15.705 | INFO | copywriter:generate_copy:90 - Generated content with 1647 characters -2025-04-18 04:11:15.705 | INFO | copywriter:generate_copy:90 - Generated content with 1647 characters -2025-04-18 04:11:16.128 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 04:11:16.128 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 04:19:51.595 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 04:19:51.595 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 04:20:10.910 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 04:20:10.910 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 04:20:10.910 | INFO | copywriter:generate_copy:90 - Generated content with 1248 characters -2025-04-18 04:20:10.910 | INFO | copywriter:generate_copy:90 - Generated content with 1248 characters -2025-04-18 04:20:11.454 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 04:20:11.454 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 04:21:29.147 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 04:21:29.147 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 04:21:59.320 | ERROR | copywriter:_call_llm_api:139 - Error calling Cohere API: -2025-04-18 04:21:59.320 | ERROR | copywriter:_call_llm_api:139 - Error calling Cohere API: -2025-04-18 04:22:36.137 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 04:22:36.137 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 04:22:36.139 | INFO | copywriter:generate_copy:90 - Generated content with 3409 characters -2025-04-18 04:22:36.139 | INFO | copywriter:generate_copy:90 - Generated content with 3409 characters -2025-04-18 04:22:36.945 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 04:22:36.945 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 16:07:13.340 | ERROR | main:list_training_data:268 - Error listing training data: Column expression, FROM clause, or other columns clause element expected, got [Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None)]. Did you mean to say select(Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None))? -2025-04-18 16:07:13.340 | ERROR | main:list_training_data:268 - Error listing training data: Column expression, FROM clause, or other columns clause element expected, got [Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None)]. Did you mean to say select(Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None))? -2025-04-18 16:08:07.769 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 16:08:07.769 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 16:08:07.772 | INFO | copywriter:generate_copy:90 - Generated content with 651 characters -2025-04-18 16:08:07.772 | INFO | copywriter:generate_copy:90 - Generated content with 651 characters -2025-04-18 16:08:09.329 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 16:08:09.329 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 16:08:47.520 | ERROR | main:list_training_data:268 - Error listing training data: Column expression, FROM clause, or other columns clause element expected, got [Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None)]. Did you mean to say select(Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None))? -2025-04-18 16:08:47.520 | ERROR | main:list_training_data:268 - Error listing training data: Column expression, FROM clause, or other columns clause element expected, got [Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None)]. Did you mean to say select(Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None))? -2025-04-18 16:09:56.223 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 16:09:56.223 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 16:10:00.678 | ERROR | main:list_training_data:268 - Error listing training data: Column expression, FROM clause, or other columns clause element expected, got [Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None)]. Did you mean to say select(Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None))? -2025-04-18 16:10:00.678 | ERROR | main:list_training_data:268 - Error listing training data: Column expression, FROM clause, or other columns clause element expected, got [Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None)]. Did you mean to say select(Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None))? -2025-04-18 16:14:28.677 | ERROR | main:list_training_data:268 - Error listing training data: Column expression, FROM clause, or other columns clause element expected, got [Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None)]. Did you mean to say select(Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None))? -2025-04-18 16:14:28.677 | ERROR | main:list_training_data:268 - Error listing training data: Column expression, FROM clause, or other columns clause element expected, got [Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None)]. Did you mean to say select(Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None))? -2025-04-18 16:16:04.245 | ERROR | main:list_training_data:268 - Error listing training data: Column expression, FROM clause, or other columns clause element expected, got [Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None)]. Did you mean to say select(Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None))? -2025-04-18 16:16:04.245 | ERROR | main:list_training_data:268 - Error listing training data: Column expression, FROM clause, or other columns clause element expected, got [Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None)]. Did you mean to say select(Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None))? -2025-04-18 16:19:37.169 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 16:19:37.169 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 16:22:09.127 | WARNING | vector_store:delete_document:246 - Invalid document ID: 1 -2025-04-18 16:22:09.127 | WARNING | vector_store:delete_document:246 - Invalid document ID: 1 -2025-04-18 16:22:27.719 | WARNING | vector_store:delete_document:246 - Invalid document ID: 2 -2025-04-18 16:22:27.719 | WARNING | vector_store:delete_document:246 - Invalid document ID: 2 -2025-04-18 16:30:22.904 | INFO | vector_store:search:212 - Found 1 matching documents for query -2025-04-18 16:30:22.904 | INFO | vector_store:search:212 - Found 1 matching documents for query -2025-04-18 16:30:31.859 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 16:30:31.859 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 16:30:31.859 | INFO | copywriter:generate_copy:90 - Generated content with 604 characters -2025-04-18 16:30:31.859 | INFO | copywriter:generate_copy:90 - Generated content with 604 characters -2025-04-18 16:30:32.289 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 16:30:32.289 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 16:32:33.304 | INFO | vector_store:search:212 - Found 2 matching documents for query -2025-04-18 16:32:33.304 | INFO | vector_store:search:212 - Found 2 matching documents for query -2025-04-18 16:32:42.281 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 16:32:42.281 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 16:32:42.283 | INFO | copywriter:generate_copy:90 - Generated content with 632 characters -2025-04-18 16:32:42.283 | INFO | copywriter:generate_copy:90 - Generated content with 632 characters -2025-04-18 16:32:42.750 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 16:32:42.750 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 17:12:33.909 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 17:12:33.909 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 17:12:33.912 | INFO | copywriter:generate_copy:90 - Generated content with 2740 characters -2025-04-18 17:12:33.912 | INFO | copywriter:generate_copy:90 - Generated content with 2740 characters -2025-04-18 17:12:37.538 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 17:12:37.538 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 17:13:04.600 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 17:13:04.600 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 17:13:17.051 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 17:13:17.051 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 17:13:17.052 | INFO | copywriter:generate_copy:90 - Generated content with 577 characters -2025-04-18 17:13:17.052 | INFO | copywriter:generate_copy:90 - Generated content with 577 characters -2025-04-18 17:13:17.652 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 17:13:17.652 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 17:14:08.039 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 17:14:08.039 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 17:14:33.729 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 17:14:33.729 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 17:14:33.741 | INFO | copywriter:generate_copy:90 - Generated content with 1717 characters -2025-04-18 17:14:33.741 | INFO | copywriter:generate_copy:90 - Generated content with 1717 characters -2025-04-18 17:14:34.184 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 17:14:34.184 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 17:28:38.798 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 17:28:38.798 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 17:28:38.800 | INFO | copywriter:generate_copy:90 - Generated content with 1962 characters -2025-04-18 17:28:38.800 | INFO | copywriter:generate_copy:90 - Generated content with 1962 characters -2025-04-18 17:28:39.569 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 17:28:39.569 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 17:29:13.466 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 17:29:13.466 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 17:29:30.844 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 17:29:30.844 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 17:29:30.845 | INFO | copywriter:generate_copy:90 - Generated content with 1416 characters -2025-04-18 17:29:30.845 | INFO | copywriter:generate_copy:90 - Generated content with 1416 characters -2025-04-18 17:29:31.237 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 17:29:31.237 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 17:31:18.658 | ERROR | main:get_user_query:429 - Error getting user query: 404: Query with timestamp 2025-04-18T16:32:42.751434 not found -2025-04-18 17:31:18.658 | ERROR | main:get_user_query:429 - Error getting user query: 404: Query with timestamp 2025-04-18T16:32:42.751434 not found -2025-04-18 17:31:40.805 | ERROR | main:get_user_query:429 - Error getting user query: 404: Query with timestamp "2025-04-18T16:32:42.751434" not found -2025-04-18 17:31:40.805 | ERROR | main:get_user_query:429 - Error getting user query: 404: Query with timestamp "2025-04-18T16:32:42.751434" not found -2025-04-18 17:32:24.114 | ERROR | main:get_user_query:429 - Error getting user query: 404: Query with timestamp 2025-04-18T17:12:37.541148 not found -2025-04-18 17:32:24.114 | ERROR | main:get_user_query:429 - Error getting user query: 404: Query with timestamp 2025-04-18T17:12:37.541148 not found -2025-04-18 17:34:18.118 | ERROR | main:get_user_query:429 - Error getting user query: 404: Query with timestamp 20250418T171237541148 not found -2025-04-18 17:34:18.118 | ERROR | main:get_user_query:429 - Error getting user query: 404: Query with timestamp 20250418T171237541148 not found -2025-04-18 17:34:40.614 | ERROR | main:get_user_query:429 - Error getting user query: 404: Query with timestamp 20250418T035226 not found -2025-04-18 17:34:40.614 | ERROR | main:get_user_query:429 - Error getting user query: 404: Query with timestamp 20250418T035226 not found -2025-04-18 17:35:36.594 | ERROR | main:get_user_query:429 - Error getting user query: 404: Query with timestamp 20250418171317. not found -2025-04-18 17:35:36.594 | ERROR | main:get_user_query:429 - Error getting user query: 404: Query with timestamp 20250418171317. not found -2025-04-18 17:36:13.263 | ERROR | main:get_user_query:429 - Error getting user query: 404: Query with timestamp 2025-04-18T17:13:17 not found -2025-04-18 17:36:13.263 | ERROR | main:get_user_query:429 - Error getting user query: 404: Query with timestamp 2025-04-18T17:13:17 not found -2025-04-18 17:36:23.158 | ERROR | main:get_user_query:429 - Error getting user query: 404: Query with timestamp 20250418T171317 not found -2025-04-18 17:36:23.158 | ERROR | main:get_user_query:429 - Error getting user query: 404: Query with timestamp 20250418T171317 not found -2025-04-18 17:40:24.503 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 17:40:24.503 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 17:40:54.614 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 17:40:54.614 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 17:40:54.615 | INFO | copywriter:generate_copy:90 - Generated content with 2080 characters -2025-04-18 17:40:54.615 | INFO | copywriter:generate_copy:90 - Generated content with 2080 characters -2025-04-18 17:40:55.135 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 17:40:55.135 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 17:41:16.349 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 17:41:16.349 | INFO | vector_store:search:212 - Found 3 matching documents for query -2025-04-18 17:41:55.042 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 17:41:55.042 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 17:41:55.046 | INFO | copywriter:generate_copy:90 - Generated content with 2070 characters -2025-04-18 17:41:55.046 | INFO | copywriter:generate_copy:90 - Generated content with 2070 characters -2025-04-18 17:41:55.458 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 17:41:55.458 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 18:11:18.236 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines -2025-04-18 18:11:18.236 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines -2025-04-18 18:11:40.648 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines -2025-04-18 18:11:40.648 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines -2025-04-18 18:13:01.347 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines -2025-04-18 18:13:01.347 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines -2025-04-18 18:36:18.449 | ERROR | main:delete_user_query:461 - Error deleting user query: 404: Query with timestamp 20250418164155 not found -2025-04-18 18:36:18.449 | ERROR | main:delete_user_query:461 - Error deleting user query: 404: Query with timestamp 20250418164155 not found -2025-04-18 18:36:43.730 | ERROR | main:delete_user_query:461 - Error deleting user query: 404: Query with timestamp 20250418161237 not found -2025-04-18 18:36:43.730 | ERROR | main:delete_user_query:461 - Error deleting user query: 404: Query with timestamp 20250418161237 not found -2025-04-18 18:37:32.259 | ERROR | copywriter:_call_llm_api:139 - Error calling Cohere API: -2025-04-18 18:37:32.259 | ERROR | copywriter:_call_llm_api:139 - Error calling Cohere API: -2025-04-18 18:38:06.509 | ERROR | copywriter:_call_llm_api:139 - Error calling Cohere API: -2025-04-18 18:38:06.509 | ERROR | copywriter:_call_llm_api:139 - Error calling Cohere API: -2025-04-18 18:38:48.267 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 18:38:48.267 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 18:38:48.272 | INFO | copywriter:generate_copy:90 - Generated content with 3812 characters -2025-04-18 18:38:48.272 | INFO | copywriter:generate_copy:90 - Generated content with 3812 characters -2025-04-18 18:38:51.235 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 18:38:51.235 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 18:39:59.364 | ERROR | main:get_user_query:437 - Error getting user query: 404: Query with timestamp 20250418173851 not found -2025-04-18 18:39:59.364 | ERROR | main:get_user_query:437 - Error getting user query: 404: Query with timestamp 20250418173851 not found -2025-04-18 18:40:23.978 | ERROR | main:get_user_query:437 - Error getting user query: 404: Query with timestamp 20250418173851 not found -2025-04-18 18:40:23.978 | ERROR | main:get_user_query:437 - Error getting user query: 404: Query with timestamp 20250418173851 not found -2025-04-18 18:43:01.011 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 18:43:01.011 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 18:43:07.295 | ERROR | main:get_training_data:306 - Error retrieving training data: Column expression, FROM clause, or other columns clause element expected, got [Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None)]. Did you mean to say select(Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None))? -2025-04-18 18:43:07.295 | ERROR | main:get_training_data:306 - Error retrieving training data: Column expression, FROM clause, or other columns clause element expected, got [Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None)]. Did you mean to say select(Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None))? -2025-04-18 18:44:21.955 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 18:44:21.955 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 18:44:28.293 | INFO | vector_store:delete_document:256 - Marked document 2 as deleted -2025-04-18 18:44:28.293 | INFO | vector_store:delete_document:256 - Marked document 2 as deleted -2025-04-18 18:44:32.713 | ERROR | main:get_training_data:306 - Error retrieving training data: Column expression, FROM clause, or other columns clause element expected, got [Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None)]. Did you mean to say select(Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None))? -2025-04-18 18:44:32.713 | ERROR | main:get_training_data:306 - Error retrieving training data: Column expression, FROM clause, or other columns clause element expected, got [Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None)]. Did you mean to say select(Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None))? -2025-04-18 18:47:11.756 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 18:47:11.756 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 18:47:12.100 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 18:47:12.100 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 18:47:21.198 | ERROR | main:get_training_data:306 - Error retrieving training data: Column expression, FROM clause, or other columns clause element expected, got [Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None)]. Did you mean to say select(Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None))? -2025-04-18 18:47:21.198 | ERROR | main:get_training_data:306 - Error retrieving training data: Column expression, FROM clause, or other columns clause element expected, got [Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None)]. Did you mean to say select(Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None))? -2025-04-18 18:48:22.623 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 18:48:22.623 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 18:48:22.636 | INFO | copywriter:generate_copy:90 - Generated content with 1802 characters -2025-04-18 18:48:22.636 | INFO | copywriter:generate_copy:90 - Generated content with 1802 characters -2025-04-18 18:48:23.411 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 18:48:23.411 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 18:48:46.063 | ERROR | main:delete_user_query:461 - Error deleting user query: 404: Query with timestamp 20250418153242 not found -2025-04-18 18:48:46.063 | ERROR | main:delete_user_query:461 - Error deleting user query: 404: Query with timestamp 20250418153242 not found -2025-04-18 18:49:03.774 | INFO | vector_store:delete_document:256 - Marked document 3 as deleted -2025-04-18 18:49:03.774 | INFO | vector_store:delete_document:256 - Marked document 3 as deleted -2025-04-18 18:49:06.850 | INFO | vector_store:delete_document:256 - Marked document 2 as deleted -2025-04-18 18:49:06.850 | INFO | vector_store:delete_document:256 - Marked document 2 as deleted -2025-04-18 18:49:11.443 | INFO | vector_store:delete_document:256 - Marked document 1 as deleted -2025-04-18 18:49:11.443 | INFO | vector_store:delete_document:256 - Marked document 1 as deleted -2025-04-18 18:51:53.774 | ERROR | main:add_training_data:214 - Error adding training data: no such table: training_data -2025-04-18 18:51:53.774 | ERROR | main:add_training_data:214 - Error adding training data: no such table: training_data -2025-04-18 18:52:03.005 | ERROR | main:add_training_data:214 - Error adding training data: no such table: training_data -2025-04-18 18:52:03.005 | ERROR | main:add_training_data:214 - Error adding training data: no such table: training_data -2025-04-18 18:52:49.739 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 18:52:49.739 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 18:52:55.266 | INFO | vector_store:delete_document:256 - Marked document 1 as deleted -2025-04-18 18:52:55.266 | INFO | vector_store:delete_document:256 - Marked document 1 as deleted -2025-04-18 18:56:30.386 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 18:56:30.386 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 18:56:30.388 | INFO | copywriter:generate_copy:90 - Generated content with 1580 characters -2025-04-18 18:56:30.388 | INFO | copywriter:generate_copy:90 - Generated content with 1580 characters -2025-04-18 18:56:30.997 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 18:56:30.997 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 18:57:15.893 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 18:57:15.893 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 18:58:37.976 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 18:58:37.976 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions -2025-04-18 18:58:37.980 | INFO | copywriter:generate_copy:90 - Generated content with 579 characters -2025-04-18 18:58:37.980 | INFO | copywriter:generate_copy:90 - Generated content with 579 characters -2025-04-18 18:58:38.798 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 18:58:38.798 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store -2025-04-18 18:59:13.625 | INFO | copywriter:improve_copy:224 - Improved content based on feedback -2025-04-18 18:59:13.625 | INFO | copywriter:improve_copy:224 - Improved content based on feedback -2025-04-18 18:59:58.642 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines -2025-04-18 18:59:58.642 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines -2025-04-18 19:00:09.875 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines -2025-04-18 19:00:09.875 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines -2025-04-18 19:00:20.643 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines -2025-04-18 19:00:20.643 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines -2025-04-18 19:05:10.093 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines -2025-04-18 19:05:10.093 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines +2025-04-21 15:34:55.240 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions +2025-04-21 15:34:55.240 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions +2025-04-21 15:34:55.249 | INFO | copywriter:generate_copy:90 - Generated content with 1525 characters +2025-04-21 15:34:55.249 | INFO | copywriter:generate_copy:90 - Generated content with 1525 characters +2025-04-21 15:34:57.296 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store +2025-04-21 15:34:57.296 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store +2025-04-21 15:38:32.741 | ERROR | main:get_user_query:437 - Error getting user query: 404: Query with timestamp 20250421143457 not found +2025-04-21 15:38:32.741 | ERROR | main:get_user_query:437 - Error getting user query: 404: Query with timestamp 20250421143457 not found +2025-04-21 15:39:36.125 | ERROR | main:delete_user_query:461 - Error deleting user query: 404: Query with timestamp 20250418175631 not found +2025-04-21 15:39:36.125 | ERROR | main:delete_user_query:461 - Error deleting user query: 404: Query with timestamp 20250418175631 not found +2025-04-21 15:39:46.658 | ERROR | main:delete_user_query:461 - Error deleting user query: 404: Query with timestamp 20250421142257 not found +2025-04-21 15:39:46.658 | ERROR | main:delete_user_query:461 - Error deleting user query: 404: Query with timestamp 20250421142257 not found +2025-04-21 15:44:00.355 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions +2025-04-21 15:44:00.355 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions +2025-04-21 15:44:00.370 | INFO | copywriter:generate_copy:90 - Generated content with 1582 characters +2025-04-21 15:44:00.370 | INFO | copywriter:generate_copy:90 - Generated content with 1582 characters +2025-04-21 15:44:01.801 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store +2025-04-21 15:44:01.801 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store +2025-04-21 15:45:45.462 | INFO | vector_store:search:212 - Found 2 matching documents for query +2025-04-21 15:45:45.462 | INFO | vector_store:search:212 - Found 2 matching documents for query +2025-04-21 15:46:00.302 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions +2025-04-21 15:46:00.302 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions +2025-04-21 15:46:00.306 | INFO | copywriter:generate_copy:90 - Generated content with 1446 characters +2025-04-21 15:46:00.306 | INFO | copywriter:generate_copy:90 - Generated content with 1446 characters +2025-04-21 15:46:00.942 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store +2025-04-21 15:46:00.942 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store +2025-04-21 16:00:18.779 | INFO | copywriter:_generate_headline_suggestions:194 - Generated 3 headline suggestions +2025-04-21 16:00:18.779 | INFO | copywriter:_generate_headline_suggestions:194 - Generated 3 headline suggestions +2025-04-21 16:00:18.794 | INFO | copywriter:generate_copy:96 - Generated content with 2146 characters +2025-04-21 16:00:18.794 | INFO | copywriter:generate_copy:96 - Generated content with 2146 characters +2025-04-21 16:00:23.811 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 16:00:23.811 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 16:11:10.788 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:11:10.788 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:11:16.235 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:11:16.235 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:11:16.240 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:11:16.240 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:11:16.240 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:11:16.240 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:11:16.241 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:11:16.241 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:11:16.241 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:11:16.241 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:11:16.242 | INFO | copywriter:_generate_headline_suggestions:201 - Generated 3 headline suggestions +2025-04-21 16:11:16.242 | INFO | copywriter:_generate_headline_suggestions:201 - Generated 3 headline suggestions +2025-04-21 16:11:16.242 | INFO | copywriter:generate_copy:99 - Generated content with 1447 characters +2025-04-21 16:11:16.242 | INFO | copywriter:generate_copy:99 - Generated content with 1447 characters +2025-04-21 16:11:17.068 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 16:11:17.068 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 16:13:36.551 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:13:36.551 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:13:41.502 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:13:41.502 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:13:41.503 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:13:41.503 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:13:41.503 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:13:41.503 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:13:41.503 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:13:41.503 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:13:41.504 | INFO | copywriter:_generate_headline_suggestions:201 - Generated 3 headline suggestions +2025-04-21 16:13:41.504 | INFO | copywriter:_generate_headline_suggestions:201 - Generated 3 headline suggestions +2025-04-21 16:13:41.504 | INFO | copywriter:generate_copy:99 - Generated content with 745 characters +2025-04-21 16:13:41.504 | INFO | copywriter:generate_copy:99 - Generated content with 745 characters +2025-04-21 16:13:42.012 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 16:13:42.012 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 16:14:14.319 | ERROR | main:delete_user_query:461 - Error deleting user query: 404: Query with timestamp 20250421151342 not found +2025-04-21 16:14:14.319 | ERROR | main:delete_user_query:461 - Error deleting user query: 404: Query with timestamp 20250421151342 not found +2025-04-21 16:14:47.616 | INFO | copywriter:generate_copy:47 - Searching for similar content to reference for prompt: Generate two short Google Search ad texts for the ... +2025-04-21 16:14:47.616 | INFO | copywriter:generate_copy:47 - Searching for similar content to reference for prompt: Generate two short Google Search ad texts for the ... +2025-04-21 16:14:47.622 | INFO | vector_store:search:163 - Searching vector store with query: Generate two short Google Search ad texts for the ... (top_k=3) +2025-04-21 16:14:47.622 | INFO | vector_store:search:163 - Searching vector store with query: Generate two short Google Search ad texts for the ... (top_k=3) +2025-04-21 16:14:47.624 | INFO | vector_store:search:169 - Vector store contains 13 documents +2025-04-21 16:14:47.624 | INFO | vector_store:search:169 - Vector store contains 13 documents +2025-04-21 16:14:51.728 | INFO | vector_store:search:221 - Found 3 matching documents for query +2025-04-21 16:14:51.728 | INFO | vector_store:search:221 - Found 3 matching documents for query +2025-04-21 16:14:51.729 | INFO | copywriter:generate_copy:51 - Found 3 similar content items to reference +2025-04-21 16:14:51.729 | INFO | copywriter:generate_copy:51 - Found 3 similar content items to reference +2025-04-21 16:15:01.679 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:15:01.679 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:15:05.208 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:15:05.208 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:15:05.208 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:15:05.208 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:15:05.209 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:15:05.209 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:15:05.209 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:15:05.209 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:15:05.211 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:15:05.211 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:15:05.212 | INFO | copywriter:_generate_headline_suggestions:201 - Generated 3 headline suggestions +2025-04-21 16:15:05.212 | INFO | copywriter:_generate_headline_suggestions:201 - Generated 3 headline suggestions +2025-04-21 16:15:05.212 | INFO | copywriter:generate_copy:99 - Generated content with 843 characters +2025-04-21 16:15:05.212 | INFO | copywriter:generate_copy:99 - Generated content with 843 characters +2025-04-21 16:15:05.697 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 16:15:05.697 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 16:17:18.505 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 16:17:18.505 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 16:17:23.989 | ERROR | main:get_training_data:306 - Error retrieving training data: Column expression, FROM clause, or other columns clause element expected, got [Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None)]. Did you mean to say select(Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None))? +2025-04-21 16:17:23.989 | ERROR | main:get_training_data:306 - Error retrieving training data: Column expression, FROM clause, or other columns clause element expected, got [Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None)]. Did you mean to say select(Table('training_data', MetaData(), Column('id', Integer(), table=, primary_key=True, nullable=False), Column('content', String(), table=, nullable=False), Column('content_type', String(), table=, nullable=False), Column('metadata', JSON(), table=, nullable=False), Column('added_at', DateTime(), table=, nullable=False, default=CallableColumnDefault()), Column('is_training_data', Boolean(), table=, nullable=False, default=ScalarElementColumnDefault(True)), schema=None))? +2025-04-21 16:18:27.027 | INFO | copywriter:generate_copy:47 - Searching for similar content to reference for prompt: Generate two short Google Search ad texts for the ... +2025-04-21 16:18:27.027 | INFO | copywriter:generate_copy:47 - Searching for similar content to reference for prompt: Generate two short Google Search ad texts for the ... +2025-04-21 16:18:27.033 | INFO | vector_store:search:163 - Searching vector store with query: Generate two short Google Search ad texts for the ... (top_k=3) +2025-04-21 16:18:27.033 | INFO | vector_store:search:163 - Searching vector store with query: Generate two short Google Search ad texts for the ... (top_k=3) +2025-04-21 16:18:27.036 | INFO | vector_store:search:169 - Vector store contains 15 documents +2025-04-21 16:18:27.036 | INFO | vector_store:search:169 - Vector store contains 15 documents +2025-04-21 16:18:29.029 | INFO | vector_store:search:221 - Found 3 matching documents for query +2025-04-21 16:18:29.029 | INFO | vector_store:search:221 - Found 3 matching documents for query +2025-04-21 16:18:29.029 | INFO | copywriter:generate_copy:51 - Found 3 similar content items to reference +2025-04-21 16:18:29.029 | INFO | copywriter:generate_copy:51 - Found 3 similar content items to reference +2025-04-21 16:18:36.563 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:18:36.563 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:18:41.121 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:18:41.121 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:18:41.122 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:18:41.122 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:18:41.122 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:18:41.122 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:18:41.122 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:18:41.122 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:18:41.123 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:18:41.123 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:18:41.123 | INFO | copywriter:_generate_headline_suggestions:201 - Generated 3 headline suggestions +2025-04-21 16:18:41.123 | INFO | copywriter:_generate_headline_suggestions:201 - Generated 3 headline suggestions +2025-04-21 16:18:41.123 | INFO | copywriter:generate_copy:99 - Generated content with 901 characters +2025-04-21 16:18:41.123 | INFO | copywriter:generate_copy:99 - Generated content with 901 characters +2025-04-21 16:18:42.126 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 16:18:42.126 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 16:20:39.321 | INFO | copywriter:generate_copy:47 - Searching for similar content to reference for prompt: Create a high-coverting sales email for a digital ... +2025-04-21 16:20:39.321 | INFO | copywriter:generate_copy:47 - Searching for similar content to reference for prompt: Create a high-coverting sales email for a digital ... +2025-04-21 16:20:39.335 | INFO | vector_store:search:163 - Searching vector store with query: Create a high-coverting sales email for a digital ... (top_k=3) +2025-04-21 16:20:39.335 | INFO | vector_store:search:163 - Searching vector store with query: Create a high-coverting sales email for a digital ... (top_k=3) +2025-04-21 16:20:39.339 | INFO | vector_store:search:169 - Vector store contains 16 documents +2025-04-21 16:20:39.339 | INFO | vector_store:search:169 - Vector store contains 16 documents +2025-04-21 16:20:41.978 | INFO | vector_store:search:221 - Found 3 matching documents for query +2025-04-21 16:20:41.978 | INFO | vector_store:search:221 - Found 3 matching documents for query +2025-04-21 16:20:41.979 | INFO | copywriter:generate_copy:51 - Found 3 similar content items to reference +2025-04-21 16:20:41.979 | INFO | copywriter:generate_copy:51 - Found 3 similar content items to reference +2025-04-21 16:21:18.404 | ERROR | copywriter:_call_llm_api:148 - Error calling Cohere API: +2025-04-21 16:21:18.404 | ERROR | copywriter:_call_llm_api:148 - Error calling Cohere API: +2025-04-21 16:21:34.274 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:21:34.274 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:21:41.016 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:21:41.016 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:21:41.016 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:21:41.016 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:21:41.016 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:21:41.016 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:21:41.017 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:21:41.017 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:21:41.017 | INFO | copywriter:_generate_headline_suggestions:201 - Generated 3 headline suggestions +2025-04-21 16:21:41.017 | INFO | copywriter:_generate_headline_suggestions:201 - Generated 3 headline suggestions +2025-04-21 16:21:41.017 | INFO | copywriter:generate_copy:99 - Generated content with 1481 characters +2025-04-21 16:21:41.017 | INFO | copywriter:generate_copy:99 - Generated content with 1481 characters +2025-04-21 16:21:41.519 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 16:21:41.519 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 16:22:55.193 | INFO | vector_store:delete_document:265 - Marked document 1 as deleted +2025-04-21 16:22:55.193 | INFO | vector_store:delete_document:265 - Marked document 1 as deleted +2025-04-21 16:29:00.997 | INFO | copywriter:generate_copy:47 - Searching for similar content to reference for prompt: Create a high-coverting sales email for a digital ... +2025-04-21 16:29:00.997 | INFO | copywriter:generate_copy:47 - Searching for similar content to reference for prompt: Create a high-coverting sales email for a digital ... +2025-04-21 16:29:01.003 | INFO | vector_store:search:163 - Searching vector store with query: Create a high-coverting sales email for a digital ... (top_k=3) +2025-04-21 16:29:01.003 | INFO | vector_store:search:163 - Searching vector store with query: Create a high-coverting sales email for a digital ... (top_k=3) +2025-04-21 16:29:01.007 | INFO | vector_store:search:169 - Vector store contains 17 documents +2025-04-21 16:29:01.007 | INFO | vector_store:search:169 - Vector store contains 17 documents +2025-04-21 16:29:05.853 | INFO | vector_store:search:221 - Found 3 matching documents for query +2025-04-21 16:29:05.853 | INFO | vector_store:search:221 - Found 3 matching documents for query +2025-04-21 16:29:05.855 | INFO | copywriter:generate_copy:51 - Found 3 similar content items to reference +2025-04-21 16:29:05.855 | INFO | copywriter:generate_copy:51 - Found 3 similar content items to reference +2025-04-21 16:29:24.095 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:29:24.095 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:29:24.106 | INFO | copywriter:_format_content_structure:385 - Formatted content structure with proper paragraphs and headings +2025-04-21 16:29:24.106 | INFO | copywriter:_format_content_structure:385 - Formatted content structure with proper paragraphs and headings +2025-04-21 16:29:30.427 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:29:30.427 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:29:30.449 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:29:30.449 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:29:30.450 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:29:30.450 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:29:30.491 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:29:30.491 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:29:30.497 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:29:30.497 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:29:30.498 | INFO | copywriter:_generate_headline_suggestions:205 - Generated 3 headline suggestions +2025-04-21 16:29:30.498 | INFO | copywriter:_generate_headline_suggestions:205 - Generated 3 headline suggestions +2025-04-21 16:29:30.498 | INFO | copywriter:generate_copy:103 - Generated content with 2087 characters +2025-04-21 16:29:30.498 | INFO | copywriter:generate_copy:103 - Generated content with 2087 characters +2025-04-21 16:29:31.871 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 16:29:31.871 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 16:31:15.444 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:31:15.444 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:31:15.453 | INFO | copywriter:_format_content_structure:385 - Formatted content structure with proper paragraphs and headings +2025-04-21 16:31:15.453 | INFO | copywriter:_format_content_structure:385 - Formatted content structure with proper paragraphs and headings +2025-04-21 16:31:20.673 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:31:20.673 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:31:20.674 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:31:20.674 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:31:20.675 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:31:20.675 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:31:20.676 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:31:20.676 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:31:20.677 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:31:20.677 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:31:20.677 | INFO | copywriter:_generate_headline_suggestions:205 - Generated 3 headline suggestions +2025-04-21 16:31:20.677 | INFO | copywriter:_generate_headline_suggestions:205 - Generated 3 headline suggestions +2025-04-21 16:31:20.677 | INFO | copywriter:generate_copy:103 - Generated content with 996 characters +2025-04-21 16:31:20.677 | INFO | copywriter:generate_copy:103 - Generated content with 996 characters +2025-04-21 16:31:21.193 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 16:31:21.193 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 16:32:32.709 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:32:32.709 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:32:32.740 | INFO | copywriter:_format_content_structure:385 - Formatted content structure with proper paragraphs and headings +2025-04-21 16:32:32.740 | INFO | copywriter:_format_content_structure:385 - Formatted content structure with proper paragraphs and headings +2025-04-21 16:32:34.753 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:32:34.753 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:32:34.754 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:32:34.754 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:32:34.755 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:32:34.755 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:32:34.758 | INFO | copywriter:_generate_headline_suggestions:205 - Generated 3 headline suggestions +2025-04-21 16:32:34.758 | INFO | copywriter:_generate_headline_suggestions:205 - Generated 3 headline suggestions +2025-04-21 16:32:34.765 | INFO | copywriter:generate_copy:103 - Generated content with 1026 characters +2025-04-21 16:32:34.765 | INFO | copywriter:generate_copy:103 - Generated content with 1026 characters +2025-04-21 16:32:35.376 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 16:32:35.376 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 16:36:01.084 | ERROR | main:delete_user_query:461 - Error deleting user query: 404: Query with timestamp 20250421153235 not found +2025-04-21 16:36:01.084 | ERROR | main:delete_user_query:461 - Error deleting user query: 404: Query with timestamp 20250421153235 not found +2025-04-21 16:40:23.882 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:40:23.882 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:40:27.769 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:40:27.769 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:40:27.770 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:40:27.770 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:40:27.770 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:40:27.770 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:40:27.773 | INFO | copywriter:_generate_headline_suggestions:201 - Generated 3 headline suggestions +2025-04-21 16:40:27.773 | INFO | copywriter:_generate_headline_suggestions:201 - Generated 3 headline suggestions +2025-04-21 16:40:27.774 | INFO | copywriter:generate_copy:99 - Generated content with 1777 characters +2025-04-21 16:40:27.774 | INFO | copywriter:generate_copy:99 - Generated content with 1777 characters +2025-04-21 16:40:28.504 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 16:40:28.504 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 16:47:04.591 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:47:04.591 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:47:09.999 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:47:09.999 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:47:10.000 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:47:10.000 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:47:10.001 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:47:10.001 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:47:10.001 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:47:10.001 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:47:10.002 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:47:10.002 | INFO | copywriter:_remove_name_mentions:319 - Removed any name mentions from generated content +2025-04-21 16:47:10.002 | INFO | copywriter:_generate_headline_suggestions:201 - Generated 3 headline suggestions +2025-04-21 16:47:10.002 | INFO | copywriter:_generate_headline_suggestions:201 - Generated 3 headline suggestions +2025-04-21 16:47:10.002 | INFO | copywriter:generate_copy:99 - Generated content with 2140 characters +2025-04-21 16:47:10.002 | INFO | copywriter:generate_copy:99 - Generated content with 2140 characters +2025-04-21 16:47:10.914 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 16:47:10.914 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 16:52:55.889 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:52:55.889 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:53:09.637 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:53:09.637 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:53:09.637 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:53:09.637 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:53:09.638 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:53:09.638 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:53:09.638 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:53:09.638 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:53:09.639 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:53:09.639 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 16:53:09.639 | INFO | copywriter:_generate_headline_suggestions:211 - Generated 3 headline suggestions +2025-04-21 16:53:09.639 | INFO | copywriter:_generate_headline_suggestions:211 - Generated 3 headline suggestions +2025-04-21 16:53:09.640 | INFO | copywriter:generate_copy:99 - Generated content with 1788 characters +2025-04-21 16:53:09.640 | INFO | copywriter:generate_copy:99 - Generated content with 1788 characters +2025-04-21 16:56:55.426 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 16:56:55.426 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 17:00:00.233 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:00:00.233 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:00:04.202 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:00:04.202 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:00:04.202 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:00:04.202 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:00:04.207 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:00:04.207 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:00:04.208 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:00:04.208 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:00:04.208 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:00:04.208 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:00:04.208 | INFO | copywriter:_generate_headline_suggestions:211 - Generated 3 headline suggestions +2025-04-21 17:00:04.208 | INFO | copywriter:_generate_headline_suggestions:211 - Generated 3 headline suggestions +2025-04-21 17:00:04.208 | INFO | copywriter:generate_copy:99 - Generated content with 704 characters +2025-04-21 17:00:04.208 | INFO | copywriter:generate_copy:99 - Generated content with 704 characters +2025-04-21 17:00:04.835 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 17:00:04.835 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 17:10:03.603 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:10:03.603 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:10:07.477 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:10:07.477 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:10:07.479 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:10:07.479 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:10:07.479 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:10:07.479 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:10:07.480 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:10:07.480 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:10:07.480 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:10:07.480 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:10:07.480 | INFO | copywriter:_generate_headline_suggestions:211 - Generated 3 headline suggestions +2025-04-21 17:10:07.480 | INFO | copywriter:_generate_headline_suggestions:211 - Generated 3 headline suggestions +2025-04-21 17:10:07.480 | INFO | copywriter:generate_copy:99 - Generated content with 998 characters +2025-04-21 17:10:07.480 | INFO | copywriter:generate_copy:99 - Generated content with 998 characters +2025-04-21 17:10:09.061 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 17:10:09.061 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 17:12:18.637 | ERROR | copywriter:_call_llm_api:158 - Error calling Cohere API: +2025-04-21 17:12:18.637 | ERROR | copywriter:_call_llm_api:158 - Error calling Cohere API: +2025-04-21 17:12:37.954 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:12:37.954 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:12:42.224 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:12:42.224 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:12:42.225 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:12:42.225 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:12:42.225 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:12:42.225 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:12:42.226 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:12:42.226 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:12:42.226 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:12:42.226 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:12:42.227 | INFO | copywriter:_generate_headline_suggestions:211 - Generated 3 headline suggestions +2025-04-21 17:12:42.227 | INFO | copywriter:_generate_headline_suggestions:211 - Generated 3 headline suggestions +2025-04-21 17:12:42.227 | INFO | copywriter:generate_copy:99 - Generated content with 2231 characters +2025-04-21 17:12:42.227 | INFO | copywriter:generate_copy:99 - Generated content with 2231 characters +2025-04-21 17:12:42.790 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 17:12:42.790 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 17:15:41.413 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:15:41.413 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:15:46.040 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:15:46.040 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:15:46.074 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:15:46.074 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:15:46.076 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:15:46.076 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:15:46.089 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:15:46.089 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:15:46.089 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:15:46.089 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:15:46.089 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:15:46.089 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:15:46.104 | INFO | copywriter:_generate_headline_suggestions:211 - Generated 3 headline suggestions +2025-04-21 17:15:46.104 | INFO | copywriter:_generate_headline_suggestions:211 - Generated 3 headline suggestions +2025-04-21 17:15:46.106 | INFO | copywriter:generate_copy:99 - Generated content with 1872 characters +2025-04-21 17:15:46.106 | INFO | copywriter:generate_copy:99 - Generated content with 1872 characters +2025-04-21 17:15:47.264 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 17:15:47.264 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 17:20:37.970 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:20:37.970 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:20:41.131 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:20:41.131 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:20:41.141 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:20:41.141 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:20:41.142 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:20:41.142 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:20:41.142 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:20:41.142 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:20:41.142 | INFO | copywriter:_generate_headline_suggestions:211 - Generated 3 headline suggestions +2025-04-21 17:20:41.142 | INFO | copywriter:_generate_headline_suggestions:211 - Generated 3 headline suggestions +2025-04-21 17:20:41.153 | INFO | copywriter:generate_copy:99 - Generated content with 1825 characters +2025-04-21 17:20:41.153 | INFO | copywriter:generate_copy:99 - Generated content with 1825 characters +2025-04-21 17:20:42.278 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 17:20:42.278 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 17:22:32.905 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 17:22:32.905 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 17:23:09.640 | INFO | copywriter:generate_copy:47 - Searching for similar content to reference for prompt: Create a twitter thread on personal branding tips... +2025-04-21 17:23:09.640 | INFO | copywriter:generate_copy:47 - Searching for similar content to reference for prompt: Create a twitter thread on personal branding tips... +2025-04-21 17:23:09.657 | INFO | vector_store:search:163 - Searching vector store with query: Create a twitter thread on personal branding tips... (top_k=3) +2025-04-21 17:23:09.657 | INFO | vector_store:search:163 - Searching vector store with query: Create a twitter thread on personal branding tips... (top_k=3) +2025-04-21 17:23:09.672 | INFO | vector_store:search:169 - Vector store contains 29 documents +2025-04-21 17:23:09.672 | INFO | vector_store:search:169 - Vector store contains 29 documents +2025-04-21 17:23:14.759 | INFO | vector_store:search:221 - Found 3 matching documents for query +2025-04-21 17:23:14.759 | INFO | vector_store:search:221 - Found 3 matching documents for query +2025-04-21 17:23:14.763 | INFO | copywriter:generate_copy:51 - Found 3 similar content items to reference +2025-04-21 17:23:14.763 | INFO | copywriter:generate_copy:51 - Found 3 similar content items to reference +2025-04-21 17:23:45.589 | ERROR | copywriter:_call_llm_api:158 - Error calling Cohere API: +2025-04-21 17:23:45.589 | ERROR | copywriter:_call_llm_api:158 - Error calling Cohere API: +2025-04-21 17:24:20.350 | ERROR | copywriter:_call_llm_api:158 - Error calling Cohere API: +2025-04-21 17:24:20.350 | ERROR | copywriter:_call_llm_api:158 - Error calling Cohere API: +2025-04-21 17:24:43.789 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:24:43.789 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:24:54.514 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:24:54.514 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:24:54.516 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:24:54.516 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:24:54.516 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:24:54.516 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:24:54.517 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:24:54.517 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:24:54.517 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:24:54.517 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:24:54.517 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:24:54.517 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:24:54.518 | INFO | copywriter:_generate_headline_suggestions:211 - Generated 3 headline suggestions +2025-04-21 17:24:54.518 | INFO | copywriter:_generate_headline_suggestions:211 - Generated 3 headline suggestions +2025-04-21 17:24:54.518 | INFO | copywriter:generate_copy:99 - Generated content with 2538 characters +2025-04-21 17:24:54.518 | INFO | copywriter:generate_copy:99 - Generated content with 2538 characters +2025-04-21 17:24:55.436 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 17:24:55.436 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 17:26:27.287 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:26:27.287 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:26:32.676 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:26:32.676 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:26:32.678 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:26:32.678 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:26:32.682 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:26:32.682 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:26:32.682 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:26:32.682 | INFO | copywriter:_remove_name_mentions:329 - Removed any name mentions from generated content +2025-04-21 17:26:32.683 | INFO | copywriter:_generate_headline_suggestions:211 - Generated 3 headline suggestions +2025-04-21 17:26:32.683 | INFO | copywriter:_generate_headline_suggestions:211 - Generated 3 headline suggestions +2025-04-21 17:26:32.683 | INFO | copywriter:generate_copy:99 - Generated content with 2734 characters +2025-04-21 17:26:32.683 | INFO | copywriter:generate_copy:99 - Generated content with 2734 characters +2025-04-21 17:26:33.488 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store +2025-04-21 17:26:33.488 | INFO | vector_store:add_documents:136 - Added 1 documents to vector store