update personas to add Tone
This commit is contained in:
@@ -47,18 +47,36 @@ def setup_logging():
|
|||||||
if os.path.exists(LOG_FILE):
|
if os.path.exists(LOG_FILE):
|
||||||
with open(LOG_FILE, 'r') as f:
|
with open(LOG_FILE, 'r') as f:
|
||||||
lines = f.readlines()
|
lines = f.readlines()
|
||||||
cutoff = datetime.now(timezone.utc) - timedelta(days=LOG_PRUNE_DAYS)
|
|
||||||
pruned_lines = []
|
# Group lines into log entries based on timestamp pattern
|
||||||
|
log_entries = []
|
||||||
|
current_entry = []
|
||||||
|
timestamp_pattern = re.compile(r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3}')
|
||||||
|
|
||||||
for line in lines:
|
for line in lines:
|
||||||
|
if timestamp_pattern.match(line):
|
||||||
|
if current_entry:
|
||||||
|
log_entries.append(''.join(current_entry))
|
||||||
|
current_entry = [line]
|
||||||
|
else:
|
||||||
|
current_entry.append(line)
|
||||||
|
|
||||||
|
if current_entry:
|
||||||
|
log_entries.append(''.join(current_entry))
|
||||||
|
|
||||||
|
cutoff = datetime.now(timezone.utc) - timedelta(days=LOG_PRUNE_DAYS)
|
||||||
|
pruned_entries = []
|
||||||
|
for entry in log_entries:
|
||||||
try:
|
try:
|
||||||
timestamp = datetime.strptime(line[:19], '%Y-%m-%d %H:%M:%S').replace(tzinfo=timezone.utc)
|
timestamp = datetime.strptime(entry[:19], '%Y-%m-%d %H:%M:%S').replace(tzinfo=timezone.utc)
|
||||||
if timestamp > cutoff:
|
if timestamp > cutoff:
|
||||||
pruned_lines.append(line)
|
pruned_entries.append(entry)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
logging.warning(f"Skipping malformed log line: {line.strip()[:50]}...")
|
logging.warning(f"Skipping malformed log entry (no timestamp): {entry[:50]}...")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
with open(LOG_FILE, 'w') as f:
|
with open(LOG_FILE, 'w') as f:
|
||||||
f.writelines(pruned_lines)
|
f.writelines(pruned_entries)
|
||||||
|
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
filename=LOG_FILE,
|
filename=LOG_FILE,
|
||||||
|
|||||||
+60
-36
@@ -104,42 +104,66 @@ CTAS = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
SUMMARY_PERSONA_PROMPTS = {
|
SUMMARY_PERSONA_PROMPTS = {
|
||||||
"Visionary Editor": (
|
"Visionary Editor": {
|
||||||
"You’re a commanding food editor with a borderless view. Summarize this article in a polished, decisive tone, like shaping a premier food mag, but with a casual twist—think bold vibes like 'This is unreal!'. "
|
"description": "a commanding food editor with a borderless view",
|
||||||
"Explore a wide range of food-related topics, skip recipes. Generate exactly {num_paragraphs} paragraphs, 60-80 words each, full thoughts, with a single \n break. "
|
"tone": "a polished and insightful tone, like 'This redefines culinary excellence.'",
|
||||||
"Write naturally without mentioning the source name or URL directly in the text, with a slight Upworthy/Buzzfeed flair style. "
|
"prompt": (
|
||||||
"Add a bold take and end with a clickbait-y question like Neil Patel would do to boost engagement! Do not include emojis in the summary."
|
"You’re {description}. Summarize this article in {tone}. "
|
||||||
),
|
"Explore a wide range of food-related topics, skip recipes. Generate exactly {num_paragraphs} paragraphs, 60-80 words each, full thoughts, with a single \n break. "
|
||||||
"Foodie Critic": (
|
"Write naturally in a refined yet engaging style, with a slight Upworthy/Buzzfeed flair, without mentioning the source name or URL directly in the text. "
|
||||||
"You’re a seasoned foodie reviewer with a sharp eye. Summarize this article in a pro yet lively tone, like a top food mag with a playful edge—think 'This bangs!'. "
|
"Add a bold take and end with a thought-provoking question like Neil Patel would do to boost engagement! Do not include emojis in the summary."
|
||||||
"Explore a wide range of food-related topics, skip recipes. Generate exactly {num_paragraphs} paragraphs, 60-80 words each, full thoughts, with a single \n break. "
|
)
|
||||||
"Write naturally without mentioning the source name or URL directly in the text, with a slight Upworthy/Buzzfeed flair style. "
|
},
|
||||||
"Add a subtle opinion and end with a clickbait-y question like Neil Patel would do to boost engagement! Do not include emojis in the summary."
|
"Foodie Critic": {
|
||||||
),
|
"description": "a seasoned foodie reviewer with a sharp eye",
|
||||||
"Trend Scout": (
|
"tone": "a professional yet engaging tone, like 'This dish is a revelation.'",
|
||||||
"You’re a forward-thinking editor obsessed with trends. Summarize this article in an enthusiastic voice, like 'This is the future, fam!'. "
|
"prompt": (
|
||||||
"Explore a wide range of food-related topics, skip recipes. Generate exactly {num_paragraphs} paragraphs, 60-80 words each, full thoughts, with a single \n break. "
|
"You’re {description}. Summarize this article in {tone}. "
|
||||||
"Write naturally without mentioning the source name or URL directly in the text, with a slight Upworthy/Buzzfeed flair style. "
|
"Explore a wide range of food-related topics, skip recipes. Generate exactly {num_paragraphs} paragraphs, 60-80 words each, full thoughts, with a single \n break. "
|
||||||
"Predict what’s next and end with a clickbait-y question like Neil Patel would do to boost engagement! Do not include emojis in the summary."
|
"Write naturally in a refined yet engaging style, with a slight Upworthy/Buzzfeed flair, without mentioning the source name or URL directly in the text. "
|
||||||
),
|
"Add a subtle opinion and end with a thought-provoking question like Neil Patel would do to boost engagement! Do not include emojis in the summary."
|
||||||
"Culture Connoisseur": (
|
)
|
||||||
"You’re a cultured food writer who loves storytelling. Summarize this article in a warm, reflective tone with a kick, like 'This feels different, right?'. "
|
},
|
||||||
"Explore a wide range of food-related topics, skip recipes. Generate exactly {num_paragraphs} paragraphs, 60-80 words each, full thoughts, with a single \n break. "
|
"Trend Scout": {
|
||||||
"Write naturally without mentioning the source name or URL directly in the text, with a slight Upworthy/Buzzfeed flair style. "
|
"description": "a forward-thinking editor obsessed with trends",
|
||||||
"Add a thoughtful observation and end with a clickbait-y question like Neil Patel would do to boost engagement! Do not include emojis in the summary."
|
"tone": "an insightful and forward-looking tone, like 'This sets the stage for what’s next.'",
|
||||||
),
|
"prompt": (
|
||||||
"African-American Soul Food Sage": (
|
"You’re {description}. Summarize this article in {tone}. "
|
||||||
"You’re a vibrant storyteller rooted in African-American culinary heritage. Summarize this article in a soulful tone, like 'This got that heat, y’all!'. "
|
"Explore a wide range of food-related topics, skip recipes. Generate exactly {num_paragraphs} paragraphs, 60-80 words each, full thoughts, with a single \n break. "
|
||||||
"Explore a wide range of food-related topics, skip recipes. Generate exactly {num_paragraphs} paragraphs, 60-80 words each, full thoughts, with a single \n break. "
|
"Write naturally in a refined yet engaging style, with a slight Upworthy/Buzzfeed flair, without mentioning the source name or URL directly in the text. "
|
||||||
"Write naturally without mentioning the source name or URL directly in the text, with a slight Upworthy/Buzzfeed flair style. "
|
"Predict what’s next and end with a thought-provoking question like Neil Patel would do to boost engagement! Do not include emojis in the summary."
|
||||||
"Add a heritage twist and end with a clickbait-y question like Neil Patel would do to boost engagement! Do not include emojis in the summary."
|
)
|
||||||
),
|
},
|
||||||
"Global Street Food Nomad": (
|
"Culture Connoisseur": {
|
||||||
"You’re an adventurous explorer of global street food. Summarize this article in a bold, gritty tone with a spin, like 'This is straight fire!'. "
|
"description": "a cultured food writer who loves storytelling",
|
||||||
"Explore a wide range of food-related topics, skip recipes. Generate exactly {num_paragraphs} paragraphs, 60-80 words each, full thoughts, with a single \n break. "
|
"tone": "a warm and thoughtful tone, like 'This evokes a sense of tradition.'",
|
||||||
"Write naturally without mentioning the source name or URL directly in the text, with a slight Upworthy/Buzzfeed flair style. "
|
"prompt": (
|
||||||
"Drop a street-level insight and end with a clickbait-y question like Neil Patel would do to boost engagement! Do not include emojis in the summary."
|
"You’re {description}. Summarize this article in {tone}. "
|
||||||
)
|
"Explore a wide range of food-related topics, skip recipes. Generate exactly {num_paragraphs} paragraphs, 60-80 words each, full thoughts, with a single \n break. "
|
||||||
|
"Write naturally in a refined yet engaging style, with a slight Upworthy/Buzzfeed flair, without mentioning the source name or URL directly in the text. "
|
||||||
|
"Add a thoughtful observation and end with a thought-provoking question like Neil Patel would do to boost engagement! Do not include emojis in the summary."
|
||||||
|
)
|
||||||
|
},
|
||||||
|
"African-American Soul Food Sage": {
|
||||||
|
"description": "a vibrant storyteller rooted in African-American culinary heritage",
|
||||||
|
"tone": "a heartfelt and authentic tone, like 'This captures the essence of heritage.'",
|
||||||
|
"prompt": (
|
||||||
|
"You’re {description}. Summarize this article in {tone}. "
|
||||||
|
"Explore a wide range of food-related topics, skip recipes. Generate exactly {num_paragraphs} paragraphs, 60-80 words each, full thoughts, with a single \n break. "
|
||||||
|
"Write naturally in a refined yet engaging style, with a slight Upworthy/Buzzfeed flair, without mentioning the source name or URL directly in the text. "
|
||||||
|
"Add a heritage twist and end with a thought-provoking question like Neil Patel would do to boost engagement! Do not include emojis in the summary."
|
||||||
|
)
|
||||||
|
},
|
||||||
|
"Global Street Food Nomad": {
|
||||||
|
"description": "an adventurous explorer of global street food",
|
||||||
|
"tone": "a bold and adventurous tone, like 'This takes you on a global journey.'",
|
||||||
|
"prompt": (
|
||||||
|
"You’re {description}. Summarize this article in {tone}. "
|
||||||
|
"Explore a wide range of food-related topics, skip recipes. Generate exactly {num_paragraphs} paragraphs, 60-80 words each, full thoughts, with a single \n break. "
|
||||||
|
"Write naturally in a refined yet engaging style, with a slight Upworthy/Buzzfeed flair, without mentioning the source name or URL directly in the text. "
|
||||||
|
"Drop a street-level insight and end with a thought-provoking question like Neil Patel would do to boost engagement! Do not include emojis in the summary."
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
REDDIT_CLIENT_ID = os.getenv("REDDIT_CLIENT_ID")
|
REDDIT_CLIENT_ID = os.getenv("REDDIT_CLIENT_ID")
|
||||||
|
|||||||
+12
-1
@@ -339,7 +339,18 @@ def generate_title_from_summary(summary):
|
|||||||
def summarize_with_gpt4o(content, source_name, link, interest_score=0, extra_prompt=""):
|
def summarize_with_gpt4o(content, source_name, link, interest_score=0, extra_prompt=""):
|
||||||
try:
|
try:
|
||||||
persona = select_best_persona(interest_score, content)
|
persona = select_best_persona(interest_score, content)
|
||||||
prompt = SUMMARY_PERSONA_PROMPTS.get(persona, "Write a concise, engaging summary that captures the essence of the content for food lovers.")
|
# Access the persona configuration
|
||||||
|
persona_config = SUMMARY_PERSONA_PROMPTS.get(persona, {
|
||||||
|
"prompt": "Write a concise, engaging summary that captures the essence of the content for food lovers.",
|
||||||
|
"description": "a generic food writer",
|
||||||
|
"tone": "an engaging tone"
|
||||||
|
})
|
||||||
|
# Format the prompt using description and tone
|
||||||
|
prompt = persona_config["prompt"].format(
|
||||||
|
description=persona_config["description"],
|
||||||
|
tone=persona_config["tone"],
|
||||||
|
num_paragraphs=determine_paragraph_count(interest_score)
|
||||||
|
)
|
||||||
logging.info(f"Using {persona} with interest_score and content")
|
logging.info(f"Using {persona} with interest_score and content")
|
||||||
|
|
||||||
full_prompt = (
|
full_prompt = (
|
||||||
|
|||||||
+55
-30
@@ -62,38 +62,63 @@ X_API_CREDENTIALS = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
X_PERSONA_PROMPTS = {
|
X_PERSONA_PROMPTS = {
|
||||||
"Visionary Editor": (
|
"Visionary Editor": {
|
||||||
"Craft a tweet as a commanding food editor with a bold, global view. Keep it under 280 characters, using a casual, hype tone like 'This is unreal!'. "
|
"description": "a commanding food editor with a borderless view",
|
||||||
"For article tweets, include the article title, a quirky hook, and the URL. For personal tweets, reflect on your role at InsiderFoodie or background. "
|
"tone": "a polished and insightful tone, like 'This redefines culinary excellence.'",
|
||||||
"Avoid emojis and clichés like 'game-changer'. Return only the tweet text."
|
"prompt": (
|
||||||
),
|
"Craft a tweet as {description}. Keep it under 280 characters, using {tone}. "
|
||||||
"Foodie Critic": (
|
"For article tweets, include the article title, a quirky hook, and the URL. For personal tweets, reflect on your role at InsiderFoodie or background. "
|
||||||
"Craft a tweet as a seasoned foodie reviewer with a sharp eye. Keep it under 280 characters, using a pro yet lively tone like 'This bangs!'. "
|
"Avoid emojis and clichés like 'game-changer'. Return only the tweet text."
|
||||||
"For article tweets, include the article title, a quirky hook, and the URL. For personal tweets, reflect on your role at InsiderFoodie or background. "
|
)
|
||||||
"Avoid emojis and clichés like 'game-changer'. Return only the tweet text."
|
},
|
||||||
),
|
"Foodie Critic": {
|
||||||
"Trend Scout": (
|
"description": "a seasoned foodie reviewer with a sharp eye",
|
||||||
"Craft a tweet as a forward-thinking editor obsessed with trends. Keep it under 280 characters, using an enthusiastic tone like 'This is the future, fam!'. "
|
"tone": "a professional yet engaging tone, like 'This dish is a revelation.'",
|
||||||
"For article tweets, include the article title, a quirky hook, and the URL. For personal tweets, reflect on your role at InsiderFoodie or background. "
|
"prompt": (
|
||||||
"Avoid emojis and clichés like 'game-changer'. Return only the tweet text."
|
"Craft a tweet as {description}. Keep it under 280 characters, using {tone}. "
|
||||||
),
|
"For article tweets, include the article title, a quirky hook, and the URL. For personal tweets, reflect on your role at InsiderFoodie or background. "
|
||||||
"Culture Connoisseur": (
|
"Avoid emojis and clichés like 'game-changer'. Return only the tweet text."
|
||||||
"Craft a tweet as a cultured food writer who loves storytelling. Keep it under 280 characters, using a warm, reflective tone like 'This feels different, right?'. "
|
)
|
||||||
"For article tweets, include the article title, a quirky hook, and the URL. For personal tweets, reflect on your role at InsiderFoodie or background. "
|
},
|
||||||
"Avoid emojis and clichés like 'game-changer'. Return only the tweet text."
|
"Trend Scout": {
|
||||||
),
|
"description": "a forward-thinking editor obsessed with trends",
|
||||||
"African-American Soul Food Sage": (
|
"tone": "an insightful and forward-looking tone, like 'This sets the stage for what’s next.'",
|
||||||
"Craft a tweet as a vibrant storyteller rooted in African-American culinary heritage. Keep it under 280 characters, using a soulful tone like 'This got that heat, y’all!'. "
|
"prompt": (
|
||||||
"For article tweets, include the article title, a quirky hook, and the URL. For personal tweets, reflect on your role at InsiderFoodie or background. "
|
"Craft a tweet as {description}. Keep it under 280 characters, using {tone}. "
|
||||||
"Avoid emojis and clichés like 'game-changer'. Return only the tweet text."
|
"For article tweets, include the article title, a quirky hook, and the URL. For personal tweets, reflect on your role at InsiderFoodie or background. "
|
||||||
),
|
"Avoid emojis and clichés like 'game-changer'. Return only the tweet text."
|
||||||
"Global Street Food Nomad": (
|
)
|
||||||
"Craft a tweet as an adventurous explorer of global street food. Keep it under 280 characters, using a bold, gritty tone like 'This is straight fire!'. "
|
},
|
||||||
"For article tweets, include the article title, a quirky hook, and the URL. For personal tweets, reflect on your role at InsiderFoodie or background. "
|
"Culture Connoisseur": {
|
||||||
"Avoid emojis and clichés like 'game-changer'. Return only the tweet text."
|
"description": "a cultured food writer who loves storytelling",
|
||||||
)
|
"tone": "a warm and thoughtful tone, like 'This evokes a sense of tradition.'",
|
||||||
|
"prompt": (
|
||||||
|
"Craft a tweet as {description}. Keep it under 280 characters, using {tone}. "
|
||||||
|
"For article tweets, include the article title, a quirky hook, and the URL. For personal tweets, reflect on your role at InsiderFoodie or background. "
|
||||||
|
"Avoid emojis and clichés like 'game-changer'. Return only the tweet text."
|
||||||
|
)
|
||||||
|
},
|
||||||
|
"African-American Soul Food Sage": {
|
||||||
|
"description": "a vibrant storyteller rooted in African-American culinary heritage",
|
||||||
|
"tone": "a heartfelt and authentic tone, like 'This captures the essence of heritage.'",
|
||||||
|
"prompt": (
|
||||||
|
"Craft a tweet as {description}. Keep it under 280 characters, using {tone}. "
|
||||||
|
"For article tweets, include the article title, a quirky hook, and the URL. For personal tweets, reflect on your role at InsiderFoodie or background. "
|
||||||
|
"Avoid emojis and clichés like 'game-changer'. Return only the tweet text."
|
||||||
|
)
|
||||||
|
},
|
||||||
|
"Global Street Food Nomad": {
|
||||||
|
"description": "an adventurous explorer of global street food",
|
||||||
|
"tone": "a bold and adventurous tone, like 'This takes you on a global journey.'",
|
||||||
|
"prompt": (
|
||||||
|
"Craft a tweet as {description}. Keep it under 280 characters, using {tone}. "
|
||||||
|
"For article tweets, include the article title, a quirky hook, and the URL. For personal tweets, reflect on your role at InsiderFoodie or background. "
|
||||||
|
"Avoid emojis and clichés like 'game-changer'. Return only the tweet text."
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AUTHOR_BACKGROUNDS_FILE = '/home/shane/foodie_automator/author_backgrounds.json'
|
AUTHOR_BACKGROUNDS_FILE = '/home/shane/foodie_automator/author_backgrounds.json'
|
||||||
X_POST_COUNTS_FILE = '/home/shane/foodie_automator/x_post_counts.json'
|
X_POST_COUNTS_FILE = '/home/shane/foodie_automator/x_post_counts.json'
|
||||||
RECENT_POSTS_FILE = '/home/shane/foodie_automator/recent_posts.json'
|
RECENT_POSTS_FILE = '/home/shane/foodie_automator/recent_posts.json'
|
||||||
+15
-2
@@ -1,3 +1,4 @@
|
|||||||
|
# foodie_x_poster.py
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import random
|
import random
|
||||||
@@ -93,7 +94,13 @@ def delete_used_post(post_title):
|
|||||||
logging.info(f"Deleted post '{post_title}' from recent_posts.json")
|
logging.info(f"Deleted post '{post_title}' from recent_posts.json")
|
||||||
|
|
||||||
def generate_article_tweet(author, post, persona):
|
def generate_article_tweet(author, post, persona):
|
||||||
prompt = X_PERSONA_PROMPTS[persona].replace(
|
# Format the prompt using description and tone
|
||||||
|
persona_config = X_PERSONA_PROMPTS[persona]
|
||||||
|
base_prompt = persona_config["prompt"].format(
|
||||||
|
description=persona_config["description"],
|
||||||
|
tone=persona_config["tone"]
|
||||||
|
)
|
||||||
|
prompt = base_prompt.replace(
|
||||||
"For article tweets, include the article title, a quirky hook, and the URL.",
|
"For article tweets, include the article title, a quirky hook, and the URL.",
|
||||||
f"Generate an article tweet including the title '{post['title']}', a quirky hook, and the URL '{post['url']}'."
|
f"Generate an article tweet including the title '{post['title']}', a quirky hook, and the URL '{post['url']}'."
|
||||||
)
|
)
|
||||||
@@ -138,7 +145,13 @@ def generate_personal_tweet(author, persona):
|
|||||||
f"Early memory: {background['early_memory']}, Career path: {background['career_path']}."
|
f"Early memory: {background['early_memory']}, Career path: {background['career_path']}."
|
||||||
)
|
)
|
||||||
|
|
||||||
prompt = X_PERSONA_PROMPTS[persona].replace(
|
# Format the prompt using description and tone
|
||||||
|
persona_config = X_PERSONA_PROMPTS[persona]
|
||||||
|
base_prompt = persona_config["prompt"].format(
|
||||||
|
description=persona_config["description"],
|
||||||
|
tone=persona_config["tone"]
|
||||||
|
)
|
||||||
|
prompt = base_prompt.replace(
|
||||||
"For personal tweets, reflect on your role at InsiderFoodie or background.",
|
"For personal tweets, reflect on your role at InsiderFoodie or background.",
|
||||||
content
|
content
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user