WIP - Streamlit UI, Porting CLI
This commit is contained in:
697
alwrity.py
697
alwrity.py
@@ -1,259 +1,518 @@
|
||||
print("Welcome, Alwrity at your service..")
|
||||
import os
|
||||
from pathlib import Path
|
||||
import configparser
|
||||
import json
|
||||
from datetime import datetime
|
||||
|
||||
import typer
|
||||
from prompt_toolkit import prompt
|
||||
from prompt_toolkit.shortcuts import radiolist_dialog
|
||||
|
||||
from dotenv import load_dotenv
|
||||
import requests
|
||||
from rich import print
|
||||
from rich.text import Text
|
||||
load_dotenv(Path('.env'))
|
||||
print("Loading, required libraries..")
|
||||
app = typer.Typer()
|
||||
import streamlit as st
|
||||
|
||||
from lib.utils.alwrity_utils import blog_from_audio, blog_from_keyword, do_web_research, do_web_research, ai_news_writer
|
||||
from lib.utils.alwrity_utils import write_story, essay_writer, blog_tools, ai_finance_ta_writer, ai_content_team
|
||||
from lib.utils.alwrity_utils import content_planning_agents, competitor_analysis, image_to_text_writer, image_generator
|
||||
# Load .env file
|
||||
load_dotenv()
|
||||
|
||||
from lib.chatbot_custom.chatbot_local_docqa import alwrity_chat_docqa
|
||||
from lib.utils.alwrity_streamlit_utils import (
|
||||
blog_from_keyword, ai_agents_team,
|
||||
blog_from_audio, write_story,
|
||||
essay_writer, ai_news_writer,
|
||||
ai_finance_ta_writer, ai_social_writer,
|
||||
do_web_research, competitor_analysis,
|
||||
)
|
||||
|
||||
def prompt_for_time_range():
|
||||
os.system("clear" if os.name == "posix" else "cls")
|
||||
print("\n🙋 If you're researching keywords that are recent, use accordingly. Default is Anytime.\n")
|
||||
choices = [("anytime", "Anytime"), ("past year", "Past Year"), ("past month", "Past Month"),
|
||||
("past week", "Past Week"), ("past day", "Past Day")]
|
||||
selected_time_range = radiolist_dialog(title="Select Search result time range:", values=choices).run()
|
||||
return selected_time_range[0] if selected_time_range else None
|
||||
|
||||
|
||||
def write_blog_options():
|
||||
choices = [
|
||||
("Keywords", "Write from few keywords"),
|
||||
("Audio To Blog", "Write from audio files"),
|
||||
("AI Story Writer", "Story Writer"),
|
||||
("AI Essay Writer", "Essay writer"),
|
||||
("AI News Articles", "Write News reports"),
|
||||
("AI Finance Writer", "Write Financial TA report"),
|
||||
("Social", "AI Social writer(instagram, tweets, linkedin, facebook post)"),
|
||||
("Copywriter", "AI Copywriter"),
|
||||
("Quit", "Quit")
|
||||
]
|
||||
selected_blog_type = radiolist_dialog(title="Choose Content creation Type:", values=choices).run()
|
||||
return selected_blog_type if selected_blog_type else None
|
||||
|
||||
|
||||
@app.command()
|
||||
def start_interactive_mode():
|
||||
os.system("clear" if os.name == "posix" else "cls")
|
||||
text = "_______________________________________________________________________\n"
|
||||
text += "\n⚠️ Alert! 💥❓💥\n"
|
||||
text += "Interactive tool, needs your attention/inputs, get off your mobile..'\n"
|
||||
text += "_______________________________________________________________________\n"
|
||||
print(text)
|
||||
|
||||
choices = [
|
||||
("AI Writers", "Write with AI"),
|
||||
("Content Planning", "Plan Content with AI"),
|
||||
("Content Teams", "AI Content Agent Teams"),
|
||||
("Quit", "Quit")
|
||||
]
|
||||
mode = radiolist_dialog(title="Choose an option:", values=choices).run()
|
||||
if mode:
|
||||
if mode == 'AI Writers':
|
||||
write_blog()
|
||||
elif mode == 'Content Planning':
|
||||
content_planning_tools()
|
||||
elif mode == 'Content Teams':
|
||||
print("AI Content teams")
|
||||
ai_content_team()
|
||||
elif mode == 'Social Media':
|
||||
print(""" #whatsapp #instagram #youtube #twitter/X #Linked-in posts """)
|
||||
raise typer.Exit()
|
||||
elif mode == 'Quit':
|
||||
typer.echo("Exiting, Getting Lost!")
|
||||
raise typer.Exit()
|
||||
|
||||
|
||||
def content_planning_tools():
|
||||
""" """
|
||||
os.system("clear" if os.name == "posix" else "cls")
|
||||
text = "_______________________________________________________________________\n"
|
||||
text += "\n⚠️ Alert! 💥❓💥\n"
|
||||
text += "作家的障碍 - Writer's block - Bloqueo de escritor - Schreibblockade\n"
|
||||
text += "Use Google Keyword planner, google ads instead. Better tools than below.\n"
|
||||
text += "Note: Who Cares, just give some titles, keywords to get started.. To Err is Human & AI..\n"
|
||||
text += "_______________________________________________________________________\n"
|
||||
print(text)
|
||||
|
||||
choices = [
|
||||
("Do keyword Research", "Keywords web research - 🤓 Will read & earn my bread.."),
|
||||
("Competitor Analysis", "Competitor Analysis - 🧐 What's my neighbour doing.."),
|
||||
("Content Calender", "🥹🥹 Just give me content calender 🥹🥹")
|
||||
]
|
||||
mode = radiolist_dialog(title="Choose an option:", values=choices).run()
|
||||
|
||||
if mode == 'Do keyword Research':
|
||||
if check_search_apis():
|
||||
do_web_research()
|
||||
elif mode == 'Competitor Analysis':
|
||||
competitor_analysis()
|
||||
elif mode == 'Content Calender':
|
||||
content_planning_agents()
|
||||
|
||||
|
||||
def check_search_apis():
|
||||
# Custom CSS for styling
|
||||
st.markdown(
|
||||
"""
|
||||
Check if necessary environment variables are present.
|
||||
Display messages with links on how to get them if not present.
|
||||
"""
|
||||
|
||||
# Use rich.print for styling and hyperlinking
|
||||
print("Alwrity uses Basic, Semantic, Neural web search using above APIs for contextual blog generation.\n")
|
||||
|
||||
api_keys = {
|
||||
"METAPHOR_API_KEY": "Metaphor AI Key (Get it here: [link=https://dashboard.exa.ai/login]Metaphor API[/link])",
|
||||
"TAVILY_API_KEY": "Tavily AI Key (Get it here: [link=https://tavily.com/#api]Tavily API[/link])",
|
||||
"SERPER_API_KEY": "Serper API Key (Get it here: [link=https://serper.dev/signup]SerperDev API[/link])",
|
||||
<style>
|
||||
div.row-widget.stRadio > div {
|
||||
flex-direction: row;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
div.row-widget.stRadio > div[role="radiogroup"] > label[data-baseweb="radio"] {
|
||||
background-color: #9AC5F4;
|
||||
padding-right: 10px;
|
||||
padding-left: 4px;
|
||||
padding-bottom: 3px;
|
||||
margin: 4px;
|
||||
}
|
||||
/* Style for the scrollbar track */
|
||||
::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
}
|
||||
|
||||
/* Style for the scrollbar handle */
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: #888;
|
||||
border-radius: 10px;
|
||||
border: 3px solid #f1f1f1;
|
||||
}
|
||||
|
||||
/* Style for the scrollbar handle on hover */
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #555;
|
||||
}
|
||||
|
||||
/* Set the width of the scrollbar */
|
||||
::-webkit-scrollbar {
|
||||
width: 16px;
|
||||
}
|
||||
body {
|
||||
background: #f9f9f9;
|
||||
background-image: linear-gradient(to bottom right, #f0f8ff, #e3f2fd);
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
}
|
||||
.main-header {
|
||||
font-size: 2.5em;
|
||||
font-weight: bold;
|
||||
color: #2196F3;
|
||||
margin-bottom: 10px;
|
||||
text-align: center;
|
||||
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
.stApp {
|
||||
margin-top: -80px;
|
||||
}
|
||||
.sub-header {
|
||||
font-size: 1.75em;
|
||||
font-weight: bold;
|
||||
color: #ff6347;
|
||||
margin-top: 40px;
|
||||
margin-bottom: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
.option-box {
|
||||
border: 2px solid #f0f0f0;
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 2px 2px 12px #aaaaaa;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.button {
|
||||
background: #ff6347; /* Orange */
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
border-radius: 5px; /* Rounded corners */
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
font-size: 16px;
|
||||
margin: 10px 2px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease; /* Smooth transition for hover effect */
|
||||
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2); /* Add a subtle shadow */
|
||||
font-weight: bold; /* Make the text bold */
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
background-color: #ff4d4d; /* Darker orange */
|
||||
box-shadow: 2px 2px 8px rgba(0, 0, 0, 0.3); /* Slightly larger shadow on hover */
|
||||
}
|
||||
.stTabs [role="tab"] {
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
background: #673AB7;
|
||||
padding: 10px;
|
||||
margin: 5px;
|
||||
border-radius: 5px;
|
||||
border: 2px solid #ddd;
|
||||
transition: background 0.3s ease;
|
||||
}
|
||||
.stTabs [role="tab"]:hover {
|
||||
background: #9575CD;
|
||||
}
|
||||
.stTabs [role="tab"][aria-selected="true"] {
|
||||
background: #D1C4E9;
|
||||
color: #333;
|
||||
border: 2px solid #673AB7;
|
||||
}
|
||||
.sidebar-header {
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.sidebar-option {
|
||||
margin-bottom: 10px;
|
||||
font-size: 1.2em;
|
||||
color: #2196F3;
|
||||
}
|
||||
.content-section {
|
||||
padding: 20px;
|
||||
margin-bottom: 30px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 2px 2px 10px #ddd;
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
.content-title {
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
color: #333;
|
||||
}
|
||||
</style>
|
||||
""",
|
||||
unsafe_allow_html=True
|
||||
)
|
||||
|
||||
|
||||
# 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)"
|
||||
}
|
||||
missing_keys = []
|
||||
|
||||
with typer.progressbar(api_keys.items(), label="Checking API keys", length=len(api_keys)) as progress:
|
||||
for key, description in progress:
|
||||
if os.getenv(key) is None:
|
||||
# Use rich.print for styling and hyperlinking
|
||||
print(f"[bold red]✖ 🚫 {key} is missing:[/bold red] [blue underline]Get {key} API Key[/blue underline]")
|
||||
missing_keys.append((key, description))
|
||||
for key, description in api_keys.items():
|
||||
if os.getenv(key) is None:
|
||||
missing_keys.append((key, description))
|
||||
|
||||
if missing_keys:
|
||||
print("\nMost are Free APIs and really worth your while signing up for them.")
|
||||
print("💩💩💩: GO GET THEM, on above urls. [bold red]")
|
||||
#print("Note: They offer free/limited api calls, so we use most of them to have a lot of free api calls.")
|
||||
st.warning(f"API keys are missing. Please provide them below:{missing_keys}")
|
||||
for key, description in missing_keys:
|
||||
get_api_key(key, description)
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
def get_api_key(api_key: str, api_description: str):
|
||||
"""
|
||||
Ask the user to input the missing API key and add it to the .env file.
|
||||
|
||||
Args:
|
||||
api_key (str): The name of the API key variable.
|
||||
api_description (str): The description of the API key.
|
||||
"""
|
||||
print("\n\n")
|
||||
print(f"[bold green] 🙋 Attention Here: 🙋 -- {api_description}")
|
||||
user_input = typer.prompt(f"💩 -**Please Enter(copy/paste) {api_key} API Key** - Here🙋:")
|
||||
with open(".env", "a") as env_file:
|
||||
env_file.write(f"{api_key}={user_input}\n")
|
||||
print(f"✅ API Key added to .env file.")
|
||||
|
||||
|
||||
def write_blog():
|
||||
blog_type = write_blog_options()
|
||||
if blog_type:
|
||||
if blog_type == 'Keywords':
|
||||
blog_from_keyword()
|
||||
elif blog_type == 'AI Story Writer':
|
||||
write_story()
|
||||
elif blog_type == 'AI Essay Writer':
|
||||
essay_writer()
|
||||
elif blog_type == 'Audio To Blog':
|
||||
blog_from_audio()
|
||||
elif blog_type == 'AI News Articles':
|
||||
ai_news_writer()
|
||||
elif blog_type == 'AI Finance Writer':
|
||||
ai_finance_ta_writer()
|
||||
elif blog_type == 'Quit':
|
||||
typer.echo("Exiting, Getting Lost..")
|
||||
raise typer.Exit()
|
||||
api_key = st.text_input(f"Enter {key}:", placeholder=description, help=description)
|
||||
if api_key:
|
||||
with open(".env", "a") as env_file:
|
||||
env_file.write(f"{key}={api_key}\n")
|
||||
os.environ[key] = api_key
|
||||
st.success(f"{key} added successfully! Enter to Continue..")
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
# Function to check LLM provider and API key
|
||||
def check_llm_environs():
|
||||
""" Function to check which LLM api is given. """
|
||||
# Load .env file
|
||||
load_dotenv(Path('.env'))
|
||||
gpt_provider = os.getenv("GPT_PROVIDER")
|
||||
|
||||
# Disable unsupported GPT providers
|
||||
supported_providers = ['google', 'openai', 'mistralai']
|
||||
|
||||
if gpt_provider is None or gpt_provider.lower() not in map(str.lower, supported_providers):
|
||||
# Prompt user to select a provider
|
||||
gpt_provider = radiolist_dialog(
|
||||
title="Select your GPT Provider(llm) from 'google', 'openai', 'mistralai'",
|
||||
values=[("google", "Google Gemini Pro"), ("openai", "OpenAI- ChatGPT"), ("mistralai", "MistralAI/WIP")]).run()
|
||||
# Update .env file
|
||||
gpt_provider = st.selectbox(
|
||||
"Select your LLM Provider",
|
||||
options=["google", "openai", "mistralai"],
|
||||
help="Select from 'google', 'openai', 'mistralai'"
|
||||
)
|
||||
os.environ["GPT_PROVIDER"] = gpt_provider
|
||||
with open(".env", "a") as env_file:
|
||||
env_file.write(f"GPT_PROVIDER={gpt_provider}\n")
|
||||
print(f"✅ API Key added to .env file.")
|
||||
st.success(f"GPT Provider set to {gpt_provider}")
|
||||
|
||||
api_key_var = ""
|
||||
if gpt_provider.lower() == "google":
|
||||
api_key_var = "GEMINI_API_KEY"
|
||||
missing_api_msg = f"To get your {api_key_var}, please visit: https://aistudio.google.com/app/apikey"
|
||||
elif gpt_provider.lower() == "openai":
|
||||
missing_api_msg = "To get your Gemini API key, please visit: https://aistudio.google.com/app/apikey"
|
||||
elif gpt_provider.lower() == "openai":
|
||||
api_key_var = "OPENAI_API_KEY"
|
||||
missing_api_msg = "To get your OpenAI API key, please visit: https://openai.com/blog/openai-api"
|
||||
elif gpt_provider.lower() == "mistralai":
|
||||
api_key_var = "MISTRAL_API_KEY"
|
||||
missing_api_msg = "To get your MistralAI API key, please visit: https://mistralai.com/api"
|
||||
|
||||
if api_key_var not in os.environ:
|
||||
get_api_key(api_key_var, missing_api_msg)
|
||||
if os.getenv(api_key_var) is None:
|
||||
api_key = st.text_input(f"Enter {api_key_var}:", placeholder=missing_api_msg, help=missing_api_msg)
|
||||
if api_key:
|
||||
with open(".env", "a") as env_file:
|
||||
env_file.write(f"{api_key_var}={api_key}\n")
|
||||
os.environ[api_key_var] = api_key
|
||||
st.success(f"{api_key_var} added successfully! Enter to continue..")
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def check_internet():
|
||||
try:
|
||||
response = requests.get("http://www.google.com", timeout=5)
|
||||
if not response.status_code == 200:
|
||||
print("💥🤯 WTFish, Internet is NOT available. Enjoy the wilderness..")
|
||||
exit(1)
|
||||
# Function to save configuration to a file
|
||||
def save_config(config):
|
||||
with open(os.getenv("ALWRITY_CONFIG"), "w") as config_file:
|
||||
json.dump(config, config_file, indent=4)
|
||||
|
||||
|
||||
# Sidebar configuration
|
||||
def sidebar_configuration():
|
||||
st.sidebar.title("🛠️ Personalization 🏗️")
|
||||
|
||||
with st.sidebar.expander("**👷 Content Personalization**"):
|
||||
blog_length = st.text_input("**Content Length**", value="2000",
|
||||
help="Length of blogs Or word count. Note: It won't be exact and depends on GPT providers and Max token count.")
|
||||
blog_tone = st.selectbox("**Content Tone**",
|
||||
options=["Casual", "Professional", "How-to", "Beginner", "Research", "Programming", "Social Media"],
|
||||
help="Choose the tone of the blog.")
|
||||
blog_demographic = st.selectbox("Target Audience",
|
||||
options=["Working professional", "Content creators & Digital marketing", "Gen-Z", "Tech-savvy", "Students", "Kids"],
|
||||
help="Choose the target audience.")
|
||||
blog_type = st.selectbox("Content Type",
|
||||
options=["Informational", "Commercial", "Company", "News", "Finance", "Competitor", "Programming", "Scholar"],
|
||||
help="Choose the type of the blog.")
|
||||
blog_language = st.selectbox("Content Language",
|
||||
options=["English", "Spanish", "German", "Chinese", "Arabic", "Nepali", "Hindi", "Hindustani"],
|
||||
help="Choose the language of the blog.")
|
||||
blog_output_format = st.selectbox("Content Output Format",
|
||||
options=["markdown", "HTML", "plaintext"],
|
||||
help="Choose the output format of the blog.")
|
||||
|
||||
with st.sidebar.expander("**🩻 Images Personalization**"):
|
||||
image_generation_model = st.selectbox("Image Generation Model",
|
||||
options=["stable-diffusion", "dalle2", "dalle3"],
|
||||
help="Choose the image generation model.")
|
||||
number_of_blog_images = st.number_input("Number of Blog Images", value=1, help="Number of blog images to include.")
|
||||
|
||||
with st.sidebar.expander("**🤖 LLM Personalization**"):
|
||||
gpt_provider = st.selectbox("GPT Provider",
|
||||
options=["google", "openai", "minstral"],
|
||||
help="Choose the GPT provider.")
|
||||
model = st.text_input("Model", value="gemini-1.5-flash-latest", help="Mention which model of the above provider to use.")
|
||||
temperature = st.slider(
|
||||
"Temperature",
|
||||
min_value=0.1,
|
||||
max_value=1.0,
|
||||
value=0.7,
|
||||
step=0.1,
|
||||
format="%.1f",
|
||||
help="""Temperature controls the 'creativity' or randomness of the text generated by GPT.
|
||||
Greater determinism with higher values indicating more randomness."""
|
||||
)
|
||||
|
||||
top_p = st.slider(
|
||||
"Top-p",
|
||||
min_value=0.0,
|
||||
max_value=1.0,
|
||||
value=0.9,
|
||||
step=0.1,
|
||||
format="%.1f",
|
||||
help="Top-p sampling controls the level of diversity in the generated text."
|
||||
)
|
||||
|
||||
# Selectbox for max tokens
|
||||
max_tokens_options = [500, 1000, 2000, 4000, 16000, 32000, 64000]
|
||||
max_tokens = st.selectbox(
|
||||
"Max Tokens",
|
||||
options=max_tokens_options,
|
||||
index=max_tokens_options.index(4000),
|
||||
help="Max tokens determine the maximum length of the output sequence generated by a model."
|
||||
)
|
||||
n = st.number_input("N",
|
||||
value=1,
|
||||
min_value=1,
|
||||
max_value=10,
|
||||
help="Defines the number of words or characters grouped together in a sequence when analyzing text.")
|
||||
frequency_penalty = st.slider(
|
||||
"Frequency Penalty",
|
||||
min_value=0.0,
|
||||
max_value=2.0,
|
||||
value=1.0,
|
||||
step=0.1,
|
||||
format="%.1f",
|
||||
help="Influences word selection during text generation, promoting diversity with higher values."
|
||||
)
|
||||
|
||||
presence_penalty = st.slider(
|
||||
"Presence Penalty",
|
||||
min_value=0.0,
|
||||
max_value=2.0,
|
||||
value=1.0,
|
||||
step=0.1,
|
||||
format="%.1f",
|
||||
help="Encourages the use of diverse words by discouraging repetition."
|
||||
)
|
||||
|
||||
with st.sidebar.expander("**🕵️ Search Engine Personalization**"):
|
||||
geographic_location = st.selectbox("Geographic Location",
|
||||
options=["us", "in", "fr", "cn"],
|
||||
help="Choose the geo location for the web search.")
|
||||
search_language = st.selectbox("Search Language",
|
||||
options=["en", "zn-cn", "de", "hi"],
|
||||
help="Choose the language for search results.")
|
||||
number_of_results = st.number_input("Number of Results",
|
||||
value=10,
|
||||
max_value=20,
|
||||
min_value=1,
|
||||
help="Number of Google search results to fetch.")
|
||||
time_range = st.selectbox("Time Range",
|
||||
options=["anytime", "past day", "past week", "past month", "past year"],
|
||||
help="Choose the time range for search results.")
|
||||
include_domains = st.text_input("Include Domains", value="",
|
||||
help="A list of domains to specifically include in the search results. Default is None, which includes all domains.")
|
||||
similar_url = st.text_input("Similar URL", value="", help="A single URL that instructs search engines to give results similar to the given URL.")
|
||||
|
||||
# Storing collected inputs in a dictionary
|
||||
config = {
|
||||
"Blog Content Characteristics": {
|
||||
"Blog Length": blog_length,
|
||||
"Blog Tone": blog_tone,
|
||||
"Blog Demographic": blog_demographic,
|
||||
"Blog Type": blog_type,
|
||||
"Blog Language": blog_language,
|
||||
"Blog Output Format": blog_output_format
|
||||
},
|
||||
"Blog Images Details": {
|
||||
"Image Generation Model": image_generation_model,
|
||||
"Number of Blog Images": number_of_blog_images
|
||||
},
|
||||
"LLM Options": {
|
||||
"GPT Provider": gpt_provider,
|
||||
"Model": model,
|
||||
"Temperature": temperature,
|
||||
"Top-p": top_p,
|
||||
"Max Tokens": max_tokens,
|
||||
"N": n,
|
||||
"Frequency Penalty": frequency_penalty,
|
||||
"Presence Penalty": presence_penalty
|
||||
},
|
||||
"Search Engine Parameters": {
|
||||
"Geographic Location": geographic_location,
|
||||
"Search Language": search_language,
|
||||
"Number of Results": number_of_results,
|
||||
"Time Range": time_range,
|
||||
"Include Domains": include_domains,
|
||||
"Similar URL": similar_url
|
||||
}
|
||||
}
|
||||
|
||||
# Writing the configuration to a file whenever a change is made
|
||||
save_config(config)
|
||||
|
||||
|
||||
|
||||
# Function to read prompts from the file
|
||||
def read_prompts(file_path="prompt_llm.txt"):
|
||||
if os.path.exists(file_path):
|
||||
with open(file_path, "r") as file:
|
||||
prompts = file.readlines()
|
||||
return [prompt.strip() for prompt in prompts]
|
||||
return []
|
||||
|
||||
# Function to write prompts to the file
|
||||
def write_prompts(prompts, file_path="prompt_llm.txt"):
|
||||
with open(file_path, "w") as file:
|
||||
for prompt in prompts:
|
||||
file.write(f"{prompt}\n")
|
||||
|
||||
def main():
|
||||
st.markdown("<div class='main-header'>Welcome to Alwrity!</div>", unsafe_allow_html=True)
|
||||
# Export the paths and file names. Dont want alwrity to be chatty and prompt for inputs.
|
||||
os.environ["SEARCH_SAVE_FILE"] = os.path.join(os.getcwd(), "lib", "workspace", "web_research_report",
|
||||
f"web_research_report_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}")
|
||||
os.environ["IMG_SAVE_DIR"] = os.path.join(os.getcwd(), "lib", "workspace", "generated_content")
|
||||
os.environ["CONTENT_SAVE_DIR"] = os.path.join(os.getcwd(), "lib", "workspace", "generated_content")
|
||||
os.environ["PROMPTS_DIR"] = os.path.join(os.getcwd(), "lib", "workspace", "prompts")
|
||||
os.environ["ALWRITY_CONFIG"] = os.path.join(os.getcwd(), "lib", "workspace", "alwrity_config", "main_config.json")
|
||||
|
||||
# Check API keys and LLM environment settings
|
||||
api_keys_valid = check_api_keys()
|
||||
llm_environs_valid = check_llm_environs()
|
||||
|
||||
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.")
|
||||
st.stop()
|
||||
|
||||
# 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 tab2:
|
||||
content_planning_tools()
|
||||
|
||||
with tab3:
|
||||
ai_agents_team()
|
||||
|
||||
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()
|
||||
|
||||
# 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 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
|
||||
def write_blog():
|
||||
options = [
|
||||
"Write from few keywords",
|
||||
"Write from audio files",
|
||||
"Story Writer",
|
||||
"Essay writer",
|
||||
"Write News reports",
|
||||
"Write Financial TA report",
|
||||
"AI Social writer (instagram, tweets, linkedin, facebook post)",
|
||||
"AI Copywriter",
|
||||
"Quit"
|
||||
]
|
||||
choice = st.selectbox("**Select a content creation type:**", options, index=0, format_func=lambda x: f"📝 {x}")
|
||||
|
||||
if choice == "Write from few keywords":
|
||||
blog_from_keyword()
|
||||
elif choice == "Write from audio files":
|
||||
blog_from_audio()
|
||||
elif choice == "Story Writer":
|
||||
write_story()
|
||||
elif choice == "Essay writer":
|
||||
essay_writer()
|
||||
elif choice == "Write News reports":
|
||||
ai_news_writer()
|
||||
elif choice == "Write Financial TA report":
|
||||
ai_finance_ta_writer()
|
||||
elif choice == "AI Social writer (instagram, tweets, linkedin, facebook post)":
|
||||
ai_social_writer()
|
||||
elif choice == "Quit":
|
||||
st.write("Exiting, Getting Lost. But.... I have nowhere to go 🥹🥹")
|
||||
|
||||
|
||||
def content_planning_tools():
|
||||
st.markdown("<div class='sub-header'>Content Planning</div>", unsafe_allow_html=True)
|
||||
st.markdown("""**Alwrity content Ideation & Planning** : Provide few keywords to do comprehensive web research.
|
||||
Provide few keywords to get Google, Neural, pytrends analysis. Know keywords, blog titles to target.
|
||||
Generate months long content calender around given keywords.""")
|
||||
options = [
|
||||
"Keywords Researcher",
|
||||
"Competitor Analysis"
|
||||
]
|
||||
choice = st.selectbox("Select a content planning tool:", options, index=0, format_func=lambda x: f"🔍 {x}")
|
||||
|
||||
if choice == "Keywords Researcher":
|
||||
do_web_research()
|
||||
elif choice == "Competitor Analysis":
|
||||
competitor_analysis()
|
||||
#elif choice == "Get Content Calender":
|
||||
# planning_agents()
|
||||
|
||||
|
||||
def alwrity_brain():
|
||||
st.title("🧠 Alwrity Brain, Better than yours!")
|
||||
st.write("Choose a folder to write content on. Alwrity will do RAG on these documents. The documents can of any type, pdf, pptx, docs, txt, cs etc. Video files and Audio files are also permitted.")
|
||||
|
||||
folder_path = st.text_input("**Enter folder path:**")
|
||||
if st.button("**Process Folder**"):
|
||||
if folder_path:
|
||||
try:
|
||||
process_folder_for_rag(folder_path)
|
||||
st.success("Folder processed successfully!")
|
||||
except Exception as e:
|
||||
st.error(f"Error processing folder: {e}")
|
||||
else:
|
||||
return
|
||||
except requests.ConnectionError:
|
||||
print("💥🤯 WTFish: Internet is NOT available. Enjoy the wilderness..")
|
||||
exit(1)
|
||||
except requests.Timeout:
|
||||
print("Request timed out. Internet might be slow.")
|
||||
exit(1)
|
||||
except Exception as e:
|
||||
print("Internet: An error occurred:", e)
|
||||
exit(1)
|
||||
st.warning("Please enter a valid folder path.")
|
||||
|
||||
|
||||
def create_env_file():
|
||||
env_file = Path('.env')
|
||||
if not env_file.is_file():
|
||||
try:
|
||||
with open('.env', 'w') as f:
|
||||
f.write('# Alwrity will add your environment variables here\n')
|
||||
except Exception as e:
|
||||
print(f"💥🤯Error occurred while creating .env file: {e}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
print("Checking Internet..")
|
||||
check_internet()
|
||||
print("Creating .env file")
|
||||
create_env_file()
|
||||
print("Checking Search APIs..")
|
||||
check_search_apis()
|
||||
print("Checking LLM APIs..")
|
||||
check_llm_environs()
|
||||
main()
|
||||
|
||||
# Export the paths and file names. Dont want alwrity to be chatty and prompt for inputs.
|
||||
os.environ["SEARCH_SAVE_FILE"] = os.path.join(os.getcwd(), "lib", "workspace",
|
||||
f"web_research_report_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}")
|
||||
os.environ["IMG_SAVE_DIR"] = os.path.join(os.getcwd(), "lib", "workspace")
|
||||
os.environ["CONTENT_SAVE_DIR"] = os.path.join(os.getcwd(), "lib", "workspace")
|
||||
os.environ["PROMPTS_DIR"] = os.path.join(os.getcwd(), "lib", "workspace", "prompts")
|
||||
|
||||
load_dotenv(Path('.env'))
|
||||
app()
|
||||
|
||||
Reference in New Issue
Block a user