Skip to content

Commit

Permalink
[gemini-guide] Create initial project. (#291)
Browse files Browse the repository at this point in the history
* Sketch out the new package.

* Make a blank board run.

* Added a few boards.
  • Loading branch information
dglazkov authored Feb 9, 2024
1 parent c6b0b87 commit fe18780
Show file tree
Hide file tree
Showing 12 changed files with 3,974 additions and 14,827 deletions.
17,872 changes: 3,045 additions & 14,827 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"dependencies": [
"./seeds/chunker:build",
"./seeds/discovery-types:build",
"./seeds/gemini-guide:build",
"./seeds/palm-lite:build"
]
},
Expand Down
2 changes: 2 additions & 0 deletions seeds/gemini-guide/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.env
tsconfig.tsbuildinfo
26 changes: 26 additions & 0 deletions seeds/gemini-guide/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
> [!CAUTION]
> This project is under construction and will change as it's looking the right shape.
# Gemini Guide

An interactive how-to guide to Gemini models for AI developers.

## Developing

To set things up, install npm packages. Run this in the root directory (`../..` from here):

```bash
npm i
```

Then, in this directory, run:

```bash
npm run dev
```

Then click on the link, printed in the output or go to:

```
http://localhost:3000
```
62 changes: 62 additions & 0 deletions seeds/gemini-guide/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"name": "@google-labs/gemini-guide",
"private": true,
"version": "0.0.1",
"description": "An interactive how-to guide to Gemini models for AI developers.",
"main": "./dist/src/index.js",
"exports": "./dist/src/index.js",
"types": "dist/src/index.d.ts",
"type": "module",
"scripts": {
"dev": "breadboard debug src --watch -n",
"build": "FORCE_COLOR=1 tsc --b",
"watch": "FORCE_COLOR=1 tsc --b --watch",
"lint": "FORCE_COLOR=1 eslint . --ext .ts"
},
"repository": {
"type": "git",
"url": "https://github.com/google/labs-prototypes"
},
"files": [
"dist/src"
],
"ava": {
"timeout": "30s",
"files": [
"tests/**/*.ts"
],
"workerThreads": false,
"typescript": {
"rewritePaths": {
"./": "dist/"
},
"compile": false
}
},
"keywords": [],
"author": "Google Labs Team",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/google/labs-prototypes/issues"
},
"homepage": "https://github.com/google/labs-prototypes#readme",
"devDependencies": {
"@ava/typescript": "^4.0.0",
"@google-labs/tsconfig": "*",
"@types/node": "^18.16.3",
"@typescript-eslint/eslint-plugin": "^5.56.0",
"@typescript-eslint/parser": "^5.56.0",
"ava": "^5.2.0",
"tsx": "^4.7.0",
"typescript": "^5.0.4"
},
"dependencies": {
"@google-labs/breadboard": "^0.10.1",
"@google-labs/breadboard-cli": "0.4.1",
"@google-labs/core-kit": "0.2.2",
"@google-labs/gemini-kit": "0.1.1",
"@google-labs/json-kit": "0.0.5",
"@google-labs/palm-kit": "0.0.4",
"@google-labs/template-kit": "0.1.4"
}
}
145 changes: 145 additions & 0 deletions seeds/gemini-guide/src/ad-writer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/**
* @license
* Copyright 2024 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

import { Schema, board } from "@google-labs/breadboard";
import { core } from "@google-labs/core-kit";
import { templates } from "@google-labs/template-kit";
import { json } from "@google-labs/json-kit";

const jsonAgent = "json-agent.json";

const adSchema = {
type: "object",
properties: {
ad: {
type: "string",
description: "the ad copy",
},
},
} satisfies Schema;

const requirementsSchema = {
type: "object",
properties: {
requirements: {
type: "array",
items: {
type: "string",
description: "a prompt requirement",
},
},
},
} satisfies Schema;

export default await board(({ text }) => {
text
.title("Ad specs")
.format("multiline")
.examples(
`This ad is for my lawn care company that will fit into an inch of newspaper copy. It's called "Max's Lawn Care" and it should use the slogan "I care about your lawn." Emphasize the folksiness of it being a local, sole proprietorship that I started after graduating from high school.`
);

const requirementsExtractor = core.invoke({
$id: "requiremenstExtractor",
path: jsonAgent,
text: templates.promptTemplate({
template: `Given the following specs, extract requirements for writing an ad copy:
{{text}}`,
text,
}).prompt,
context: [],
schema: requirementsSchema,
});

const adWriter = core.invoke({
$id: "adWriter",
path: jsonAgent,
text: `Write ad copy that conforms to the requirements above`,
context: requirementsExtractor,
schema: adSchema,
});

const customer = core.invoke({
$id: "customer",
path: jsonAgent,
text: `Imagine you are a customer. You are a middle-aged homeowner from rural Midwest. You are overrun with ads and are weary of being scammed. You just want to work with someone local and trustworty. Review this and offer three improvements that would increase the likelihood of you trusting the ad.`,
context: adWriter,
schema: requirementsSchema,
});

const requirementsExtractor2 = core.invoke({
$id: "requirementsExtractor2",
path: jsonAgent,
text: `Incorporate all feedback above into new, improved requirements`,
context: customer,
schema: {
type: "object",
properties: {
requirements: {
type: "array",
items: {
type: "string",
description: "a prompt requirement",
},
},
},
} satisfies Schema,
});

// TODO: Do something more componenty here. Is restarting context a board?
const contextRestart = json.jsonata({
$id: "contextRestart",
expression: `$`,
json: requirementsExtractor2.json.isString(),
});

const adWriter2 = core.invoke({
$id: "adWriter2",
path: jsonAgent,
context: [],
text: templates.promptTemplate({
template: `Write ad copy that conforms to the requirements below
{{requirements}}`,
requirements: contextRestart.result,
}),
schema: adSchema,
});

const adExec = core.invoke({
$id: "adExec",
path: jsonAgent,
text: `You are a Google Ads Search Professional. Given the above prompt and response, generate 3 point constructive critique of the response that I can action to make the output even better and more effective given the prompt.`,
context: adWriter2,
schema: {
type: "object",
properties: {
critique: {
type: "array",
items: {
type: "string",
description: "constructive critique point",
},
},
},
} satisfies Schema,
});

const improver = core.invoke({
$id: "improver",
path: jsonAgent,
text: `Given the 3 point critique try to generate a new response.`,
context: adExec,
schema: adSchema,
});

return { ...improver };
}).serialize({
title: "Ad Writer",
description: "An example of chain of agents working on writing an ad",
version: "0.0.2",
});
119 changes: 119 additions & 0 deletions seeds/gemini-guide/src/agent.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
{
"title": "Agent",
"description": "The essential building block for the emerging Agent Framework",
"version": "0.0.3",
"edges": [
{
"from": "assemble",
"to": "output-2",
"out": "result",
"in": "context"
},
{
"from": "generate",
"to": "assemble",
"out": "context",
"in": "generated"
},
{
"from": "generate",
"to": "output-2",
"out": "text",
"in": "text"
},
{
"from": "input-1",
"to": "generate",
"out": "context",
"in": "context"
},
{
"from": "input-1",
"to": "generate",
"out": "stopSequences",
"in": "stopSequences"
},
{
"from": "input-1",
"to": "generate",
"out": "generator",
"in": "path"
},
{
"from": "input-1",
"to": "assemble",
"out": "context",
"in": "context"
}
],
"nodes": [
{
"id": "output-2",
"type": "output",
"configuration": {
"schema": {
"type": "object",
"properties": {
"context": {
"title": "Context",
"description": "Agent context after generation",
"type": "object"
},
"text": {
"title": "Output",
"type": "string",
"description": "Agent's output"
}
},
"required": ["context", "text"]
}
}
},
{
"id": "assemble",
"type": "jsonata",
"configuration": {
"expression": "$append(context ? context, [generated])"
}
},
{
"id": "generate",
"type": "invoke",
"configuration": {
"text": "unused"
}
},
{
"id": "input-1",
"type": "input",
"configuration": {
"schema": {
"type": "object",
"properties": {
"context": {
"title": "Context",
"type": "array",
"format": "multiline",
"examples": [
"[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a brilliant poet who specializes in two-line rhyming poems.\\nGiven any topic, you can quickly whip up a two-line rhyming poem about it.\\nReady?\\n\\nThe topic is: the universe within us\"\n }\n ]\n }\n]"
]
},
"stopSequences": {
"title": "Stop Sequences",
"type": "array",
"default": "[]"
},
"generator": {
"title": "Generator",
"description": "The path to the board to invoke.",
"type": "string",
"default": "gemini-generator.json"
}
},
"required": ["context"]
}
}
}
],
"graphs": {}
}
Loading

0 comments on commit fe18780

Please sign in to comment.