WIP - UI, Audio, firecrawl, long-form - V0.5
This commit is contained in:
@@ -20,20 +20,20 @@ If you have 💻 Laptop + 🛜 Internet + 10 minutes, you will be generating blo
|
||||
|
||||
---
|
||||
### [Getting started for Developers](https://github.com/AJaySi/AI-Writer/wiki/Alwrity--%E2%80%90-Get-started)
|
||||
`
|
||||
```
|
||||
Step1: git clone https://github.com/AJaySi/AI-Writer.git
|
||||
Step2: pip install -r requirements.txt
|
||||
Step3: streamlit run alwrity.py
|
||||
|
||||
Step4: Visit Alwrity UI in Browser & Start generation AI personalized content.
|
||||
`
|
||||
```
|
||||
---
|
||||
### Updating to latest Code: (Existing users)
|
||||
`
|
||||
```
|
||||
1). Git pull
|
||||
2). streamlit run alwrity.py
|
||||
3). pip install -r requirements.txt
|
||||
`
|
||||
```
|
||||
---
|
||||
**Still stuck, [Open issue here](https://github.com/AJaySi/AI-Writer/issues) & Someone will bail you out.
|
||||
|
||||
@@ -92,6 +92,7 @@ Use the [main_config](https://github.com/AJaySi/AI-Writer/blob/main/main_config)
|
||||
- [Gemini API](https://gemini.google.com/app): Google powered LLM for natural language processing tasks.
|
||||
- [Ollama](https://ollama.com/) : Local, Privacy focused, LLM provider for research and content generation capabilities.
|
||||
- [CrewAI](https://www.crewai.com/): Collaborative AI agents framework.
|
||||
- [firecrawl](https://www.firecrawl.dev/): Turn websites into LLM-ready data
|
||||
---
|
||||
|
||||
## Features
|
||||
|
||||
60
alwrity.py
60
alwrity.py
@@ -33,7 +33,7 @@ def check_api_keys():
|
||||
missing_keys.append((key, description))
|
||||
|
||||
if missing_keys:
|
||||
st.warning("🚨 Some API keys are missing! Please provide them below: 🚨")
|
||||
st.error("🚨 Some API keys are missing! Please provide them below: 🚨")
|
||||
|
||||
new_keys = []
|
||||
for key, description in missing_keys:
|
||||
@@ -321,45 +321,43 @@ def main():
|
||||
if api_keys_valid and llm_environs_valid:
|
||||
# Clear previous messages and display the sidebar configuration
|
||||
sidebar_configuration()
|
||||
else:
|
||||
st.error("Error loading Environment variables.")
|
||||
|
||||
# Define the tabs
|
||||
tab1, tab2, tab3, tab4, tab5 = st.tabs(
|
||||
# Define the tabs
|
||||
tab1, tab2, tab3, tab4, tab5 = st.tabs(
|
||||
["AI Writers", "Content Planning", "Agents Content Teams", "Alwrity Brain", "Ask Alwrity"])
|
||||
with tab1:
|
||||
write_blog()
|
||||
with tab1:
|
||||
write_blog()
|
||||
|
||||
with tab2:
|
||||
content_planning_tools()
|
||||
with tab2:
|
||||
content_planning_tools()
|
||||
|
||||
with tab3:
|
||||
ai_agents_team()
|
||||
with tab3:
|
||||
ai_agents_team()
|
||||
|
||||
with tab4:
|
||||
alwrity_brain()
|
||||
with tab4:
|
||||
alwrity_brain()
|
||||
|
||||
with tab5:
|
||||
st.info("Chatbot")
|
||||
st.markdown("Create a collection by uploading files (PDF, MD, CSV, etc), or crawl a data source (Websites, more sources coming soon.")
|
||||
st.markdown("One can ask/chat, summarize and do semantic search over the uploaded data")
|
||||
#alwrity_chat_docqa()
|
||||
with tab5:
|
||||
st.info("Chatbot")
|
||||
st.markdown("Create a collection by uploading files (PDF, MD, CSV, etc), or crawl a data source (Websites, more sources coming soon.")
|
||||
st.markdown("One can ask/chat, summarize and do semantic search over the uploaded data")
|
||||
#alwrity_chat_docqa()
|
||||
|
||||
# Sidebar for prompt modification
|
||||
st.sidebar.title("📝 Modify Prompts")
|
||||
prompts = read_prompts()
|
||||
# Sidebar for prompt modification
|
||||
st.sidebar.title("📝 Modify Prompts")
|
||||
prompts = read_prompts()
|
||||
|
||||
if prompts:
|
||||
edited_prompts = []
|
||||
for i, prompt in enumerate(prompts):
|
||||
edited_prompt = st.sidebar.text_area(f"Prompt {i+1}", prompt)
|
||||
edited_prompts.append(edited_prompt)
|
||||
if prompts:
|
||||
edited_prompts = []
|
||||
for i, prompt in enumerate(prompts):
|
||||
edited_prompt = st.sidebar.text_area(f"Prompt {i+1}", prompt)
|
||||
edited_prompts.append(edited_prompt)
|
||||
|
||||
if st.sidebar.button("Save Prompts"):
|
||||
write_prompts(edited_prompts)
|
||||
st.sidebar.success("Prompts saved successfully!")
|
||||
else:
|
||||
st.sidebar.warning("No prompts found in the file.")
|
||||
if st.sidebar.button("Save Prompts"):
|
||||
write_prompts(edited_prompts)
|
||||
st.sidebar.success("Prompts saved successfully!")
|
||||
else:
|
||||
st.sidebar.warning("No prompts found in the file.")
|
||||
|
||||
|
||||
# Functions for the main options
|
||||
|
||||
@@ -1,21 +1,27 @@
|
||||
import sys
|
||||
import os
|
||||
import asyncio
|
||||
from textwrap import dedent
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
import streamlit as st
|
||||
|
||||
from gtts import gTTS
|
||||
import base64
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Load environment variables
|
||||
load_dotenv(Path('../../.env'))
|
||||
# Logger setup
|
||||
from loguru import logger
|
||||
logger.remove()
|
||||
logger.add(sys.stdout,
|
||||
colorize=True,
|
||||
format="<level>{level}</level>|<green>{file}:{line}:{function}</green>| {message}"
|
||||
)
|
||||
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
|
||||
# Import other necessary modules
|
||||
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
|
||||
@@ -23,6 +29,21 @@ from ..blog_postprocessing.save_blog_to_file import save_blog_to_file
|
||||
from ..gpt_providers.text_to_image_generation.main_generate_image_from_prompt import generate_image
|
||||
|
||||
|
||||
# Function to convert text to speech and save as an audio file
|
||||
def text_to_speech(text, lang='en'):
|
||||
tts = gTTS(text=text, lang=lang)
|
||||
tts.save("output.mp3")
|
||||
return "output.mp3"
|
||||
|
||||
|
||||
# Function to get audio file as a downloadable link
|
||||
def get_audio_file(audio_file):
|
||||
with open(audio_file, "rb") as file:
|
||||
data = file.read()
|
||||
b64_data = base64.b64encode(data).decode()
|
||||
return f'<a href="data:audio/mp3;base64,{b64_data}" download="output.mp3">Download audio file</a>'
|
||||
|
||||
|
||||
def write_blog_from_keywords(search_keywords, url=None):
|
||||
"""
|
||||
This function will take a blog Topic to first generate sections for it
|
||||
@@ -45,8 +66,8 @@ def write_blog_from_keywords(search_keywords, url=None):
|
||||
|
||||
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}",
|
||||
state="complete", expanded=False)
|
||||
status.update(label=f"🙆 Finished Google Search & Tavily AI Search on: {search_keywords}",
|
||||
state="complete", expanded=False)
|
||||
|
||||
except Exception as err:
|
||||
st.error(f"Failed in web research: {err}")
|
||||
@@ -66,21 +87,21 @@ def write_blog_from_keywords(search_keywords, url=None):
|
||||
|
||||
# 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.
|
||||
# Do Tavily AI research to augment the above blog.
|
||||
try:
|
||||
#example_blog_titles.append(t_titles)
|
||||
# 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}", expanded=True)
|
||||
status.update(label=f"Finished Writing Blog From Tavily Results:{blog_markdown_str}", expanded=True)
|
||||
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.", expanded=True)
|
||||
try:
|
||||
blog_title, blog_meta_desc, blog_tags, blog_categories = blog_metadata(blog_markdown_str)
|
||||
blog_title, blog_meta_desc, blog_tags, blog_categories = asyncio.run(blog_metadata(blog_markdown_str))
|
||||
except Exception as err:
|
||||
st.error(f"Failed to get blog metadata: {err}")
|
||||
|
||||
@@ -94,38 +115,21 @@ def write_blog_from_keywords(search_keywords, url=None):
|
||||
except Exception as err:
|
||||
st.warning(f"Failed in Image generation: {err}")
|
||||
|
||||
saved_blog_to_file = save_blog_to_file(blog_markdown_str, blog_title, blog_meta_desc,
|
||||
blog_tags, blog_categories, generated_image_filepath)
|
||||
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}")
|
||||
logger.info(f"\n\n --------- Finished writing Blog for : {search_keywords} -------------- \n")
|
||||
|
||||
# Render the result on streamlit UI
|
||||
st.image(generated_image_filepath)
|
||||
st.markdown(f"{blog_markdown_str}")
|
||||
status.update(label=f"Finished, Review & Use your Original Content Below: {saved_blog_to_file}", state="complete")
|
||||
|
||||
# Display options below the content
|
||||
col1, col2, col3, col4, col5 = st.columns(5)
|
||||
if col1.button('Copy'):
|
||||
pyperclip.copy(blog_markdown_str)
|
||||
st.success("Text copied to clipboard!")
|
||||
|
||||
if col2.button('Rephrase'):
|
||||
rephrased_text = rephrase_text(blog_markdown_str)
|
||||
st.markdown(rephrased_text)
|
||||
|
||||
if col3.button('Change Tone'):
|
||||
tone = st.selectbox("Select Tone", ["Formal", "Casual", "Professional"])
|
||||
if st.button("Apply Tone"):
|
||||
toned_text = change_tone(blog_markdown_str, tone)
|
||||
st.markdown(toned_text)
|
||||
|
||||
if col4.button('Make Shorter'):
|
||||
shorter_text = make_shorter(blog_markdown_str)
|
||||
st.markdown(shorter_text)
|
||||
|
||||
if col5.button('Translate'):
|
||||
language = st.selectbox("Select Language", ["Spanish", "French", "German"])
|
||||
if st.button("Translate"):
|
||||
translated_text = translate_text(blog_markdown_str, language)
|
||||
st.markdown(translated_text)
|
||||
# Render the result on streamlit UI
|
||||
if generated_image_filepath:
|
||||
st.image(generated_image_filepath)
|
||||
st.markdown(f"{blog_markdown_str}")
|
||||
status.update(label=f"Finished, Review & Use your Original Content Below: {saved_blog_to_file}",
|
||||
state="complete")
|
||||
|
||||
# Passing the text and language to the engine, here we have marked slow=False. Which tells
|
||||
# the module that the converted audio should have a high speed
|
||||
tts = gTTS(text=blog_markdown_str, lang='en', slow=False)
|
||||
# Saving the converted audio in a mp3 file
|
||||
tts.save("delete_me.mp3")
|
||||
st.audio("delete_me.mp3")
|
||||
|
||||
@@ -124,15 +124,15 @@ def long_form_generator(content_keywords):
|
||||
# Configure generative AI
|
||||
load_dotenv(Path('../.env'))
|
||||
generation_config = {
|
||||
"temperature": 0.6,
|
||||
"temperature": 0.7,
|
||||
"top_p": 1,
|
||||
"max_output_tokens": 8096,
|
||||
}
|
||||
|
||||
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', generation_config=generation_config)
|
||||
model = genai.GenerativeModel('gemini-1.5-flash', generation_config=generation_config)
|
||||
model_pro = genai.GenerativeModel('gemini-pro', 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)
|
||||
@@ -203,14 +203,14 @@ def long_form_generator(content_keywords):
|
||||
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")
|
||||
search_terms = f"""
|
||||
I will provide you with blog outline, your task is to read the outline & return 8 google search keywords.
|
||||
I will provide you with content outline below, your task is to read the outline & return 8 google search keywords.
|
||||
Your response will be used to do web research for writing on the given outline.
|
||||
Do not explain your response, provide 8 google search sentences encompassing the given content outline.
|
||||
Provide the search term results as comma separated values.\n\n
|
||||
Important: 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
|
||||
search_words = generate_with_retry(model, search_terms).text
|
||||
status.update(label=f"Search terms from written draft: {search_words}")
|
||||
|
||||
while 'IAMDONE' not in continuation:
|
||||
@@ -218,6 +218,7 @@ def long_form_generator(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)
|
||||
try:
|
||||
|
||||
@@ -17,7 +17,7 @@ logger.add(sys.stdout,
|
||||
)
|
||||
|
||||
from ..ai_web_researcher.firecrawl_web_crawler import scrape_url
|
||||
from ..blog_metadata.get_blog_metadata import blog_metadata
|
||||
from ..blog_metadata.get_blog_metadata import blog_metadata, run_async
|
||||
from ..blog_postprocessing.save_blog_to_file import save_blog_to_file
|
||||
from ..gpt_providers.text_to_image_generation.main_generate_image_from_prompt import generate_image
|
||||
from ..gpt_providers.text_generation.main_text_generation import llm_text_gen
|
||||
@@ -31,7 +31,11 @@ def blog_from_url(weburl):
|
||||
# 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 = []
|
||||
# Initializing the variables
|
||||
blog_title = None
|
||||
blog_meta_desc = None
|
||||
blog_tags = None
|
||||
blog_categories = None
|
||||
|
||||
logger.info(f"Researching and Writing Blog on: {weburl}")
|
||||
with st.status("Started Writing..", expanded=True) as status:
|
||||
@@ -39,12 +43,12 @@ def blog_from_url(weburl):
|
||||
status.update(label=f"Researching and Writing Blog on: {weburl}")
|
||||
try:
|
||||
scraped_text = scrape_url(weburl)
|
||||
logger.info(scraped_text)
|
||||
#logger.info(scraped_text)
|
||||
except Exception as err:
|
||||
st.error(f"Failed to scrape web page from url-{weburl} - Error: {err}")
|
||||
logger.error(f"Failed in web research: {err}")
|
||||
st.stop()
|
||||
status.update(label="Successfully Scraped/Fetched url: {weburl}", expanded=False, state="complete")
|
||||
status.update(label=f"Successfully Scraped/Fetched url: {weburl}", expanded=False, state="complete")
|
||||
|
||||
with st.status(f"Started Writing blog from {weburl}..", expanded=True) as status:
|
||||
# Do Tavily AI research to augument the above blog.
|
||||
@@ -58,7 +62,7 @@ def blog_from_url(weburl):
|
||||
|
||||
try:
|
||||
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)
|
||||
blog_title, blog_meta_desc, blog_tags, blog_categories = run_async(blog_metadata(blog_markdown_str))
|
||||
except Exception as err:
|
||||
st.error(f"Failed to get blog metadata: {err}")
|
||||
|
||||
@@ -71,8 +75,11 @@ def blog_from_url(weburl):
|
||||
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}")
|
||||
|
||||
logger.info(f"\n\n --------- Finished writing Blog for : {weburl} -------------- \n")
|
||||
st.image(generated_image_filepath)
|
||||
if generated_image_filepath:
|
||||
st.image(generated_image_filepath)
|
||||
|
||||
st.markdown(f"{blog_markdown_str}")
|
||||
status.update(label=f"Finished, Review & Use your Original Content Below: {saved_blog_to_file}", state="complete")
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import sys
|
||||
import streamlit as st
|
||||
from loguru import logger
|
||||
import random
|
||||
import time
|
||||
import asyncio
|
||||
|
||||
logger.remove()
|
||||
logger.add(sys.stdout,
|
||||
@@ -12,7 +12,7 @@ logger.add(sys.stdout,
|
||||
|
||||
from ..gpt_providers.text_generation.main_text_generation import llm_text_gen
|
||||
|
||||
def blog_metadata(blog_article):
|
||||
async def blog_metadata(blog_article):
|
||||
""" Common function to get blog metadata """
|
||||
logger.info(f"Generating Content MetaData\n")
|
||||
|
||||
@@ -20,22 +20,22 @@ def blog_metadata(blog_article):
|
||||
total_steps = 4
|
||||
|
||||
# Step 1: Generate blog title
|
||||
time.sleep(random.uniform(1, 3))
|
||||
await asyncio.sleep(random.uniform(1, 3))
|
||||
blog_title = generate_blog_title(blog_article)
|
||||
progress_bar.progress(1 / total_steps)
|
||||
|
||||
# Step 2: Generate blog meta description
|
||||
time.sleep(random.uniform(1, 3))
|
||||
await asyncio.sleep(random.uniform(1, 3))
|
||||
blog_meta_desc = generate_blog_description(blog_article)
|
||||
progress_bar.progress(2 / total_steps)
|
||||
|
||||
# Step 3: Generate blog tags
|
||||
time.sleep(random.uniform(1, 3))
|
||||
await asyncio.sleep(random.uniform(1, 3))
|
||||
blog_tags = get_blog_tags(blog_article)
|
||||
progress_bar.progress(3 / total_steps)
|
||||
|
||||
# Step 4: Generate blog categories
|
||||
time.sleep(random.uniform(1, 3))
|
||||
await asyncio.sleep(random.uniform(1, 3))
|
||||
blog_categories = get_blog_categories(blog_article)
|
||||
progress_bar.progress(4 / total_steps)
|
||||
|
||||
@@ -117,3 +117,10 @@ def get_blog_tags(blog_article):
|
||||
logger.error(f"Failed to get response from LLM: {err}")
|
||||
raise err
|
||||
|
||||
# Helper function to run the asyncio event loop within Streamlit
|
||||
def run_async(coro):
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
result = loop.run_until_complete(coro)
|
||||
loop.close()
|
||||
return result
|
||||
|
||||
@@ -2,6 +2,8 @@ import os
|
||||
import re
|
||||
import sys
|
||||
import streamlit as st
|
||||
from streamlit_mic_recorder import speech_to_text
|
||||
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
import configparser
|
||||
@@ -10,7 +12,6 @@ import uuid
|
||||
from PIL import Image
|
||||
from PyPDF2 import PdfReader
|
||||
from docx import Document
|
||||
|
||||
from loguru import logger
|
||||
logger.remove()
|
||||
logger.add(sys.stdout,
|
||||
@@ -19,7 +20,6 @@ logger.add(sys.stdout,
|
||||
)
|
||||
|
||||
|
||||
from rich import print
|
||||
from lib.ai_web_researcher.gpt_online_researcher import gpt_web_researcher
|
||||
from lib.ai_web_researcher.metaphor_basic_neural_web_search import metaphor_find_similar
|
||||
from lib.ai_writers.keywords_to_blog_streamlit import write_blog_from_keywords
|
||||
@@ -41,11 +41,40 @@ from lib.gpt_providers.text_to_image_generation.main_generate_image_from_prompt
|
||||
from lib.content_planning_calender.content_planning_agents_alwrity_crew import ai_agents_planner
|
||||
|
||||
|
||||
def record_voice(language="en"):
|
||||
# https://github.com/B4PT0R/streamlit-mic-recorder?tab=readme-ov-file#example
|
||||
|
||||
state = st.session_state
|
||||
|
||||
if "text_received" not in state:
|
||||
state.text_received = []
|
||||
|
||||
text = speech_to_text(
|
||||
start_prompt="🎙️Record🔊",
|
||||
stop_prompt="🔇Stop Recording🚨",
|
||||
language=language,
|
||||
use_container_width=True,
|
||||
just_once=False,
|
||||
)
|
||||
|
||||
if text:
|
||||
state.text_received.append(text)
|
||||
|
||||
result = ""
|
||||
for text in state.text_received:
|
||||
result += text
|
||||
|
||||
state.text_received = []
|
||||
|
||||
return result if result else None
|
||||
|
||||
|
||||
def is_youtube_link(text):
|
||||
if text is not None:
|
||||
youtube_regex = re.compile(r'(https?://)?(www\.)?(youtube|youtu|youtube-nocookie)\.(com|be)/(watch\?v=|embed/|v/|.+\?v=)?([^&=%\?]{11})')
|
||||
return youtube_regex.match(text)
|
||||
|
||||
|
||||
def is_web_link(text):
|
||||
if text is not None:
|
||||
web_regex = re.compile(r'(https?://)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)')
|
||||
@@ -87,10 +116,11 @@ def process_input(input_text, uploaded_file):
|
||||
return "video_file"
|
||||
return None
|
||||
|
||||
|
||||
def blog_from_keyword():
|
||||
""" Input blog keywords, research and write a factual blog."""
|
||||
st.title("Blog Content Writer")
|
||||
col1, col2 = st.columns([2, 1.5])
|
||||
col1, col2, col3 = st.columns([2, 1.5, 0.5])
|
||||
with col1:
|
||||
user_input = st.text_area('**👇Enter Keywords/Title/YouTube Link/Web URLs**',
|
||||
help='Provide keywords, titles, YouTube links, or web URLs to generate content.',
|
||||
@@ -104,6 +134,10 @@ def blog_from_keyword():
|
||||
uploaded_file = st.file_uploader("**👇Attach files (Audio, Video, Image, Document)**",
|
||||
type=["txt", "pdf", "docx", "jpg", "jpeg", "png", "mp3", "wav", "mp4", "mkv", "avi"],
|
||||
help='Attach files such as audio, video, images, or documents.')
|
||||
with col3:
|
||||
user_input = record_voice()
|
||||
if user_input:
|
||||
st.info(user_input)
|
||||
|
||||
temp_file_path = None
|
||||
if uploaded_file is not None:
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
from pathlib import Path
|
||||
from loguru import logger
|
||||
logger.remove()
|
||||
logger.add(sys.stdout,
|
||||
colorize=True,
|
||||
format="<level>{level}</level>|<green>{file}:{line}:{function}</green>| {message}"
|
||||
)
|
||||
|
||||
|
||||
def read_return_config_section(config_section):
|
||||
""" read_return_config_section
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 162 KiB After Width: | Height: | Size: 270 KiB |
@@ -1,13 +1,27 @@
|
||||
writing_guidelines: |
|
||||
As an expert content writer and web researcher, write highly detailed long form, {content_type} content on {content_keywords}.
|
||||
Follow these writing guidelines:
|
||||
1. You must Write in {content_language} language.
|
||||
2. Ensure your content appeals to the target audience of {target_audience}.
|
||||
3. Maintain a consistent tone of {content_tone} throughout.
|
||||
4. Use simple {content_language} words to appeal to all readers.
|
||||
5. Format your content using {output_format}.
|
||||
6. Avoid words like: Unleash, ultimate, uncover, discover, elevate, revolutionizing, unveiling, harnessing, dive, delve into, embrace.
|
||||
Remember, your main goal is to write as much as you can. If you get through the story too fast, that is bad. Expand, never summarize.
|
||||
|
||||
Writing Guidelines:
|
||||
As an expert {content_type} content writer and web researcher on {content_keywords}, follow these writing guidelines:
|
||||
|
||||
Language: Write in the {content_language} language.
|
||||
Audience: Ensure your content appeals to the target audience of {target_audience}.
|
||||
Tone: Maintain a consistent tone of {content_tone} throughout.
|
||||
Simplicity: Use simple {content_language} words to appeal to all readers.
|
||||
Formatting: Format your content using {output_format}.
|
||||
Word Choice: Avoid words like: unleash, ultimate, uncover, discover, elevate, revolutionizing, unveiling, harnessing, dive, delve into, embrace.
|
||||
|
||||
Immerse yourself fully in the topic you're exploring. Use vivid descriptions to captivate your readers and bring your subject to life.
|
||||
Develop your ideas thoroughly—let their nuances, challenges, and intricacies unfold naturally.
|
||||
Follow the structure of your outline, but don't feel constrained by it. Allow your blog post to evolve as you write.
|
||||
|
||||
Incorporate rich imagery, sensory details, and evocative language to make your content engaging and relatable.
|
||||
Introduce elements subtly that can grow into deeper discussions, related topics, or additional insights later in the post.
|
||||
Keep your readers intrigued by not resolving everything too quickly.
|
||||
Plant the seeds of subtopics or potential shifts in perspective that can be expanded upon in future posts.
|
||||
|
||||
Remember, your main goal is to provide valuable, in-depth content. If you rush through your topic, it will leave readers wanting more.
|
||||
Expand your ideas, never summarize. Write as much as you can, ensuring that your content is thorough and comprehensive.
|
||||
|
||||
|
||||
|
||||
content_title: |
|
||||
@@ -51,7 +65,7 @@ starting_prompt: |
|
||||
First, silently review the content outline and title. Consider how to begin writing your content. Take your time.
|
||||
Start by writing the very beginning of the outline. You are not expected to finish the entire content now.
|
||||
Your writing should be detailed, only scratching the surface of the first bullet of your outline.
|
||||
Try to write AT MINIMUM 1000 WORDS and MAXIMUM 2000 WORDS.
|
||||
Try to write AT MINIMUM 500 WORDS.
|
||||
|
||||
"""{{writing_guidelines}}"""
|
||||
|
||||
@@ -60,30 +74,29 @@ starting_prompt: |
|
||||
continuation_prompt: |
|
||||
As an expert {content_language} content writer and web researcher specializing in SEO-optimized content, continue writing the content for the given title and outline.
|
||||
|
||||
The Title of the content is:
|
||||
"""{{content_title}}"""
|
||||
Title of the Content:
|
||||
{{content_title}}
|
||||
|
||||
The content Outline is:
|
||||
"""{{content_outline}}"""
|
||||
Content Outline:
|
||||
{{content_outline}}
|
||||
|
||||
Relevant web research results to use:
|
||||
"""{{web_research_result}}"""
|
||||
Relevant Web Research Results to Use:
|
||||
{{web_research_result}}
|
||||
|
||||
You've begun to immerse yourself in this world, and the words are flowing.
|
||||
Here's what you've written so far:
|
||||
"""{{content_text}}"""
|
||||
You've begun to immerse yourself in this subject, and the words are flowing. Here's what you've written so far:
|
||||
{{content_text}}
|
||||
|
||||
=====
|
||||
|
||||
===========
|
||||
First, silently review the content outline and what you've written so far.
|
||||
Take your time to understand the flow and context.
|
||||
Identify the next section of your outline to write about.
|
||||
It is important to continue from where you left off.
|
||||
|
||||
First, silently review the content outline and what you've written so far. Take your time.
|
||||
Identify what the single next part of your outline you should write.
|
||||
Important to Continue from where you left off.
|
||||
Your task is to continue writing from where you left off and cover the next part of the outline.
|
||||
You are not expected to finish the entire content now.
|
||||
Your writing should be detailed enough to thoroughly explore the next part of your outline.
|
||||
Aim to write at least 500 words. However, only once the entire content is completely finished, write IAMDONE.
|
||||
Remember, do not write the whole outline sections right now.
|
||||
|
||||
Your task is to continue where you left off and write the next part of the outline.
|
||||
You are not expected to finish the whole content now. Your writing should be
|
||||
detailed enough that you are only scratching the surface of the next part of
|
||||
your outline. Try to write AT MINIMUM 1000 WORDS. However, only once the whole outline content
|
||||
is COMPLETELY finished, write IAMDONE. Remember, do NOT write a whole outline sections right now.
|
||||
|
||||
"""{{writing_guidelines}}"""
|
||||
{writing_guidelines}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 5.8 MiB |
@@ -33,3 +33,5 @@ streamlit
|
||||
yfinance
|
||||
pandas_ta
|
||||
firecrawl-py
|
||||
gTTS
|
||||
streamlit-mic-recorder
|
||||
|
||||
Reference in New Issue
Block a user