Skip to content

Commit

Permalink
[bbrt] Model can set title, improved instructions, misc fixes (#4135)
Browse files Browse the repository at this point in the history
- The model can call "set_title" to set the title.
- New better shorter default system instructions.
- Auto focus prompt when changing session
- Fix bug where active tools were not updated for each iteration of a
chain of tool calls
  • Loading branch information
aomarks authored Jan 15, 2025
1 parent 69f3646 commit 3c30dd0
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 83 deletions.
19 changes: 17 additions & 2 deletions packages/bbrt/src/components/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ import { readBoardServersFromIndexedDB } from "../breadboard/indexed-db-servers.
import type { BBRTDriver } from "../drivers/driver-interface.js";
import { GeminiDriver } from "../drivers/gemini.js";
import { OpenAiDriver } from "../drivers/openai.js";
import { SYSTEM_INSTRUCTION } from "../instructions/system-instruction.js";
import { Conversation } from "../llm/conversation.js";
import type { CutEvent, ForkEvent, RetryEvent } from "../llm/events.js";
import { BREADBOARD_ASSISTANT_SYSTEM_INSTRUCTION } from "../llm/system-instruction.js";
import { IndexedDBSettingsSecrets } from "../secrets/indexed-db-secrets.js";
import type { SecretsProvider } from "../secrets/secrets-provider.js";
import { ReactiveAppState } from "../state/app.js";
Expand All @@ -58,6 +58,7 @@ import { DisplayFile } from "../tools/files/display-file.js";
import { ReadFile } from "../tools/files/read-file.js";
import { WriteFile } from "../tools/files/write-file.js";
import { BoardLister } from "../tools/list-tools.js";
import { SetTitleTool } from "../tools/set-title.js";
import { type BBRTTool } from "../tools/tool-types.js";
import { connectedEffect } from "../util/connected-effect.js";
import type { Result } from "../util/result.js";
Expand Down Expand Up @@ -203,6 +204,15 @@ export class BBRTMain extends SignalWatcher(LitElement) {
() => this.#sessionState
),

// Meta
new SetTitleTool((title) => {
if (!this.#sessionState) {
return { ok: false, error: "No active session" };
}
this.#sessionState.title = title;
return { ok: true, value: undefined };
}),

// Files
new ReadFile(this.#artifacts),
new WriteFile(this.#artifacts, this.#displayFile),
Expand All @@ -224,7 +234,7 @@ export class BBRTMain extends SignalWatcher(LitElement) {

const sessionStore = new SessionStore({
defaults: {
systemPrompt: BREADBOARD_ASSISTANT_SYSTEM_INSTRUCTION,
systemPrompt: SYSTEM_INSTRUCTION,
driverId: this.#drivers.keys().next().value!,
activeToolIds: standardTools.map((tool) => tool.metadata.id),
},
Expand Down Expand Up @@ -345,6 +355,7 @@ export class BBRTMain extends SignalWatcher(LitElement) {
<bbrt-session-picker
.appState=${this.#appState}
.sessionStore=${this.#sessions}
@bbrt-focus-prompt=${this.#onFocusPrompt}
></bbrt-session-picker>
<bbrt-tool-palette
.conversation=${this.#conversation}
Expand Down Expand Up @@ -468,6 +479,10 @@ export class BBRTMain extends SignalWatcher(LitElement) {
});
}

#onFocusPrompt() {
this.#prompt.value?.focus();
}

#findEventIndexForTurn(turn: ReactiveTurnState) {
if (!this.#sessionState) {
return -1;
Expand Down
6 changes: 6 additions & 0 deletions packages/bbrt/src/components/session-picker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@ export class BBRTSesssionPicker extends SignalWatcher(LitElement) {
this.sessionStore.createSession(brief).then((result) => {
if (result.ok) {
appState.activeSessionId = brief.id;
this.dispatchEvent(
new Event("bbrt-focus-prompt", { bubbles: true, composed: true })
);
} else {
// TODO(aomarks) Show an error.
console.error(`Failed to create session: ${result.error}`);
Expand All @@ -145,6 +148,9 @@ export class BBRTSesssionPicker extends SignalWatcher(LitElement) {
// TODO(aomarks) Make this a real hyperlink, syncronize session via hash.
if (this.appState) {
this.appState.activeSessionId = sessionId;
this.dispatchEvent(
new Event("bbrt-focus-prompt", { bubbles: true, composed: true })
);
}
}

Expand Down
22 changes: 22 additions & 0 deletions packages/bbrt/src/instructions/system-instruction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

export const SYSTEM_INSTRUCTION = `
- You must use the "set_title" function within the first 2-3 turns of the
conversation, with a best effort concise title.
- If the user asks to make something such as a document, report, post, or any
other kind of text artifact, you must use the "write_file" function to create
a new markdown file.
- Never call "display_file" unless you need to show an old file. Never try to
provide a link to a file you have written. Never duplicate the contents of
a file you have just written in your resposne.
- You have access to hundreds of additional tools, particularly for image and
audio generation, and for connecting to external services. To discover them,
first call "list_tools", and then call "activate_tool" with specific tool ids.
`;
4 changes: 3 additions & 1 deletion packages/bbrt/src/llm/conversation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,12 @@ export class Conversation {
);

const done = (async (): Promise<void> => {
const activeTools = await this.#getActiveTools();
let remainingModelCalls = 1 + Math.max(0, MAX_TOOL_ITERATIONS);
let functionCalls: ReactiveFunctionCallState[];
do {
// Note that tools can change between iterations, since "activate_tool"
// could be called.
const activeTools = await this.#getActiveTools();
const allowFunctionCalls = remainingModelCalls > 1;
functionCalls = (
await this.#callModel(
Expand Down
80 changes: 0 additions & 80 deletions packages/bbrt/src/llm/system-instruction.ts

This file was deleted.

64 changes: 64 additions & 0 deletions packages/bbrt/src/tools/set-title.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

import "../components/activate-modal.js";
import type { EmptyObject } from "../util/empty-object.js";
import type { Result } from "../util/result.js";
import type { BBRTTool, BBRTToolAPI, BBRTToolMetadata } from "./tool-types.js";

interface Inputs {
title: string;
}

type Callback = (title: string) => Result<void>;

export class SetTitleTool implements BBRTTool<Inputs, EmptyObject> {
#callback: Callback;

constructor(callback: Callback) {
this.#callback = callback;
}

readonly metadata: BBRTToolMetadata = {
id: "set_title",
title: "Set Title",
description: "Set the title of the conversation.",
icon: "/bbrt/images/tool.svg",
};

async api(): Promise<Result<BBRTToolAPI>> {
return {
ok: true as const,
value: {
inputSchema: {
type: "object",
properties: {
title: {
type: "string",
description: "The new title.",
},
},
},
outputSchema: {
type: "object",
properties: {},
},
} satisfies BBRTToolAPI,
};
}

execute(args: Inputs) {
return { result: this.#execute(args) };
}

async #execute({ title }: Inputs): Promise<Result<{ data: EmptyObject }>> {
const result = this.#callback(title);
if (!result.ok) {
return result;
}
return { ok: true, value: { data: {} } };
}
}

0 comments on commit 3c30dd0

Please sign in to comment.