Reactive Prompts

Paul Kinlan

I've been doing a lot of work on Breadboard. Breadboard is great because it changes the way you think about data flow through an LLM application by focusing on thinking about graphs. One of the things it does well is reacting to inputs updating and chaining of prompts. I wanted to see if I can make a simple imperative way to react to changing inputs.

I thought it would be neat to experiment with:

  1. Prompt responses should rerun (aka react) as the inputs to the prompt change (like a Web App with React)
  2. You should be able to chain responses easily, that is the output of one response can be used in another prompt.
  3. It should integrate with Chrome's (very experimental)

Preact's Signals seemed like an ideal way to manage this.

The reactive-prompt library exports a single function called prompt. It's a tagged template literal which allows you to substitute any variable including Signals. When a Signal is referenced and updated, it's prompt will be recalculated.... and now we have reactive prompts.

Simple Demo

import { prompt } from "@paulkinlan/reactive-prompt";
import { signal, effect } from "@preact/signals-core";

const name = signal("Paul");

const response = prompt`Say "Hello ${name}".`;

effect(async () => {
  console.log(await response.value);
});

setTimeout(() => name.value = "Serene", 2000);

Prompt Chaining

You can chain multiple prompts together, that is the output of one prompt can be the input of another prompt. For sufficiently complex data flows this means that you only the prompts that need updating will be re-run.

import { prompt } from "@paulkinlan/reactive-prompt";
import { signal, effect } from "@preact/signals-core";

const nameSignal = signal("Paul Kinlan");

const prompterSignal = prompt`Using "${nameSignal}", extract the following data:

+ First name
+ Surname
+ Date of Birth

Return as valid JSON
`;

const uiBuilderSignal = prompt`You are an expert web developer, and you have been tasked with creating a form for a client. The form should have the following fields: "${prompterSignal}".

Return the required HTML for the form only and populate the default values.`;

effect(async () => {
  output.innerHTML = parseCodeFromMarkdown(await uiBuilderSignal.value);
});

setTimeout(() => name.value = "Jack Jones, 18th May 1967", 5000);

Chrome's experimental prompt API

This library relies on Chrome's experimental prompt API.

To use this, you need at least Chrome 127 (Dev Channel) and to enable the following flags.

  • chrome://flags/#prompt-api-for-gemini-nano
  • chrome://flags/#optimization-guide-on-device-model "Enable Bypass"

Then go to chrome://components and click "Check for updates" on "Optimization Guide On Device Model". After some time the model will be available.

What about other prompt APIs?

The prompt tagged template is just built for Chrome's prompt API, but there is nothing stopping this being being ported to other APIs like OpenAI or Gemini's REST APIs.

I lead the Chrome Developer Relations team at Google.

We want people to have the best experience possible on the web without having to install a native app or produce content in a walled garden.

Our team tries to make it easier for developers to build on the web by supporting every Chrome release, creating great content to support developers on web.dev, contributing to MDN, helping to improve browser compatibility, and some of the best developer tools like Lighthouse, Workbox, Squoosh to name just a few.

I love to learn about what you are building, and how I can help with Chrome or Web development in general, so if you want to chat with me directly, please feel free to book a consultation.

I'm trialing a newsletter, you can subscribe below (thank you!)