Skip to content

Example Project

Description

We created an example project that uses Dandy to generate a book using most of the examples in this tutorial.

For more information and the full context of the provided example, please check out the Example Project on GitHub to view and understand the code structure in more detail.

Code Snippets

Main

example/main.py
import logging

from example.book.intelligence.bots.book_bot import BookBot
from dandy import DandyException, Recorder

if __name__ == '__main__':
    try:
        logging.basicConfig(
            level=logging.INFO,
            format='%(asctime)s - %(levelname)s - %(message)s',
            datefmt='%Y-%m-%d %H:%M:%S',
        )

        Recorder.start_recording('book_generation')

        logging.info('Creating a Book')

        dandy_book = BookBot().process(
            user_input="""It's 2035 and the dandy intelligence python library has changed the world for ever. In an effort
            to build awareness the people behind the library have created a working version of their lovable mascot the 
            dandy robot. He has now been turned on and given the directive to let the world know about the dandy library
            and given full agency to do it ... what could go wrong!""",
        )

        dandy_book.to_markdown_file()

        logging.info('Complete')

    except DandyException:
        raise DandyException

    finally:
        Recorder.stop_recording('book_generation')
        Recorder.to_html_file('book_generation')

Intel

example/book/intelligence/intel.py
from dandy.intel.intel import BaseIntel
from example.book.enums import BookTheme
from example.book.intelligence.chapter.intel import ChaptersIntel

from example.book.intelligence.character.intel import CharactersIntel
from example.book.intelligence.plot.intel import PlotIntel
from example.book.intelligence.world.intel import WorldIntel


class BookStartIntel(BaseIntel):
    title: str
    overview: str


class BookIntel(BaseIntel):
    user_input: str
    theme: BookTheme
    start: BookStartIntel | None = None
    characters: CharactersIntel | None = None
    plot: PlotIntel | None = None
    world: WorldIntel | None = None
    chapters: ChaptersIntel | None = None

Prompt

example/book/intelligence/prompts.py
from __future__ import annotations

from typing import TYPE_CHECKING

from dandy import Prompt
from example.book.intelligence.character.prompts import characters_intel_prompt
from example.book.intelligence.plot.prompts import plot_intel_prompt

if TYPE_CHECKING:
    from example.book.intelligence.intel import BookIntel


def book_intel_prompt(book_intel: BookIntel) -> Prompt:
    prompt = Prompt()

    if book_intel.start:
        prompt.title(f'Title: {book_intel.start.title}')
        prompt.heading(f'Overview: {book_intel.start.overview}')
        prompt.line_break()

    if book_intel.world:

        prompt.heading('World:')
        prompt.sub_heading(f'Name: {book_intel.world.name}')
        prompt.text(label='Description', text=book_intel.world.description)

        prompt.line_break()

        prompt.heading('Locations:')
        for location_intel in book_intel.world.locations:
            prompt.line_break()

            prompt.sub_heading(f'Name: {location_intel.name}')
            prompt.text(label='Description', text=location_intel.description)

        prompt.line_break()

    if book_intel.characters:
        prompt.prompt(characters_intel_prompt(book_intel.characters))

        prompt.line_break()

    if book_intel.plot:
        prompt.prompt(plot_intel_prompt(book_intel.plot))

    return prompt

Bot

example/book/intelligence/bots/book_start_llm_bot.py
from dandy import cache_to_sqlite, Bot, Prompt
from example.book.intelligence.intel import BookStartIntel


class BookStartLlmBot(Bot):
    instructions_prompt = (
        Prompt()
        .text('You are a book starting bot. You will be given an idea by the user.')
        .text('you will generate a book title and overview.')
    )

    @cache_to_sqlite('example')
    def process(
            self,
            user_input: str,
    ) -> BookStartIntel:

        return self.llm.prompt_to_intel(
            prompt=Prompt(user_input),
            intel_class=BookStartIntel
        )

Advanced Bot

example/book/intelligence/chapter/bots/chapters_creation_bot.py
from __future__ import annotations

from typing import TYPE_CHECKING

from dandy import Bot
from example.book.intelligence.chapter.intel import ChaptersIntel

from example.book.intelligence.chapter import bots

if TYPE_CHECKING:
    from example.book.intelligence.intel import BookIntel


class ChaptersCreationBot(Bot):
    def process(
            self,
            book_intel: BookIntel,
            chapter_count: int
    ) -> ChaptersIntel:
        chapters_intel = bots.ChaptersLlmBot().process(
            book_intel=book_intel,
            chapter_count=chapter_count,
        )

        for i, chapter_intel in enumerate(chapters_intel):
            chapters_intel[i] = bots.SceneLlmBot().process(
                book_intel=book_intel,
                chapter_intel=chapter_intel,
            )

        for i, chapter_intel in enumerate(chapters_intel):
            chapters_intel[i] = bots.ChapterContentLlmBot().process(
                book_intel=book_intel,
                chapter_intel=chapter_intel,
            )

        return chapters_intel

Decoder

example/book/intelligence/decoders.py
from dandy import Decoder
from example.book.enums import BookTheme


class BookThemeDecoder(Decoder):
    mapping_keys_description = 'book themes'
    mapping = {
        'romance, love, kissing, feelings, emotions, sex': BookTheme.ROMANCE,
        'thriller, unknown, exciting, action, adventure': BookTheme.THRILLER,
        'science fiction, dystopian, space, technology, robots': BookTheme.SCIENCE_FICTION,
        'fantasy, magic, swords, dragons, elfs, wizards': BookTheme.FANTASY,
        'mystery, suspense, murder, crime, detective': BookTheme.MYSTERY,
        'violence, scary, horror, death, fear': BookTheme.HORROR,
    }