Initial commit

This commit is contained in:
Ayomide
2025-07-10 15:16:16 +01:00
commit 350f21637c
14 changed files with 515 additions and 0 deletions
+109
View File
@@ -0,0 +1,109 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
# Jupyter Notebook
.ipynb_checkpoints
### Environment ###
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Virtual environment
pythonenv*
### IDE ###
# VS Code
.vscode/
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
# PyCharm
.idea/
*.iml
*.ipr
*.iws
### Data Files ###
# Raw and processed news
data/raw_news/
data/processed_news/
*.csv
*.json
*.parquet
*.feather
*.pkl
*.pickle
*.db
*.sqlite
# Vector database files
*.faiss
*.index
*.bin
*.vec
### Logs ###
*.log
logs/
### OS Generated ###
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
### Groq/Cohere Cache ###
.cache/
model_cache/
### Test Files ###
test_output/
benchmark_results/
### Documentation ###
docs/_build/
View File
+78
View File
@@ -0,0 +1,78 @@
from typing import Dict
import json
from pathlib import Path
class BrandStyle:
def __init__(self):
self.style = self._load_style()
self.templates = {
"email": self._load_template("email"),
"social": self._load_template("social"),
"general": self._load_template("general")
}
def _load_style(self) -> Dict:
path = Path("data/style_guidelines/style.json")
if path.exists():
return json.loads(path.read_text())
else:
# Create default style if doesn't exist
default_style = {
"tone": "professional",
"phrases": ["innovative", "results-driven", "empowering", "transformation"],
"avoid": ["cheap", "guarantee", "spam", "scam"]
}
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(json.dumps(default_style, indent=2))
return default_style
def _load_template(self, name: str) -> str:
path = Path(f"data/style_guidelines/{name}_template.txt")
if path.exists():
return path.read_text()
else:
# Create default templates if they don't exist
templates = {
"email": "Write a professional email that engages the reader and includes a clear call-to-action.",
"social": "Create an engaging social media post that captures attention and encourages interaction.",
"general": "Generate marketing copy that is compelling, authentic, and aligned with brand values."
}
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(templates.get(name, ""))
return templates.get(name, "")
def get_prompt(self, request) -> str:
# Handle both dict and Pydantic model objects
if hasattr(request, 'dict'):
# It's a Pydantic model
request_dict = request.dict()
tone = request.tone or self.style['tone']
content_type = request.content_type
else:
# It's already a dict
request_dict = request
tone = request_dict.get('tone', self.style['tone'])
content_type = request_dict.get('content_type', 'general')
return f"""
You are a marketing assistant for Adriana James. Follow these brand guidelines:
TONE: {tone}
STYLE: Professional, authentic, and empowering
PREFERRED PHRASES: {', '.join(self.style['phrases'])}
AVOID USING: {', '.join(self.style['avoid'])}
CONTENT TYPE: {content_type}
TEMPLATE GUIDANCE: {self.templates.get(content_type, self.templates['general'])}
Create marketing copy that:
1. Reflects Adriana James' brand voice
2. Is engaging and authentic
3. Includes a clear value proposition
4. Has a compelling call-to-action when appropriate
5. Feels personal and relatable
Remember: Focus on transformation, empowerment, and results while maintaining professionalism.
"""
+11
View File
@@ -0,0 +1,11 @@
import os
from dotenv import load_dotenv
load_dotenv()
class Config:
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
COHERE_API_KEY = os.getenv("COHERE_API_KEY")
DATA_PATH = "data/past_campaigns/campaigns.json"
FAISS_INDEX_PATH = "data/vector_store.index"
+24
View File
@@ -0,0 +1,24 @@
# backend/copywriter.py
from .vector_store import VectorStore
from .brand_style import BrandStyle
import openai
class Copywriter:
def __init__(self):
self.vector_store = VectorStore()
self.brand_style = BrandStyle()
def generate_copy(self, request):
# Move the generation logic from main.py here
similar = self.vector_store.search(request.prompt, request.content_type)
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": self.brand_style.get_prompt(request)},
{"role": "user", "content": f"Prompt: {request.prompt}\n\nSimilar examples:\n{similar}"}
],
temperature=0.7
)
return response.choices[0].message.content
+18
View File
@@ -0,0 +1,18 @@
from config import Config
import cohere
import openai
class Embeddings:
def __init__(self):
self.cohere = cohere.Client(Config.COHERE_API_KEY)
def get_embedding(self, text: str, engine: str = "cohere"):
if engine == "cohere":
response = self.cohere.embed(texts=[text], model="small")
return response.embeddings[0]
else: # OpenAI fallback
response = openai.Embedding.create(
input=[text],
model="text-embedding-ada-002"
)
return response.data[0].embedding
+131
View File
@@ -0,0 +1,131 @@
from fastapi import FastAPI, HTTPException, UploadFile, File
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from typing import Optional, List
import json
from datetime import datetime
from .vector_store import VectorStore
from .brand_style import BrandStyle
from .config import Config
import openai
import os
# Initialize OpenAI
openai.api_key = Config.OPENAI_API_KEY
# Initialize
app = FastAPI(title="Marketing Assistant AI", version="0.1.0")
vector_store = VectorStore()
brand_style = BrandStyle()
# CORS
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
# Models
class CampaignRequest(BaseModel):
prompt: str
content_type: str = "general"
tone: Optional[str] = None
class Campaign(BaseModel):
content: str
content_type: str
metadata: dict = {}
# Routes
@app.post("/generate")
async def generate_copy(request: CampaignRequest):
"""Generate marketing copy based on prompt and brand guidelines"""
try:
# Get similar content from vector store
similar = vector_store.search(request.prompt, request.content_type)
# Format similar content for context
similar_content = ""
if similar:
similar_content = "\n\nSimilar past campaigns for reference:\n"
for i, campaign in enumerate(similar[:3], 1):
similar_content += f"{i}. {campaign.get('content', '')}\n"
# Generate with OpenAI
system_prompt = brand_style.get_prompt(request)
user_prompt = f"Create marketing copy for: {request.prompt}{similar_content}"
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt}
],
temperature=0.7,
max_tokens=500
)
generated_copy = response.choices[0].message.content
# Store the generated copy for future reference
new_campaign = {
"content": generated_copy,
"content_type": request.content_type,
"metadata": {
"prompt": request.prompt,
"tone": request.tone,
"generated_at": datetime.now().isoformat()
}
}
# Add to vector store for future similarity searches
vector_store.add_campaign(new_campaign)
return {"result": generated_copy}
except Exception as e:
print(f"Error in generate_copy: {str(e)}") # For debugging
raise HTTPException(status_code=500, detail=str(e))
@app.post("/add-campaign")
async def add_campaign(campaign: Campaign):
"""Add a new campaign to the vector store"""
try:
# Add timestamp to metadata
campaign_data = campaign.dict()
campaign_data["metadata"]["added_at"] = datetime.now().isoformat()
vector_store.add_campaign(campaign_data)
return {"status": "success"}
except Exception as e:
print(f"Error in add_campaign: {str(e)}") # For debugging
raise HTTPException(status_code=500, detail=str(e))
@app.get("/search")
async def search_campaigns(query: str, limit: int = 5):
"""Search for similar campaigns"""
try:
results = vector_store.search(query, k=limit)
return {"results": results}
except Exception as e:
print(f"Error in search_campaigns: {str(e)}") # For debugging
raise HTTPException(status_code=500, detail=str(e))
@app.get("/")
async def root():
"""Health check endpoint"""
return {"message": "Marketing Assistant AI is running", "version": "0.1.0"}
@app.get("/health")
async def health_check():
"""Detailed health check"""
return {
"status": "healthy",
"vector_store_size": len(vector_store.campaigns),
"timestamp": datetime.now().isoformat()
}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
+7
View File
@@ -0,0 +1,7 @@
fastapi
uvicorn
openai==0.28
cohere
sentence-transformers
faiss-cpu
python-dotenv
+37
View File
@@ -0,0 +1,37 @@
import faiss
import numpy as np
from sentence_transformers import SentenceTransformer
from .config import Config
import json
from pathlib import Path
class VectorStore:
def __init__(self):
self.model = SentenceTransformer('all-MiniLM-L6-v2')
self.index = faiss.IndexFlatL2(384)
self.campaigns = []
self._load_data()
def _load_data(self):
if Path(Config.DATA_PATH).exists():
with open(Config.DATA_PATH) as f:
self.campaigns = json.load(f)
if self.campaigns:
embeddings = self.model.encode([c["content"] for c in self.campaigns])
self.index.add(embeddings)
def add_campaign(self, campaign: dict):
self.campaigns.append(campaign)
embedding = self.model.encode([campaign["content"]])
self.index.add(embedding)
self._save_data()
def search(self, query: str, content_type: str = None, k: int = 3):
query_embedding = self.model.encode([query])
distances, indices = self.index.search(query_embedding, k)
return [self.campaigns[i] for i in indices[0]]
def _save_data(self):
with open(Config.DATA_PATH, 'w') as f:
json.dump(self.campaigns, f)
+1
View File
@@ -0,0 +1 @@
Write a professional email that engages the reader and includes a clear call-to-action.
@@ -0,0 +1 @@
Generate marketing copy that is compelling, authentic, and aligned with brand values.
@@ -0,0 +1 @@
Create an engaging social media post that captures attention and encourages interaction.
View File
+97
View File
@@ -0,0 +1,97 @@
# Marketing Assistant AI
## Project Overview
Marketing Assistant AI is an AI-powered tool designed to streamline the process of ideation, copywriting, and marketing campaign creation. It generates marketing content in line with the brand tone and voice of Adriana James, producing drafts that can be validated and refined by a human marketer.
## Objectives
* Reduce the time required to generate marketing copy.
* Create content for emails, campaigns, social media, website copy, funnel pages, and more.
* Ensure the AI produces copywriting that aligns with the brand tone and voice of Adriana James.
* Allow ongoing updates to improve the AIs performance and accuracy.
## Deliverables
* A custom-trained LLM fine-tuned for marketing and copywriting.
* Ability to generate copy in the same style and brand tone of Adriana James.
## Tech Stack
* **LLM** : Open-source or proprietary LLM fine-tuned for marketing.
* **Embeddings & Re-Ranking** : Cohere for embeddings and ranking results.
* **Backend** : FastAPI for API services.
* **Vector Database** : FAISS for content retrieval.
* **Storage** : Local storage for historical marketing data.
## File Structure
```
Marketing_Assistant_AI/
│-- backend/
│ │-- main.py # FastAPI backend
│ │-- copywriter.py # AI-powered copy generation module
│ │-- vector_store.py # Manages vector database operations
│ │-- embeddings.py # Generates embeddings using Cohere
│ │-- brand_style.py # Ensures brand tone consistency
│ │-- config.py # Configuration settings
│ │-- requirements.txt # Dependencies
│-- data/
│ │-- past_campaigns/ # Stores past marketing campaigns
│ │-- user_queries/ # Stores past user queries for AI training
│ │-- style_guidelines/ # Reference materials for brand tone
│-- docs/
│ │-- README.md # Documentation for new developers
│ │-- API_Documentation.md # API details
│-- .env # Environment variables
│-- .gitignore # Git ignore file
│-- LICENSE # License information
```
## Setup & Installation
### 1. Clone the Repository
```bash
git clone http://23.29.118.76:3000/Test/ds_task_marketing_assistant_ai
cd marketing-assistant-ai
```
### 2. Set Up the Backend
```bash
cd backend
pip install -r requirements.txt
python main.py
```
## AI Copywriting Process
1. **User Input** : The user submits a request (e.g., "Generate an email campaign for a product launch").
2. **Preprocessing** : The AI extracts key details and matches them with past marketing data.
3. **Generation** : The fine-tuned LLM creates a draft aligned with Adriana James' brand tone.
4. **Refinement** : The AI applies re-ranking to prioritize relevant content.
5. **Final Output** : The generated copy is displayed for user review and editing.
### Example API Usage
#### Generate Marketing Copy
```python
import requests
url = "http://localhost:8000/generate-copy"
data = {"prompt": "Write a social media post for our new product launch"}
response = requests.post(url, json=data)
print(response.json())
```
## Success Criteria
* AI generates copywriting that accurately reflects the brand tone.
* AI can be updated with new marketing materials.
* CRUD functionality to manage training data.
* AI adapts to new marketing trends and user queries.