|
import gradio as gr |
|
import torch |
|
from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline |
|
from newspaper import Article |
|
import nltk |
|
from datetime import datetime, timedelta |
|
import requests |
|
from bs4 import BeautifulSoup |
|
import re |
|
|
|
|
|
try: |
|
nltk.data.find('tokenizers/punkt') |
|
except LookupError: |
|
nltk.download('punkt') |
|
|
|
|
|
def load_models(): |
|
|
|
generator_model = "facebook/opt-350m" |
|
generator_tokenizer = AutoTokenizer.from_pretrained(generator_model) |
|
generator = AutoModelForCausalLM.from_pretrained(generator_model) |
|
|
|
|
|
sentiment_analyzer = pipeline( |
|
"sentiment-analysis", |
|
model="finiteautomata/bertweet-base-sentiment-analysis" |
|
) |
|
|
|
|
|
bias_detector = pipeline( |
|
"text-classification", |
|
model="unitary/unbiased-bertscore" |
|
) |
|
|
|
return generator_tokenizer, generator, sentiment_analyzer, bias_detector |
|
|
|
|
|
def fetch_recent_news(query, num_articles=3): |
|
base_url = "https://news.google.com/rss/search" |
|
params = { |
|
'q': query, |
|
'hl': 'en-US', |
|
'gl': 'US', |
|
'ceid': 'US:en' |
|
} |
|
|
|
try: |
|
response = requests.get(base_url, params=params) |
|
soup = BeautifulSoup(response.content, 'xml') |
|
items = soup.find_all('item')[:num_articles] |
|
|
|
news_data = [] |
|
for item in items: |
|
try: |
|
article = Article(item.link.text) |
|
article.download() |
|
article.parse() |
|
article.nlp() |
|
news_data.append({ |
|
'title': article.title, |
|
'summary': article.summary |
|
}) |
|
except: |
|
continue |
|
|
|
return news_data |
|
except Exception as e: |
|
return [{'title': 'Error fetching news', 'summary': str(e)}] |
|
|
|
|
|
def generate_content( |
|
product_name, |
|
product_description, |
|
target_audience, |
|
key_features, |
|
unique_benefits, |
|
platform, |
|
tone, |
|
generator_tokenizer, |
|
generator, |
|
sentiment_analyzer, |
|
bias_detector |
|
): |
|
|
|
char_limit = 280 if platform == "Twitter" else 500 |
|
|
|
|
|
news_data = fetch_recent_news(f"{product_name} {target_audience}") |
|
news_context = "\n".join([f"Recent news: {item['title']}" for item in news_data]) |
|
|
|
|
|
prompt = f""" |
|
Product: {product_name} |
|
Description: {product_description} |
|
Target Audience: {target_audience} |
|
Key Features: {key_features} |
|
Unique Benefits: {unique_benefits} |
|
Tone: {tone} |
|
Platform: {platform} |
|
Character Limit: {char_limit} |
|
|
|
{news_context} |
|
|
|
Create a {platform} post that highlights the product's benefits while maintaining a {tone} tone: |
|
""" |
|
|
|
|
|
inputs = generator_tokenizer(prompt, return_tensors="pt", max_length=512, truncation=True) |
|
outputs = generator.generate( |
|
inputs["input_ids"], |
|
max_length=char_limit, |
|
num_return_sequences=3, |
|
temperature=0.7, |
|
top_p=0.9, |
|
do_sample=True, |
|
) |
|
|
|
generated_texts = [generator_tokenizer.decode(output, skip_special_tokens=True) for output in outputs] |
|
|
|
|
|
filtered_content = [] |
|
for text in generated_texts: |
|
|
|
text = text.replace(prompt, "").strip() |
|
|
|
|
|
sentiment = sentiment_analyzer(text)[0] |
|
|
|
|
|
bias = bias_detector(text)[0] |
|
|
|
|
|
if ( |
|
sentiment['label'] != 'negative' and |
|
float(bias['score']) < 0.7 and |
|
len(text) <= char_limit |
|
): |
|
filtered_content.append({ |
|
'text': text, |
|
'sentiment': sentiment['label'], |
|
'bias_score': f"{float(bias['score']):.2f}" |
|
}) |
|
|
|
return filtered_content |
|
|
|
|
|
def create_interface(): |
|
generator_tokenizer, generator, sentiment_analyzer, bias_detector = load_models() |
|
|
|
def process_input( |
|
product_name, |
|
product_description, |
|
target_audience, |
|
key_features, |
|
unique_benefits, |
|
platform, |
|
tone |
|
): |
|
results = generate_content( |
|
product_name, |
|
product_description, |
|
target_audience, |
|
key_features, |
|
unique_benefits, |
|
platform, |
|
tone, |
|
generator_tokenizer, |
|
generator, |
|
sentiment_analyzer, |
|
bias_detector |
|
) |
|
|
|
output = "" |
|
for i, content in enumerate(results, 1): |
|
output += f"\nVersion {i}:\n" |
|
output += f"Content: {content['text']}\n" |
|
output += f"Sentiment: {content['sentiment']}\n" |
|
output += f"Bias Score: {content['bias_score']}\n" |
|
output += "-" * 50 + "\n" |
|
|
|
return output |
|
|
|
|
|
iface = gr.Interface( |
|
fn=process_input, |
|
inputs=[ |
|
gr.Textbox(label="Product Name"), |
|
gr.Textbox(label="Product Description", lines=3), |
|
gr.Textbox(label="Target Audience"), |
|
gr.Textbox(label="Key Features", lines=2), |
|
gr.Textbox(label="Unique Benefits", lines=2), |
|
gr.Radio( |
|
choices=["Twitter", "Instagram"], |
|
label="Platform", |
|
value="Twitter" |
|
), |
|
gr.Textbox(label="Tone (e.g., professional, casual, friendly)"), |
|
], |
|
outputs=gr.Textbox(label="Generated Content", lines=10), |
|
title="Ethimar - AI Marketing Content Generator", |
|
description="Generate ethical marketing content with AI-powered insights", |
|
theme="default" |
|
) |
|
|
|
return iface |
|
|
|
|
|
if __name__ == "__main__": |
|
iface = create_interface() |
|
iface.launch() |