Skip to content

Commit

Permalink
Improving dotprompt plugin (#231)
Browse files Browse the repository at this point in the history
* Improving dotprompt plugin

- defineDotprompt() no longer requires plugin loading
- plugin still needs to be loaded for prompt files
- new registry path for code-defined prompts
- validated compatibility with esm modules

* Upgrade testapp to ESM module to test compatibility issues
  • Loading branch information
maxl0rd authored May 23, 2024
1 parent 7a8afec commit 952b305
Show file tree
Hide file tree
Showing 16 changed files with 50 additions and 45 deletions.
4 changes: 2 additions & 2 deletions js/plugins/dotprompt/src/prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,10 @@ export class Dotprompt<Variables = unknown> 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,
Expand Down
24 changes: 14 additions & 10 deletions js/plugins/dotprompt/src/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,29 @@ 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(
name: string,
variant?: string,
dir: string = './prompts'
): Promise<Dotprompt> {
// 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.
Expand Down Expand Up @@ -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;
}
2 changes: 1 addition & 1 deletion js/plugins/dotprompt/tests/prompt_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ output:
});
});

describe('definePrompt', () => {
describe('defineDotprompt', () => {
it('registers a prompt and its variant', async () => {
registerDotprompt();
defineDotprompt(
Expand Down
5 changes: 3 additions & 2 deletions js/testapps/menu/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -27,5 +27,6 @@
},
"devDependencies": {
"typescript": "^5.3.3"
}
},
"type": "module"
}
2 changes: 1 addition & 1 deletion js/testapps/menu/src/01/prompts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions js/testapps/menu/src/02/flows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
4 changes: 2 additions & 2 deletions js/testapps/menu/src/02/prompts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions js/testapps/menu/src/02/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<MenuItem> = require('../../data/menu.json');
import menuData from '../../data/menu.json' assert { type: 'json' };

export const menuTool = defineTool(
{
Expand Down
7 changes: 3 additions & 4 deletions js/testapps/menu/src/03/flows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<MenuItem>;
import menuData from '../../data/menu.json' assert { type: 'json' };

// Render the preamble prompt that seeds our chat history.
const preamble: Array<MessageData> = s03_chatPreamblePrompt.renderMessages({
Expand Down
2 changes: 1 addition & 1 deletion js/testapps/menu/src/03/prompts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions js/testapps/menu/src/04/flows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
2 changes: 1 addition & 1 deletion js/testapps/menu/src/04/prompts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
{
Expand Down
4 changes: 2 additions & 2 deletions js/testapps/menu/src/05/flows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion js/testapps/menu/src/05/prompts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
{
Expand Down
21 changes: 10 additions & 11 deletions js/testapps/menu/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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([
{
Expand All @@ -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';
4 changes: 3 additions & 1 deletion js/testapps/menu/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
{
"compilerOptions": {
"module": "NodeNext",
"moduleResolution": "NodeNext",
"noImplicitReturns": true,
"noUnusedLocals": false,
"outDir": "lib",
"sourceMap": true,
"strict": true,
"target": "es2017",
"skipLibCheck": true,
"esModuleInterop": true
"esModuleInterop": true,
"resolveJsonModule": true
},
"compileOnSave": true,
"include": ["src"]
Expand Down

0 comments on commit 952b305

Please sign in to comment.