Firebase Genkit는 생성형 AI 프롬프트 작성 및 정리에 도움이 되는 Dotprompt 플러그인과 텍스트 형식을 제공합니다.
Dotprompt는 프롬프트가 코드라는 전제 하에 설계되었습니다. 개발자는 dotprompt 파일이라는 특수 형식의 파일에 프롬프트를 작성 및 유지 관리하고, 코드에 사용하는 것과 동일한 버전 제어 시스템을 사용하여 변경사항을 추적하며, 생성형 AI 모델을 호출하는 코드와 함께 배포합니다.
Dotprompt를 사용하려면 먼저 프로젝트 루트에 prompts
디렉터리를 만들고 이 디렉터리에 .prompt
파일을 만듭니다. greeting.prompt
라고 하는 간단한 예시를 살펴 보겠습니다.
---
model: vertexai/gemini-1.5-flash
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}}.
이 프롬프트를 사용하려면 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()
// Default to the project in GCLOUD_PROJECT and the location "us-central1".
vertexai.Init(ctx, nil)
// The .prompt file specifies vertexai/gemini-1.5-flash, which is
// automatically defined by Init(). However, if it specified a model that
// isn't automatically loaded (such as a specific version), you would need
// to define it here:
// vertexai.DefineModel("gemini-1.0-pro-002", &ai.ModelCapabilities{
// Multiturn: true,
// Tools: true,
// SystemRole: true,
// Media: false,
// })
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
}
fmt.Println(response.Text())
또는 템플릿을 문자열로 렌더링합니다.
renderedPrompt, err := prompt.RenderText(map[string]any{
"location": "a restaurant",
"style": "a pirate",
})
Dotprompt의 구문은 Handlebars 템플릿 언어를 기반으로 합니다. if
, unless
, each
도우미를 사용하여 프롬프트에 조건부 부분을 추가하거나 정형 콘텐츠를 통해 반복합니다. 파일 형식은 YAML 전면을 활용하여 템플릿과 함께 프롬프트 인라인에 대한 메타데이터를 제공합니다.
Picoschema로 입력/출력 스키마 정의
Dotprompt에는 Picoschema라고 하는 축약형 YAML 기반 스키마 정의 형식을 포함하여 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는 스칼라 유형 string
, integer
, number
, boolean
, any
를 지원합니다.
객체, 배열 및 enum의 경우 필드 이름 뒤에 괄호가 표시됩니다.
Picoschema로 정의된 객체에는 ?
에 의해 선택사항으로 표시되지 않는 한 필수 속성이 모두 포함되며 추가 속성은 허용되지 않습니다. 속성이 선택사항으로 표시되면 LLM이 필드를 생략하는 대신 null을 반환하도록 편의를 제공하기 위해 null을 허용하도록 설정됩니다.
객체 정의에서 특수 키 (*)
를 사용하여 '와일드 카드' 필드 정의를 선언할 수 있습니다. 이렇게 하면 명시적 키에서 제공하지 않는 추가 속성이 일치합니다.
Picoschema는 전체 JSON 스키마의 많은 기능을 지원하지 않습니다. 보다 강력한 스키마가 필요한 경우 JSON 스키마를 대신 제공할 수 있습니다.
output:
schema:
type: object
properties:
field1:
type: number
minimum: 20
프롬프트 메타데이터 재정의
.prompt
파일을 사용하면 모델 구성과 같은 메타데이터를 파일 자체에 삽입할 수 있으며 호출별로 이러한 값을 재정의할 수도 있습니다.
// 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.5-flash
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.5-flash
input:
schema:
photoUrl: string
---
Describe this image in a detailed paragraph:
{{media url=photoUrl}}
URL은 '인라인' 이미지 사용을 위한 https://
또는 base64로 인코딩된 data:
URI일 수 있습니다. 코드에서 다음과 같습니다.
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.5 Flash를 사용하고 있었지만 Gemini 1.5 Pro가 더 잘 작동하는지 확인하려고 한다면 다음과 같은 두 개의 파일을 만들 수 있습니다.
my_prompt.prompt
: '기준' 프롬프트my_prompt.geminipro.prompt
: 'geminipro'라는 변형
프롬프트 변형을 사용하려면 로드할 때 변형을 지정합니다.
describeImagePrompt, err := dotprompt.OpenVariant("describe_image", "geminipro")
프롬프트 로더는 해당 이름의 변형을 로드하려고 시도한 후 존재하지 않으면 기준으로 돌아갑니다. 즉 애플리케이션에 적합한 기준에 따라 조건부 로딩을 사용할 수 있습니다.
var myPrompt *dotprompt.Prompt
var err error
if isBetaTester(user) {
myPrompt, err = dotprompt.OpenVariant("describe_image", "geminipro")
} else {
myPrompt, err = dotprompt.Open("describe_image")
}
변형 이름은 생성 trace의 메타데이터에 포함되므로 Genkit trace 검사기에서 변형 간의 실제 성능을 비교하고 대조할 수 있습니다.