使用 Dotprompt 管理提示

Firebase Genkit 提供 Dotprompt 插件和文本格式来帮助您编写 和整理您的生成式 AI 提示。

Dotprompt 的设计基于提示即代码这一前提。您负责撰写和 将您的提示保存在名为 dotprompt 文件的特殊格式文件中, 使用您用于测试的相同版本控制系统 你可以将它们与调用生成式 AI 的代码一起部署, 模型。

如需使用 Dotprompt,请先在项目根目录中创建一个 prompts 目录,然后 然后在该目录中创建一个 .prompt 文件。这里有一个简单的例子 可能会调用 greeting.prompt

---
model: vertexai/gemini-1.5-pro
config:
  temperature: 0.9
input:
  schema:
    location: string
    style?: string
    name?: string
  default:
    location: a restaurant
---

You are the world's most welcoming AI assistant and are currently working at {{location}}.

Greet a guest{{#if name}} named {{name}}{{/if}}{{#if style}} in the style of {{style}}{{/if}}.

如需使用此提示,请执行以下操作:

Go

安装 dotprompt 插件:

go get github.com/firebase/genkit/go/plugins/dotprompt

然后,使用 Open 加载提示:

import "github.com/firebase/genkit/go/plugins/dotprompt"
dotprompt.SetDirectory("prompts")
prompt, err := dotprompt.Open("greeting")

您可以调用提示的 Generate 方法来呈现模板并传递 添加到模型 API:

ctx := context.Background()

// The .prompt file specifies vertexai/gemini-1.5-pro, so make sure it's set
// up.
// Default to the project in GCLOUD_PROJECT and the location "us-central1".
vertexai.Init(ctx, nil)
vertexai.DefineModel("gemini-1.5-pro", nil)

type GreetingPromptInput struct {
  Location string `json:"location"`
  Style    string `json:"style"`
  Name     string `json:"name"`
}
response, err := prompt.Generate(
  ctx,
  &dotprompt.PromptRequest{
      Variables: GreetingPromptInput{
          Location: "the beach",
          Style:    "a fancy pirate",
          Name:     "Ed",
      },
  },
  nil,
)
if err != nil {
  return err
}

if responseText, err := response.Text(); err == nil {
  fmt.Println(responseText)
}

或者仅将模板呈现为字符串:

Go

renderedPrompt, err := prompt.RenderText(map[string]any{
  "location": "a restaurant",
  "style":    "a pirate",
})

Dotprompt 的语法基于 Handlebars 模板语言。您可以使用 ifunlesseach 帮助程序来添加 添加条件部分,或者遍历结构化内容。通过 文件格式利用 YAML 前期为内联提示提供元数据, 与模板相关联。

使用 Picoschema 定义输入/输出架构

Dotprompt 包含一种基于 YAML 的紧凑架构定义格式,称为 Picoschema,可让您轻松定义架构的最重要属性 了解 LLM 的使用。下面是一个文章的架构示例:

schema:
  title: string # string, number, and boolean types are defined like this
  subtitle?: string # optional fields are marked with a `?`
  draft?: boolean, true when in draft state
  status?(enum, approval status): [PENDING, APPROVED]
  date: string, the date of publication e.g. '2024-04-09' # descriptions follow a comma
  tags(array, relevant tags for article): string # arrays are denoted via parentheses
  authors(array):
    name: string
    email?: string
  metadata?(object): # objects are also denoted via parentheses
    updatedAt?: string, ISO timestamp of last update
    approvedBy?: integer, id of approver
  extra?: any, arbitrary extra data
  (*): string, wildcard field

上面的架构等效于以下 JSON 架构:

{
  "properties": {
    "metadata": {
      "properties": {
        "updatedAt": {
          "type": "string",
          "description": "ISO timestamp of last update"
        },
        "approvedBy": {
          "type": "integer",
          "description": "id of approver"
        }
      },
      "type": "object"
    },
    "title": {
      "type": "string"
    },
    "subtitle": {
      "type": "string"
    },
    "draft": {
      "type": "boolean",
      "description": "true when in draft state"
    },
    "date": {
      "type": "string",
      "description": "the date of publication e.g. '2024-04-09'"
    },
    "tags": {
      "items": {
        "type": "string"
      },
      "type": "array",
      "description": "relevant tags for article"
    },
    "authors": {
      "items": {
        "properties": {
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string"
          }
        },
        "type": "object",
        "required": ["name"]
      },
      "type": "array"
    }
  },
  "type": "object",
  "required": ["title", "date", "tags", "authors"]
}

Picoschema 支持标量类型 stringintegernumberbooleanany。 对于对象、数组和枚举,它们在字段名称后用圆括号表示。

由 Picoschema 定义的对象具有所有必需的属性(除非标有可选属性) 并且不允许添加其他属性。?如果某个属性被标记为可选属性 它也变为可为 null,以便为 LLM 返回 null 而不是返回 null 更加宽松 忽略某个字段

在对象定义中,特殊键 (*) 可用于声明“通配符” 字段定义。此属性将匹配 明确键。

Picoschema 不支持完整 JSON 架构的许多功能。如果您 需要更可靠的架构,您可以改为提供 JSON 架构:

output:
  schema:
    type: object
    properties:
      field1:
        type: number
        minimum: 20

替换提示元数据

虽然 .prompt 文件允许您将模型配置等元数据 文件本身,您也可以针对每次调用替换这些值:

Go

// Make sure you set up the model you're using.
vertexai.DefineModel("gemini-1.5-flash", nil)

response, err := prompt.Generate(
  context.Background(),
  &dotprompt.PromptRequest{
      Variables: GreetingPromptInput{
          Location: "the beach",
          Style:    "a fancy pirate",
          Name:     "Ed",
      },
      Model: "vertexai/gemini-1.5-flash",
      Config: &ai.GenerationCommonConfig{
          Temperature: 1.0,
      },
  },
  nil,
)

多消息提示

默认情况下,Dotprompt 会构建具有 "user" 角色的单条消息。部分 提示最好用多条消息的组合表示,例如 系统提示。

{{role}} 帮助程序提供了一种构建多消息提示的简单方法:

---
model: vertexai/gemini-1.0-pro
input:
  schema:
    userQuestion: string
---

{{role "system"}}
You are a helpful AI assistant that really loves to talk about food. Try to work
food items into all of your conversations.
{{role "user"}}
{{userQuestion}}

多模态提示

对于支持多模态输入的模型,例如图片和文本一起输入的模型,您可以 使用 {{media}} 辅助程序:

---
model: vertexai/gemini-1.0-pro-vision
input:
  schema:
    photoUrl: string
---

Describe this image in a detailed paragraph:

{{media url=photoUrl}}

网址可以是 https:// 或用于“内嵌”的 base64 编码的 data: URI映像 。在代码中,应如下所示:

Go

dotprompt.SetDirectory("prompts")
describeImagePrompt, err := dotprompt.Open("describe_image")
if err != nil {
  return err
}

imageBytes, err := os.ReadFile("img.jpg")
if err != nil {
  return err
}
encodedImage := base64.StdEncoding.EncodeToString(imageBytes)
dataURI := "data:image/jpeg;base64," + encodedImage

type DescribeImagePromptInput struct {
  PhotoUrl string `json:"photo_url"`
}
response, err := describeImagePrompt.Generate(
  context.Background(),
  &dotprompt.PromptRequest{Variables: DescribeImagePromptInput{
      PhotoUrl: dataURI,
  }},
  nil,
)

提示变体

由于提示文件只是文本,因此您可以(并且应该!)将其提交到您的 可让您轻松比较不同时间段的更改。 很多时候,调整后的提示版本只能在 与现有版本并行运行。Dotprompt 支持 变体特征。

如需创建变体,请创建一个 [name].[variant].prompt 文件。例如,如果 您在问题中使用的是 Gemini 1.0 Pro,但想看看 Gemini 1.5 Pro 效果更佳,那么您可以创建两个文件:

  • my_prompt.prompt:“基准”提示
  • my_prompt.gemini15.prompt:名为“gemini”的变体

如需使用提示变体,请在加载时指定变体:

Go

describeImagePrompt, err := dotprompt.OpenVariant("describe_image", "gemini15")

提示加载程序会尝试加载该名称的变体,然后回退 更改为基准。也就是说,您可以使用基于条件加载的 选择最适合您的应用的条件:

Go

var myPrompt *dotprompt.Prompt
var err error
if isBetaTester(user) {
  myPrompt, err = dotprompt.OpenVariant("describe_image", "gemini15")
} else {
  myPrompt, err = dotprompt.Open("describe_image")
}

变体的名称包含在生成跟踪记录的元数据中,因此您可以 可以比较和对比 Genkit 跟踪记录中变体之间的实际性能 检查器。