From 656233f41d1000f83b4285bbb25360a45e77cc2f Mon Sep 17 00:00:00 2001 From: "Estrada Irribarra, Rodrigo Andres" Date: Tue, 15 Oct 2024 12:46:27 -0300 Subject: [PATCH] fix: Minor bugs and improve cover prompts --- examples/example_usage.md | 9 +++++++++ storycraftr/agent/chapters.py | 17 ++++++++++++----- storycraftr/cli.py | 10 ++++++---- storycraftr/cmd/chapters.py | 2 +- storycraftr/prompts/chapters.py | 10 +++++++++- storycraftr/utils/core.py | 4 +++- 6 files changed, 40 insertions(+), 12 deletions(-) diff --git a/examples/example_usage.md b/examples/example_usage.md index 8ac0dfa..54172e7 100644 --- a/examples/example_usage.md +++ b/examples/example_usage.md @@ -17,3 +17,12 @@ storycraftr worldbuilding culture "Describe the culture of a dystopian society w storycraftr worldbuilding technology "Describe the technology of a dystopian world where advanced biotechnology and nanotechnology are perceived as magic. Focus on the elite's use of this technology for immortality, enhanced abilities, and control over the workers, who are unaware of its true nature." storycraftr worldbuilding magic-system "Describe the magic system in a dystopian world where advanced biotechnology and nanotechnology are mistaken for magic. Explain how the elite families use this 'magic' to control the population, and how the workers have developed their own beliefs around it." + +storycraftr chapters chapter 1 "Write Chapter 1 based on the synopsis provided: Zevid is in the final stages of his grand plan. As the rebellion rages outside, he prepares to infiltrate the Dark Tower, the center of the elites' control over biotechnology. The rebellion he orchestrated serves as a distraction while he pursues his true goal of seizing the power within the tower." + +storycraftr chapters chapter 2 "Write Chapter 2 based on the synopsis provided: Zevid continues to manipulate the false hero leading the workers. While the workers believe they are liberating themselves from the elite, Zevid uses their blind trust to further his own ends." + +storycraftr chapters cover "Generate a cover text for the novel 'The Purge of the Gods' where a villain manipulates both the elite and the workers in a dystopian world of advanced technology disguised as magic." + +storycraftr chapters cover "Generate a cover text for the novel 'The Purge of the Gods' where a villain manipulates both the elite and the workers in a dystopian world of advanced technology disguised as magic." + diff --git a/storycraftr/agent/chapters.py b/storycraftr/agent/chapters.py index 1f26378..34d6683 100644 --- a/storycraftr/agent/chapters.py +++ b/storycraftr/agent/chapters.py @@ -15,12 +15,12 @@ console = Console() # Function to generate a new chapter based on a prompt -def generate_chapter(book_name, prompt, chapter_number): +def generate_chapter(book_name, chapter_number, prompt): """Generate a new chapter based on a prompt.""" console.print(f"[bold blue]Generating chapter {chapter_number}...[/bold blue]") # Progress message assistant = create_or_get_assistant(book_name) thread = get_thread() - + # Prepare the chapter file path chapter_file = f"chapter-{chapter_number}.md" file_path = os.path.join(book_name, 'chapters', chapter_file) @@ -86,18 +86,25 @@ def generate_cover(book_name, prompt): def generate_back_cover(book_name, prompt): """Generate the back cover page for the book.""" console.print("[bold blue]Generating back cover...[/bold blue]") # Progress message + config = load_book_config(book_name) assistant = create_or_get_assistant(book_name) thread = get_thread() # Generate the back cover content back_cover_content = create_message( thread_id=thread.id, - content=BACK_COVER_PROMPT.format(prompt=prompt, language=load_book_config(book_name).primary_language), + content=BACK_COVER_PROMPT.format( title=config.book_name, + author=config.default_author, + genre=config.genre, + alternate_languages=', '.join(config.alternate_languages), + prompt=prompt, + language=config.primary_language, + license=config.license), assistant=assistant - ) + ) # Save to markdown - save_to_markdown(book_name, "chapters/back_cover.md", "Back Cover", back_cover_content) + save_to_markdown(book_name, "chapters/back-cover.md", "Back Cover", back_cover_content) console.print("[bold green]✔ Back cover generated successfully[/bold green]") # Success message update_agent_files(book_name, assistant) return back_cover_content diff --git a/storycraftr/cli.py b/storycraftr/cli.py index a5b6241..3e9aab6 100644 --- a/storycraftr/cli.py +++ b/storycraftr/cli.py @@ -31,7 +31,7 @@ def project_not_initialized_error(book_name): console.print(f"[bold red]✖[/bold red] Project '[bold]{book_name}[/bold]' is not initialized. " f"Run '[bold]storycraftr init {book_name}[/bold]' first.", style="bold red") -def init_structure(book_name, primary_language, alternate_languages, default_author, genre, behavior_content): +def init_structure(book_name, license, primary_language, alternate_languages, default_author, genre, behavior_content): # Show initialization start console.print(f"[bold blue]Initializing book structure: {book_name}[/bold blue]") @@ -56,7 +56,8 @@ def init_structure(book_name, primary_language, alternate_languages, default_aut "primary_language": primary_language, "alternate_languages": alternate_languages, "default_author": default_author, - "genre": genre + "genre": genre, + "license": license } config_file = os.path.join(book_name, 'storycraftr.json') @@ -88,12 +89,13 @@ def cli(): @click.command() @click.argument("book_name") +@click.option("--license", default="CC BY-NC-SA", help="Define the type of Creative Commons license to use. Options include 'CC BY', 'CC BY-SA', 'CC BY-ND', 'CC BY-NC', 'CC BY-NC-SA', 'CC BY-NC-ND'. The default is 'CC BY-NC-SA'.") @click.option("--primary-language", default="en", help="The primary language for the book (default: 'en').") @click.option("--alternate-languages", default="", help="Comma-separated list of alternate languages (e.g., 'es,fr').") @click.option("--author", default="Author Name", help="The default author of the book.") @click.option("--genre", default="fantasy", help="The genre of the book (default: 'fantasy').") @click.option("--behavior", help="Behavior content, either as a string or a path to a file.") -def init(book_name, primary_language, alternate_languages, author, genre, behavior): +def init(book_name, license, primary_language, alternate_languages, author, genre, behavior): """Initialize the book structure with relevant configuration and behavior content.""" if not is_initialized(book_name): alternate_languages_list = [lang.strip() for lang in alternate_languages.split(',')] if alternate_languages else [] @@ -105,7 +107,7 @@ def init(book_name, primary_language, alternate_languages, author, genre, behavi else: behavior_content = behavior # Si no es un archivo, asumimos que es un string - init_structure(book_name, primary_language, alternate_languages_list, author, genre, behavior_content) + init_structure(book_name, license, primary_language, alternate_languages_list, author, genre, behavior_content) else: console.print(f"[bold yellow]⚠[/bold yellow] Project '[bold]{book_name}[/bold]' is already initialized.", style="yellow") diff --git a/storycraftr/cmd/chapters.py b/storycraftr/cmd/chapters.py index e4280a7..d93659a 100644 --- a/storycraftr/cmd/chapters.py +++ b/storycraftr/cmd/chapters.py @@ -18,8 +18,8 @@ def chapters(): @chapters.command() @click.argument('chapter_number', type=int) -@click.option('--book-name', type=click.Path(), help='Path to the book directory') @click.argument('prompt') +@click.option('--book-name', type=click.Path(), help='Path to the book directory') def chapter(chapter_number, prompt, book_name=None): """Generate a new chapter for the book.""" if not book_name: diff --git a/storycraftr/prompts/chapters.py b/storycraftr/prompts/chapters.py index f2e207b..94606e4 100644 --- a/storycraftr/prompts/chapters.py +++ b/storycraftr/prompts/chapters.py @@ -9,11 +9,19 @@ """ COVER_PROMPT = """ -Create a professional book cover in markdown format for the book titled '{title}'. Include the title, author ('{author}'), genre ('{genre}'), and alternate languages ('{alternate_languages}'). Use this prompt as additional context: {prompt}. Write the content in {language}. +Create a professional book cover in markdown format for the book titled '{title}'. +Include the title, author ('{author}'). +The cover reference a image that I would request later. Reference the image. +STRICTLY Return only the cover markdown limited only to what should be printed. +Use this prompt as additional context: {prompt}. Write the content in {language}. """ BACK_COVER_PROMPT = """ Generate a detailed synopsis for the back cover of the book based on this prompt: {prompt}. Write it in {language}. +Include the title, author ('{author}'), genre ('{genre}'), and alternate languages ('{alternate_languages}'). +Return only the back cover markdown. +Include de license of type {license} with its description like a professional book. +Use this prompt as additional context: {prompt}. Write the content in {language}. """ EPILOGUE_PROMPT_NEW = """ diff --git a/storycraftr/utils/core.py b/storycraftr/utils/core.py index 3f7b1e9..f525b26 100644 --- a/storycraftr/utils/core.py +++ b/storycraftr/utils/core.py @@ -12,6 +12,7 @@ class BookConfig(NamedTuple): alternate_languages: list default_author: str genre: str + license: str # Function to load the JSON file and convert it into a BookConfig object def load_book_config(book_name): @@ -24,7 +25,8 @@ def load_book_config(book_name): primary_language=data['primary_language'], alternate_languages=data['alternate_languages'], default_author=data['default_author'], - genre=data['genre'] + genre=data['genre'], + license=data['license'] ) except FileNotFoundError or NotADirectoryError: console.print(f"[bold red]⚠[/bold red] Folder '[bold]{book_name}[/bold]' is not a storycraftr project.", style="red")