TKK_E32230176/Source-Code-Web/.agents/skills/developing-genkit-python/references/dotprompt.md

2.7 KiB

Dotprompt — Genkit Python

What it is

.prompt files combine YAML frontmatter (model config, schemas) with Handlebars templates. Keeps prompt logic out of Python code and makes variants easy.

File format

---
model: googleai/gemini-flash-latest
input:
  schema:
    food: string
    ingredients?(array): string   # ? = optional
output:
  schema: Recipe    # references a schema registered with ai.define_schema()
  format: json
---
You are a chef. Generate a recipe for {{food}}.

{{#if ingredients}}
Include these ingredients:
{{list ingredients}}
{{/if}}

Place .prompt files in a prompts/ directory and point prompt_dir at it.

Python setup

from pathlib import Path
from pydantic import BaseModel
from genkit import Genkit
from genkit.plugins.google_genai import GoogleAI

ai = Genkit(
    plugins=[GoogleAI()],
    model='googleai/gemini-flash-latest',
    prompt_dir=Path(__file__).resolve().parent.parent / 'prompts',
)

# Register Pydantic models referenced in .prompt output.schema
class Recipe(BaseModel):
    title: str
    steps: list[str]

ai.define_schema('Recipe', Recipe)

Calling a prompt

# Non-streaming — double-call syntax: ai.prompt('name')(input={...})
response = await ai.prompt('recipe')(input={'food': 'banana bread'})
result = Recipe.model_validate(response.output)

# Variant (recipe.robot.prompt file)
response = await ai.prompt('recipe', variant='robot')(input={'food': 'banana bread'})

Streaming from a prompt

from genkit import ActionRunContext

@ai.flow()
async def tell_story(subject: str, ctx: ActionRunContext) -> str:
    result = ai.prompt('story').stream(input={'subject': subject})
    full = ''
    async for chunk in result.stream:
        if chunk.text:
            ctx.send_chunk(chunk.text)
            full += chunk.text
    return full

Note: .stream(input={...}) not ai.generate_stream(...) — different call shape for prompts.

Render without generating (for LLM-judge evals)

rendered = await ai.prompt('my_prompt').render(input={'key': 'value'})
response = await ai.generate(model='googleai/gemini-flash-latest', messages=rendered.messages)

Helpers

Register Python functions callable inside Handlebars templates:

def list_helper(data: object, *args, **kwargs) -> str:
    if not isinstance(data, list):
        return ''
    return '\n'.join(f'- {item}' for item in data)

ai.define_helper('list', list_helper)

Then use {{list ingredients}} in your .prompt file.

Variants

Name the file <name>.<variant>.prompt — e.g. recipe.robot.prompt. Call with ai.prompt('recipe', variant='robot').

Partials

Use {{>partial_name param=value}} in templates. Partial files are named _partial_name.prompt.