Files
ALwrity/alwrity.py
ي 44e5f7dc1f Refactor, modular code & comments for maintainability
Modularize Code: Break down the large sidebar_configuration function into smaller, more manageable functions to improve readability and maintainability.

Error Handling: Implement error handling for critical operations, such as reading and writing files, to ensure the application handles exceptions gracefully.

Docstrings and Comments: Add docstrings and comments to functions and critical code sections to improve code documentation and readability.

Code Consistency: Ensure consistent use of naming conventions and code formatting.
2025-01-15 19:40:25 +05:30

215 lines
10 KiB
Python

import streamlit as st
import os
import json
from dotenv import load_dotenv
from datetime import datetime
from lib.utils.config_manager import save_config
from lib.utils.ui_setup import setup_ui, setup_tabs
from lib.utils.api_key_manager import check_all_api_keys
from lib.utils.file_processor import read_prompts, write_prompts
# Constants for various options
BLOG_TONE_OPTIONS = ["Casual", "Professional", "How-to", "Beginner", "Research", "Programming", "Social Media", "Customize"]
BLOG_DEMOGRAPHIC_OPTIONS = ["Professional", "Gen-Z", "Tech-savvy", "Student", "Digital Marketing", "Customize"]
BLOG_LANGUAGE_OPTIONS = ["English", "Spanish", "German", "Chinese", "Arabic", "Nepali", "Hindi", "Hindustani", "Customize"]
CONTENT_TYPE_OPTIONS = ["Informational", "Commercial", "Company", "News", "Finance", "Competitor", "Programming", "Scholar"]
OUTPUT_FORMAT_OPTIONS = ["markdown", "HTML", "plaintext"]
IMAGE_MODEL_OPTIONS = ["stable-diffusion", "dalle2", "dalle3"]
GPT_PROVIDER_OPTIONS = ["google", "openai", "minstral"]
GEOGRAPHIC_LOCATION_OPTIONS = ["us", "in", "fr", "cn"]
SEARCH_LANGUAGE_OPTIONS = ["en", "zn-cn", "de", "hi"]
TIME_RANGE_OPTIONS = ["anytime", "past day", "past week", "past month", "past year"]
def get_custom_input(label, options, help_text, placeholder=""):
"""
Get custom input from the user.
Parameters:
- label (str): The label for the input field.
- options (list): List of options for the select box.
- help_text (str): Help text for the select box.
- placeholder (str): Placeholder text for the custom input field.
Returns:
- str: The selected or custom input value.
"""
selection = st.selectbox(f"**{label}**", options=options, help=help_text)
if selection == "Customize":
custom_input = st.text_input(f"Enter your {label.lower()}", help=f"Specify your {label.lower()}.", placeholder=placeholder)
if custom_input:
selection = custom_input
else:
st.warning(f"Please specify your {label.lower()}.")
return selection
def content_personalization(sb):
"""
Sidebar content personalization section.
Parameters:
- sb: The Streamlit sidebar object.
Returns:
- dict: Dictionary containing personalized content configuration.
"""
with sb.expander("**👷 Content Personalization**"):
blog_length = sb.text_input("**Content Length (words)**", value="2000", help="Approximate word count for blogs.")
blog_tone = get_custom_input("Content Tone", BLOG_TONE_OPTIONS, "Select the desired tone for the blog content.")
blog_demographic = get_custom_input("Target Audience", BLOG_DEMOGRAPHIC_OPTIONS, "Select the primary audience for the blog content.", "Eg. Domain expert, Content creator, Financial expert etc.")
blog_type = sb.selectbox("**Content Type**", options=CONTENT_TYPE_OPTIONS, help="Select the category that best describes the blog content.")
blog_language = get_custom_input("Content Language", BLOG_LANGUAGE_OPTIONS, "Select the language in which the blog will be written.")
blog_output_format = sb.selectbox("**Content Output Format**", options=OUTPUT_FORMAT_OPTIONS, help="Select the format for the blog output.")
return {
"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
}
def images_personalization(sb):
"""
Sidebar images personalization section.
Parameters:
- sb: The Streamlit sidebar object.
Returns:
- dict: Dictionary containing personalized images configuration.
"""
with sb.expander("**🩻 Images Personalization**"):
image_generation_model = sb.selectbox("**Image Generation Model**", options=IMAGE_MODEL_OPTIONS, help="Select the model to generate images for the blog.")
number_of_blog_images = sb.number_input("**Number of Blog Images**", value=1, help="Specify the number of images to include in the blog.")
return {
"Image Generation Model": image_generation_model,
"Number of Blog Images": number_of_blog_images
}
def llm_personalization(sb):
"""
Sidebar LLM personalization section.
Parameters:
- sb: The Streamlit sidebar object.
Returns:
- dict: Dictionary containing personalized LLM configuration.
"""
with sb.expander("**🤖 LLM Personalization**"):
gpt_provider = sb.selectbox("**GPT Provider**", options=GPT_PROVIDER_OPTIONS, help="Select the provider for the GPT model.")
model = sb.text_input("**Model**", value="gemini-1.5-flash-latest", help="Specify the model version to use from the selected provider.")
temperature = sb.slider("Temperature", min_value=0.1, max_value=1.0, value=0.7, step=0.1, format="%.1f", help="Controls the 'creativity' or randomness of the text generated.")
top_p = sb.slider("Top-p", min_value=0.0, max_value=1.0, value=0.9, step=0.1, format="%.1f", help="Controls the level of diversity in the generated text.")
max_tokens = sb.selectbox("Max Tokens", options=[500, 1000, 2000, 4000, 16000, 32000, 64000], index=3, help="Maximum length of the output sequence generated by a model.")
n = sb.number_input("N", value=1, min_value=1, max_value=10, help="Defines the number of words or characters grouped together in a sequence.")
frequency_penalty = sb.slider("Frequency Penalty", min_value=0.0, max_value=2.0, value=1.0, step=0.1, format="%.1f", help="Promotes diversity with higher values.")
presence_penalty = sb.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.")
return {
"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
}
def search_engine_personalization(sb):
"""
Sidebar search engine personalization section.
Parameters:
- sb: The Streamlit sidebar object.
Returns:
- dict: Dictionary containing personalized search engine configuration.
"""
with sb.expander("**🕵️ Search Engine Personalization**"):
geographic_location = sb.selectbox("**Geographic Location**", options=GEOGRAPHIC_LOCATION_OPTIONS, help="Select the geographic location for tailoring search results.")
search_language = sb.selectbox("**Search Language**", options=SEARCH_LANGUAGE_OPTIONS, help="Select the language for the search results.")
number_of_results = sb.number_input("**Number of Results**", value=10, min_value=1, max_value=20, help="Specify the number of search results to retrieve.")
time_range = sb.selectbox("**Time Range**", options=TIME_RANGE_OPTIONS, help="Select the time range for filtering search results.")
include_domains = sb.text_input("**Include Domains**", value="", help="List specific domains to include in search results.")
similar_url = sb.text_input("**Similar URL**", value="", help="Provide a URL to find similar results.")
return {
"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
}
def sidebar_configuration():
"""
Sidebar configuration for personalization and settings.
This function consolidates various personalization settings into the sidebar.
"""
sb = st.sidebar
sb.title("🛠️ Personalization & Settings 🏗️")
content_config = content_personalization(sb)
images_config = images_personalization(sb)
llm_config = llm_personalization(sb)
search_config = search_engine_personalization(sb)
config = {
"Blog Content Characteristics": content_config,
"Blog Images Details": images_config,
"LLM Options": llm_config,
"Search Engine Parameters": search_config
}
# Save the configuration to a file whenever a change is made
save_config(config)
def setup_environment_paths():
"""
Sets up environment paths for saving files and configurations.
"""
os.environ["SEARCH_SAVE_FILE"] = os.path.join(os.getcwd(), "lib", "workspace", "alwrity_web_research",
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", "alwrity_content")
os.environ["CONTENT_SAVE_DIR"] = os.path.join(os.getcwd(), "lib", "workspace", "alwrity_content")
os.environ["PROMPTS_DIR"] = os.path.join(os.getcwd(), "lib", "workspace", "alwrity_prompts")
os.environ["ALWRITY_CONFIG"] = os.path.join(os.getcwd(), "lib", "workspace", "alwrity_config", "main_config.json")
def modify_prompts_sidebar():
"""
Provides a sidebar for modifying prompts.
"""
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.")
def main():
"""
Main function to run the Streamlit app.
Initializes the environment, checks API keys, sets up paths, and configures the UI.
"""
load_dotenv()
setup_ui()
if check_all_api_keys():
setup_environment_paths()
sidebar_configuration()
setup_tabs()
modify_prompts_sidebar()
if __name__ == "__main__":
main()