diff --git a/js/plugins/dotprompt/src/prompt.ts b/js/plugins/dotprompt/src/prompt.ts index b0fc9c4a0..43ffc4664 100644 --- a/js/plugins/dotprompt/src/prompt.ts +++ b/js/plugins/dotprompt/src/prompt.ts @@ -142,10 +142,10 @@ export class Dotprompt implements PromptMetadata { return { ...toFrontmatter(this), template: this.template }; } - define(): void { + define(options?: { ns: string }): void { definePrompt( { - name: registryDefinitionKey(this.name, this.variant), + name: registryDefinitionKey(this.name, this.variant, options?.ns), description: 'Defined by Dotprompt', inputSchema: this.input?.schema, inputJsonSchema: this.input?.jsonSchema, diff --git a/js/plugins/dotprompt/src/registry.ts b/js/plugins/dotprompt/src/registry.ts index 7a574a69d..9ccba374c 100644 --- a/js/plugins/dotprompt/src/registry.ts +++ b/js/plugins/dotprompt/src/registry.ts @@ -21,12 +21,17 @@ import { existsSync, readdir, readFileSync } from 'fs'; import { basename, join, resolve } from 'path'; import { Dotprompt } from './prompt.js'; -export function registryDefinitionKey(name: string, variant?: string) { - return `dotprompt/${name}${variant ? `.${variant}` : ''}`; +export function registryDefinitionKey( + name: string, + variant?: string, + ns?: string +) { + // "ns/prompt.variant" where ns and variant are optional + return `${ns ? `${ns}/` : ''}${name}${variant ? `.${variant}` : ''}`; } -export function registryLookupKey(name: string, variant?: string) { - return `/prompt/${registryDefinitionKey(name, variant)}`; +export function registryLookupKey(name: string, variant?: string, ns?: string) { + return `/prompt/${registryDefinitionKey(name, variant, ns)}`; } export async function lookupPrompt( @@ -34,12 +39,11 @@ export async function lookupPrompt( variant?: string, dir: string = './prompts' ): Promise { - // Expect to find the prompt in the registry - const registryPrompt = (await lookupAction( - registryLookupKey(name, variant) - )) as PromptAction; + let registryPrompt = + (await lookupAction(registryLookupKey(name, variant))) || + (await lookupAction(registryLookupKey(name, variant, 'dotprompt'))); if (registryPrompt) { - return Dotprompt.fromAction(registryPrompt); + return Dotprompt.fromAction(registryPrompt as PromptAction); } else { // Handle the case where initialization isn't complete // or a file was added after the prompt folder was loaded. @@ -110,6 +114,6 @@ export function loadPrompt(path: string, filename: string): Dotprompt { if (variant) { prompt.variant = variant; } - prompt.define(); + prompt.define({ ns: 'dotprompt' }); return prompt; } diff --git a/js/plugins/dotprompt/tests/prompt_test.ts b/js/plugins/dotprompt/tests/prompt_test.ts index f9a93cc23..ab5534ac7 100644 --- a/js/plugins/dotprompt/tests/prompt_test.ts +++ b/js/plugins/dotprompt/tests/prompt_test.ts @@ -185,7 +185,7 @@ output: }); }); - describe('definePrompt', () => { + describe('defineDotprompt', () => { it('registers a prompt and its variant', async () => { registerDotprompt(); defineDotprompt( diff --git a/js/testapps/menu/package.json b/js/testapps/menu/package.json index 288fa68f2..9a4f3c258 100644 --- a/js/testapps/menu/package.json +++ b/js/testapps/menu/package.json @@ -2,7 +2,7 @@ "name": "menu", "version": "1.0.0", "description": "A Genkit test app for understanding a restaurant menu", - "main": "lib/index.js", + "main": "./lib/src/index.js", "scripts": { "start": "node lib/index.js", "compile": "tsc", @@ -27,5 +27,6 @@ }, "devDependencies": { "typescript": "^5.3.3" - } + }, + "type": "module" } diff --git a/js/testapps/menu/src/01/prompts.ts b/js/testapps/menu/src/01/prompts.ts index f632dc7c1..5de13bb71 100644 --- a/js/testapps/menu/src/01/prompts.ts +++ b/js/testapps/menu/src/01/prompts.ts @@ -18,7 +18,7 @@ import { definePrompt } from '@genkit-ai/ai'; import { GenerateRequest } from '@genkit-ai/ai/model'; import { defineDotprompt } from '@genkit-ai/dotprompt'; import { geminiPro } from '@genkit-ai/vertexai'; -import { MenuQuestionInput, MenuQuestionInputSchema } from '../types'; +import { MenuQuestionInput, MenuQuestionInputSchema } from '../types.js'; // Define a prompt to handle a customer question about the menu. // This prompt uses definePrompt directly. diff --git a/js/testapps/menu/src/02/flows.ts b/js/testapps/menu/src/02/flows.ts index ef2bc5761..7821de63f 100644 --- a/js/testapps/menu/src/02/flows.ts +++ b/js/testapps/menu/src/02/flows.ts @@ -15,8 +15,8 @@ */ import { defineFlow } from '@genkit-ai/flow'; -import { AnswerOutputSchema, MenuQuestionInputSchema } from '../types'; -import { s02_dataMenuPrompt } from './prompts'; +import { AnswerOutputSchema, MenuQuestionInputSchema } from '../types.js'; +import { s02_dataMenuPrompt } from './prompts.js'; // Define a flow which generates a response from the prompt. diff --git a/js/testapps/menu/src/02/prompts.ts b/js/testapps/menu/src/02/prompts.ts index c9350bd90..23fcdc969 100644 --- a/js/testapps/menu/src/02/prompts.ts +++ b/js/testapps/menu/src/02/prompts.ts @@ -16,8 +16,8 @@ import { defineDotprompt } from '@genkit-ai/dotprompt'; import { geminiPro } from '@genkit-ai/vertexai'; -import { MenuQuestionInputSchema } from '../types'; -import { menuTool } from './tools'; +import { MenuQuestionInputSchema } from '../types.js'; +import { menuTool } from './tools.js'; // The prompt uses a tool which will load the menu data, // if the user asks a reasonable question about the menu. diff --git a/js/testapps/menu/src/02/tools.ts b/js/testapps/menu/src/02/tools.ts index d9a60290d..4c47b2614 100644 --- a/js/testapps/menu/src/02/tools.ts +++ b/js/testapps/menu/src/02/tools.ts @@ -16,9 +16,9 @@ import { defineTool } from '@genkit-ai/ai'; import * as z from 'zod'; -import { MenuItem, MenuItemSchema } from '../types'; +import { MenuItemSchema } from '../types.js'; -const menuData: Array = require('../../data/menu.json'); +import menuData from '../../data/menu.json' assert { type: 'json' }; export const menuTool = defineTool( { diff --git a/js/testapps/menu/src/03/flows.ts b/js/testapps/menu/src/03/flows.ts index c9addc77d..4dd925ab7 100644 --- a/js/testapps/menu/src/03/flows.ts +++ b/js/testapps/menu/src/03/flows.ts @@ -19,16 +19,15 @@ import { MessageData } from '@genkit-ai/ai/model'; import { defineFlow, run } from '@genkit-ai/flow'; import { geminiPro } from '@genkit-ai/vertexai'; -import { MenuItem } from '../types'; import { ChatHistoryStore, ChatSessionInputSchema, ChatSessionOutputSchema, -} from './chats'; -import { s03_chatPreamblePrompt } from './prompts'; +} from './chats.js'; +import { s03_chatPreamblePrompt } from './prompts.js'; // Load the menu data from a JSON file. -const menuData = require('../../data/menu.json') as Array; +import menuData from '../../data/menu.json' assert { type: 'json' }; // Render the preamble prompt that seeds our chat history. const preamble: Array = s03_chatPreamblePrompt.renderMessages({ diff --git a/js/testapps/menu/src/03/prompts.ts b/js/testapps/menu/src/03/prompts.ts index 18abc13bb..1d80258dc 100644 --- a/js/testapps/menu/src/03/prompts.ts +++ b/js/testapps/menu/src/03/prompts.ts @@ -16,7 +16,7 @@ import { defineDotprompt } from '@genkit-ai/dotprompt'; import { geminiPro } from '@genkit-ai/vertexai'; -import { DataMenuQuestionInputSchema } from '../types'; +import { DataMenuQuestionInputSchema } from '../types.js'; // This prompt will generate two messages when rendered. // These two messages will be used to seed the exchange with the model. diff --git a/js/testapps/menu/src/04/flows.ts b/js/testapps/menu/src/04/flows.ts index fbef53a0c..b372840f2 100644 --- a/js/testapps/menu/src/04/flows.ts +++ b/js/testapps/menu/src/04/flows.ts @@ -27,8 +27,8 @@ import { MenuItem, MenuItemSchema, MenuQuestionInputSchema, -} from '../types'; -import { s04_ragDataMenuPrompt } from './prompts'; +} from '../types.js'; +import { s04_ragDataMenuPrompt } from './prompts.js'; // Define a flow which indexes items on the menu. diff --git a/js/testapps/menu/src/04/prompts.ts b/js/testapps/menu/src/04/prompts.ts index ddb5dc28a..bd54054b9 100644 --- a/js/testapps/menu/src/04/prompts.ts +++ b/js/testapps/menu/src/04/prompts.ts @@ -16,7 +16,7 @@ import { defineDotprompt } from '@genkit-ai/dotprompt'; import { geminiPro } from '@genkit-ai/vertexai'; -import { DataMenuQuestionInputSchema } from '../types'; +import { DataMenuQuestionInputSchema } from '../types.js'; export const s04_ragDataMenuPrompt = defineDotprompt( { diff --git a/js/testapps/menu/src/05/flows.ts b/js/testapps/menu/src/05/flows.ts index 4caddfa6f..644e2e9ae 100644 --- a/js/testapps/menu/src/05/flows.ts +++ b/js/testapps/menu/src/05/flows.ts @@ -23,8 +23,8 @@ import { AnswerOutputSchema, MenuQuestionInputSchema, TextMenuQuestionInputSchema, -} from '../types'; -import { s05_readMenuPrompt, s05_textMenuPrompt } from './prompts'; +} from '../types.js'; +import { s05_readMenuPrompt, s05_textMenuPrompt } from './prompts.js'; // Define a flow that takes an image, passes it to Gemini Vision Pro, // and extracts all of the text from the photo of the menu. diff --git a/js/testapps/menu/src/05/prompts.ts b/js/testapps/menu/src/05/prompts.ts index cfcf10669..7154cf77d 100644 --- a/js/testapps/menu/src/05/prompts.ts +++ b/js/testapps/menu/src/05/prompts.ts @@ -17,7 +17,7 @@ import { defineDotprompt } from '@genkit-ai/dotprompt'; import { geminiPro, geminiProVision } from '@genkit-ai/vertexai'; import * as z from 'zod'; -import { TextMenuQuestionInputSchema } from '../types'; +import { TextMenuQuestionInputSchema } from '../types.js'; export const s05_readMenuPrompt = defineDotprompt( { diff --git a/js/testapps/menu/src/index.ts b/js/testapps/menu/src/index.ts index 364737e2e..3becbee32 100644 --- a/js/testapps/menu/src/index.ts +++ b/js/testapps/menu/src/index.ts @@ -15,14 +15,13 @@ */ import { configureGenkit } from '@genkit-ai/core'; import { devLocalVectorstore } from '@genkit-ai/dev-local-vectorstore'; -import { dotprompt } from '@genkit-ai/dotprompt'; import { textEmbeddingGecko, vertexAI } from '@genkit-ai/vertexai'; // Initialize Genkit configureGenkit({ plugins: [ - dotprompt(), + // dotprompt(), vertexAI({ location: 'us-central1' }), devLocalVectorstore([ { @@ -41,20 +40,20 @@ configureGenkit({ // Export all of the example prompts and flows // 01 -export { s01_staticMenuDotPrompt, s01_vanillaPrompt } from './01/prompts'; +export { s01_staticMenuDotPrompt, s01_vanillaPrompt } from './01/prompts.js'; // 02 -export { s02_menuQuestionFlow } from './02/flows'; -export { s02_dataMenuPrompt } from './02/prompts'; +export { s02_menuQuestionFlow } from './02/flows.js'; +export { s02_dataMenuPrompt } from './02/prompts.js'; // 03 -export { s03_multiTurnChatFlow } from './03/flows'; -export { s03_chatPreamblePrompt } from './03/prompts'; +export { s03_multiTurnChatFlow } from './03/flows.js'; +export { s03_chatPreamblePrompt } from './03/prompts.js'; // 04 -export { s04_indexMenuItemsFlow, s04_ragMenuQuestionFlow } from './04/flows'; -export { s04_ragDataMenuPrompt } from './04/prompts'; +export { s04_indexMenuItemsFlow, s04_ragMenuQuestionFlow } from './04/flows.js'; +export { s04_ragDataMenuPrompt } from './04/prompts.js'; // 05 export { s05_readMenuFlow, s05_textMenuQuestionFlow, s05_visionMenuQuestionFlow, -} from './05/flows'; -export { s05_readMenuPrompt, s05_textMenuPrompt } from './05/prompts'; +} from './05/flows.js'; +export { s05_readMenuPrompt, s05_textMenuPrompt } from './05/prompts.js'; diff --git a/js/testapps/menu/tsconfig.json b/js/testapps/menu/tsconfig.json index e51f33ae3..0ae845740 100644 --- a/js/testapps/menu/tsconfig.json +++ b/js/testapps/menu/tsconfig.json @@ -1,6 +1,7 @@ { "compilerOptions": { "module": "NodeNext", + "moduleResolution": "NodeNext", "noImplicitReturns": true, "noUnusedLocals": false, "outDir": "lib", @@ -8,7 +9,8 @@ "strict": true, "target": "es2017", "skipLibCheck": true, - "esModuleInterop": true + "esModuleInterop": true, + "resolveJsonModule": true }, "compileOnSave": true, "include": ["src"]