| import streamlit as st |
| from datetime import datetime, timedelta |
| import requests |
| import json |
| import uuid |
| import os |
| from io import BytesIO |
| from PIL import Image |
| from reportlab.lib.pagesizes import letter |
| from reportlab.lib.units import inch |
| from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle |
| from reportlab.lib.enums import TA_CENTER |
| from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer |
|
|
| |
| GROQ_API_KEY = st.secrets["API_KEY"] |
|
|
| GROQ_API_URL = "https://api.groq.com/openai/v1/chat/completions" |
| |
| def handle_errors(func): |
| def wrapper(*args, **kwargs): |
| try: |
| return func(*args, **kwargs) |
| except Exception as e: |
| st.error(f"An error occurred: {str(e)}") |
| return None |
| return wrapper |
|
|
| @handle_errors |
| def generate_marketing_content(instruction, input_context, is_strategy=False): |
| headers = { |
| "Authorization": f"Bearer {GROQ_API_KEY}", |
| "Content-Type": "application/json" |
| } |
| |
| system_message = "You are a helpful AI assistant specializing in marketing and content creation." |
| if is_strategy: |
| system_message += " For strategy, provide a unique day-by-day breakdown tailored to the specific input." |
| else: |
| system_message += " For content, focus on creating a single cohesive piece without day-by-day breakdown." |
| |
| system_message += " Avoid generating any external links or off-topic content." |
| |
| data = { |
| "model": "llama3-8b-8192", |
| "messages": [ |
| {"role": "system", "content": system_message}, |
| {"role": "user", "content": f"Instruction: {instruction}\nInput: {input_context}\nPlease format your response in markdown, excluding any links."} |
| ], |
| "max_tokens": 1000, |
| "temperature": 0.7 |
| } |
| |
| response = requests.post(GROQ_API_URL, headers=headers, json=data) |
| |
| if response.status_code == 200: |
| return response.json()['choices'][0]['message']['content'] |
| else: |
| raise Exception(f"Unable to generate content. Status code: {response.status_code}") |
| |
|
|
| def create_pdf(content): |
| buffer = BytesIO() |
| doc = SimpleDocTemplate(buffer, pagesize=letter, |
| rightMargin=inch, leftMargin=inch, |
| topMargin=inch, bottomMargin=inch) |
| |
| styles = getSampleStyleSheet() |
| |
| |
| title_style = ParagraphStyle( |
| 'TitleStyle', |
| parent=styles['Heading1'], |
| fontSize=18, |
| alignment=TA_CENTER, |
| spaceAfter=12 |
| ) |
| |
| heading_style = ParagraphStyle( |
| 'HeadingStyle', |
| parent=styles['Heading2'], |
| fontSize=14, |
| spaceBefore=12, |
| spaceAfter=6 |
| ) |
| |
| normal_style = ParagraphStyle( |
| 'NormalStyle', |
| parent=styles['Normal'], |
| fontSize=11, |
| spaceBefore=6, |
| spaceAfter=6 |
| ) |
| |
| story = [] |
| |
| |
| paragraphs = content.split('\n\n') |
| |
| |
| for i, para in enumerate(paragraphs): |
| if i == 0: |
| p = Paragraph(para, title_style) |
| elif para.startswith('#'): |
| level = para.count('#') |
| text = para.lstrip('#').strip() |
| if level == 2: |
| p = Paragraph(text, heading_style) |
| else: |
| p = Paragraph(text, normal_style) |
| else: |
| p = Paragraph(para, normal_style) |
| |
| story.append(p) |
| story.append(Spacer(1, 6)) |
| |
| doc.build(story) |
| buffer.seek(0) |
| return buffer |
|
|
|
|
| import streamlit as st |
| from PIL import Image, ImageOps |
| import io |
|
|
| def remove_background(image): |
| |
| image = image.convert('RGBA') |
|
|
| |
| datas = image.getdata() |
| new_data = [] |
|
|
| |
| for item in datas: |
| if item[0] < 50 and item[1] < 50 and item[2] < 50: |
| new_data.append((255, 255, 255, 0)) |
| else: |
| new_data.append(item) |
|
|
| |
| image.putdata(new_data) |
| return image |
|
|
| def main(): |
| |
| logo = Image.open("Compassai.png") |
|
|
| |
| logo = remove_background(logo) |
|
|
| |
|
|
| |
| img_byte_arr = io.BytesIO() |
| logo.save(img_byte_arr, format='PNG') |
| img_byte_arr = img_byte_arr.getvalue() |
|
|
| |
| st.set_page_config( |
| page_title="Compass AI", |
| page_icon=img_byte_arr, |
| layout="centered" |
| ) |
|
|
| |
| st.markdown(""" |
| <style> |
| .banner-container { |
| width: 100%; /* Make it span the entire width */ |
| display: flex; |
| justify-content: center; |
| align-items: center; |
| padding: 10px 0; |
| } |
| .banner-container img { |
| width: 100%; /* Banner stretches across the page */ |
| height: auto; |
| } |
| </style> |
| """, unsafe_allow_html=True) |
|
|
| |
| st.markdown('<div class="banner-container">', unsafe_allow_html=True) |
| st.image(logo, use_column_width=True) |
| st.markdown('</div>', unsafe_allow_html=True) |
|
|
| |
| page = st.sidebar.selectbox("Choose a page", ["Home", "Post Creation", "Marketing Strategy", "Scheduling", "Analytics"]) |
|
|
| |
| if page == "Home": |
| show_home() |
| elif page == "Post Creation": |
| show_post_creation() |
| elif page == "Marketing Strategy": |
| show_marketing_strategy() |
| elif page == "Scheduling": |
| show_scheduling() |
| elif page == "Analytics": |
| show_analytics() |
|
|
|
|
|
|
|
|
| def show_home(): |
| st.markdown(""" |
| <style> |
| .big-font { |
| font-size:50px !important; |
| font-weight: bold; |
| color: #1E90FF; |
| text-align: center; |
| margin-bottom: 20px; |
| } |
| .sub-font { |
| font-size:25px !important; |
| color: #4682B4; |
| text-align: center; |
| margin-bottom: 30px; |
| } |
| .feature-font { |
| font-size:30px !important; |
| color: #4169E1; |
| text-align: center; |
| margin-bottom: 30px; |
| } |
| .feature-card { |
| background-color: #F0F8FF; |
| border-radius: 10px; |
| padding: 20px; |
| margin-bottom: 20px; |
| border: 2px solid #1E90FF; |
| box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); |
| } |
| .feature-title { |
| font-size: 24px !important; |
| font-weight: bold; |
| color: #1E90FF; |
| margin-bottom: 10px; |
| } |
| .feature-list { |
| color: #333; |
| font-size: 16px !important; |
| } |
| </style> |
| """, unsafe_allow_html=True) |
|
|
| st.markdown('<p class="big-font">Welcome to AI Marketing Campaign Agent</p>', unsafe_allow_html=True) |
| st.markdown('<p class="sub-font">Your intelligent assistant for creating, managing, and analyzing marketing campaigns</p>', unsafe_allow_html=True) |
|
|
| st.markdown('<p class="feature-font">🚀 Key Features</p>', unsafe_allow_html=True) |
|
|
| col1, col2 = st.columns(2) |
|
|
| with col1: |
| st.markdown(''' |
| <div class="feature-card"> |
| <p class="feature-title">Campaign Creation</p> |
| <ul class="feature-list"> |
| <li>AI-powered content generation</li> |
| <li>Customized for your brand</li> |
| <li>Multiple content types</li> |
| </ul> |
| </div> |
| ''', unsafe_allow_html=True) |
|
|
| st.markdown(''' |
| <div class="feature-card"> |
| <p class="feature-title">Strategy Planning</p> |
| <ul class="feature-list"> |
| <li>Comprehensive marketing strategies</li> |
| <li>Day-by-day breakdown</li> |
| <li>Tailored to your objectives</li> |
| </ul> |
| </div> |
| ''', unsafe_allow_html=True) |
|
|
| with col2: |
| st.markdown(''' |
| <div class="feature-card"> |
| <p class="feature-title">Content Scheduling</p> |
| <ul class="feature-list"> |
| <li>Multi-platform scheduling</li> |
| <li>Optimize posting times</li> |
| <li>Manage your content calendar</li> |
| </ul> |
| </div> |
| ''', unsafe_allow_html=True) |
|
|
| st.markdown(''' |
| <div class="feature-card"> |
| <p class="feature-title">Analytics (Coming Soon)</p> |
| <ul class="feature-list"> |
| <li>Track campaign performance</li> |
| <li>Gain actionable insights</li> |
| <li>Improve your marketing ROI</li> |
| </ul> |
| </div> |
| ''', unsafe_allow_html=True) |
|
|
| st.markdown('<p class="sub-font">Get started by selecting a feature from the sidebar!</p>', unsafe_allow_html=True) |
|
|
|
|
| @handle_errors |
| def show_post_creation(): |
| st.header("Post Creation") |
| |
| content_type = st.selectbox("Content Type", ["Social Media Post", "Ad Copy", "Email"]) |
| content_prompt = st.text_area("Describe the content you want to generate") |
|
|
| if st.button("Generate Content"): |
| if not content_prompt: |
| st.warning("Please provide a content description.") |
| else: |
| instruction = f"Create a single {content_type}" |
| |
| with st.spinner("Generating content..."): |
| generated_content = generate_marketing_content(instruction, content_prompt) |
| |
| st.markdown(generated_content) |
| |
| |
| pdf = create_pdf(generated_content) |
| st.download_button( |
| label="Download Generated Content as PDF", |
| data=pdf,file_name="generated_content.pdf", |
| mime="application/pdf" |
| ) |
|
|
| @handle_errors |
| def show_marketing_strategy(): |
| st.header("Marketing Strategy") |
| |
| |
| st.subheader("Brand Questionnaire") |
| brand_name = st.text_input("Brand Name") |
| industry = st.selectbox("Industry", ["Technology", "Fashion", "Food & Beverage", "Other"]) |
| target_audience = st.text_area("Describe your target audience") |
| campaign_objective = st.selectbox("Campaign Objective", ["Brand Awareness", "Lead Generation", "Sales", "Other"]) |
| |
| start_date = st.date_input("Campaign Start Date") |
| duration = st.number_input("Campaign Duration (days)", min_value=1, value=30) |
| |
| if st.button("Generate Strategy"): |
| if not all([brand_name, industry, target_audience, campaign_objective]): |
| st.warning("Please fill in all the fields in the Brand Questionnaire.") |
| else: |
| instruction = f"Generate a unique day-by-day marketing strategy for {duration} days" |
| input_context = f"Brand: {brand_name}, Industry: {industry}, Target Audience: {target_audience}, Objective: {campaign_objective}, Start Date: {start_date}, Duration: {duration} days" |
| |
| with st.spinner("Generating strategy..."): |
| strategy = generate_marketing_content(instruction, input_context, is_strategy=True) |
| |
| st.subheader("Generated Marketing Strategy") |
| st.markdown(strategy) |
| |
| |
| pdf = create_pdf(strategy) |
| st.download_button( |
| label="Download Marketing Strategy as PDF", |
| data=pdf, |
| file_name="marketing_strategy.pdf", |
| mime="application/pdf" |
| ) |
| import streamlit as st |
| import requests |
| import json |
| from datetime import datetime, timedelta |
| from PIL import Image |
| import io |
| import os |
| import uuid |
| ACCESS_TOKEN = st.secrets["META_ACCESS_TOKEN"] |
| PAGE_ID = st.secrets["META_PAGE_ID"] |
|
|
| HEADERS = { |
| "Authorization": f"Bearer {ACCESS_TOKEN}", |
| "Content-Type": "application/json" |
| } |
|
|
| def post_to_facebook(message, image_url=None, scheduled_time=None): |
| url = f"https://graph.facebook.com/v20.0/{PAGE_ID}/feed" |
| data = { |
| "message": message, |
| "published": False if scheduled_time else True, |
| } |
| if image_url: |
| data["link"] = image_url |
| if scheduled_time: |
| data["scheduled_publish_time"] = int(scheduled_time.timestamp()) |
| |
| response = requests.post(url, headers=HEADERS, json=data) |
| return response.json() |
|
|
|
|
|
|
| def save_scheduled_post(platform, content, image_path, scheduled_time): |
| |
| post_id = str(uuid.uuid4()) |
| |
| |
| scheduled_posts = load_scheduled_posts() |
| scheduled_posts[post_id] = { |
| "platform": platform, |
| "content": content, |
| "image_path": image_path, |
| "scheduled_time": scheduled_time.isoformat() |
| } |
| |
| with open("scheduled_posts.json", "w") as f: |
| json.dump(scheduled_posts, f) |
|
|
| def load_scheduled_posts(): |
| if os.path.exists("scheduled_posts.json"): |
| with open("scheduled_posts.json", "r") as f: |
| return json.load(f) |
| return {} |
|
|
|
|
|
|
|
|
| def show_scheduling(): |
| st.header("Content Scheduling") |
| |
| platforms = ["Facebook"] |
| |
| post_content = st.text_area("Post Content", key="schedule_post_content") |
| |
| uploaded_image = st.file_uploader("Upload Image", type=["png", "jpg", "jpeg"], key="schedule_image_upload") |
| |
| post_date = st.date_input("Post Date", key="schedule_post_date") |
| post_time = st.time_input("Post Time", key="schedule_post_time") |
| |
| if post_content or uploaded_image: |
| st.subheader("Preview") |
| |
| col1, col2 = st.columns(2) |
| |
| with col1: |
| if post_content: |
| st.text_area("Content Preview", post_content, height=150, disabled=True, key="schedule_content_preview") |
| |
| with col2: |
| if uploaded_image: |
| image = Image.open(uploaded_image) |
| st.image(image, caption="Uploaded Image", use_column_width=True) |
| |
| if st.button("Schedule Post", key="schedule_post_button"): |
| if not post_content and not uploaded_image: |
| st.warning("Please add content or upload an image.") |
| else: |
| scheduled_datetime = datetime.combine(post_date, post_time) |
| |
| |
| image_path = None |
| if uploaded_image: |
| image_path = f"temp_image_{uuid.uuid4()}.jpg" |
| Image.open(uploaded_image).save(image_path) |
| |
| response = post_to_facebook(post_content, image_path, scheduled_datetime) |
| if "id" in response: |
| st.success(f"Post scheduled for Facebook at {scheduled_datetime}") |
| |
| save_scheduled_post("Facebook", post_content, image_path, scheduled_datetime) |
| else: |
| st.error(f"Error scheduling Facebook post: {response.get('error', {}).get('message', 'Unknown error')}") |
| |
| |
| st.subheader("Scheduled Post Details") |
| st.write(f"Date and Time: {scheduled_datetime}") |
| st.write("Platform: Facebook") |
| if post_content: |
| st.write("Content:") |
| st.text_area("Scheduled Content", post_content, height=150, disabled=True, key="scheduled_content_display") |
| if uploaded_image: |
| st.write("Image:") |
| st.image(image, caption="Scheduled Image", use_column_width=True) |
|
|
| |
| st.subheader("Scheduled Posts") |
| scheduled_posts = load_scheduled_posts() |
| for post_id, post_data in scheduled_posts.items(): |
| st.write(f"Platform: {post_data['platform']}") |
| st.write(f"Scheduled Time: {post_data['scheduled_time']}") |
| st.text_area(f"Content for post {post_id}", post_data['content'], height=100, disabled=True, key=f"scheduled_post_{post_id}") |
| if post_data['image_path']: |
| st.image(post_data['image_path'], caption="Scheduled Image", width=200) |
| st.write("---") |
|
|
| def show_analytics(): |
| st.header("Campaign Analytics") |
| st.write("This feature is under development. It will show campaign performance metrics and insights.") |
|
|
| if __name__ == "__main__": |
| main() |