Skip to content

Example Project

Description

We created an example test 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

project/main.py
import logging
from unittest import TestCase

from dandy import Recorder
from tests.example_project.book.workflow import create_book


class TestExampleProject(TestCase):
    def test_book_generation(self):
        dandy_book = None

        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 = create_book(
                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!""",
                chapter_count=2,
            )

            dandy_book.to_markdown_file()

            logging.info('Complete')

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

            self.assertTrue(dandy_book)

Intel

project/book/intelligence/intel.py
from dandy.intel.intel import BaseIntel
from tests.example_project.book.enums import BookTheme
from tests.example_project.book.intelligence.chapter.intel import ChaptersIntel
from tests.example_project.book.intelligence.character.intel import CharactersIntel
from tests.example_project.book.intelligence.plot.intel import PlotPointsIntel
from tests.example_project.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: PlotPointsIntel | None = None
    world: WorldIntel | None = None
    chapters: ChaptersIntel | None = None

Prompt

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

from typing import TYPE_CHECKING

from dandy import Prompt
from tests.example_project.book.intelligence.character.prompts import (
    characters_intel_prompt,
)
from tests.example_project.book.intelligence.plot.prompts import plot_intel_prompt

if TYPE_CHECKING:
    from tests.example_project.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

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


class BookStartLlmBot(Bot):
    role = 'Book Overview Writer'
    task = 'Take the idea provide by the user and create a title and overview for a new book.'
    guidelines = Prompt().list([
        'Read through the user input and create a title and overview for a new book.',
        'The title should be catchy and attention-grabbing.',
        'The overview should provide a brief summary of the book and its main themes.',
    ])
    intel_class = BookStartIntel

Advanced Bot

project/book/intelligence/chapter/bots/chapter_conent_bot.py
from __future__ import annotations

from typing import TYPE_CHECKING

from dandy import Bot, Prompt
from tests.example_project.book.intelligence.chapter.prompts import (
    chapter_intel_overview_prompt,
)
from tests.example_project.book.intelligence.prompts import book_intel_prompt

if TYPE_CHECKING:
    from tests.example_project.book.intelligence.chapter.intel import ChapterIntel
    from tests.example_project.book.intelligence.intel import BookIntel


class ChapterContentLlmBot(Bot):
    role = 'Chapter Content Writer'
    task = 'You are a chapter writing bot that will use all the information provided to write the content for a new chapter.'
    guidelines = Prompt().list(
        [
            'Do not include a chapter titles, chapter numbers or scene information when you write the content.'
            'The content for a chapter should be at least 10 paragraphs long or longer including dialog.'
        ]
    )

    def process(
        self,
        book_intel: BookIntel,
        chapter_intel: ChapterIntel,
    ) -> ChapterIntel:
        prompt = Prompt()

        prompt.prompt(book_intel_prompt(book_intel))

        prompt.line_break()

        prompt.heading('Current Chapter to Write Content For:')

        prompt.prompt(chapter_intel_overview_prompt(chapter_intel))

        return self.llm.prompt_to_intel(
            prompt=prompt,
            intel_object=chapter_intel,
            include_fields={'content'},
        )