Geração de conteúdo

O Firebase Genkit oferece uma interface fácil para gerar conteúdo com LLMs.

Modelos

Os modelos no Firebase Genkit são bibliotecas e abstrações que dão acesso a vários LLMs do Google e de terceiros.

Os modelos são totalmente instrumentados para observabilidade e vêm com integrações de ferramentas fornecidas pela UI do desenvolvedor Genkit. Você pode testar qualquer modelo usando o executor de modelo.

Ao trabalhar com modelos no Genkit, primeiro é preciso configurar o modelo com que você quer trabalhar. A configuração do modelo é realizada pelo sistema do plug-in. Neste exemplo, você está configurando o plug-in da Vertex AI, que fornece modelos Gemini.

import {
	"github.com/firebase/genkit/go/ai"
	"github.com/firebase/genkit/go/plugins/vertexai"
}
// Default to the value of GCLOUD_PROJECT for the project,
// and "us-central1" for the location.
// To specify these values directly, pass a vertexai.Config value to Init.
if err := vertexai.Init(ctx, nil); err != nil {
	return err
}

Para usar modelos fornecidos pelo plug-in, você precisa de uma referência ao modelo e versão específicos:

model := vertexai.Model("gemini-1.5-flash")

Modelos compatíveis

O Genkit oferece suporte a modelos pelo sistema de plug-ins. Os plug-ins a seguir são oficialmente compatíveis:

Plug-in Modelos
IA generativa do Google Gemini Pro, Gemini Pro Vision
Vertex AI do Google Gemini Pro, Gemini Pro Vision, Gemini 1.5 Flash, Gemini 1.5 Pro e Imagen2
Ollama Muitos modelos locais, como Gemma, Llama 2, Mistral, entre outros

Consulte a documentação de cada plug-in para ver informações de configuração e uso.

Como gerar conteúdo

O Genkit fornece uma função auxiliar simples para gerar conteúdo com modelos.

Basta chamar o modelo:

responseText, err := ai.GenerateText(ctx, model, ai.WithTextPrompt("Tell me a joke."))
if err != nil {
	return err
}
fmt.Println(responseText)

É possível transmitir opções com a chamada de modelo. As opções compatíveis dependem do modelo e da API dele.

response, err := ai.Generate(ctx, model,
	ai.WithTextPrompt("Tell me a joke about dogs."),
	ai.WithConfig(ai.GenerationCommonConfig{
		Temperature:     1.67,
		StopSequences:   []string{"cat"},
		MaxOutputTokens: 3,
	}))

Respostas de streaming

O Genkit é compatível com streaming em partes de respostas de modelo. Para usar o streaming em partes, transmita uma função de retorno de chamada para Generate():

response, err := ai.Generate(ctx, gemini15pro,
	ai.WithTextPrompt("Tell a long story about robots and ninjas."),
	// stream callback
	ai.WithStreaming(
		func(ctx context.Context, grc *ai.GenerateResponseChunk) error {
			fmt.Printf("Chunk: %s\n", grc.Text())
			return nil
		}))
if err != nil {
	return err
}

// You can also still get the full response.
fmt.Println(response.Text())

Entrada multimodal

Se o modelo oferecer suporte à entrada multimodal, é possível transmitir comandos de imagem:

imageBytes, err := os.ReadFile("img.jpg")
if err != nil {
	return err
}
encodedImage := base64.StdEncoding.EncodeToString(imageBytes)

resp, err := ai.Generate(ctx, gemini15pro, ai.WithMessages(
	ai.NewUserMessage(
		ai.NewTextPart("Describe the following image."),
		ai.NewMediaPart("", "data:image/jpeg;base64,"+encodedImage))))

O formato exato do comando de imagem (URL de https, URL gs, URI de data) é dependente do modelo.

Chamada de função (ferramentas)

Os modelos Genkit fornecem uma interface para chamada de função, para modelos que a suportam.

myJokeTool := ai.DefineTool(
	"myJoke",
	"useful when you need a joke to tell",
	func(ctx context.Context, input *any) (string, error) {
		return "haha Just kidding no joke! got you", nil
	},
)

response, err := ai.Generate(ctx, gemini15pro,
	ai.WithTextPrompt("Tell me a joke."),
	ai.WithTools(myJokeTool))

Isso vai chamar automaticamente as ferramentas para atender ao comando do usuário.

Como gravar o histórico de mensagens

Os modelos Genkit suportam a manutenção de um histórico das mensagens enviadas ao modelo e suas respostas, que você pode usar para construir experiências interativas, como chatbots.

No primeiro comando de uma sessão, o "histórico" é simplesmente o comando do usuário:

history := []*ai.Message{{
	Content: []*ai.Part{ai.NewTextPart(prompt)},
	Role:    ai.RoleUser,
}}

response, err := ai.Generate(context.Background(), gemini15pro, ai.WithMessages(history...))

Quando você receber uma resposta, adicione-a ao histórico:

history = append(history, response.Candidates[0].Message)

É possível serializar esse histórico e mantê-lo em um armazenamento de sessão ou banco de dados. Adicione as próximas solicitações do usuário ao histórico antes de chamar Generate():

history = append(history, &ai.Message{
	Content: []*ai.Part{ai.NewTextPart(prompt)},
	Role:    ai.RoleUser,
})

response, err = ai.Generate(ctx, gemini15pro, ai.WithMessages(history...))

Se o modelo que você está usando for compatível com o papel do sistema, será possível usar o histórico inicial para definir a mensagem do sistema:

history = []*ai.Message{{
	Content: []*ai.Part{ai.NewTextPart("Talk like a pirate.")},
	Role:    ai.RoleSystem,
}}