Skip to content

Commit

Permalink
feat: Add Flashback command and new technique to avoid cache
Browse files Browse the repository at this point in the history
  • Loading branch information
Estrada Irribarra, Rodrigo Andres committed Oct 19, 2024
1 parent 6bc9146 commit 3db4259
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 25 deletions.
4 changes: 3 additions & 1 deletion storycraftr/agent/agents.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os
import glob
import time
from datetime import datetime
from dotenv import load_dotenv
from openai import OpenAI
from rich.console import Console
Expand Down Expand Up @@ -229,7 +230,8 @@ def create_message(
try:
# Send prompt to OpenAI API
avoid_cache_content = generate_prompt_with_hash(
f"content\n\n{FORMAT_OUTPUT.format(reference_author=config.reference_author, language=config.primary_language)}"
f"content\n\n{FORMAT_OUTPUT.format(reference_author=config.reference_author, language=config.primary_language)}",
datetime.now().strftime("%B %d, %Y"),
)
client.beta.threads.messages.create(
thread_id=thread_id, role="user", content=avoid_cache_content
Expand Down
24 changes: 18 additions & 6 deletions storycraftr/agent/iterate.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
STRENGTHEN_ARGUMENT_PROMPT,
INSERT_CHAPTER_PROMPT,
REWRITE_SURROUNDING_CHAPTERS_PROMPT,
INSERT_FLASHBACK_CHAPTER_PROMPT,
REWRITE_SURROUNDING_CHAPTERS_FOR_FLASHBACK_PROMPT,
)
from storycraftr.agent.agents import (
update_agent_files,
Expand Down Expand Up @@ -321,7 +323,7 @@ def strengthen_core_argument(book_path, argument):
return


def insert_new_chapter(book_path, position, prompt):
def insert_new_chapter(book_path, position, prompt, flashback=False):
"""
Function to insert a new chapter at the specified position, renaming chapters and adjusting content accordingly.
"""
Expand Down Expand Up @@ -368,8 +370,10 @@ def insert_new_chapter(book_path, position, prompt):
assistant = create_or_get_assistant(book_path)
thread = get_thread()

prompt = INSERT_FLASHBACK_CHAPTER_PROMPT if flashback else INSERT_CHAPTER_PROMPT

# Generate new chapter content using context
prompt_text = INSERT_CHAPTER_PROMPT.format(prompt=prompt, position=position)
prompt_text = prompt.format(prompt=prompt, position=position)
new_chapter_text = create_message(
book_path,
thread_id=thread.id,
Expand Down Expand Up @@ -423,6 +427,7 @@ def insert_new_chapter(book_path, position, prompt):
prompt,
progress,
task_openai,
flashback,
)

if next_chapter:
Expand All @@ -435,10 +440,13 @@ def insert_new_chapter(book_path, position, prompt):
prompt,
progress,
task_openai,
flashback,
)


def rewrite_chapters(book_path, path, num, position, prompt, progress, task_chapters):
def rewrite_chapters(
book_path, path, num, position, prompt, progress, task_chapters, flashback=False
):
"""
Function to rewrite the chapters before and after the inserted chapter to ensure consistency with the new chapter.
Utilizes the retrieval system to access the full context of the book without loading chapter contents directly.
Expand All @@ -447,11 +455,15 @@ def rewrite_chapters(book_path, path, num, position, prompt, progress, task_chap
assistant = create_or_get_assistant(book_path)
thread = get_thread()

# Rewrite chapters using retrieval context
rewrite_prompt = REWRITE_SURROUNDING_CHAPTERS_PROMPT.format(
prompt=prompt, position=position, chapter=num
prompt = (
REWRITE_SURROUNDING_CHAPTERS_FOR_FLASHBACK_PROMPT
if flashback
else REWRITE_SURROUNDING_CHAPTERS_PROMPT
)

# Rewrite chapters using retrieval context
rewrite_prompt = prompt.format(prompt=prompt, position=position, chapter=num)

updated_chapters = create_message(
book_path,
thread_id=thread.id,
Expand Down
33 changes: 20 additions & 13 deletions storycraftr/cmd/iterate.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,41 +166,48 @@ def insert_chapter(position, prompt, book_path=None):


@iterate.command()
@click.option("--book-path", type=click.Path(), help="Path to the book directory")
@click.option(
"--book-path", type=click.Path(), help="Path to the book directory", required=False
)
@click.argument("position", type=int)
@click.argument("prompt")
@click.argument("chapter_number", type=int)
def split_chapter(prompt, chapter_number, book_path):
"""Split a chapter and adjust the numbering of subsequent chapters."""
def add_flashback(position, prompt, book_path=None):
"""Add a flashback scene between two chapters."""
if not book_path:
book_path = os.getcwd()

if not load_book_config(book_path):
return None

console.print(
f"[yellow]The command 'split-chapter' is not yet implemented.[/yellow]"
f"[bold blue]Inserting a new flashback chapter at position {position} in the book: {book_path}[/bold blue]"
)

# Call the function to insert the new chapter and adjust the surrounding chapters
insert_new_chapter(book_path, position, prompt, flashback=True)

# Success log
console.print(
f"[green bold] Flashback Chapter insertion completed at position {position}, and chapters renumbered accordingly![/green bold]"
)
console.print(f"Prompt: {prompt}, Split chapter: {chapter_number}")


@iterate.command()
@click.option("--book-path", type=click.Path(), help="Path to the book directory")
@click.argument("prompt")
@click.argument("chapter_position", type=int)
def add_flashback(prompt, chapter_position, book_path):
"""Add a flashback scene between two chapters."""
@click.argument("chapter_number", type=int)
def split_chapter(prompt, chapter_number, book_path):
"""Split a chapter and adjust the numbering of subsequent chapters."""
if not book_path:
book_path = os.getcwd()

if not load_book_config(book_path):
return None

console.print(
f"[yellow]The command 'add-flashback' is not yet implemented.[/yellow]"
)
console.print(
f"Prompt: {prompt}, Flashback between chapters: {chapter_position} and {chapter_position + 1}"
f"[yellow]The command 'split-chapter' is not yet implemented.[/yellow]"
)
console.print(f"Prompt: {prompt}, Split chapter: {chapter_number}")


@iterate.command()
Expand Down
22 changes: 22 additions & 0 deletions storycraftr/prompts/iterate.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,33 @@
all subsequent chapters will be renumbered accordingly.
For example, if a new chapter is inserted at position 3, the current chapter 3 will become chapter 4, chapter 4 will become chapter 5, and so on.
Use the retrieval system to access the chapters before and after this position, ensuring that the new chapter fits seamlessly with the narrative, themes, and character arcs.
Generate content only for the newly inserted chapter, not for the surrounding chapters.
Use this prompt for context: {prompt}.
"""

REWRITE_SURROUNDING_CHAPTERS_PROMPT = """
Write the chapters {chapter}, ensuring that they fit seamlessly with the previous and next chapter.
Utilize the retrieval system to gather context from the full book, making sure the tone, style, and character arcs remain consistent.
Generate content only for the requested chapter, without altering or including content from other chapters.
Use this prompt for context: {prompt}.
"""

INSERT_FLASHBACK_CHAPTER_PROMPT = """
Insert a new chapter at position {position} in the book, ensuring that the inserted chapter serves as a meaningful flashback.
The flashback should provide essential backstory or context that deepens the reader's understanding of the characters, themes, or events.
All subsequent chapters will be renumbered accordingly.
For example, if a new chapter is inserted at position 3, the current chapter 3 will become chapter 4, chapter 4 will become chapter 5, and so on.
Use the retrieval system to access the chapters before and after this position, ensuring that the new flashback fits seamlessly with the narrative,
maintaining the tone and character arcs established in the book.
Generate content only for the newly inserted flashback chapter, not for the surrounding chapters.
Use this prompt for context: {prompt}.
"""

REWRITE_SURROUNDING_CHAPTERS_FOR_FLASHBACK_PROMPT = """
Write the chapters {chapter}, ensuring that they fit seamlessly with the previous and next chapter,
and that the newly inserted flashback enhances the overall narrative flow.
Utilize the retrieval system to gather context from the full book, ensuring that the tone, style, and character arcs remain consistent.
The flashback should feel integral to the story, adding depth without disrupting the pacing or narrative.
Generate content only for the requested chapter, without altering or including content from other chapters.
Use this prompt for context: {prompt}.
"""
14 changes: 9 additions & 5 deletions storycraftr/utils/core.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
import os
import secrets # Para generar números aleatorios seguros
import hashlib
import json
from typing import NamedTuple
from rich.console import Console
from storycraftr.prompts.permute import longer_date_formats

console = Console()


def generate_prompt_with_hash(original_prompt):
def generate_prompt_with_hash(original_prompt, date):
# Genera un hash basado en el contenido del prompt
hash_object = hashlib.sha256(original_prompt.encode())
hash_hex = hash_object.hexdigest()

# Combina el hash con el prompt original (puedes limitar el hash a los primeros caracteres si prefieres)
modified_prompt = (
f"{hash_hex}: {original_prompt}" # Usa los primeros 10 caracteres del hash
)
# Selecciona una frase aleatoria de la lista usando secrets.choice para mayor seguridad
random_phrase = secrets.choice(longer_date_formats).format(date=date)

# Combina la frase seleccionada, un salto de línea, el hash y el prompt original
modified_prompt = f"{random_phrase}\n\n{hash_hex[:10]}: {original_prompt}" # Usa los primeros 10 caracteres del hash

return modified_prompt


Expand Down

0 comments on commit 3db4259

Please sign in to comment.