diff --git a/backend/brand_style.py b/backend/brand_style.py index d337e93..58ba16a 100644 --- a/backend/brand_style.py +++ b/backend/brand_style.py @@ -8,10 +8,10 @@ from vector_store import VectorStore from config import settings class BrandStyleManager: - def __init__(self): + def __init__(self, embeddings: CohereEmbeddings, vector_store: VectorStore): self.settings = settings - self.embeddings = CohereEmbeddings() - self.vector_store = VectorStore() + self.embeddings = embeddings + self.vector_store = vector_store self.brand_voice = self._load_brand_voice() self.sample_campaigns = self._load_sample_campaigns() @@ -91,11 +91,11 @@ class BrandStyleManager: results = self.vector_store.search(prompt_embedding, k=k) # Optionally rerank results - if results: - texts = [result["text"] for result in results] - reranked = self.embeddings.rerank_results(prompt, texts, top_n=k) - # Convert reranked results to the expected format - return [{"text": text} for text in reranked] + # if results: + # texts = [result["text"] for result in results] + # reranked = self.embeddings.rerank_results(prompt, texts, top_n=k) + # # Convert reranked results to the expected format + # return [{"text": text} for text in reranked] # If no results, return empty list return [] @@ -139,16 +139,3 @@ class BrandStyleManager: else: print(f"No content extracted from {pdf_path}") -# # Example usage -# if __name__ == "__main__": -# brand_style_manager = BrandStyleManager() - -# # Example: Get relevant context for a marketing prompt -# prompt = "Generate a marketing campaign for an Umbrella company" -# context = brand_style_manager.get_relevant_context(prompt) - -# # Print the context in a readable format -# print(f"Relevant context for prompt: '{prompt}'") -# for i, item in enumerate(context): -# print(f"\nReference {i+1}:") -# print(item["text"]) diff --git a/backend/copywriter.py b/backend/copywriter.py index fa03874..6bf59fa 100644 --- a/backend/copywriter.py +++ b/backend/copywriter.py @@ -4,16 +4,14 @@ import json from config import settings from brand_style import BrandStyleManager -# Initialize brand style manager -brand_style_manager = BrandStyleManager() - class MarketingCopywriter: - def __init__(self): + def __init__(self, brand_style_manager: BrandStyleManager): self.settings = settings self.api_key = self.settings.DEEPSEEK_API_KEY self.api_url = "https://api.deepseek.com/v1/chat/completions" + self.brand_style_manager = brand_style_manager - def _build_prompt(self, prompt: str, context: List[Dict], content_type: str, tone: str, + def _build_prompt(self, prompt: str, context: List[Dict], tone: str, brand_voice: Dict[str, Any], sample_campaigns: List[Dict[str, Any]]) -> str: """Build a prompt for the LLM using context and parameters.""" # Format context from book excerpts @@ -31,7 +29,7 @@ class MarketingCopywriter: sample_campaigns_text += f"Content:\n{campaign.get('content', '')}\n" return f"""You are a professional marketing copywriter for {self.settings.BRAND_VOICE}. - Your task is to create {content_type} content that matches the following request: {prompt} + Your task is to create content that matches the following request: {prompt} BRAND VOICE GUIDELINES: {brand_voice_text} @@ -81,10 +79,10 @@ class MarketingCopywriter: def generate_marketing_copy(prompt: str) -> str: """Helper function to generate marketing copy.""" - copywriter = MarketingCopywriter() + brand_style_manager = BrandStyleManager() + copywriter = MarketingCopywriter(brand_style_manager) context = brand_style_manager.get_relevant_context(prompt) - content_type = "email" tone = "professional and empathetic" brand_voice = brand_style_manager.get_brand_voice() sample_campaigns = brand_style_manager.get_sample_campaigns() - return copywriter.generate_copy(prompt, context, content_type, tone, brand_voice, sample_campaigns) \ No newline at end of file + return copywriter.generate_copy(prompt, context, tone, brand_voice, sample_campaigns) \ No newline at end of file diff --git a/backend/main.py b/backend/main.py index 0a44cc7..e935bda 100644 --- a/backend/main.py +++ b/backend/main.py @@ -1,22 +1,90 @@ -from flask import Flask, request, jsonify, render_template +from flask import Flask, request, jsonify, render_template, redirect, url_for from pydantic import BaseModel from typing import Optional, List, Dict, Any from copywriter import generate_marketing_copy from brand_style import BrandStyleManager from config import settings +import os +import json +import datetime app = Flask(__name__) # Initialize brand style manager +brand_style_manager = BrandStyleManager() +data_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "data")) +campaign_prompt = [] + +def load_campaigns(): + campaigns_file = os.path.join(data_dir, "past_campaigns", "campaigns.json") + if os.path.exists(campaigns_file): + with open(campaigns_file, 'r', encoding='utf-8') as f: + data = json.load(f) + campaigns = data.get("campaigns", []) + return campaigns + return [] + +def save_campaigns(campaigns): + campaigns_file = os.path.join(data_dir, "past_campaigns", "campaigns.json") + os.makedirs(os.path.dirname(campaigns_file), exist_ok=True) + with open(campaigns_file, 'w', encoding='utf-8') as f: + json.dump({"campaigns": campaigns}, f, indent=4) @app.route('/', methods=['GET', 'POST']) def root(): + global prompt if request.method == 'POST': prompt = request.form.get('prompt') + campaign_prompt.pop() + campaign_prompt.append(prompt) marketing_copy = generate_marketing_copy(prompt) return render_template('index.html', generated_copy=marketing_copy) - # generated_copy = generate_marketing_copy("Generate a marketing campaign for our new comers") return render_template('index.html') +@app.route('/campaigns') +def view_campaigns(): + campaigns = load_campaigns() + return render_template('campaigns.html', campaigns=campaigns) + +@app.route('/save-edit', methods=['POST']) +def save_edit(): + edited_copy = request.form.get('editedCopy') + global campaign_prompt + prompt = campaign_prompt[-1] + campaigns = load_campaigns() + new_campaign = { + "prompt": prompt, + "content": edited_copy, + "timestamp": datetime.datetime.now().isoformat() + } + campaigns.append(new_campaign) + save_campaigns(campaigns) + + return render_template('index.html', generated_copy="Campaign saved successfully") + +@app.route('/update-campaign', methods=['POST']) +def update_campaign(): + index = int(request.form.get('index')) + edited_copy = request.form.get('editedCopy') + + campaigns = load_campaigns() + if 0 <= index < len(campaigns): + campaigns[index]['content'] = edited_copy + campaigns[index]['timestamp'] = datetime.datetime.now().isoformat() + save_campaigns(campaigns) + + return redirect(url_for('view_campaigns')) + +@app.route('/delete-campaign', methods=['POST']) +def delete_campaign(): + index = int(request.form.get('index')) + + campaigns = load_campaigns() + if 0 <= index < len(campaigns): + campaigns.pop(index) + save_campaigns(campaigns) + + return redirect(url_for('view_campaigns')) + if __name__ == "__main__": app.run(host='localhost', port=8000, debug=True) \ No newline at end of file diff --git a/backend/templates/campaigns.html b/backend/templates/campaigns.html new file mode 100644 index 0000000..bcbcbe0 --- /dev/null +++ b/backend/templates/campaigns.html @@ -0,0 +1,151 @@ + + + + + + Past Campaigns - Marketing Assistant AI + + + +

Past Campaigns

+ ← Back to Generator + +
+ +
+ Number of campaigns: {{ campaigns|length }} +
+ + {% if campaigns %} + {% for campaign in campaigns %} +
+
+

Prompt: {{ campaign.prompt }}

+
+ +
+ + +
+
+
+
Created: {{ campaign.timestamp }}
+
+

{{ campaign.content }}

+
+ +
+ {% endfor %} + {% else %} +

No campaigns found.

+ {% endif %} +
+ + + + \ No newline at end of file diff --git a/backend/templates/index.html b/backend/templates/index.html index 2bc6d28..533ac5a 100644 --- a/backend/templates/index.html +++ b/backend/templates/index.html @@ -63,12 +63,37 @@ margin-top: 0; color: #333; } + .edit-textarea { + width: 100%; + min-height: 200px; + padding: 10px; + margin: 10px 0; + border: 1px solid #ddd; + border-radius: 4px; + font-size: 16px; + line-height: 1.5; + resize: vertical; + } + .save-button { + background-color: #2196F3; + color: white; + border: none; + padding: 10px 20px; + border-radius: 4px; + cursor: pointer; + font-size: 14px; + margin-top: 10px; + } + .save-button:hover { + background-color: #1976D2; + }

Marketing Assistant AI

+ View Past Campaigns →
@@ -81,7 +106,11 @@ {% if generated_copy %}

Generated Marketing Copy:

-
{{ generated_copy | safe }}
+ + + + +
{% endif %}
diff --git a/data/past_campaigns/campaigns.json b/data/past_campaigns/campaigns.json new file mode 100644 index 0000000..6003ecf --- /dev/null +++ b/data/past_campaigns/campaigns.json @@ -0,0 +1,14 @@ +{ + "campaigns": [ + { + "prompt": "", + "content": "Subject: Ready to Transform Your Work Journey? \r\n\r\nHi [Name], \r\n\r\nDo you feel stuck in your professional path, unsure how to take the next step? You\u2019re not alone\u2014and the solution is closer than you think. \r\n\r\nIn this exclusive session, you\u2019ll learn how to: \r\n- Unlock your unique strengths and leverage them for success \r\n- Create a clear, actionable plan to achieve your goals \r\n- Build confidence in your professional voice and vision \r\n- Balance ambition with fulfillment\u2014no burnout required \r\n\r\nThis isn\u2019t just about working harder. It\u2019s about working *smarter*, with purpose and clarity. \r\n\r\nJoin us and take the first step toward a career that excites and fulfills you. \r\n\r\nReserve your spot now: [Link] \r\n\r\nWarmly, \r\n[Your Name]", + "timestamp": "2025-04-18T19:43:30.474972" + }, + { + "prompt": "chair company", + "content": "Subject: Elevate Your Workspace with Premium Comfort \r\n\r\nHi [Name], \r\n\r\nYour workspace should inspire productivity and comfort\u2014without compromise. Whether you're building your business from home or leading a team in the office, the right chair can transform.\r\n\r\nHere\u2019s what you deserve: \r\n- **Ergonomic support** to keep you focused and pain-free \r\n- **Timeless design** that complements your professional aesthetic \r\n- **Durable craftsmanship** for long-lasting performance \r\n- **Adjustable features** tailored to your unique needs \r\n\r\nDon\u2019t settle for discomfort. Upgrade to a chair that supports your ambition and reflects your standards. \r\n\r\nExplore your options now: [Link] \r\n\r\nWarmly, \r\n[Your Name] \r\n\r\nP.S. Limited stock available\u2014prioritize your comfort today.", + "timestamp": "2025-04-18T19:52:34.117453" + } + ] +} \ No newline at end of file