WIP - Streamlit UI, firecrawl - V0.5
This commit is contained in:
28
alwrity.py
28
alwrity.py
@@ -22,11 +22,11 @@ from lib.utils.alwrity_utils import (
|
|||||||
# Function to check if API keys are present and prompt user to input if not
|
# Function to check if API keys are present and prompt user to input if not
|
||||||
def check_api_keys():
|
def check_api_keys():
|
||||||
api_keys = {
|
api_keys = {
|
||||||
"METAPHOR_API_KEY": "Metaphor AI Key (Get it here: https://dashboard.exa.ai/login)",
|
"METAPHOR_API_KEY": "[Get Metaphor AI Key](https://dashboard.exa.ai/login)",
|
||||||
"TAVILY_API_KEY": "Tavily AI Key (Get it here: https://tavily.com/#api)",
|
"TAVILY_API_KEY": "[Get Tavily AI Key](https://tavily.com/#api)",
|
||||||
"SERPER_API_KEY": "Serper API Key (Get it here: https://serper.dev/signup)",
|
"SERPER_API_KEY": "[Get Serper API Key](https://serper.dev/signup)",
|
||||||
"STABILITY_API_KEY": "Stability API Key (Get it here: https://platform.stability.ai/)",
|
"STABILITY_API_KEY": "[Get Stability API Key Here](https://platform.stability.ai/)",
|
||||||
"FIRECRAWL_API_KEY": "Firecrawl API key (Get it here: https://www.firecrawl.dev/account)"
|
"FIRECRAWL_API_KEY": "[Get Firecrawl API key Here](https://www.firecrawl.dev/account)"
|
||||||
}
|
}
|
||||||
missing_keys = []
|
missing_keys = []
|
||||||
|
|
||||||
@@ -35,14 +35,21 @@ def check_api_keys():
|
|||||||
missing_keys.append((key, description))
|
missing_keys.append((key, description))
|
||||||
|
|
||||||
if missing_keys:
|
if missing_keys:
|
||||||
st.warning(f"API keys are missing. Please provide them below:{missing_keys}")
|
st.warning("🚨 Some API keys are missing! Please provide them below: 🚨")
|
||||||
|
|
||||||
|
new_keys = []
|
||||||
for key, description in missing_keys:
|
for key, description in missing_keys:
|
||||||
api_key = st.text_input(f"Enter {key}:", placeholder=description, help=description)
|
api_key = st.text_input(f"Enter 🔏 {key}: 👉{description}👈", placeholder=description, help=description)
|
||||||
if api_key:
|
if api_key:
|
||||||
with open(".env", "a") as env_file:
|
new_keys.append((key, api_key))
|
||||||
|
|
||||||
|
if new_keys:
|
||||||
|
with open(".env", "a") as env_file:
|
||||||
|
for key, api_key in new_keys:
|
||||||
env_file.write(f"{key}={api_key}\n")
|
env_file.write(f"{key}={api_key}\n")
|
||||||
os.environ[key] = api_key
|
os.environ[key] = api_key
|
||||||
st.success(f"{key} added successfully! Enter to Continue..")
|
st.success(f"✅ {key} added successfully! Press Enter to continue.")
|
||||||
|
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -317,7 +324,6 @@ def main():
|
|||||||
sidebar_configuration()
|
sidebar_configuration()
|
||||||
else:
|
else:
|
||||||
st.error("Error loading Environment variables.")
|
st.error("Error loading Environment variables.")
|
||||||
st.stop()
|
|
||||||
|
|
||||||
# Define the tabs
|
# Define the tabs
|
||||||
tab1, tab2, tab3, tab4, tab5 = st.tabs(
|
tab1, tab2, tab3, tab4, tab5 = st.tabs(
|
||||||
|
|||||||
@@ -74,11 +74,11 @@ def write_blog_from_keywords(search_keywords, url=None):
|
|||||||
if blog_markdown_str and tavily_search_result:
|
if blog_markdown_str and tavily_search_result:
|
||||||
logger.info(f"\n\n######### Blog content after Tavily AI research: ######### \n\n")
|
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)
|
blog_markdown_str = write_blog_google_serp(search_keywords, tavily_search_result)
|
||||||
status.update(label="Finished Writing Blog From Tavily Results:{blog_markdown_str}")
|
status.update(label="Finished Writing Blog From Tavily Results:{blog_markdown_str}", expanded=True)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
logger.error(f"Failed to do Tavily AI research: {err}")
|
logger.error(f"Failed to do Tavily AI research: {err}")
|
||||||
|
|
||||||
status.update(label="🙎 Generating - Title, Meta Description, Tags, Categories for the content.")
|
status.update(label="🙎 Generating - Title, Meta Description, Tags, Categories for the content.", expanded=True)
|
||||||
try:
|
try:
|
||||||
blog_title, blog_meta_desc, blog_tags, blog_categories = blog_metadata(blog_markdown_str)
|
blog_title, blog_meta_desc, blog_tags, blog_categories = blog_metadata(blog_markdown_str)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
@@ -87,21 +87,14 @@ def write_blog_from_keywords(search_keywords, url=None):
|
|||||||
try:
|
try:
|
||||||
generated_image_filepath = generate_image(f"{blog_title} + ' ' + {blog_meta_desc}")
|
generated_image_filepath = generate_image(f"{blog_title} + ' ' + {blog_meta_desc}")
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
st.error(f"Failed in Image generation: {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,
|
saved_blog_to_file = save_blog_to_file(blog_markdown_str, blog_title, blog_meta_desc,
|
||||||
blog_tags, blog_categories, generated_image_filepath)
|
blog_tags, blog_categories, generated_image_filepath)
|
||||||
status.update(label=f"Saved the content in this file: {saved_blog_to_file}")
|
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")
|
logger.info(f"\n\n --------- Finished writing Blog for : {search_keywords} -------------- \n")
|
||||||
st.markdown(f"{blog_frontmatter}")
|
|
||||||
|
# Render the result on streamlit UI
|
||||||
st.image(generated_image_filepath)
|
st.image(generated_image_filepath)
|
||||||
st.markdown(f"{blog_markdown_str}")
|
st.markdown(f"{blog_markdown_str}")
|
||||||
status.update(label=f"Finished, Review & Use your Original Content Below: {saved_blog_to_file}")
|
status.update(label=f"Finished, Review & Use your Original Content Below: {saved_blog_to_file}", state="complete")
|
||||||
|
|||||||
@@ -1,28 +1,52 @@
|
|||||||
import sys
|
import sys
|
||||||
import streamlit as st
|
import streamlit as st
|
||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
import random
|
||||||
|
import time
|
||||||
|
|
||||||
logger.remove()
|
logger.remove()
|
||||||
logger.add(sys.stdout,
|
logger.add(sys.stdout,
|
||||||
colorize=True,
|
colorize=True,
|
||||||
format="<level>{level}</level>|<green>{file}:{line}:{function}</green>| {message}"
|
format="<level>{level}</level>|<green>{file}:{line}:{function}</green>| {message}"
|
||||||
)
|
)
|
||||||
|
|
||||||
from ..gpt_providers.text_generation.main_text_generation import llm_text_gen
|
from ..gpt_providers.text_generation.main_text_generation import llm_text_gen
|
||||||
|
|
||||||
|
|
||||||
def blog_metadata(blog_article):
|
def blog_metadata(blog_article):
|
||||||
""" Common function to get blog metadata """
|
""" Common function to get blog metadata """
|
||||||
logger.info(f"Generating Content MetaData\n")
|
logger.info(f"Generating Content MetaData\n")
|
||||||
|
|
||||||
|
progress_bar = st.progress(0)
|
||||||
|
total_steps = 4
|
||||||
|
|
||||||
|
# Step 1: Generate blog title
|
||||||
|
time.sleep(random.uniform(1, 3))
|
||||||
blog_title = generate_blog_title(blog_article)
|
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))
|
||||||
blog_meta_desc = generate_blog_description(blog_article)
|
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))
|
||||||
blog_tags = get_blog_tags(blog_article)
|
blog_tags = get_blog_tags(blog_article)
|
||||||
|
progress_bar.progress(3 / total_steps)
|
||||||
|
|
||||||
|
# Step 4: Generate blog categories
|
||||||
|
time.sleep(random.uniform(1, 3))
|
||||||
blog_categories = get_blog_categories(blog_article)
|
blog_categories = get_blog_categories(blog_article)
|
||||||
|
progress_bar.progress(4 / total_steps)
|
||||||
|
|
||||||
|
# Present the result in a table format
|
||||||
|
st.table({
|
||||||
|
"Metadata": ["Blog Title", "Meta Description", "Tags", "Categories"],
|
||||||
|
"Value": [blog_title, blog_meta_desc, blog_tags, blog_categories]
|
||||||
|
})
|
||||||
|
|
||||||
return blog_title, blog_meta_desc, blog_tags, blog_categories
|
return blog_title, blog_meta_desc, blog_tags, blog_categories
|
||||||
|
|
||||||
|
|
||||||
def generate_blog_title(blog_article):
|
def generate_blog_title(blog_article):
|
||||||
"""
|
"""
|
||||||
Given a blog title generate an outline for it
|
Given a blog title generate an outline for it
|
||||||
@@ -43,7 +67,6 @@ def generate_blog_title(blog_article):
|
|||||||
logger.error(f"Failed to get response from LLM: {err}")
|
logger.error(f"Failed to get response from LLM: {err}")
|
||||||
raise err
|
raise err
|
||||||
|
|
||||||
|
|
||||||
def generate_blog_description(blog_content):
|
def generate_blog_description(blog_content):
|
||||||
"""
|
"""
|
||||||
Prompt designed to give SEO optimized blog descripton
|
Prompt designed to give SEO optimized blog descripton
|
||||||
@@ -62,7 +85,6 @@ def generate_blog_description(blog_content):
|
|||||||
logger.error(f"Failed to get response from LLM:{err}")
|
logger.error(f"Failed to get response from LLM:{err}")
|
||||||
raise err
|
raise err
|
||||||
|
|
||||||
|
|
||||||
def get_blog_categories(blog_article):
|
def get_blog_categories(blog_article):
|
||||||
"""
|
"""
|
||||||
Function to generate blog categories for given blog content.
|
Function to generate blog categories for given blog content.
|
||||||
@@ -80,12 +102,10 @@ def get_blog_categories(blog_article):
|
|||||||
except Exception as err:
|
except Exception as err:
|
||||||
logger.error(f"get_blog_categories:Failed to get response from LLM: {err}")
|
logger.error(f"get_blog_categories:Failed to get response from LLM: {err}")
|
||||||
|
|
||||||
|
|
||||||
def get_blog_tags(blog_article):
|
def get_blog_tags(blog_article):
|
||||||
"""
|
"""
|
||||||
Function to suggest tags for the given blog content
|
Function to suggest tags for the given blog content
|
||||||
"""
|
"""
|
||||||
# Suggest at least 5 tags for the following blog post [Enter your blog post text here].
|
|
||||||
prompt = f"""As an expert SEO and blog writer, suggest only 2 relevant and specific blog tags
|
prompt = f"""As an expert SEO and blog writer, suggest only 2 relevant and specific blog tags
|
||||||
for the given blog content. Only reply with comma separated values.
|
for the given blog content. Only reply with comma separated values.
|
||||||
Blog content: {blog_article}."""
|
Blog content: {blog_article}."""
|
||||||
@@ -96,3 +116,4 @@ def get_blog_tags(blog_article):
|
|||||||
except Exception as err:
|
except Exception as err:
|
||||||
logger.error(f"Failed to get response from LLM: {err}")
|
logger.error(f"Failed to get response from LLM: {err}")
|
||||||
raise err
|
raise err
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import streamlit as st
|
||||||
|
|
||||||
import google.generativeai as genai
|
import google.generativeai as genai
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
@@ -44,6 +45,7 @@ def gemini_text_response(prompt, temperature, top_p, n, max_tokens):
|
|||||||
for chunk in response:
|
for chunk in response:
|
||||||
# text_response.append(chunk.text)
|
# text_response.append(chunk.text)
|
||||||
print(chunk.text)
|
print(chunk.text)
|
||||||
|
#st.write(chunk.text)
|
||||||
else:
|
else:
|
||||||
print(response)
|
print(response)
|
||||||
logger.info(f"Number of Token in Prompt Sent: {model.count_tokens(prompt)}")
|
logger.info(f"Number of Token in Prompt Sent: {model.count_tokens(prompt)}")
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -95,7 +95,7 @@ input[type="text"] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Custom button styling */
|
/* Custom button styling */
|
||||||
button {
|
div.stButton > button:first-child {
|
||||||
background: #1565C0; /* Match tab color */
|
background: #1565C0; /* Match tab color */
|
||||||
color: white;
|
color: white;
|
||||||
border: none;
|
border: none;
|
||||||
@@ -112,8 +112,8 @@ button {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
button:hover {
|
div.stButton > button:hover:first-child {
|
||||||
background-color: #1976D2; /* Match tab hover color */
|
background-color: #1976A2; /* Match tab hover color */
|
||||||
box-shadow: 2px 2px 8px rgba(0, 0, 0, 0.3);
|
box-shadow: 2px 2px 8px rgba(0, 0, 0, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 855 KiB |
@@ -5,6 +5,7 @@ python-dotenv
|
|||||||
loguru
|
loguru
|
||||||
openai
|
openai
|
||||||
crewai[tools]
|
crewai[tools]
|
||||||
|
crewai_tools
|
||||||
google.generativeai
|
google.generativeai
|
||||||
mistralai
|
mistralai
|
||||||
tenacity
|
tenacity
|
||||||
|
|||||||
Reference in New Issue
Block a user