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
|
||||
def check_api_keys():
|
||||
api_keys = {
|
||||
"METAPHOR_API_KEY": "Metaphor AI Key (Get it here: https://dashboard.exa.ai/login)",
|
||||
"TAVILY_API_KEY": "Tavily AI Key (Get it here: https://tavily.com/#api)",
|
||||
"SERPER_API_KEY": "Serper API Key (Get it here: https://serper.dev/signup)",
|
||||
"STABILITY_API_KEY": "Stability API Key (Get it here: https://platform.stability.ai/)",
|
||||
"FIRECRAWL_API_KEY": "Firecrawl API key (Get it here: https://www.firecrawl.dev/account)"
|
||||
"METAPHOR_API_KEY": "[Get Metaphor AI Key](https://dashboard.exa.ai/login)",
|
||||
"TAVILY_API_KEY": "[Get Tavily AI Key](https://tavily.com/#api)",
|
||||
"SERPER_API_KEY": "[Get Serper API Key](https://serper.dev/signup)",
|
||||
"STABILITY_API_KEY": "[Get Stability API Key Here](https://platform.stability.ai/)",
|
||||
"FIRECRAWL_API_KEY": "[Get Firecrawl API key Here](https://www.firecrawl.dev/account)"
|
||||
}
|
||||
missing_keys = []
|
||||
|
||||
@@ -35,14 +35,21 @@ def check_api_keys():
|
||||
missing_keys.append((key, description))
|
||||
|
||||
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:
|
||||
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:
|
||||
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")
|
||||
os.environ[key] = api_key
|
||||
st.success(f"{key} added successfully! Enter to Continue..")
|
||||
os.environ[key] = api_key
|
||||
st.success(f"✅ {key} added successfully! Press Enter to continue.")
|
||||
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -317,7 +324,6 @@ def main():
|
||||
sidebar_configuration()
|
||||
else:
|
||||
st.error("Error loading Environment variables.")
|
||||
st.stop()
|
||||
|
||||
# Define the 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:
|
||||
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}")
|
||||
status.update(label="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.")
|
||||
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)
|
||||
except Exception as err:
|
||||
@@ -87,21 +87,14 @@ def write_blog_from_keywords(search_keywords, url=None):
|
||||
try:
|
||||
generated_image_filepath = generate_image(f"{blog_title} + ' ' + {blog_meta_desc}")
|
||||
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,
|
||||
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}")
|
||||
|
||||
# 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}")
|
||||
status.update(label=f"Finished, Review & Use your Original Content Below: {saved_blog_to_file}", state="complete")
|
||||
|
||||
@@ -1,28 +1,52 @@
|
||||
import sys
|
||||
import streamlit as st
|
||||
|
||||
from loguru import logger
|
||||
import random
|
||||
import time
|
||||
|
||||
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 ..gpt_providers.text_generation.main_text_generation import llm_text_gen
|
||||
|
||||
|
||||
def blog_metadata(blog_article):
|
||||
""" Common function to get blog metadata """
|
||||
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)
|
||||
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)
|
||||
progress_bar.progress(2 / total_steps)
|
||||
|
||||
# Step 3: Generate blog tags
|
||||
time.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))
|
||||
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
|
||||
|
||||
|
||||
def generate_blog_title(blog_article):
|
||||
"""
|
||||
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}")
|
||||
raise err
|
||||
|
||||
|
||||
def generate_blog_description(blog_content):
|
||||
"""
|
||||
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}")
|
||||
raise err
|
||||
|
||||
|
||||
def get_blog_categories(blog_article):
|
||||
"""
|
||||
Function to generate blog categories for given blog content.
|
||||
@@ -80,12 +102,10 @@ def get_blog_categories(blog_article):
|
||||
except Exception as err:
|
||||
logger.error(f"get_blog_categories:Failed to get response from LLM: {err}")
|
||||
|
||||
|
||||
def get_blog_tags(blog_article):
|
||||
"""
|
||||
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
|
||||
for the given blog content. Only reply with comma separated values.
|
||||
Blog content: {blog_article}."""
|
||||
@@ -96,3 +116,4 @@ def get_blog_tags(blog_article):
|
||||
except Exception as err:
|
||||
logger.error(f"Failed to get response from LLM: {err}")
|
||||
raise err
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
import streamlit as st
|
||||
|
||||
import google.generativeai as genai
|
||||
from dotenv import load_dotenv
|
||||
@@ -44,6 +45,7 @@ def gemini_text_response(prompt, temperature, top_p, n, max_tokens):
|
||||
for chunk in response:
|
||||
# text_response.append(chunk.text)
|
||||
print(chunk.text)
|
||||
#st.write(chunk.text)
|
||||
else:
|
||||
print(response)
|
||||
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 */
|
||||
button {
|
||||
div.stButton > button:first-child {
|
||||
background: #1565C0; /* Match tab color */
|
||||
color: white;
|
||||
border: none;
|
||||
@@ -112,8 +112,8 @@ button {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #1976D2; /* Match tab hover color */
|
||||
div.stButton > button:hover:first-child {
|
||||
background-color: #1976A2; /* Match tab hover color */
|
||||
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
|
||||
openai
|
||||
crewai[tools]
|
||||
crewai_tools
|
||||
google.generativeai
|
||||
mistralai
|
||||
tenacity
|
||||
|
||||
Reference in New Issue
Block a user