Streamlit UI, Porting CLI - WIP

This commit is contained in:
ajaysi
2024-05-25 18:51:53 +05:30
parent 4153cf7d93
commit 458042afc4
42 changed files with 4591 additions and 202 deletions

View File

@@ -0,0 +1,77 @@
import time #Iwish
import os
import json
import requests
import streamlit as st
def generate_facebook_post(business_type, target_audience, post_goal, post_tone, include, avoid):
"""
Generates a Facebook post prompt for an LLM based on user input.
Args:
business_type: The type of business, e.g., fashion retailer, fitness coach.
target_audience: A description of the target audience.
post_goal: The goal of the Facebook post.
post_tone: The desired tone of the post.
include: Elements to include in the post (e.g., images, videos, links).
avoid: Elements to avoid in the post (e.g., long paragraphs, technical jargon).
Returns:
A string containing the LLM prompt.
"""
prompt = f"""I am a {business_type}.
Please help me write a detailed Facebook post that will engage my target audience, {target_audience}.
Here are some additional details to consider:
* **Post Goal:** {post_goal}
* **Post Tone:** {post_tone}
* **Include:** {include}
* **Avoid:** {avoid}
**Example Post Structure:**
1. **Attention-Grabbing Opening:** Start with a question or a bold statement to capture attention.
2. **Engaging Content:** Briefly describe the main message or offer, highlighting key benefits or features.
3. **Call-to-Action (CTA):** Encourage the audience to take a specific action (e.g., visit a link, comment, share).
4. **Multimedia:** Mention the types of multimedia elements to include (e.g., images, videos).
5. **Hashtags:** Include relevant hashtags to increase post visibility.
"""
try:
response = generate_text_with_exception_handling(prompt)
return response
except Exception as err:
st.error(f"An error occurred while generating the prompt: {e}")
return None
def facebook_post_writer():
st.title("Alwrity - Facebook Post Generator")
st.markdown("This app will help you create a Facebook post prompt for an LLM.")
try:
# Collect user inputs with default values
business_type = st.text_input("**What is your business type?**", placeholder="fitness coach")
target_audience = st.text_input("**Describe your target audience:**", placeholder="fitness enthusiasts")
post_goal = st.selectbox("**What is the goal of your post?**", ["Promote a new product", "Share valuable content", "Increase engagement", "Other"], index=2)
post_tone = st.selectbox("**What tone do you want to use?**", ["Informative", "Humorous", "Inspirational", "Upbeat", "Casual"], index=3)
include = st.text_input("**What elements do you want to include?** (e.g., images, videos, links, hashtags, questions)", placeholder="short video with a sneak peek of the challenge")
avoid = st.text_input("**What elements do you want to avoid?** (e.g., long paragraphs, technical jargon)", placeholder="long paragraphs")
if st.button("Write FaceBook Post"):
if not business_type or not target_audience:
st.error("🚫 Provide required inputs. Least, you can do..")
generated_post = generate_facebook_post(business_type, target_audience, post_goal, post_tone, include, avoid)
if generated_post:
st.subheader(f'**🧕 Verify: Alwrity can make mistakes.**')
st.write("## Generated Facebook Post:")
st.write(generated_post)
st.write("\n\n\n\n\n")
else:
st.error("Error: Failed to generate Facebook Post.")
except Exception as e:
st.error(f"An error occurred: {e}")

View File

@@ -0,0 +1,73 @@
import time #Iwish
import os
import json
import requests
import streamlit as st
def insta_writer():
# Title and description
st.title("✍️ Instagram Caption Writer")
# Input section
with st.expander("**PRO-TIP** - Read the instructions below.", expanded=True):
input_insta_keywords = st.text_input('**Enter main keywords of Your instagram caption!**')
col1, col2, space, col3, col4 = st.columns([5, 5, 0.5, 5, 5])
with col1:
input_insta_type = st.selectbox('Voice Tone', ('Neutral', 'Formal', 'Casual', 'Funny',
'Optimistic', 'Assertive', 'Friendly', 'Encouraging', 'Sarcastic'), index=0)
with col2:
input_insta_cta = st.selectbox('CTA (Call To Action)', ('Shop Now',
'Learn More', 'Swipe Up', 'Sign Up', 'Link in Bio', 'Sense of urgency'), index=0)
with col3:
input_insta_audience = st.selectbox('Choose Target Audience', ('For All',
'Age:18-24 (Gen Z)', 'Age:25-34 (Millennials)'), index=0)
with col4:
input_insta_language = st.selectbox('Choose Language', ('English', 'Hindustani',
'Chinese', 'Hindi', 'Spanish'), index=0)
# Generate Blog Title button
if st.button('**Get Instagram Captions**'):
with st.spinner():
# Clicking without providing data, really ?
if not input_insta_keywords:
st.error('** 🫣 P🫣 Provide Inputs to generate Blog Tescription. Keywords, are required!**')
elif input_insta_keywords:
insta_captions = generate_insta_captions(input_insta_keywords,
input_insta_type,
input_insta_cta,
input_insta_audience,
input_insta_language
)
if insta_captions:
st.subheader('**👩👩🔬Go Viral, with these Instagram captions!🎆🎇 🎇**')
st.code(insta_captions)
else:
st.error("💥**Failed to generate instagram Captions. Please try again!**")
# Function to generate blog metadesc
def generate_insta_captions(input_insta_keywords, input_insta_type, input_insta_cta, input_insta_audience, input_insta_language):
""" Function to call upon LLM to get the work done. """
# If keywords and content both are given.
if input_insta_keywords:
prompt = f"""As an instagram expert and experienced content writer,
I will provide you with my 'instagram caption keywords', along with CTA, Target Audience & voice tone.
Your task is to write 3 instagram captions.
Follow below guidelines to generate instagram captions:
1). Front-Loading: Capture attention by placing key info at the beginning of your captions.
2). Optimise your captions for {input_insta_cta} Call-to-Action (CTA).
3). Hashtag Usage: Limit yourself to four relevant hashtags per caption.
4). Brand Voice and Tone: Use and convey {input_insta_type} voice tone in your captions.
5). Optimise your captions for {input_insta_audience} target audience.
6). Emojis: Inject personality and emotion into your captions with emojis.
7). Brevity: Keep your captions concise and to the point.
8). Important: Your response should be in {input_insta_language} language.
\nInstagram caption keywords: '{input_insta_keywords}'\n
"""
insta_captions = generate_text_with_exception_handling(prompt)
return insta_captions

View File

@@ -0,0 +1,102 @@
import sys
import os
from textwrap import dedent
from pathlib import Path
from datetime import datetime
import streamlit as st
from dotenv import load_dotenv
load_dotenv(Path('../../.env'))
from loguru import logger
logger.remove()
logger.add(sys.stdout,
colorize=True,
format="<level>{level}</level>|<green>{file}:{line}:{function}</green>| {message}"
)
from ..ai_web_researcher.gpt_online_researcher import do_google_serp_search,\
do_tavily_ai_search, do_metaphor_ai_research, do_google_pytrends_analysis
from .blog_from_google_serp import write_blog_google_serp, blog_with_research
from ..ai_web_researcher.you_web_reseacher import get_rag_results, search_ydc_index
from ..blog_metadata.get_blog_metadata import blog_metadata
from ..blog_postprocessing.save_blog_to_file import save_blog_to_file
def write_blog_from_keywords(search_keywords, url=None):
"""
This function will take a blog Topic to first generate sections for it
and then generate content for each section.
"""
# Use to store the blog in a string, to save in a *.md file.
blog_markdown_str = None
tavily_search_result = None
example_blog_titles = []
logger.info(f"Researching and Writing Blog on keywords: {search_keywords}")
with st.status("Started Writing..", expanded=True) as status:
st.empty()
status.update(label="Researching and Writing Blog on keywords.")
# Call on the got-researcher, tavily apis for this. Do google search for organic competition.
try:
google_search_result, g_titles = do_google_serp_search(search_keywords)
status.update(label=f"🙎 Finished with Google web for Search: {search_keywords}")
example_blog_titles.append(g_titles)
status.update(label=f"🛀 Starting Tavily AI research: {search_keywords}")
tavily_search_result, t_titles, t_answer = do_tavily_ai_search(search_keywords)
status.update(label=f"🙆 Finished Google Search & Tavily AI Search on: {search_keywords}", expanded=False)
except Exception as err:
logger.error(f"Failed in web research: {err}")
with st.status("Started Writing blog from google search..", expanded=True) as status:
status.update(label="Researching and Writing Blog on keywords.")
# Call on the got-researcher, tavily apis for this. Do google search for organic competition.
try:
status.update(label=f"🛀 Writing blog from Google Search on: {search_keywords}")
blog_markdown_str = write_blog_google_serp(search_keywords, google_search_result)
st.markdown(blog_markdown_str)
# Hate the robotic introductions.
#blog_markdown_str = improve_blog_intro(blog_markdown_str, t_answer)
#st.markdown(blog_markdown_str)
status.update(label="🙎 Draft 1: Your Content from Google search result.", expanded=False)
except Exception as err:
logger.error(f"Failed in Google web research: {err}")
# logger.info/check the final blog content.
logger.info("######### Draft1: Finished Blog from Google web search: ###########")
with st.status("Started Writing blog from Tavily Web search..", expanded=True) as status:
# Do Tavily AI research to augument the above blog.
try:
#example_blog_titles.append(t_titles)
if blog_markdown_str and tavily_search_result:
logger.info(f"\n\n######### Blog content after Tavily AI research: ######### \n\n")
blog_markdown_str = write_blog_google_serp(search_keywords, tavily_search_result)
status.update(label="Finished Writing Blog From Tavily Results:{blog_markdown_str}")
else:
print("Not Writing with TAVILY..\n\n")
except Exception as err:
logger.error(f"Failed to do Tavily AI research: {err}")
status.update(label="🙎 Generating - Title, Meta Description, Tags, Categories for the content.")
blog_title, blog_meta_desc, blog_tags, blog_categories = blog_metadata(blog_markdown_str,
search_keywords, example_blog_titles)
generated_image_filepath = None
saved_blog_to_file = save_blog_to_file(blog_markdown_str, blog_title, blog_meta_desc,
blog_tags, blog_categories, generated_image_filepath)
status.update(label=f"Saved the content in this file: {saved_blog_to_file}")
blog_frontmatter = dedent(f"""
\n---------------------------------------------------------------------
title: {blog_title.strip()}\n
categories: [{blog_categories.strip()}]\n
tags: [{blog_tags.strip()}]\n
Meta description: {blog_meta_desc.replace(":", "-").strip()}\n
---------------------------------------------------------------------\n
""")
logger.info(f"\n\n --------- Finished writing Blog for : {search_keywords} -------------- \n")
st.markdown(f"{blog_frontmatter}\n\n{blog_markdown_str}")
status.update(label=f"Finished, Review & Use your Original Content Below: {saved_blog_to_file}")

View File

@@ -0,0 +1,67 @@
import time #Iwish
import os
import json
import requests
import streamlit as st
def linked_post_writer():
# Title and description
st.title("✍️ Alwrity - AI Linkedin Blog Post Generator")
# Input section
with st.expander("**PRO-TIP** - Read the instructions below.", expanded=True):
input_blog_keywords = st.text_input('**Enter main keywords of your Post!** (2-3 words that defines your blog)')
col1, col2, space, col3 = st.columns([5, 5, 0.5, 5])
with col1:
input_linkedin_type = st.selectbox('Post Type', ('General', 'How-to Guides', 'Polls', 'Listicles',
'Reality check posts', 'Job Posts', 'FAQs', 'Checklists/Cheat Sheets'), index=0)
with col2:
input_linkedin_length = st.selectbox('Post Length', ('1000 words', 'Long Form', 'Short form'), index=0)
with col3:
input_linkedin_language = st.selectbox('Choose Language', ('English', 'Vietnamese',
'Chinese', 'Hindi', 'Spanish'), index=0)
# Generate Blog FAQ button
if st.button('**Get LinkedIn Post**'):
with st.spinner():
# Clicking without providing data, really ?
if not input_blog_keywords:
st.error('** 🫣Provide Inputs to generate Blinkedin Post. Keywords, required!**')
elif input_blog_keywords:
linkedin_post = generate_linkedin_post(input_blog_keywords, input_linkedin_type,
input_linkedin_length, input_linkedin_language)
if linkedin_post:
st.subheader('**🧕🔬👩 Go Rule LinkedIn with this Blog Post!**')
st.write(linkedin_post)
st.write("\n\n\n")
else:
st.error("💥**Failed to generate linkedin Post. Please try again!**")
# Function to generate blog metadesc
def generate_linkedin_post(input_blog_keywords, input_linkedin_type, input_linkedin_length, input_linkedin_language):
""" Function to call upon LLM to get the work done. """
# Fetch SERP results & PAA questions for FAQ.
serp_results, people_also_ask = get_serp_results(input_blog_keywords)
# If keywords and content both are given.
if serp_results:
prompt = f"""As a SEO expert and experienced linkedin content writer,
I will provide you with my 'blog keywords' and 'google serp results'.
Your task is to write a detailed linkedin post, using given keywords and search results.
Follow below guidelines for generating the linkedin post:
1). Write a title, introduction, sections, faqs and a conclusion for the post.
2). Your FAQ should be based on 'People also ask' and 'Related Queries' from given serp results.
3). Maintain consistent voice of tone, keep the sentence short and simple.
4). Make sure to include important results from the given google serp results.
5). Optimise your response for blog type of {input_linkedin_type}.
6). Important to provide your response in {input_linkedin_language} language.\n
blog keywords: '{input_blog_keywords}'\n
google serp results: '{serp_results}'
people_also_ask: '{people_also_ask}'
"""
linkedin_post = generate_text_with_exception_handling(prompt)
return linkedin_post

View File

@@ -13,6 +13,7 @@ import yaml
from pathlib import Path
from dotenv import load_dotenv
from configparser import ConfigParser
import streamlit as st
from google.api_core import retry
import google.generativeai as genai
@@ -57,190 +58,195 @@ def long_form_generator(content_keywords):
Write long form content using prompt chaining and iterative generation.
Parameters:
"""
# Read the main_config to define tone, character, personality of the content to be generated.
try:
logger.info(f"Starting to write content on {content_keywords}.")
# Define persona and writing guidelines
content_tone, target_audience, content_type, content_language, output_format = read_return_config_section('blog_characteristics')
except Exception as err:
logger.error(f"Failed to Read config params from main_config: {err}")
return
try:
filepath = os.path.join(os.environ["PROMPTS_DIR"], "long_form_ai_writer.prompts")
# Check if file exists
if not os.path.exists(filepath):
raise FileNotFoundError(f"File {filepath} does not exist")
with open(filepath, 'r') as file:
prompts = yaml.safe_load(file)
except Exception as err:
logger.error(f"Exit: Failed to read prompts from {filepath}: {err}")
exit(1)
writing_guidelines = prompts.get('writing_guidelines').format(
content_language=content_language,
content_tone=content_tone,
content_type=content_type,
output_format=output_format,
content_keywords=content_keywords,
target_audience=target_audience
)
content_title = prompts.get('content_title').format(
content_language=content_language,
content_keywords=content_keywords,
target_audience=target_audience
)
with st.status("Start Writing Long Form Article, Hold my Beer..", expanded=True) as status:
# Read the main_config to define tone, character, personality of the content to be generated.
try:
logger.info(f"Starting to write content on {content_keywords}.")
# Define persona and writing guidelines
content_tone, target_audience, content_type, content_language, output_format = read_return_config_section('blog_characteristics')
except Exception as err:
logger.error(f"Failed to Read config params from main_config: {err}")
return
content_outline = prompts.get('content_outline').format(
content_language=content_language,
content_title='{content_title}',
content_type=content_type,
target_audience=target_audience
)
starting_prompt = prompts.get('starting_prompt').format(
content_language=content_language,
content_title='{content_title}',
content_outline='{content_outline}',
writing_guidelines=writing_guidelines
)
continuation_prompt = prompts.get('continuation_prompt').format(
content_language=content_language,
content_title='{content_title}',
content_outline='{content_outline}',
content_text='{content_text}',
web_research_result='{web_research_result}',
writing_guidelines=writing_guidelines
)
# Configure generative AI
load_dotenv(Path('../.env'))
generation_config = {
"temperature": 0.8,
"top_p": 0.95,
"max_output_tokens": 8192,
}
genai.configure(api_key=os.getenv('GEMINI_API_KEY'))
# Initialize the generative model
model = genai.GenerativeModel('gemini-pro', generation_config=generation_config)
model_pro = genai.GenerativeModel('gemini-1.5-flash-latest', generation_config=generation_config)
# Do SERP web research for given keywords to generate title and outline.
web_research_result, g_titles = do_google_serp_search(content_keywords)
# Generate prompts
try:
content_title = generate_with_retry(model_pro, content_title.format(web_research_result=web_research_result)).text
logger.info(f"The title of the content is: {content_title}")
except Exception as err:
logger.error(f"Content title Generation Error: {err}")
return
try:
content_outline = generate_with_retry(model_pro, content_outline.format(
content_title=content_title,
web_research_result=web_research_result)).text
logger.info(f"The content Outline is: {content_outline}\n\n")
except Exception as err:
logger.error(f"Failed to generate content outline: {err}")
try:
logger.info("Do web research with Tavily to provide context for content creation.")
# Do Metaphor/Exa AI search.
table_data = []
web_research_result, m_titles, t_titles = do_tavily_ai_search(content_keywords, max_results=5)
for item in web_research_result.get("results"):
title = item.get("title", "")
snippet = item.get("content", "")
table_data.append([title, snippet])
web_research_result = table_data
except Exception as err:
logger.error(f"Failed to do Tavily AI search: {err}")
return
try:
starting_draft = generate_with_retry(model_pro, starting_prompt.format(
content_title=content_title,
content_outline=content_outline,
web_research_result=web_research_result,
writing_guidelines=writing_guidelines)).text
except Exception as err:
logger.error(f"Failed to Generate Starting draft: {err}")
return
try:
logger.info(f"Starting to write on the outline introduction.")
draft = starting_draft
continuation = generate_with_retry(model, continuation_prompt.format(
content_title=content_title,
content_outline=content_outline,
content_text=draft,
web_research_result=web_research_result,
writing_guidelines=writing_guidelines)).text
except Exception as err:
logger.error(f"Failed to write the initial draft: {err}")
# Add the continuation to the initial draft, keep building the story until we see 'IAMDONE'
try:
draft += '\n\n' + continuation
except Exception as err:
logger.error(f"Failed as: {err} and {continuation}")
logger.info(f"Writing in progress... Current draft length: {len(draft)} characters")
search_terms = f"""
I will provide you with blog outline, your task is to read the outline & return 3 google search keywords.
Your response will be used to do web research for writing on the given outline.
Do not explain your response, provide 3 google search sentences encompassing the given content outline.
Content Outline:\n\n
{content_outline}
"""
search_words = generate_with_retry(model_pro, search_terms).text
while 'IAMDONE' not in continuation:
try:
#web_research_result, m_titles = do_metaphor_ai_research(content_keywords)
str_list = re.split(r',\s*', search_words)
# Strip quotes from each element
str_list = [s.strip('\'"') for s in str_list]
for search_term in str_list:
web_research_result, m_titles, t_titles = do_tavily_ai_search(search_term, max_results=5)
filepath = os.path.join(os.environ["PROMPTS_DIR"], "long_form_ai_writer.prompts")
# Check if file exists
if not os.path.exists(filepath):
raise FileNotFoundError(f"File {filepath} does not exist")
with open(filepath, 'r') as file:
prompts = yaml.safe_load(file)
except Exception as err:
logger.error(f"Exit: Failed to read prompts from {filepath}: {err}")
exit(1)
writing_guidelines = prompts.get('writing_guidelines').format(
content_language=content_language,
content_tone=content_tone,
content_type=content_type,
output_format=output_format,
content_keywords=content_keywords,
target_audience=target_audience
)
content_title = prompts.get('content_title').format(
content_language=content_language,
content_keywords=content_keywords,
target_audience=target_audience
)
content_outline = prompts.get('content_outline').format(
content_language=content_language,
content_title='{content_title}',
content_type=content_type,
target_audience=target_audience
)
starting_prompt = prompts.get('starting_prompt').format(
content_language=content_language,
content_title='{content_title}',
content_outline='{content_outline}',
writing_guidelines=writing_guidelines
)
continuation_prompt = prompts.get('continuation_prompt').format(
content_language=content_language,
content_title='{content_title}',
content_outline='{content_outline}',
content_text='{content_text}',
web_research_result='{web_research_result}',
writing_guidelines=writing_guidelines
)
# Configure generative AI
load_dotenv(Path('../.env'))
generation_config = {
"temperature": 0.6,
"top_p": 1,
"max_output_tokens": 4096,
}
genai.configure(api_key=os.getenv('GEMINI_API_KEY'))
# Initialize the generative model
model = genai.GenerativeModel('gemini-pro', generation_config=generation_config)
model_pro = genai.GenerativeModel('gemini-1.5-flash-latest', generation_config=generation_config)
# Do SERP web research for given keywords to generate title and outline.
web_research_result, g_titles = do_google_serp_search(content_keywords)
# Generate prompts
try:
content_title = generate_with_retry(model_pro, content_title.format(web_research_result=web_research_result)).text
logger.info(f"The title of the content is: {content_title}")
status.update(label=f"The title of the content is: {content_title}")
except Exception as err:
logger.error(f"Content title Generation Error: {err}")
return
try:
content_outline = generate_with_retry(model_pro, content_outline.format(
content_title=content_title,
web_research_result=web_research_result)).text
logger.info(f"The content Outline is: {content_outline}\n\n")
status.update(label="Generated the content outline.")
except Exception as err:
logger.error(f"Failed to generate content outline: {err}")
try:
logger.info("Do web research with Tavily to provide context for content creation.")
# Do Metaphor/Exa AI search.
table_data = []
web_research_result, m_titles, t_titles = do_tavily_ai_search(content_keywords, max_results=5)
for item in web_research_result.get("results"):
title = item.get("title", "")
snippet = item.get("content", "")
table_data.append([title, snippet])
web_research_result = table_data
except Exception as err:
logger.error(f"Failed to do Tavily AI search: {err}")
return
try:
starting_draft = generate_with_retry(model_pro, starting_prompt.format(
content_title=content_title,
content_outline=content_outline,
web_research_result=web_research_result,
writing_guidelines=writing_guidelines)).text
except Exception as err:
logger.error(f"Failed to Generate Starting draft: {err}")
return
try:
logger.info(f"Starting to write on the outline introduction.")
draft = starting_draft
continuation = generate_with_retry(model, continuation_prompt.format(
content_title=content_title,
content_title=content_title,
content_outline=content_outline,
content_text=draft,
web_research_result=web_research_result,
writing_guidelines=writing_guidelines)).text
draft += '\n\n' + continuation
logger.info(f"Writing in progress... Current draft length: {len(draft)} characters")
# At this point, the context is little stale. We should more web research on
# related queries as per the content outline, to augment the LLM context.
except Exception as err:
logger.error(f"Failed to continually write the Essay: {err}")
return
logger.error(f"Failed to write the initial draft: {err}")
# Remove 'IAMDONE' and print the final story
final = draft.replace('IAMDONE', '').strip()
blog_title, blog_meta_desc, blog_tags, blog_categories = blog_metadata(final,
content_keywords, m_titles)
generated_image_filepath = None
# TBD: Save the blog content as a .md file. Markdown or HTML ?
save_blog_to_file(final, blog_title, blog_meta_desc, blog_tags, blog_categories, generated_image_filepath)
blog_frontmatter = f"""
---
title: {blog_title}
categories: [{blog_categories}]
tags: [{blog_tags}]
Meta description: {blog_meta_desc.replace(":", "-")}
---"""
logger.info(f"\n{blog_frontmatter}{final}\n\n")
logger.info(f"\n\n ################ Finished writing Blog for : {content_keywords} #################### \n")
# Add the continuation to the initial draft, keep building the story until we see 'IAMDONE'
try:
draft += '\n\n' + continuation
except Exception as err:
logger.error(f"Failed as: {err} and {continuation}")
logger.info(f"Writing in progress... Current draft length: {len(draft)} characters")
search_terms = f"""
I will provide you with blog outline, your task is to read the outline & return 3 google search keywords.
Your response will be used to do web research for writing on the given outline.
Do not explain your response, provide 3 google search sentences encompassing the given content outline.
Provide the search term results as comma separated values.\n\n
Content Outline:\n
'{content_outline}'
"""
search_words = generate_with_retry(model_pro, search_terms).text
status.update(label=f"Search terms from written draft: {search_words}")
while 'IAMDONE' not in continuation:
try:
#web_research_result, m_titles = do_metaphor_ai_research(content_keywords)
str_list = re.split(r',\s*', search_words)
# Strip quotes from each element
str_list = [s.strip('\'"') for s in str_list]
for search_term in str_list:
web_research_result, m_titles, t_titles = do_tavily_ai_search(search_term, max_results=5)
continuation = generate_with_retry(model, continuation_prompt.format(
content_title=content_title,
content_outline=content_outline,
content_text=draft,
web_research_result=web_research_result,
writing_guidelines=writing_guidelines)).text
draft += '\n\n' + continuation
logger.info(f"Writing in progress... Current draft length: {len(draft)} characters")
status.update(label=f"Writing in progress... Current draft length: {len(draft)} characters")
# At this point, the context is little stale. We should more web research on
# related queries as per the content outline, to augment the LLM context.
except Exception as err:
logger.error(f"Failed to continually write the Essay: {err}")
return
# Remove 'IAMDONE' and print the final story
final = draft.replace('IAMDONE', '').strip()
blog_title, blog_meta_desc, blog_tags, blog_categories = blog_metadata(final,
content_keywords, m_titles)
generated_image_filepath = None
# TBD: Save the blog content as a .md file. Markdown or HTML ?
save_blog_to_file(final, blog_title, blog_meta_desc, blog_tags, blog_categories, generated_image_filepath)
blog_frontmatter = f"""
---
title: {blog_title}
categories: [{blog_categories}]
tags: [{blog_tags}]
Meta description: {blog_meta_desc.replace(":", "-")}
---"""
logger.info(f"\n{blog_frontmatter}{final}\n\n")
st.write(f"\n{blog_frontmatter}{final}\n\n")
logger.info(f"\n\n ################ Finished writing Blog for : {content_keywords} #################### \n")

View File

@@ -0,0 +1,74 @@
import time #Iwish
import os
import json
import requests
import streamlit as st
def tweet_writer():
""" AI Tweet Generator """
with st.expander("**PRO-TIP** - Read the instructions below.", expanded=True):
col1, col2 = st.columns([5, 5])
with col1:
hook = st.text_input(
label="What's the tweet about:(Hook)",
placeholder="e.g., Discover the future of tech today!",
help="Provide a compelling opening statement or question to grab attention."
)
with col2:
# Collect user inputs with placeholders and help text
target_audience = st.text_input(
label="Target Audience",
placeholder="e.g., technology enthusiasts, travel lovers",
help="Describe the audience you want to target with this tweet."
)
if st.button('**Write Tweets**'):
with st.status("Assigning AI professional to write your Google Ads copy..", expanded=True) as status:
if not target_audience or not hook:
st.error("🚫 Please provide all required inputs.")
else:
response = tweet_generator(target_audience, hook)
if response:
st.subheader(f'**🧕👩: Your Final Tweets!**')
st.write(response)
st.write("\n\n\n\n\n\n")
else:
st.error("💥**Failed to write Letter. Please try again!**")
def tweet_generator(target_audience, hook):
""" Email project_update_writer """
prompt = f"""
You are a social media expert creating tweets for an audience interested in {target_audience}.
Write 5 engaging, concise, and visually appealing tweets that each:
1. Start with a compelling hook based on the following keywords: "{hook}"
2. Include a compelling call to action.
3. Use 2-3 relevant hashtags.
4. Adopt a tone that matches the following options:
- Humorous
- Informative
- Inspirational
- Serious
- Casual
5. Be under 100 characters (including spaces and punctuation).
Here are some examples of call-to-actions to include:
- Retweet this if you agree!
- Share your thoughts in the comments!
- Learn more at [link]
- Follow for more [topic] content
- Like if you're excited about [topic]
Output each tweet separated by a newline.
"""
try:
response = generate_text_with_exception_handling(prompt)
return response
except Exception as err:
st.error(f"Exit: Failed to get response from LLM: {err}")
exit(1)

View File

@@ -0,0 +1,257 @@
import time #Iwish
import os
import json
import streamlit as st
def write_yt_description():
st.title("📽️ YT Description Writer")
col1, col2 = st.columns([1, 1])
with col1:
keywords = st.text_input('**Describe Your YT video Keywords (comma-separated)**',
help="Enter keywords separated by commas.").split(',')
target_audience = st.multiselect('**Select Your Target Audience**',
['Beginners', 'Marketers', 'Gamers', 'Foodies', 'Entrepreneurs', 'Students', 'Parents',
'Tech Enthusiasts', 'General Audience', 'News Readers', 'Finance Enthusiasts'],
help="Select the target audience for your video.")
with col2:
tone_style = st.selectbox('**Select Tone and Style of YT Description**',
['Casual', 'Professional', 'Humorous', 'Formal', 'Informal', 'Inspirational'],
help="Select the tone and style of your video.")
language = st.selectbox('**Select YT description Language**',
['English', 'Spanish', 'Chinese', 'Hindi', 'Arabic'],
help="Select the language for the video description.")
if st.button('**Generate YT Description**'):
with st.spinner():
if not keywords:
st.error("🚫 Please provide all required inputs.")
else:
response = generate_youtube_description(keywords, target_audience, tone_style, language)
if response:
st.subheader(f'**🧕👩: Your Final youtube Description !**')
st.write(response)
st.write("\n\n\n\n\n\n")
else:
st.error("💥**Failed to write YT Description. Please try again!**")
def generate_youtube_description(keywords, target_audience, tone_style, language):
""" Generate youtube script generator """
prompt = f"""
Please write a descriptive YouTube description in {language} for a video about {keywords} based on the following information:
Keywords: {', '.join(keywords)}
Target Audience: {', '.join(target_audience)}
Language for description: {', '.join(language)}
Tone and Style: {tone_style}
Specific Instructions:
- Include Primary Keywords Early: Place the most important keywords at the beginning to enhance SEO.
- Write a Compelling Hook: Start with an engaging sentence to grab attention and entice viewers to watch the video.
- Provide a Brief Overview: Summarize the video's content and what viewers can expect to learn or experience.
- Use Relevant Keywords: Integrate additional keywords naturally to improve searchability.
- Add Timestamps: Include timestamps for different sections of the video, if applicable.
- Include Links: Add links to related videos, playlists, or external resources.
- Encourage Engagement: Ask viewers to like, comment, and subscribe, and include a clear call to action.
- Provide Contact Information: Include relevant social media handles, website links, or contact information.
- Use Clear and Concise Language: Avoid jargon and keep sentences straightforward and easy to understand.
- Include Hashtags: Use relevant hashtags to increase discoverability, placing them at the end of the description.
- Tailor the Language and Tone: Adjust to suit the target audience.
- Engage and Describe: Use descriptive language to make the video sound interesting.
- Be Concise but Informative: Provide enough context about the video.
- Highlight Unique Details: Mention any important details or highlights that make the video unique.
- Ensure Proper Grammar and Spelling: Maintain a high standard of writing.
Generate a detailed YouTube description that adheres to the above guidelines and includes a compelling hook, a brief overview, relevant keywords, a call to action, hashtags, and any other relevant information. Ensure proper formatting and a clear structure.
"""
try:
response = generate_text_with_exception_handling(prompt)
return response
except Exception as err:
st.error(f"Exit: Failed to get response from LLM: {err}")
exit(1)
def write_yt_title():
""" Generat YT Titles UI """
st.title("🎬 Write YT Video Titles")
with st.expander("**PRO-TIP** - Read the instructions below.", expanded=True):
col1, col2 = st.columns([5, 5])
with col1:
main_points = st.text_area('**What is your video about ?**',
placeholder='Write few words on your video for title ? (e.g., "New trek, Latest in news, Finance, Tech...")')
tone_style = st.selectbox('**Select Tone & Style**', ['Casual', 'Professional', 'Humorous', 'Formal', 'Informal', 'Inspirational'])
with col2:
target_audience = st.multiselect('**Select Video Target Audience(One Or Multiple)**', [
'Beginners',
'Marketers',
'Gamers',
'Foodies',
'Entrepreneurs',
'Students',
'Parents',
'Tech Enthusiasts',
'General Audience',
'News article',
'Finance Article'])
use_case = st.selectbox('**Youtube Title Use Case**', [
'Tutorials',
'Product Reviews',
'Explainer Videos',
'Vlogs',
'Motivational Speeches',
'Comedy Skits',
'Educational Content'
])
if st.button('**Write YT Titles**'):
with st.status("Assigning AI professional to write your YT Titles..", expanded=True) as status:
if not main_points:
st.error("🚫 Please provide all required inputs.")
else:
response = generate_youtube_title(target_audience, main_points, tone_style, use_case)
if response:
st.subheader(f'**🧕👩: Your Final youtube Titles !**')
st.markdown(response)
st.write("\n\n\n")
else:
st.error("💥**Failed to write Letter. Please try again!**")
def generate_youtube_title(target_audience, main_points, tone_style, use_case):
""" Generate youtube script generator """
prompt = f"""
**Instructions:**
Please generate 5 YouTube title options for a video about **{main_points}** based on the following information:
**Target Audience:** {target_audience}
**Tone and Style:** {tone_style}
**Use Case:** {use_case}
**Specific Instructions:**
* Make the titles catchy and attention-grabbing.
* Use relevant keywords to improve SEO.
* Tailor the language and tone to the target audience.
* Ensure the title reflects the content and use case of the video.
"""
try:
response = generate_text_with_exception_handling(prompt)
return response
except Exception as err:
st.error(f"Exit: Failed to get response from LLM: {err}")
exit(1)
def write_yt_script():
""" Generate youtube scripts """
with st.expander("**PRO-TIP** - Read the instructions below.", expanded=True):
col1, col2 = st.columns([5, 5])
with col1:
main_points = st.text_area('**What is your video about ?**',
placeholder='Write few lines on Video idea for transcript ? (e.g., "New trek, Latest in news, Finance, Tech...")')
tone_style = st.selectbox('**Select Tone & Style**', ['Casual', 'Professional', 'Humorous', 'Formal', 'Informal', 'Inspirational'])
target_audience = st.multiselect('**Select Video Target Audience(One Or Multiple)**', [
'Beginners',
'Marketers',
'Gamers',
'Foodies',
'Entrepreneurs',
'Students',
'Parents',
'Tech Enthusiasts',
'General Audience',
'News article',
'Finance Article'
])
with col2:
# Selectbox for Video Length
video_length = st.selectbox('**Select Video Length**', [
'Short (1-3 minutes)',
'Medium (3-5 minutes)',
'Long (5-10 minutes)',
'Very Long (10+ minutes)'
])
# Selectbox for Script Structure
script_structure = st.selectbox('**Script Structure**', [
'Linear',
'Storytelling',
'Q&A'
])
use_case = st.selectbox('**Youtube Script Use Case**', [
'Tutorials',
'Product Reviews',
'Explainer Videos',
'Vlogs',
'Motivational Speeches',
'Comedy Skits',
'Educational Content'
])
if st.button('**Write YT Script**'):
with st.status("Assigning AI professional to write your YT script..", expanded=True) as status:
if not main_points:
st.error("🚫 Please provide all required inputs.")
else:
response = generate_youtube_script(target_audience, main_points, tone_style, video_length, use_case, script_structure)
if response:
st.subheader(f'**🧕👩: Your Final youtube script!**')
st.write(response)
st.write("\n\n\n\n\n\n")
else:
st.error("💥**Failed to write Letter. Please try again!**")
def generate_youtube_script(target_audience, main_points, tone_style, video_length, use_case, script_structure):
""" Generate youtube script generator """
prompt = f"""
Please write a YouTube script for a video about {main_points} based on the following information:
Target Audience: {', '.join(target_audience)}
Main Points: {', '.join(main_points)}
Tone and Style: {tone_style}
Video Length: {video_length}
Script Structure: {script_structure}
Specific Instructions:
* Include a strong hook to grab attention at the start.
* Structure the script with clear sections and headings.
* Provide engaging introductions and conclusions for each section.
* Use clear and concise language, avoiding jargon or overly technical terms.
* Tailor the language and tone to the target audience.
* Include relevant examples, anecdotes, and stories to make the video more engaging.
* Add questions to encourage viewer interaction and participation.
* End the script with a strong call to action, encouraging viewers to subscribe, like the video, or visit your website.
Use Case: {use_case}
Output Format:
Please provide the script in a clear and easy-to-read format.
Include clear headings for each section and ensure that all instructions are followed.
"""
try:
response = generate_text_with_exception_handling(prompt)
return response
except Exception as err:
st.error(f"Exit: Failed to get response from LLM: {err}")
exit(1)