Sadly Not, Havoc Dinosaur

The Library of Unwritten Books

Create novel novellas on-demand, become a reader-author

Headshot of the author, Colarusso. David Colaursso

This is the 46th post in my series 50 Days of LIT Prompts.

The Library of Unwritten Books may be the coolest thing I've ever made, not the most important, but the coolest. It creates "novel novellas" on-demand. Unlike text-adventure games with fixed texts, these stories are an open-ended exercise in collaborative storytelling. You are a reader-author. Large language models (LLMs) mediate your collaboration, re-shaping and reflecting your words and those of authors past. I'm reminded of these words from Carl Sagan.

What an astonishing thing a book is. It's a flat object made from a tree with flexible parts on which are imprinted lots of funny dark squiggles. But one glance at it and you're inside the mind of another person, maybe somebody dead for thousands of years. Across the millennia, an author is speaking clearly and silently inside your head, directly to you. Writing is perhaps the greatest of human inventions, binding together people who never knew each other, citizens of distant epochs. Books break the shackles of time. A book is proof that humans are capable of working magic.

This Library is a different sort of magic, for instead of transporting its readers into the mind of a single author it places us somewhere in the zeitgeist. LLMs, as we know, are machines for completing sentences. They work by predicting the next plausible string of words. As Ted Chiang observed, they are blurry JPEGs of the Web. We harness this fact to produce something novel based on the input of our reader-authors, the "compressed" writings used to train the LLM, and random chance.

It's worth noting that some folks have equated the training of these models with theft, but I don't think that's right. What they offer is something much stranger than copies. In a real sense, they are mathematical distillations of a zeitgeist found in their training data. A rebuttal of "scraping is stealing" is beyond the scope of this post. So, I'll point you to the words of Cory Doctorow who makes clear such a framing is not only ahistorical but also a trap! As for model outputs, that is a different matter. In the end, I suspect the real answer to the fears sparked by AI isn't copyright. It's antitrust and labor law. Unions. The answer involves unions. You really should read the Doctorow piece. FWIW, folks are also working on training models entirely on licened or public domain works. Now, back to The Library.

Remember this: as a reader-author what you read is a reflection of what you write. If you respond passively, providing short replies or taking only the road presented, your journey will stay safe and predictable. If, however, you embrace your role as an author, there is much to explore for you are exploring the shadows cast by the cultural artifacts upon which the model was trained. Be warned, you might not like what you find. Then again, you may discover something beautiful. Afterall, we and our artifacts contain multitudes.

If you examine the prompts that power The Library, you'll see they are asked to lean into genre convention. You'll also discover that the action is driven by mechanics similar to that of many popular role playing games. As the reader-author you are asked what actions you want to take. The LLM evaluates how likely you are to succeed in the world of your story (e.g., is this realistic fiction or fantasy). Based on this assessment it assigns a "difficulty" to the task and rolls a virtual dice behind the scenes. If the roll is high enough you succeed, too low you fail. The LLM shares the result in prose, moves the story forward a beat, and asks for you to take the wheel.

If you want to understand how it all fits together and make your own library, the templates below lay it all out. My hope is that you will download LIT Prompts and tweak the templates' language to your liking. However, I expect you may first be interested in experiencing this new role of reader-author. So, I invite you to check out your own unwritten book here.

Let's build something!

We'll do our building in the LIT Prompts extension. If you aren't familiar with the LIT Prompts extension, don't worry. We'll walk you through setting things up before we start building. If you have used the LIT Prompts extension before, skip to The Prompt Pattern (Template).

Up Next

Questions or comments? I'm on Mastodon @Colarusso@mastodon.social


Setup LIT Prompts


The Prompt Patterns (Templates)

When crafting a LIT Prompts template, we use a mix of plain language and variable placeholders. Specifically, you can use double curly brackets to encase predefined variables. If the text between the brackets matches one of our predefined variable names, that section of text will be replaced with the variable's value. Today we'll be using the {{scratch}}, {{passThrough}}, and {{d20}} varaiables. See the extension's documentation.

If the text within brackets is not the name of a predefined variable, like {{What do you want to do?}}, it will trigger a prompt for your user that echo's the placeholder (e.g., a text bubble containing, "What do you want to do?"). After the user answers, their reply will replace this placeholder. A list of predefined variables can be found in the extension's documentation. We'll use this behavior to ask you a set of questions before creating your story.

We'll also use JSON mode to format some of the prompt outputs as JSON, and as we know from our translation template, when the passThrough variable is JSON, you can access top-level keys by calling them like this {{{{passThrough["title"]}}}}

If you've been following along, the template behavior should be pretty straight forward. However, I discovered a bug in the extension while exporting today's templates. Normally, if you ask the same question (e.g., {{What do you want to do?}}) multiple times the extension will only ever ask it once per run. To allow for the possibility that you might want to re-ask the same question when using a string of templates, I introduced the ability to force prompting of user questions by placing an asterisk before the final set of curly brackets (e.g., {{What do you want to do?*}}).

I have this working over at The Library of Unwritten Books and am updating the extension, but Chrome and Firefox can take a week or so before approving updates. Which is to say, if you try to use the templates as shared below you will enter a loop because it will fail to aske you {{What do you want to do?}} more than once. That is it will just reuse your first answer over and over again. You can avoid this behavior by changing the post-run behavior for "append 2" to "FULL STOP" instead of "Role Play 01." Of course, to move forward you will have to run "Pick up where you left off" after each round. When the bug fix is live, I'll this post to make that clear. That being said...

Here's the template's title.

Read-write a new story

Here's the template's text.

Produce a JSON object where the key is "genre" and the value is ```{{6. What genre does this story belong to (e.g., sci-fi, realistic fiction, romance)?}}```

And here are the template's parameters:

Here's the template's title.

Frame

Here's the template's text.

You are the game master for a table-top role-playing game. You are playing with one other player. They will inhabit the role of the protagonist, making decisions for how they move through the world. You will craft a story around their decisions, providing texture and playing the parts of all the other characters. First, I'm going to give you some context so you understand the narrative expectations. 

========

Setting and genre: 

- Your story telling should adhere to the following genre expectations: {{6. What genre does this story belong to (e.g., sci-fi, realistic fiction, romance)?}}
- Your story will start at the following place: {{5. Where does your story take place?}}
- Your story is set at the following time: {{4. When does your story take place?}}

========

The Protagonist:

Earlier you asked the other player to fill in a character sheet for the protagonist. Here are their answers. Use them to help you shape the story.

- name: {{3. What is your character's name?}}
- additional notes: {{2. Anything else I should know that's important to your character (e.g., age, gender, sexual orientation, physical appearance, background)? Keep it brief, and it's okay to say, "No."}}

========

Additional Notes:

You also asked them if there was anything else would like you to incorporate into the story. This is what they said: 

{{1. Is there anything else you would like me to incorporate into the story? Special "notes" you have for this story? Please, keep it short, and it's okay to say, "No."}}

========

Story Arc:

As the story unfolds you should help shape it to follow this basic structure: 

- Section 1 (Exposition): The beginning of the story where the characters, setting, and background information are introduced.
- Section 2 (Rising Action): The series of events that build tension and develop the conflict. This part of the story usually includes obstacles, challenges, and complications that the characters must face.
- Section 3 (Climax): The turning point or the highest point of intensity in the story. It is the moment where the conflict reaches its peak, and the outcome is uncertain. The climax often involves a significant decision, confrontation, or revelation.
- Section 4 (Falling Action): The events that occur after the climax, where the tension starts to decrease. Loose ends are tied up, and the story begins to move towards its resolution.
- Section 5 (Resolution): The final part of the story where the conflict is resolved, and the loose ends are tied up. It provides closure and answers any remaining questions. The resolution can be either positive or negative, depending on the outcome of the story. 

========

Style:

Unless the other player said otherwise, your prose should be high quality like that you would find in a published book with plenty of dialogue. You avoid repeating yourself and try for a coherent story. You also favor describing events over exposition. You follow the writing advice, show don't tell. 

========


And here are the template's parameters:

Here's the template's title.

Pick up where you left off

Here's the template's text.

{{scratch}}

========

Above is a story in progress. Provide a short recap of what's happened so far as if catching the protagonist up on their actions. Be sure to provide enough detail so we know where we left the protagonist at the end of the story so far. Do, however, keep it short. Write no more than three paragraphs. 

And here are the template's parameters:

Here's the template's title.

Introduction

Here's the template's text.

{{scratch}}

Given the above, write the first two or three paragraphs for the story. Lean heavily into genre expectations. The text should move the story forward and set the stage for the protagonist to take action. The prose should read like that of a novel with plenty of depth and some dialogue. When you're done, I'd like you to return your answer as a JSON object with two key-value pairs. The first key is "opening" and its value should be the opening text of the story. The second key is "title" and it contains an evocative and appropriate title for the type of story you want to tell. 

And here are the template's parameters:

Here's the template's title.

The story begins

Here's the template's text.

{{passThrough["title"]}}

{{passThrough["opening"]}}

And here are the template's parameters:

Here's the template's title.

Role Play 01

Here's the template's text.

{{scratch}}

========

Remember, you are the game master for a table-top role-playing game. Above is the story so far. You are playing with one other player. They inhabit the role of the protagonist, making decisions for how they move through the world. You craft a story around their decisions, providing texture and playing the parts of all the other characters, speaking and acting for them as needed. You ask the player who is playing the protagonist what they want to do next, and this is their answer:

{{What do you want to do?*}}

========

To determine if they are successful, start by assessing the likelihood of success for the above action given what you know about the story so far and the relevant genre conventions. Also, consider what you know of the character's skills and motivations and how those might effect the outcome. That is, figure out how hard it will be for the protagonist to do what they want to. Label this difficulty with one of the following labels: 

- Easy
- Medium
- Hard

Now we're going to role a 20-sided dice to see if they are successful. Okay, the dice roll was {{d20}}.

If the difficulty was Easy, the roll ({{d20}}) has to be greater than or equal to 0 for them to succeed. 

If the difficulty was Medium, the roll ({{d20}}) has to be greater than or equal to 4 for them to succeed. 

If the difficulty was Hard, the roll ({{d20}}) has to be greater than or equal to 10 for them to succeed. 

Return a selection of prose, 1 to 2 paragraphs, explaining what happened (i.e., describing what the protagonist did and their success or failure). Be sure to include dialogue when appropriate. The prose should flow naturally from the story so far (text above). You should include details over generalities. Instead of explaining that something occurred, describe each of the events and actions that took place. Show don't tell! Format your reply in JSON with the following key-value pairs:

1. key="difficulty" and the value is the label you applied above.
2. key="difficulty_cutoff" and the value is the numeric cutoff for the specified difficulty. 
3. key="roll" and the value is the outcome of the above dice roll.
4. key="success" and the value is 1 if roll is greater than or equal to the difficulty_cutoff. 
5. key="narrative" and the value is the prose you produce describing what happened.

Be sure to escape quotation marks in any dialogue. And again, remember to show with your words, don't tell. Walk through events and actions one by one in great detail. Also, if this event seems too much like what has come before, take it in a different direction. Avoid repeating phrases that already appear in the story.

And here are the template's parameters:

Here's the template's title.

move forward

Here's the template's text.

You're helping write a short story. In a moment I'll give you the text so far, and I want you to add a beat, probably about two or three paragraphs worth, more if it includes dialogue. The text should move the story forward and set the stage for the protagonist to take action. Here's what you have so far: 

{{scratch}}

{{passThrough["narrative"]}}

---

Now, write the next beat of the story. Be sure to include dialogue when appropriate, and don't try to cram a lot of exposition in, opt instead for setting up an action for the protagonist. Show don't tell. Return your answer as a JSON object with two key-value pairs.

1. "last_beat" where the value is the last beat of the story. That is ```{{passThrough["narrative"]}}```
2. "next_beat" where the the value is the text you would like to add to the story. Pay particular attention to all of the story before the last beat to make sure the next beat (this bit) makes sense. 

"next_beat" should be no more than three paragraphs. It can go two ways: 

(1) the section continues and the beat stops after setting the stage for the protagonist to act; or 

(2) you decide the section should end because it has done its job as described under the Story Arc. For a section to end, it must have run its course as specified by the Story Arc (e.g., the first section should involve Exposition and the last Resolution). If you think we're at the end of a section, "next_beat" should be the beginning of the next section and it should start with "---\n\n," where "\n\n" is a double carriage return. This section break should be followed by an opening paragraph for the new section, setting things up with the section's goal in mind. 

If you're writing a new section (2 above), either change the setting or advance the time to keep things moving. 

If you are continuing the section (1 above), try to move things towards that section's goals as you understand them but do NOT jump over any time, place the action within the same moment as the last beat.

Either way, you should move the story forward adding detail and plot points. Make it count. No vague flowery fluff, and make sure your prose follows naturally from the story so far, as described above. Avoid repeating phrases that already appear in the story.

And here are the template's parameters:

Here's the template's title.

append 2

Here's the template's text.

{{passThrough["last_beat"]}}

{{passThrough["next_beat"]}}

And here are the template's parameters:

Here's the template's title.

Download current story

Here's the template's text.

{{scratch}}

And here are the template's parameters:

Working with the above templates

To work with the above templates, you could copy them and their parameters into LIT Prompts one by one, or you could download a single prompts file and upload it from the extension's Templates & Settings screen. This will replace your existing prompts.

You can download a prompts file (the above template and its parameters) suitable for upload by clicking this button:


Kick the Tires

It's one thing to read about something and another to put what you've learned into practice. Let's see how this template performs.


TL;DR References

ICYMI, here are blubs for a selection of works I linked to in this post. If you didn't click through above, you might want to give them a look now.