diff --git a/alwrity.py b/alwrity.py index 246439ed..8b54000d 100644 --- a/alwrity.py +++ b/alwrity.py @@ -8,7 +8,7 @@ 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 +# 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"] @@ -21,6 +21,18 @@ 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) @@ -30,59 +42,70 @@ def get_custom_input(label, options, help_text, placeholder=""): st.warning(f"Please specify your {label.lower()}.") return selection -def sidebar_configuration(): - # Alias for sidebar - sb = st.sidebar +def content_personalization(sb): + """ + Sidebar content personalization section. - sb.title("πŸ› οΈ Personalization & Settings πŸ—οΈ") - + Parameters: + - sb: The Streamlit sidebar object. + + Returns: + - dict: Dictionary containing personalized content configuration. + """ with sb.expander("**πŸ‘· Content Personalization**"): - blog_length = st.text_input("**Content Length (words)**", value="2000", help="Approximate word count for blogs.") - + 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 = st.selectbox("**Content Type**", options=CONTENT_TYPE_OPTIONS, help="Select the category that best describes 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 = st.selectbox("**Content Output Format**", options=OUTPUT_FORMAT_OPTIONS, help="Select the format for the blog output.") - - with sb.expander("**🩻 Images Personalization**"): - image_generation_model = st.selectbox("**Image Generation Model**", options=IMAGE_MODEL_OPTIONS, help="Select the model to generate images for the blog.") - number_of_blog_images = st.number_input("**Number of Blog Images**", value=1, help="Specify the number of images to include in the blog.") - - with sb.expander("**πŸ€– LLM Personalization**"): - gpt_provider = st.selectbox("**GPT Provider**", options=GPT_PROVIDER_OPTIONS, help="Select the provider for the GPT model.") - model = st.text_input("**Model**", value="gemini-1.5-flash-latest", help="Specify the model version to use from the selected provider.") - temperature = st.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 = st.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 = st.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 = 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.") - frequency_penalty = st.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 = 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 sb.expander("**πŸ•΅οΈ Search Engine Personalization**"): - geographic_location = st.selectbox("**Geographic Location**", options=GEOGRAPHIC_LOCATION_OPTIONS, help="Select the geographic location for tailoring search results.") - search_language = st.selectbox("**Search Language**", options=SEARCH_LANGUAGE_OPTIONS, help="Select the language for the search results.") - number_of_results = st.number_input("**Number of Results**", value=10, min_value=1, max_value=20, help="Specify the number of search results to retrieve.") - time_range = st.selectbox("**Time Range**", options=TIME_RANGE_OPTIONS, help="Select the time range for filtering search results.") - include_domains = st.text_input("**Include Domains**", value="", help="List specific domains to include in search results.") - similar_url = st.text_input("**Similar URL**", value="", help="Provide a URL to find similar results.") - - # Storing collected inputs in a dictionary - config = { - "Blog Content Characteristics": { + 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 - }, - "Blog Images Details": { + } + +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 - }, - "LLM Options": { + } + +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, @@ -91,8 +114,26 @@ def sidebar_configuration(): "N": n, "Frequency Penalty": frequency_penalty, "Presence Penalty": presence_penalty - }, - "Search Engine Parameters": { + } + +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, @@ -100,25 +141,34 @@ def sidebar_configuration(): "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 } - # Writing the configuration to a file whenever a change is made + # Save the configuration to a file whenever a change is made save_config(config) -def main(): - #load_environment - load_dotenv() - setup_ui() - - if check_all_api_keys(): - setup_environment_paths() - sidebar_configuration() - setup_tabs() - modify_prompts_sidebar() - - def setup_environment_paths(): - """Sets up environment paths for saving files and configurations.""" + """ + 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") @@ -126,9 +176,10 @@ def setup_environment_paths(): 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.""" + """ + Provides a sidebar for modifying prompts. + """ st.sidebar.title("πŸ“ Modify Prompts") prompts = read_prompts() @@ -144,81 +195,19 @@ def modify_prompts_sidebar(): 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() -# Functions for the main options -def ai_writers(): - options = [ - "AI Blog Writer", - "Story Writer", - "Essay writer", - "Write News reports", - "Write Financial TA report", - "AI Product Description Writer", - "AI Copywriter", - "Quit" - ] - choice = st.selectbox("**πŸ‘‡Select a content creation type:**", options, index=0, format_func=lambda x: f"πŸ“ {x}") - - if choice == "AI Blog Writer": - blog_from_keyword() - elif choice == "Story Writer": - story_input_section() - 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 Product Description Writer": - write_ai_prod_desc() - elif choice == "Quit": - st.subheader("Exiting, Getting Lost. But.... I have nowhere to go πŸ₯ΉπŸ₯Ή") - - -def content_planning_tools(): - 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 calendar around given keywords.""") - - options = [ - "Keywords Researcher", - "Competitor Analysis", - "Content Calender Ideator" - ] - choice = st.radio("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 == "Content Calender Ideator": - plan_keywords = st.text_input( - "**Enter Your main Keywords to get 2 months content calendar:**", - placeholder="Enter 2-3 main keywords to generate AI content calendar with keyword researched blog titles", - help="The keywords are the ones where you would want to generate 50-60 blogs/articles on." - ) - if st.button("**Ideate Content Calender**"): - if plan_keywords: - ai_agents_content_planner(plan_keywords) - else: - st.error("Come on, really, Enter some keywords to plan on..") - - -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: - st.warning("Please enter a valid folder path.") - + if check_all_api_keys(): + setup_environment_paths() + sidebar_configuration() + setup_tabs() + modify_prompts_sidebar() if __name__ == "__main__": main()