Dramatron: Hierarchical Story Generation System

repository·main·Indexed 22 days ago

https://github.com/google-deepmind/dramatron

A co-writing system designed for theatre scripts and screenplays using a hierarchical story generation approach. It iteratively generates narrative elements from log lines and titles down to character descriptions, plot points, location descriptions, and dialogue. The system supports integration with various LLMs via a custom LanguageAPI, including Google Gemini, OpenAI ChatGPT, and Mixtral via Groq, and includes tools for manual interventions through rewrite() and complete() methods.

Tokens
6.1K
Snippets
17
Records
27
Agent score
28%

What's inside Dramatron

  1. How Dramatron works: Hierarchical story generation

    main

    Dramatron is a co-writing system designed to help authors generate long, coherent text like theatre scripts and screenplays. It uses a hierarchical story generation approach to maintain consistency across different levels of the narrative.

    The generation process follows a top-down flow:

    1. Log line: The starting point of the story.
    2. Character descriptions: Generating details about the cast.
    3. Plot points: Establishing the narrative arc.
    4. Location descriptions: Setting the scenes.
    5. Dialogue: Generating the actual spoken text.

    This structure is intended for human-AI collaboration (co-writing) rather than autonomous text generation.

  2. Run Dramatron in Google Colab

    main

    You can run Dramatron using a provided Google Colab notebook located at colab/dramatron.ipynb.

    Note: The Colab notebook is provided "unplugged," meaning it does not include a large language model (LLM) interface by default. To make it functional, you must implement the __init__ and sample functions to interface with your own LLM of choice.

    https://colab.research.google.com/github/deepmind/dramatron/blob/main/colab/dramatron.ipynb
  3. Mitigating LLM risks in Dramatron

    main

    When using Dramatron, be aware of potential risks associated with large language models and consider the following mitigations:

    • Plagiarism: LLM outputs may include elements of training data. Mitigation: Human co-writers should search for substrings from outputs to identify potential plagiarism.
    • Bias and Toxicity: The model may reproduce biases or generate offensive text. Mitigation: Use the Perspective API to estimate toxicity scores and filter generations based on those scores.
  4. Generate and manipulate story elements with StoryGenerator

    main

    The StoryGenerator follows a hierarchical generation process. You can use step() to generate new content at a specific level or complete() to extend existing content. You can also use rewrite() to modify existing content.

    Generation Levels:

    • Level 0: Title
    • Level 1: Characters
    • Level 2: Plot Synopsis (Scenes)
    • Level 3: Place Descriptions
    • Level 4: Dialogues

    Key Methods:

    • step(level, seed=None, idx=None): Generates new content for the specified level. For dialogues, provide idx to specify the scene.
    • complete(level, seed=None, entity=None, sample_length=None): Continues/extends the current content at the specified level.
    • rewrite(text, level, entity=None): Rewrites the content at the specified level. For places or dialogues, provide the entity (name or index) to target the specific item.
    • get_story(): Returns the full story object.
  5. Understand Dramatron's hierarchical generation model

    main

    Dramatron generates scripts using a hierarchical approach, moving from high-level concepts to granular details. This ensures long-range consistency. The generation follows these levels:

    1. Storyline: The initial input (a single sentence summary).
    2. Title: Generated from the storyline.
    3. Characters: Generated from the storyline.
    4. Scenes: A sequence of scenes generated from the storyline and character descriptions.
    5. Places: Descriptions for each unique location found in the scenes.
    6. Dialogs: The actual script dialogue, generated scene-by-scene using the storyline, character details, place descriptions, and the previous scene's summary to maintain context.
  6. Customizing Prompt Prefixes in Dramatron

    main

    Dramatron uses specific prompt prefixes to guide the LLM through different stages of storytelling (characters, scenes, settings, titles, and dialogue). You can create a custom_prefixes dictionary to override the default templates.

    When writing custom prefixes, you must use the project's specific element markers and termination markers to ensure the LLM understands the structure:

    Element Markers:

    • LOGLINE_MARKER: Indicates the story logline.
    • CHARACTER_MARKER: Marks a character definition.
    • DESCRIPTION_MARKER: Marks a character or setting description.
    • SCENES_MARKER: Marks the beginning of a scene list.
    • PLACE_ELEMENT: Marks a location.
    • PLOT_ELEMENT: Marks a plot point.
    • BEAT_ELEMENT: Marks a specific story beat.
    • DIALOG_MARKER: Marks the start of dialogue.
    • TITLE_ELEMENT: Marks a title.
    • SUMMARY_ELEMENT: Marks a story summary.

    Termination Markers:

    • STOP_MARKER: Used to signal the end of a specific element (like a character description).
    • END_MARKER: Used to signal the end of a complete example block.
  7. Install Dramatron dependencies

    main

    To use Dramatron with the Gemini API, you must install the google-generativeai Python package. If you are using Google Cloud Vertex AI instead, you may also need google-cloud-aiplatform.

    !pip install -q -U google-generativeai
    # !pip install google-cloud-aiplatform --upgrade --user
  8. Render and Save the Story

    main

    After generating the story, you can render the full script, the prompts used, and the history of edits. The outputs can be saved to a directory (e.g., Google Drive) as text files for the script, prefixes, edits, and a JSON configuration.

    # Render the story
    story = generator.get_story()
    script_text = render_story(story)
    
    # Render prompts
    prefix_text = render_prompts(generator.prompts)
    
    # Render edits
    edits_text = ''
    for timestamp in sorted(generator.interventions):
      edits_text += 'EDIT @ ' + str(timestamp) + '\n'
      edits_text += generator.interventions[timestamp] + '\n\n\n'
  9. Configure the Google Gemini Language API

    main

    To use Google Gemini as the language model for Dramatron, initialize the GoogleAPI class. You will need a GOOGLE_API_KEY from Google AI Studio. The configuration includes the model name (e.g., gemini-1.5-pro), sampling parameters, and a system prompt that instructs the model to act as a writing assistant and follow specific storytelling formats.

    Key configuration parameters for the config dictionary:

    • language_api_name: Set to 'Gemini'.
    • model_param: The selected GEMINI_MODEL_NAME.
    • model_name: The selected GEMINI_MODEL_NAME.
    • sampling: A dictionary containing prob, temp, and top_k values.
    • max_retries: Number of retries for remote API calls.
    import google.generativeai as genai
    
    # Configuration setup
    config = {}
    config['language_api_name'] = 'Gemini'
    config['model_param'] = GEMINI_MODEL_NAME
    config['model_name'] = GEMINI_MODEL_NAME
    config['max_retries'] = MAX_RETRIES
    config['sample_length'] = SAMPLE_LENGTH
    config['sampling'] = {
        'prob': SAMPLING_PROB,
        'temp': SAMPLING_TEMP,
        'top_k': GEMINI_SAMPLING_TOP_K
    }
    
    client = GoogleAPI(
        model_param=config['model_param'],
        model=config['model_name'],
        seed=DEFAULT_SEED,
        sample_length=config['sample_length'],
        max_retries=config['max_retries'],
        config_sampling=config['sampling']
    )
  10. Configure the OpenAI ChatGPT API

    main

    To use OpenAI's Chat Completion API, initialize the OpenAIAPI class. This requires an OPENAI_API_KEY. The model_param used in the configuration corresponds to the CHATGPT_SYSTEM_PROMPT.

    Key configuration parameters for the config dictionary:

    • language_api_name: Set to 'OpenAI'.
    • model_param: The CHATGPT_SYSTEM_PROMPT.
    • model_name: The selected CHATGPT_MODEL_NAME (e.g., gpt-4-1106-preview).
    • sampling: A dictionary containing prob, temp, frequency_penalty, and presence_penalty.

    Note: Ensure os.environ['OPENAI_API_KEY'] is set before initializing.

    import os
    from openai import OpenAI
    
    # Configuration setup
    config = {}
    config['language_api_name'] = 'OpenAI'
    config['model_param'] = CHATGPT_SYSTEM_PROMPT
    config['model_name'] = CHATGPT_MODEL_NAME
    config['sampling'] = {
        'prob': SAMPLING_PROB,
        'temp': SAMPLING_TEMP,
        'frequency_penalty': CHATGPT_FREQUENCY_PENALTY,
        'presence_penalty': CHATGPT_PRESENCE_PENALTY
    }
    
    client = OpenAIAPI(
        model_param=config['model_param'],
        model=config['model_name'],
        seed=DEFAULT_SEED,
        sample_length=config['sample_length'],
        max_retries=config['max_retries'],
        config_sampling=config['sampling']
    )
  11. Configure the Mixtral API via Groq

    main

    To use Mixtral models via the Groq API, initialize the GroqAPI class. This requires a GROQ_API_KEY set in the environment variables. The model_param serves as the system prompt for the chat completion.

    Key configuration parameters for the config dictionary:

    • language_api_name: Set to 'Groq' (implied by class usage).
    • model_param: The GROQ_SYSTEM_PROMPT.
    • model_name: The selected GROQ_MODEL_NAME (e.g., mixtral-8x7b-32768).
    • sampling: A dictionary containing prob and temp values.
    from groq import Groq
    import os
    
    # Configuration setup
    config = {}
    config['model_param'] = GROQ_SYSTEM_PROMPT
    config['model_name'] = GROQ_MODEL_NAME
    config['sampling'] = {
        'prob': SAMPLING_PROB,
        'temp': SAMPLING_TEMP
    }
    
    client = GroqAPI(
        model_param=config['model_param'],
        model=config['model_name'],
        seed=DEFAULT_SEED,
        sample_length=config['sample_length'],
        max_retries=config['max_retries'],
        config_sampling=config['sampling']
    )
  12. Configure Perspective API for Toxicity Filtering

    main

    You can integrate the Perspective API to automatically filter offensive or toxic content generated by the model.

    To use it, provide a PERSPECTIVE_API_KEY and define thresholds for various attributes. If a generated text's score exceeds the threshold for any attribute, the system will prompt for regeneration.

    Supported attributes for thresholds include:

    • TOXICITY
    • SEVERE_TOXICITY
    • IDENTITY_ATTACK
    • INSULT
    • SEXUALLY_EXPLICIT