[Tooling] definePrompt defineDotPrompt design fault #337
-
Describe the bug
To Reproduce definePrompt(
{
name: 'helloGetNamePrompt',
inputSchema: z.object({
response: z.string(),
retryCount: z.number().default(0),
argTools: z.record(z.string(), z.any()),
argHistory: z.array(z.record(z.string(), z.any())),
argReturnToolRequests: z.boolean(),
}),
},
async (input) => {
const basePrompt = `Hello!?`;
const retryPrompt = `We previously asked. You answered {{input.response}} Could you please provide your again?`;
const promptText = input.retryCount > 0 ? retryPrompt : basePrompt;
return {
messages: [
{ role: 'system', content: [{ text: SYSTEM_PROMPT }] },
{ role: 'user', content: [{ text: promptText }] },
],
//config: { model:'', temperature: 0.3 },
history: input.argHistory,
tools: Object.values(input.argTools),
returnToolRequests: input.argReturnToolRequests,
model: gpt4o, // << MODEL DEFINITION SUPPORTED
};
}
);
const renderedPrompt = await renderPrompt({
prompt: definePromptDefinedAbove,
input: {
response: "hello",
retryCount: 0,
argTools: Object.values(this._tools),
argHistory: history,
argReturnToolRequests: true
} ,
model: 'googleai/gemini-pro' SHOULD NOT BE REQUIRED // << model is required
}); As you can see the model is required. This negates the point of defining it in the definePrompt
Expected behavior |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 4 replies
-
Hey Ashley - thanks for the report. Sorry this is confusing. :) The title mentions
If you intend to make use of Essentially you'll be able to do something like the following:
You'll have access to everything you need, including tools, history, etc. |
Beta Was this translation helpful? Give feedback.
-
Thanks for the help Michael, sorry about the confusion. To clarify I have to use definePrompt As I am using tools, context and history (which bizarrely have to be passed in to just be passed out, see argReturnToolRequests, argHistory etc). Anyhow, that aside, "definePrompt" allows for the "model:" (property) to be defined, however, as far as I can tell, it is pointless because "model:" is required when using "renderPrompt". Thus the design of "renderPrompt" appears flawed as there are no other helpers to use when calling the "generate" method with a "definePrompt" prompt. Either a new helper, like "renderPrompt", is needed or "model:" needs to be optional on the "renderPrompt" method. Furthermore, there does not appear to be any immediate alternative approach because "defineDotPrompt" does not support tools, context or history. I'd love to use defineDotPrompt but it lacks key functionality. Unfortunately, the entire prompt framework both "definePrompt" (which mixes the code definition with model) and "defineDotPrompt" (which has benefits of separation of code but cannot be used as it does not support tools, context or history), especially, the naming convention between both may also need rethinking in terms of functionality - it seems confused and perhaps requires more thought. For example: the defineDotPrompt should support config, tools, context and history that way it could be used without having to resort to definePrompt. definePrompt could be called definePluginPrompt so its intention is clearer. |
Beta Was this translation helpful? Give feedback.
-
No worries, I mean to say, I am sorry you had a confusing experience getting started with Genkit. The main thing to understand is that dotprompt is 2 parts; (1) configuration parameters and (2) a prompt template. The configuration is where things like model, temperature, and tool references go. The prompt template drives the creation of messages, which includes things like history. The most natural fit for this is when storing prompts as their own separate text files (.prompt files), and then loading them in via import { defineTool } from '@genkit-ai/ai/tool';
import { defineDotprompt } from '@genkit-ai/dotprompt';
import { defineFlow } from '@genkit-ai/flow';
import { gemini15Flash } from '@genkit-ai/googleai';
import * as z from 'zod';
const getWeather = defineTool(
{
name: 'getWeather',
description: 'Get the weather for the given location.',
inputSchema: z.object({ city: z.string() }),
outputSchema: z.object({
temperatureF: z.number(),
conditions: z.string(),
}),
},
async (input) => {
const conditions = ['Sunny', 'Cloudy', 'Partially Cloudy', 'Raining'];
const c = Math.floor(Math.random() * conditions.length);
const temp = Math.floor(Math.random() * (120 - 32) + 32);
return {
temperatureF: temp,
conditions: conditions[c],
};
}
);
const template = `
{{role "system"}}
Always try to be as efficient as possible, and request tool calls in batches.
{{role "user"}}
I really enjoy traveling to places where it's not too hot and not too cold.
{{role "model"}}
Sure, I can help you with that.
{{role "user"}}
Help me decide which is a better place to visit today based on the weather.
I want to be outside as much as possible. Here are the cities I am
considering:\n\n{{#each cities}}{{this}}\n{{/each}}`;
export const weatherPrompt = defineDotprompt(
{
name: 'weatherPrompt',
model: gemini15Flash,
input: {
schema: z.object({
cities: z.array(z.string()),
}),
},
output: {
format: 'text',
},
config: {
maxOutputTokens: 2048,
temperature: 0.6,
topK: 16,
topP: 0.95,
},
tools: [getWeather],
},
template
);
defineFlow(
{
name: 'flowWeather',
inputSchema: z.object({
cities: z.array(z.string()),
}),
outputSchema: z.string(),
},
async (input) => {
const response = await weatherPrompt.generate({
input,
});
return response.text();
}
); |
Beta Was this translation helpful? Give feedback.
-
That's great thank you Michael, I'll try it tomorrow. From the quick look I didn't see History, would that have to be dynamically added to the template variable somehow? Also would you be able to provide the example in both .prompt and code formats? |
Beta Was this translation helpful? Give feedback.
Discussion aside, I split your report into two separate issues. #338 and #339 that we will address.