diff --git a/js/pnpm-lock.yaml b/js/pnpm-lock.yaml index 43b021368..3d904d2da 100644 --- a/js/pnpm-lock.yaml +++ b/js/pnpm-lock.yaml @@ -828,6 +828,34 @@ importers: specifier: ^5.3.3 version: 5.4.3 + samples/docs-menu-generation: + dependencies: + '@genkit-ai/ai': + specifier: workspace:* + version: link:../../ai + '@genkit-ai/core': + specifier: workspace:* + version: link:../../core + '@genkit-ai/firebase': + specifier: workspace:* + version: link:../../plugins/firebase + '@genkit-ai/flow': + specifier: workspace:* + version: link:../../flow + '@genkit-ai/googleai': + specifier: workspace:* + version: link:../../plugins/googleai + express: + specifier: ^4.19.2 + version: 4.19.2 + zod: + specifier: ^3.22.4 + version: 3.22.4 + devDependencies: + typescript: + specifier: ^5.3.3 + version: 5.4.3 + samples/eval: dependencies: '@genkit-ai/ai': diff --git a/js/samples/docs-menu-generation/README.md b/js/samples/docs-menu-generation/README.md new file mode 100644 index 000000000..d3152d370 --- /dev/null +++ b/js/samples/docs-menu-generation/README.md @@ -0,0 +1,30 @@ +## Build it + +``` +pnpm build +``` + +or if you need to, build everything: + +``` +cd ; pnpm run setup; cd - +``` + +where `` is the top level of the genkit repo. + +## Run the flows via cli + +``` +genkit flow:run menuStreamingFlow '"astronauts"' +genkit flow:run menuHistoryFlow '"cats"' +genkit flow:run menuImageFlow '{"imageUrl": "https://raw.githubusercontent.com/firebase/genkit/main/js/samples/docs-menu-generation/menu.jpeg", "subject": "tiger"}' +``` + +## Run the flow in the Developer UI + +``` +genkit start +``` + +Click on `menuHistoryFlow`, `menuStreamingFlow`, or `menuImageFlow` +in the lefthand navigation panel to run the new flows. diff --git a/js/samples/docs-menu-generation/menu.jpeg b/js/samples/docs-menu-generation/menu.jpeg new file mode 100644 index 000000000..ae096cd7b Binary files /dev/null and b/js/samples/docs-menu-generation/menu.jpeg differ diff --git a/js/samples/docs-menu-generation/package.json b/js/samples/docs-menu-generation/package.json new file mode 100644 index 000000000..93a493670 --- /dev/null +++ b/js/samples/docs-menu-generation/package.json @@ -0,0 +1,29 @@ +{ + "name": "generation", + "version": "1.0.0", + "description": "", + "main": "lib/index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "node lib/index.js", + "compile": "tsc", + "build": "npm run build:clean && npm run compile", + "build:clean": "rm -rf ./lib", + "build:watch": "tsc --watch" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "@genkit-ai/ai": "workspace:*", + "@genkit-ai/core": "workspace:*", + "@genkit-ai/firebase": "workspace:*", + "@genkit-ai/flow": "workspace:*", + "@genkit-ai/googleai": "workspace:*", + "express": "^4.19.2", + "zod": "^3.22.4" + }, + "devDependencies": { + "typescript": "^5.3.3" + } +} diff --git a/js/samples/docs-menu-generation/src/index.ts b/js/samples/docs-menu-generation/src/index.ts new file mode 100644 index 000000000..c05c69f88 --- /dev/null +++ b/js/samples/docs-menu-generation/src/index.ts @@ -0,0 +1,106 @@ +/** + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// This sample is referenced by the genkit docs. Changes should be made to +// both. +import { generate, generateStream } from '@genkit-ai/ai'; +import { MessageData } from '@genkit-ai/ai/model'; +import { configureGenkit } from '@genkit-ai/core'; +import { defineFlow, startFlowsServer } from '@genkit-ai/flow'; +import { geminiPro, geminiProVision, googleAI } from '@genkit-ai/googleai'; +import * as z from 'zod'; +import { sampleMenuHistory } from './menuHistory'; + +configureGenkit({ + plugins: [googleAI()], + logLevel: 'debug', + enableTracingAndMetrics: true, +}); + +export const menuSuggestionFlowStreaming = defineFlow( + { + name: 'menuSuggestionFlowStreaming', + inputSchema: z.string(), + outputSchema: z.void(), + }, + async (subject) => { + const { response, stream } = await generateStream({ + prompt: `Suggest many items for the menu of a ${subject} themed restaurant`, + model: geminiPro, + config: { + temperature: 1, + }, + }); + + for await (let chunk of stream()) { + for (let content of chunk.content) { + console.log(content.text); + } + } + + console.log((await response()).text()); + } +); + +let historyMap: MessageData[] = sampleMenuHistory; +export const menuHistoryFlow = defineFlow( + { + name: 'menuHistoryFlow', + inputSchema: z.string(), + outputSchema: z.string(), + }, + async (subject) => { + let history = historyMap; + let response = await generate({ + prompt: `Suggest a menu item description for a ${subject} themed restaurant`, + model: geminiPro, + history, + }); + historyMap = response.toHistory(); + return response.text(); + } +); + +export const menuImageFlow = defineFlow( + { + name: 'menuImageFlow', + inputSchema: z.object({ imageUrl: z.string(), subject: z.string() }), + outputSchema: z.string(), + }, + async (input) => { + const visionResponse = await generate({ + model: geminiProVision, + prompt: [ + { + text: `Extract _all_ of the text, in order, + from the following image of a restaurant menu.`, + }, + { media: { url: input.imageUrl, contentType: 'image/jpeg' } }, + ], + }); + const imageDescription = visionResponse.text(); + + const response = await generate({ + model: geminiPro, + prompt: `Here is the text of today's menu: ${imageDescription} + Rename the items to match the restaurant's ${input.subject} theme.`, + }); + + return response.text(); + } +); + +startFlowsServer(); diff --git a/js/samples/docs-menu-generation/src/menuHistory.ts b/js/samples/docs-menu-generation/src/menuHistory.ts new file mode 100644 index 000000000..7bb4f8839 --- /dev/null +++ b/js/samples/docs-menu-generation/src/menuHistory.ts @@ -0,0 +1,52 @@ +/** + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { MessageData } from '@genkit-ai/ai/model'; + +export const sampleMenuHistory: MessageData[] = [ + { + role: 'user', + content: [ + { + text: 'Suggest a single menu item title of a truck themed restaurant', + }, + ], + }, + { + role: 'model', + content: [ + { + text: '"Blazing Burnout Burger"', + }, + ], + }, + { + role: 'user', + content: [ + { + text: "That's pretty good, but suggest another one that's spicier", + }, + ], + }, + { + role: 'model', + content: [ + { + text: '"Redline Reaper Wrap"', + }, + ], + }, +]; diff --git a/js/samples/docs-menu-generation/tsconfig.json b/js/samples/docs-menu-generation/tsconfig.json new file mode 100644 index 000000000..efbb566bf --- /dev/null +++ b/js/samples/docs-menu-generation/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compileOnSave": true, + "include": ["src"], + "compilerOptions": { + "module": "commonjs", + "noImplicitReturns": true, + "outDir": "lib", + "sourceMap": true, + "strict": true, + "target": "es2017", + "skipLibCheck": true, + "esModuleInterop": true + } +}