-
Notifications
You must be signed in to change notification settings - Fork 566
Lifting definePrompt to genkit core #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| # Prompts | ||
|
|
||
| Prompt manipulation is the primary way that you, as an app developer, influence | ||
| the output of generative AI models. For example, when using LLMs, you can craft | ||
| prompts that influence the tone, format, length, and other characteristics of | ||
| the models’ responses. | ||
|
|
||
| Genkit is designed around the premise that _prompts are code_. You write and | ||
| maintain your prompts in source files, track changes to them using the same version | ||
| control system that you use for your code, and you deploy them along with the code | ||
| that calls your generative AI models. | ||
|
|
||
| Most developers will find that the included [Dotprompt](./dotprompt.md) library | ||
| meets their needs for working with prompts in Genkit. However, alternative | ||
| approaches are also supported by working with prompts directly. | ||
|
|
||
| ## Defining prompts | ||
|
|
||
| Genkit's `generate()` helper function accepts string prompts, and you can | ||
| call models this way for straight-forward use cases. | ||
|
|
||
| ```ts | ||
| import { generate } from '@genkit-ai/ai'; | ||
|
|
||
| generate({ | ||
| model: 'googleai/gemini-pro', | ||
| prompt: 'You are a helpful AI assistant named Walt.', | ||
| }); | ||
| ``` | ||
|
|
||
| In most cases, you will need to include some customer provided inputs in your prompt. | ||
| You could define a function to render them like this. | ||
|
|
||
| ```ts | ||
| function helloPrompt(name: string) { | ||
| return `You are a helpful AI assistant named Walt. Say hello to ${name}.`; | ||
| } | ||
|
|
||
| generate({ | ||
| model: 'googleai/gemini-pro', | ||
| prompt: helloPrompt('Fred'), | ||
| }); | ||
| ``` | ||
|
|
||
| One shortcoming of defining prompts in your code is that testing requires executing | ||
| them as part of a flow. To faciliate more rapid iteration, Genkit provides a facility | ||
| to define your prompts and run them in the Developer UI. | ||
|
|
||
| Use the `definePrompt` function to register your prompts with Genkit. | ||
|
|
||
| ```ts | ||
| import { definePrompt } from '@genkit-ai/ai'; | ||
| import z from 'zod'; | ||
|
|
||
| export const helloPrompt = definePrompt( | ||
| { | ||
| name: 'helloPrompt', | ||
| inputSchema: z.object({ name: z.string() }), | ||
| }, | ||
| async (input) => { | ||
| const promptText = `You are a helpful AI assistant named Walt. | ||
| Say hello to ${input.name}.`; | ||
|
|
||
| return { | ||
| messages: [{ role: 'user', content: [{ text: promptText }] }], | ||
| config: { temperature: 0.3 } | ||
| }); | ||
| } | ||
| ); | ||
| ``` | ||
|
|
||
| A prompt action defines a function that returns a `GenerateRequest` object | ||
| which can be used with any model. Optionally, you can also define an input schema | ||
| for the prompt, which is analagous to the input schema for a flow. | ||
| Prompts can also define any of the common model configuration options, such as | ||
| temperature or number of output tokens. | ||
|
|
||
| You can use this prompt in your code with the `renderPrompt()` helper function. | ||
| Provide the input variables expected by the prompt, and the model to call. | ||
|
|
||
| ```javascript | ||
| import { generate, render } from '@genkit-ai/ai'; | ||
|
|
||
| generate( | ||
| renderPrompt({ | ||
| prompt: helloPrompt, | ||
| input: { name: 'Fred' }, | ||
| model: 'googleai/gemini-pro', | ||
| }) | ||
| ); | ||
| ``` | ||
|
|
||
| In the Genkit Developer UI, you can run any prompt you have defined in this way. | ||
| This allows you to experiment with individual prompts outside of the scope of | ||
| the flows in which they might be used. | ||
|
|
||
| ## Dotprompt | ||
|
|
||
| Genkit includes the [Dotprompt](./dotprompt.md) library which adds additional | ||
| functionality to prompts. | ||
|
|
||
| - Loading prompts from `.prompt` source files | ||
| - Handlebars-based templates | ||
| - Support for multi-turn prompt templates and multimedia content | ||
| - Concise input and output schema definitions | ||
| - Fluent usage with `generate()` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| /** | ||
| * 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 { Action, action, JSONSchema7 } from '@genkit-ai/core'; | ||
| import { lookupAction, registerAction } from '@genkit-ai/core/registry'; | ||
| import { setCustomMetadataAttributes } from '@genkit-ai/core/tracing'; | ||
| import z from 'zod'; | ||
| import { GenerateOptions } from './generate'; | ||
| import { GenerateRequest, GenerateRequestSchema, ModelArgument } from './model'; | ||
|
|
||
| export type PromptFn<I extends z.ZodTypeAny = z.ZodTypeAny> = ( | ||
| input: z.infer<I> | ||
| ) => Promise<GenerateRequest>; | ||
|
|
||
| export type PromptAction<I extends z.ZodTypeAny = z.ZodTypeAny> = Action< | ||
| I, | ||
| typeof GenerateRequestSchema | ||
| > & { | ||
| __action: { | ||
| metadata: { | ||
| type: 'prompt'; | ||
| }; | ||
| }; | ||
| }; | ||
|
|
||
| export function definePrompt<I extends z.ZodTypeAny>( | ||
| { | ||
| name, | ||
| description, | ||
| inputSchema, | ||
| inputJsonSchema, | ||
| metadata, | ||
| }: { | ||
| name: string; | ||
| description?: string; | ||
| inputSchema?: I; | ||
| inputJsonSchema?: JSONSchema7; | ||
| metadata?: Record<string, any>; | ||
| }, | ||
| fn: PromptFn<I> | ||
| ): PromptAction<I> { | ||
| const a = action( | ||
| { | ||
| name, | ||
| description, | ||
| inputSchema, | ||
| inputJsonSchema, | ||
| metadata: { ...(metadata || { prompt: {} }), type: 'prompt' }, | ||
| }, | ||
| (i: I): Promise<GenerateRequest> => { | ||
| setCustomMetadataAttributes({ subtype: 'prompt' }); | ||
| return fn(i); | ||
| } | ||
| ); | ||
| registerAction('prompt', name, a); | ||
| return a as PromptAction<I>; | ||
| } | ||
|
|
||
| /** | ||
| * A veneer for rendering a prompt action to GenerateOptions. | ||
| */ | ||
|
|
||
| export type PromptArgument<I extends z.ZodTypeAny = z.ZodTypeAny> = | ||
| | string | ||
| | PromptAction<I>; | ||
|
|
||
| export async function renderPrompt< | ||
| I extends z.ZodTypeAny = z.ZodTypeAny, | ||
| CustomOptions extends z.ZodTypeAny = z.ZodTypeAny, | ||
| >(params: { | ||
| prompt: PromptArgument<I>; | ||
| input: z.infer<I>; | ||
| model: ModelArgument<CustomOptions>; | ||
| config?: z.infer<CustomOptions>; | ||
| }): Promise<GenerateOptions> { | ||
| let prompt: PromptAction<I>; | ||
| if (typeof params.prompt === 'string') { | ||
| prompt = await lookupAction(`/prompt/${params.prompt}`); | ||
| } else { | ||
| prompt = params.prompt as PromptAction<I>; | ||
| } | ||
| const rendered = await prompt(params.input); | ||
| return { | ||
| model: params.model, | ||
| config: { ...(rendered.config || {}), ...params.config }, | ||
| history: rendered.messages.slice(0, rendered.messages.length - 1), | ||
| prompt: rendered.messages[rendered.messages.length - 1].content, | ||
| }; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.