From 80c52facc5b80848221a28435526e37641578561 Mon Sep 17 00:00:00 2001 From: AjaySi Date: Sun, 14 Apr 2024 17:54:28 +0530 Subject: [PATCH] Alwrity AI Essay writer --- alwrity.py | 55 +++++- .../text_generation/ai_essay_writer.py | 186 ++++++++++++++++++ .../text_generation/ai_story_writer.py | 2 +- 3 files changed, 241 insertions(+), 2 deletions(-) create mode 100644 lib/gpt_providers/text_generation/ai_essay_writer.py diff --git a/alwrity.py b/alwrity.py index 8e700c0..0b40beb 100644 --- a/alwrity.py +++ b/alwrity.py @@ -7,6 +7,10 @@ from prompt_toolkit import prompt from prompt_toolkit.styles import Style from prompt_toolkit.shortcuts import radiolist_dialog +from prompt_toolkit.formatted_text import HTML +from prompt_toolkit.layout.containers import HSplit, Window +from prompt_toolkit.layout.controls import BufferControl + from dotenv import load_dotenv import requests from rich import print @@ -21,6 +25,7 @@ from lib.ai_writers.keywords_to_blog import write_blog_from_keywords from lib.ai_writers.speech_to_blog.main_audio_to_blog import generate_audio_blog from lib.gpt_providers.text_generation.ai_story_writer import ai_story_generator +from lib.gpt_providers.text_generation.ai_essay_writer import ai_essay_generator def prompt_for_time_range(): @@ -60,6 +65,7 @@ def start_interactive_mode(): choices = [ ("AI Blog Writer", "AI Blog Writer"), ("AI Story Writer", "AI Story Writer"), + ("AI Essay Writer", "AI Essay Writer"), ("Do keyword Research", "Do keyword Research"), ("Create Blog Images(TBD)", "Create Blog Images(TBD)"), ("Competitor Analysis", "Competitor Analysis"), @@ -73,6 +79,8 @@ def start_interactive_mode(): write_blog() elif mode == 'AI Story Writer': write_story() + elif mode == 'AI Essay Writer': + essay_writer() elif mode == 'Do keyword Research': do_web_research() elif mode == 'Create Blog Images(TBD)': @@ -139,7 +147,7 @@ def get_api_key(api_key: str, api_description: str): api_key (str): The name of the API key variable. api_description (str): The description of the API key. """ - user_input = typer.prompt(f"\nπŸ™†πŸ™†Please enter {api_key} API Key:") + user_input = typer.prompt(f"\n\nπŸ™†πŸ’©πŸ’©πŸ™† - Please enter {api_key} API Key:") with open(".env", "a") as env_file: env_file.write(f"{api_key}={user_input}\n") print(f"βœ… {api_description} API Key added to .env file.") @@ -204,6 +212,51 @@ def write_story(): exit(1) + +def essay_writer(): + # Define essay types and education levels + essay_types = [ + ("Argumentative", "Argumentative - Forming an opinion via research. Building an evidence-based argument."), + ("Expository", "Expository - Knowledge of a topic. Communicating information clearly."), + ("Narrative", "Narrative - Creative language use. Presenting a compelling narrative."), + ("Descriptive", "Descriptive - Creative language use. Describing sensory details.") + ] + + education_levels = [ + ("Primary School", "Primary School"), + ("High School", "High School"), + ("College", "College"), + ("Graduate School", "Graduate School") + ] + + # Define the options for number of pages + num_pages_options = [ + ("Short Form (1-2 pages)", "Short Form"), + ("Medium Form (3-5 pages)", "Medium Form"), + ("Long Form (6+ pages)", "Long Form") + ] + + # Ask the user for the title of the essay + essay_title = input_dialog(title="Essay Title", text="Enter the title of your essay:").run() + while not essay_title.strip(): + print("Please enter a valid title for your essay.") + essay_title = input_dialog(title="Essay Title", text="Enter the title of your essay:").run() + + # Ask the user for type of essay, level of education, and number of pages + selected_essay_type = radiolist_dialog(title="Type of Essay", text="Choose the type of essay you want to write:", + values=essay_types).run() + + selected_education_level = radiolist_dialog(title="Level of Education", text="Choose your level of education:", + values=education_levels).run() + + # Prompt the user to select the length of the essay + num_pages_prompt = "Select the length of your essay:" + selected_num_pages = radiolist_dialog(title="Number of Pages", text=num_pages_prompt, values=num_pages_options).run() + + ai_essay_generator(essay_title, selected_essay_type, selected_education_level, selected_num_pages) + + + def blog_tools(): os.system("clear" if os.name == "posix" else "cls") text = "_______________________________________________________________________\n" diff --git a/lib/gpt_providers/text_generation/ai_essay_writer.py b/lib/gpt_providers/text_generation/ai_essay_writer.py new file mode 100644 index 0000000..0f679d2 --- /dev/null +++ b/lib/gpt_providers/text_generation/ai_essay_writer.py @@ -0,0 +1,186 @@ +##################################################### +# +# Alwrity, AI essay writer - Essay_Writing_with_Prompt_Chaining +# +##################################################### + +import os +from pathlib import Path +from dotenv import load_dotenv +from google.api_core import retry +import google.generativeai as genai +from pprint import pprint + + +def generate_with_retry(model, prompt): + """ + Generates content from the model with retry handling for errors. + + Parameters: + model (GenerativeModel): The generative model to use for content generation. + prompt (str): The prompt to generate content from. + + Returns: + str: The generated content. + """ + try: + # FIXME: Need a progress bar here. + return model.generate_content(prompt, request_options={'retry':retry.Retry()}) + except Exception as e: + print(f"Error generating content: {e}") + return "" + + +def ai_essay_generator(essay_title, selected_essay_type, selected_education_level, selected_num_pages): + """ + Write an Essay using prompt chaining and iterative generation. + + Parameters: + persona (str): The persona statement for the author. + story_genre (str): The genre of the story. + characters (str): The characters in the story. + """ + print(f"Starting to write Essay on {essay_title}..") + try: + # Define persona and writing guidelines + guidelines = f'''\ + Writing Guidelines + + As an expert Essay writer and academic researcher, demostrate your world class essay writing skills. + + Follow the below writing guidelines for writing your essay: + 1). You specialize in {selected_essay_type} essay writing. + 2). Your target audiences include readers from {selected_education_level} level. + 3). The title of the essay is {essay_title}. + 4). I will provide you with web research for essay title. + 5). The final essay should of {selected_num_pages} words/pages. + 3). Plant the seeds of subplots or potential character arc shifts that can be expanded later. + + Remember, your main goal is to write as much as you can. If you get through + the story too fast, that is bad. Expand, never summarize. + ''' + # Generate prompts + premise_prompt = f'''\ + As an expert essay writer, specilizing in {selected_essay_type} essay writing. + + Write an Essay title for given keywords {essay_title}. + The title should appeal to audience level of {selected_education_level}. + ''' + + outline_prompt = f'''\ + As an expert essay writer, specilizing in {selected_essay_type} essay writing. + + Your Essay title is: + + {{premise}} + + Write an outline for the essay. + ''' + + starting_prompt = f'''\ + As an expert essay writer, specilizing in {selected_essay_type} essay writing. + + Your essay title is: + + {{premise}} + + The outline of the Essay is: + + {{outline}} + + First, silently review the outline and the essay title. Consider how to start the Essay. + Start to write the very beginning of the Essay. You are not expected to finish + the whole Essay now. Your writing should be detailed enough that you are only + scratching the surface of the first bullet of your outline. Try to write AT + MINIMUM 1000 WORDS. + + {guidelines} + ''' + + continuation_prompt = f'''\ + As an expert essay writer, specilizing in {selected_essay_type} essay writing. + + Your essay title is: + + {{premise}} + + The outline of the Essay is: + + {{outline}} + + You've begun to write the essay and continue to do so. + Here's what you've written so far: + + {{story_text}} + + ===== + + First, silently review the outline and essay so far. + Identify what the single next part of your outline you should write. + + Your task is to continue where you left off and write the next part of the Essay. + You are not expected to finish the whole essay now. Your writing should be + detailed enough that you are only scratching the surface of the next part of + your outline. Try to write AT MINIMUM 1000 WORDS. However, only once the essay + is COMPLETELY finished, write IAMDONE. Remember, do NOT write a whole chapter + right now. + + {guidelines} + ''' + + # Configure generative AI + load_dotenv(Path('../.env')) + genai.configure(api_key=os.getenv('GEMINI_API_KEY')) + # Initialize the generative model + model = genai.GenerativeModel('gemini-1.0-pro') + + # Generate prompts + try: + premise = generate_with_retry(model, premise_prompt).text + print(f"The title of the Essay is: {premise}") + except Exception as err: + print(f"Essay title Generation Error: {err}") + return + + outline = generate_with_retry(model, outline_prompt.format(premise=premise)).text + print(f"The Outline of the essay is: {outline}\n\n") + if not outline: + print("Failed to generate Essay outline. Exiting...") + return + + try: + starting_draft = generate_with_retry(model, + starting_prompt.format(premise=premise, outline=outline)).text + pprint(starting_draft) + except Exception as err: + print(f"Failed to Generate Essay draft: {err}") + return + + try: + draft = starting_draft + continuation = generate_with_retry(model, + continuation_prompt.format(premise=premise, outline=outline, story_text=draft)).text + pprint(continuation) + except Exception as err: + print(f"Failed to write the initial draft: {err}") + + # Add the continuation to the initial draft, keep building the story until we see 'IAMDONE' + try: + draft += '\n\n' + continuation + except Exception as err: + print(f"Failed as: {err} and {continuation}") + while 'IAMDONE' not in continuation: + try: + continuation = generate_with_retry(model, + continuation_prompt.format(premise=premise, outline=outline, story_text=draft)).text + draft += '\n\n' + continuation + except Exception as err: + print(f"Failed to continually write the Essay: {err}") + return + + # Remove 'IAMDONE' and print the final story + final = draft.replace('IAMDONE', '').strip() + pprint(final) + + except Exception as e: + print(f"Main Essay writing: An error occurred: {e}") diff --git a/lib/gpt_providers/text_generation/ai_story_writer.py b/lib/gpt_providers/text_generation/ai_story_writer.py index 7d53b8e..8f90dff 100644 --- a/lib/gpt_providers/text_generation/ai_story_writer.py +++ b/lib/gpt_providers/text_generation/ai_story_writer.py @@ -42,7 +42,7 @@ def ai_story_generator(persona, story_genre, characters): print(f"Starting to write {story_genre} story based on characters: {characters}..") try: # Define persona and writing guidelines - guidelines = '''\ + guidelines = f'''\ Writing Guidelines Delve deeper. Lose yourself in the world you're building. Unleash vivid