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,
}