AI 模型是生成式 AI 的核心。生成模型的两个最突出的示例是大语言模型 (LLM) 和图片生成模型。这些模型会接受称为“提示”的输入(通常为文本、图片或二者结合),并据此生成文本、图片,甚至音频或视频输出。
这些模型的输出效果令人惊艳:LLM 生成的文本几乎可以乱真,图片生成模型也能生成逼真的照片或近似人类创作的艺术作品。
此外,LLM 还能胜任简单文本生成以外的任务:
- 编写计算机程序。
- 规划完成复杂任务所需的各个子任务。
- 整理杂乱无序的数据。
- 理解并提取文本语料库中的信息数据。
- 根据活动的文字说明跟踪和执行自动化活动。
您可以从多家不同的提供商处获得多种模型。每种模型都有其优势和局限,一种模型可能在某项任务中表现突出,在其他任务中则相对逊色。利用生成式 AI 的应用通常可以根据当前任务使用多个不同的模型。
作为应用开发者,您通常不会直接与生成式 AI 模型互动,而是通过以 Web API 形式提供的服务进行互动。虽然这些服务通常功能类似,但它们通过各自不同且不兼容的 API 提供这些功能。如果您希望使用多种模型服务,就必须使用它们各自的专有 SDK,而这些 SDK 可能不兼容。如果您希望将模型升级为最新且功能更强的版本,可能需要从头构建该集成。
Genkit 通过提供一个单一接口来解决此难题,该接口可抽象出访问可能的任何生成式 AI 模型服务的详细信息,并且已经提供了多种预构建实现。围绕 Genkit 构建 AI 赋能的应用可简化首次生成式 AI 调用流程,并可轻松组合多个模型或在出现新模型时将一个模型换成另一个模型。
准备工作
如果您想运行本页面中的代码示例,请先完成使用入门指南中的步骤。所有示例都假定您已在项目中将 Genkit 作为依赖项进行安装。
Genkit 支持的模型
Genkit 的设计具备足够灵活性,可支持使用任何可能的生成式 AI 模型服务。其核心库定义了用于处理模型的通用接口,而模型插件定义了用于处理特定模型及其 API 的实现细节。
Genkit 团队会维护用于处理 Vertex AI、Google 生成式 AI 和 Ollama 提供的模型的插件:
- Gemini 系列 LLM,通过 Google Cloud Vertex AI 插件。
- Gemini 系列 LLM,通过 Google AI 插件。
- 通过 Ollama 插件使用 Gemma 3、Llama 4 以及更多开放式模型(您必须自行托管 Ollama 服务器)。
加载和配置模型插件
在使用 Genkit 开始生成内容之前,您需要加载并配置模型插件。如果您是从“使用入门”指南中过来的,那么您已经完成了此步骤。否则,请参阅使用入门指南或各插件文档,并在继续操作前完成相关步骤。
genkit.Generate()
函数
在 Genkit 中,您与生成式 AI 模型互动的主要接口是 genkit.Generate()
函数。
最简单的 genkit.Generate()
调用会指定您要使用的模型和文本提示:
import (
"context"
"log"
"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/genkit"
"github.com/firebase/genkit/go/plugins/googlegenai"
)
func main() {
ctx := context.Background()
g, err := genkit.Init(ctx,
genkit.WithPlugins(&googlegenai.GoogleAI{}),
genkit.WithDefaultModel("googleai/gemini-2.0-flash"),
)
if err != nil {
log.Fatal(err)
}
resp, err := genkit.Generate(ctx, g,
ai.WithPrompt("Invent a menu item for a pirate themed restaurant."),
)
if err != nil {
log.Fatal(err)
}
log.Println(resp.Text())
}
运行此简短示例时,它会输出一些调试信息,然后输出 genkit.Generate()
调用的输出(通常是 Markdown 文本),如以下示例所示:
## The Blackheart's Bounty
**A hearty stew of slow-cooked beef, spiced with rum and molasses, served in a
hollowed-out cannonball with a side of crusty bread and a dollop of tangy
pineapple salsa.**
**Description:** This dish is a tribute to the hearty meals enjoyed by pirates
on the high seas. The beef is tender and flavorful, infused with the warm spices
of rum and molasses. The pineapple salsa adds a touch of sweetness and acidity,
balancing the richness of the stew. The cannonball serving vessel adds a fun and
thematic touch, making this dish a perfect choice for any pirate-themed
adventure.
再次运行该脚本时,您将会看到不同的输出结果。
上述代码示例将生成请求发送到了您在配置 Genkit 实例时指定的默认模型。
您还可以为单个 genkit.Generate()
调用指定模型:
resp, err := genkit.Generate(ctx, g,
ai.WithModelName("googleai/gemini-2.5-pro"),
ai.WithPrompt("Invent a menu item for a pirate themed restaurant."),
)
模型字符串标识符的格式为 providerid/modelid
,其中提供方 ID(在本例中为 googleai
)用于标识插件,而模型 ID 则是特定模型版本的插件专用字符串标识符。
这些示例还说明了一个要点:当您使用 genkit.Generate()
进行生成式 AI 模型调用时,更改要使用的模型只需向模型参数传递不同的值即可。通过使用 genkit.Generate()
替代原生模型 SDK,您可以更灵活地在应用中集成多个不同模型,并在未来轻松切换所用模型。
到目前为止,您只看到了最简单的 genkit.Generate()
调用的示例。不过,genkit.Generate()
还提供了一个接口,用于与生成模型进行更高级的交互,您将在后续部分看到该接口。
系统提示
某些模型支持提供系统提示,以告知模型您希望它如何响应来自用户的消息。您可以使用系统提示来指定特征,例如您希望模型采用的角色、其回答的语气、回答的格式等等。
如果您使用的模型支持系统提示,您可以使用 WithSystem()
选项提供一个提示:
resp, err := genkit.Generate(ctx, g,
ai.WithSystem("You are a food industry marketing consultant."),
ai.WithPrompt("Invent a menu item for a pirate themed restaurant."),
)
对于不支持系统提示的模型,WithSystem()
会通过修改请求,使其呈现出类似系统提示的形式,从而实现模拟效果。
模型参数
genkit.Generate()
函数接受 WithConfig()
选项,您可以通过该选项指定可选设置,以控制模型生成内容的方式:
resp, err := genkit.Generate(ctx, g,
ai.WithModelName("googleai/gemini-2.0-flash"),
ai.WithPrompt("Invent a menu item for a pirate themed restaurant."),
ai.WithConfig(&googlegenai.GeminiConfig{
MaxOutputTokens: 500,
StopSequences: ["<end>", "<fin>"],
Temperature: 0.5,
TopP: 0.4,
TopK: 50,
}),
)
支持的确切参数取决于各个模型和模型 API。不过,上例中的参数对几乎所有模型都适用。以下是这些参数的说明:
用于控制输出长度的参数
MaxOutputTokens
LLM 对称为 token 的单元进行操作。token 通常会映射到特定字符序列,但并非总是如此。当您将提示传递给模型时,模型首先要做的一件事就是将提示字符串词元化成一系列 token。然后,LLM 会根据已词元化的输入生成一系列 token。最后,token 序列会转换回文本,即输出内容。
输出 token 数上限参数用于设置使用 LLM 生成的 token 数上限。每个模型都可能使用不同的词元化器,但一个很好的经验法则是,将单个英语单词视为由 2 到 4 个 token 组成。
如前所述,某些 token 可能并不映射到字符序列。例如,通常有一个 token 表示序列的结束:当 LLM 生成此 token 时,它会停止生成更多 token。因此,LLM 生成的 token 数量通常会少于最大值,因为它生成了“stop”token。
StopSequences
您可以使用此参数设置 token 或 token 序列,以在生成时指示 LLM 输出结束。此处要使用的正确值通常取决于模型的训练方式,并且通常由模型插件设置。不过,如果您已提示模型生成其他 stop 序列,则可以在此处指定该序列。
请注意,您指定的是字符序列,而不是真正的 token 本体。在大多数情况下,您需要指定一个字符序列,以便模型的词元化器将其映射到单个 token。
用于控制“创意”的参数
温度、Top-P 和 Top-K 参数共同控制您希望模型的“创意”程度。本部分简要介绍了这些参数的含义,但更重要的一点是:这些参数用于调整 LLM 输出的风格特性。这些参数的最佳值取决于您的目标和偏好,并且可能只有通过实验才能找到。
温度
LLM 从根本上说是 token 预测机器。对于给定的 token 序列(例如提示),LLM 会针对其词汇表中的每个 token 预测该 token 在序列中出现的可能性。温度是一个缩放比例,用于在将这些预测结果归一化为介于 0 到 1 之间的概率之前对其进行除法运算。
低温值(介于 0.0 到 1.0 之间)会放大 token 之间可能性的差异,导致模型更不可能生成它已评估为不太可能的 token。这通常被认为是缺乏创意的输出。虽然从技术上讲 0.0 并非有效值,但许多模型会将其视为一种指示,让模型以确定性方式运行,并仅考虑最有可能的那个 token。
高温度值(大于 1.0)会压缩不同 token 的可能性差异,从而导致模型更有可能生成之前评估为不太可能的 token。这通常被视为更有创意的输出。某些模型 API 会设置一个最高温度,通常为 2.0。
TopP
Top-p 是一个介于 0.0 到 1.0 之间的值,用于通过指定 token 的累计概率来控制您希望模型考虑的可能 token 的数量。例如,值为 1.0 表示考虑所有可能的 token(但仍会考虑每个 token 的概率)。值为 0.4 表示仅考虑概率总和为 0.4 的最可能的 token,并排除其他 token。
TopK
Top-k 是一个整数值,它同样控制您希望模型考虑的可能 token 的数量,但这次是通过明确指定 token 数量上限来控制。指定值 1 表示模型应以确定的方式运行。
对模型参数进行实验
您可以使用开发者界面,试验这些参数对不同模型和提示组合生成的输出的影响。使用 genkit start
命令启动开发者界面,它将自动加载项目中配置的插件定义的所有模型。您可以快速尝试不同的提示和配置值,而无需在代码中反复进行这些更改。
将模型与其配置配对
由于每个提供方甚至具体模型可能都有其专用的配置架构或特定要求,因此分别使用 WithModelName()
和 WithConfig()
设置选项可能容易出错,因为后者与前者之间不具备强类型约束。
如需将模型与其配置配对,您可以创建一个模型引用,并将其传递到生成调用中:
model := googlegenai.GoogleAIModelRef("gemini-2.0-flash", &googlegenai.GeminiConfig{
MaxOutputTokens: 500,
StopSequences: ["<end>", "<fin>"],
Temperature: 0.5,
TopP: 0.4,
TopK: 50,
})
resp, err := genkit.Generate(ctx, g,
ai.WithModel(model),
ai.WithPrompt("Invent a menu item for a pirate themed restaurant."),
)
if err != nil {
log.Fatal(err)
}
模型引用的构造函数会强制提供正确的配置类型,这可能会减少不匹配的情况。
结构化输出
在应用中将生成式 AI 作为组件使用时,您通常希望输出的格式不是纯文本。即使只是生成面向用户展示的内容,您也可以借助结构化输出,以更具吸引力的方式呈现。但对于更高级的生成式 AI 应用(例如以程序化方式使用模型输出,或将一个模型的输出作为输入传递给另一个模型),结构化输出是必不可少的。
在 Genkit 中,您可以在调用 genkit.Generate()
时指定输出类型,以便向模型请求结构化输出:
type MenuItem struct {
Name string `json:"name"`
Description string `json:"description"`
Calories int `json:"calories"`
Allergens []string `json:"allergens"`
}
resp, err := genkit.Generate(ctx, g,
ai.WithPrompt("Invent a menu item for a pirate themed restaurant."),
ai.WithOutputType(MenuItem{}),
)
if err != nil {
log.Fatal(err) // One possible error is that the response does not conform to the type.
}
模型输出类型使用 invopop/jsonschema
软件包指定为 JSON 架构。这提供了运行时类型检查,可弥合静态 Go 类型与生成式 AI 模型不可预测的输出之间的差距。借助此系统,您可以编写代码,并可依赖于成功的生成调用始终会返回符合 Go 类型的输出这一事实。
当您在 genkit.Generate()
中指定输出类型时,Genkit 会在后台执行多项操作:
- 在提示中添加有关所选输出格式的更多指导。这还会附带一个效果,即向模型明确指定您希望生成的具体内容(例如,不仅要建议菜单项,还要生成描述、过敏原列表等)。
- 验证输出是否符合架构。
- 将模型输出编组为 Go 类型。
如需从成功的生成调用中获取结构化输出,请对模型回答调用 Output()
,并传入该类型的空值:
var item MenuItem
if err := resp.Output(&item); err != nil {
log.Fatalf(err)
}
log.Printf("%s (%d calories, %d allergens): %s\n",
item.Name, item.Calories, len(item.Allergens), item.Description)
或者,您可以使用 genkit.GenerateData()
进行更简洁的调用:
item, resp, err := genkit.GenerateData[MenuItem](ctx, g,
ai.WithPrompt("Invent a menu item for a pirate themed restaurant."),
)
if err != nil {
log.Fatal(err)
}
log.Printf("%s (%d calories, %d allergens): %s\n",
item.Name, item.Calories, len(item.Allergens), item.Description)
此函数需要输出类型参数,但会在返回值之前自动设置 WithOutputType()
选项并调用 resp.Output()
。
处理错误
请注意,在上一个示例中,genkit.Generate()
调用可能会导致错误。如果模型未能生成符合架构的输出,可能会发生一种错误。处理此类错误的最佳策略取决于您的确切用例,但以下是一些常规提示:
尝试使用其他模型。为了成功生成结构化输出,模型必须能够以 JSON 格式生成输出。像 Gemini 这样功能强大的 LLM 足够灵活,可以做到这一点;但较小的模型(例如您在 Ollama 中使用的某些本地模型)如果未经专门训练,往往无法稳定生成结构化输出。
简化架构。LLM 在生成复杂类型或深度嵌套类型时可能会遇到问题。如果您无法可靠地生成结构化数据,请尝试使用明确的名称、较少的字段或扁平化结构。
重试
genkit.Generate()
调用。如果您选择的模型通常能够生成符合规范的输出,您可以将此类错误视为网络连接错误处理,并通过某种增量退避策略重试请求。
流式传输
在生成大量文本时,您可以通过在生成输出时显示输出(对输出进行流式传输)来改善用户体验。在大多数 LLM 聊天应用中,流式传输的典型示例是:用户可以在模型生成回答消息的同时实时读取内容,从而提升应用的响应感知,并增强与智能体对话的沉浸感。
在 Genkit 中,您可以使用 WithStreaming()
选项对输出进行流式传输:
resp, err := genkit.Generate(ctx, g,
ai.WithPrompt("Suggest a complete menu for a pirate themed restaurant."),
ai.WithStreaming(func(ctx context.Context, chunk *ai.ModelResponseChunk) error {
// Do something with the chunk...
log.Println(chunk.Text())
return nil
}),
)
if err != nil {
log.Fatal(err)
}
log.Println(resp.Text())
多模态输入
到目前为止,您看到的示例都使用文本字符串作为模型提示。虽然这仍然是提示生成式 AI 模型的最常用方式,但许多模型也可以接受其他媒体作为提示。媒体提示通常与文本提示结合使用,以指示模型对媒体执行某些操作,例如为图片添加说明或将录音转录为文字。
模型是否支持媒体输入以及可接受的媒体类型,完全由该模型及其 API 决定。例如,Gemini 2.0 系列模型可以接受图片、视频和音频作为提示。
如需向支持媒体提示的模型提供媒体提示,请传递一个由媒体部分和文本部分组成的数组,而不是将简单的文本提示传递给 genkit.Generate()
。此示例使用可公开访问的 HTTPS 网址指定了图片。
resp, err := genkit.Generate(ctx, g,
ai.WithModelName("googleai/gemini-2.0-flash"),
ai.WithMessages(
NewUserMessage(
NewMediaPart("image/jpeg", "https://example.com/photo.jpg"),
NewTextPart("Compose a poem about this image."),
),
),
)
您还可以通过将媒体数据编码为数据网址来直接传递媒体数据。例如:
image, err := ioutil.ReadFile("photo.jpg")
if err != nil {
log.Fatal(err)
}
resp, err := genkit.Generate(ctx, g,
ai.WithModelName("googleai/gemini-2.0-flash"),
ai.WithMessages(
NewUserMessage(
NewMediaPart("image/jpeg", "data:image/jpeg;base64," + base64.StdEncoding.EncodeToString(image)),
NewTextPart("Compose a poem about this image."),
),
),
)
所有支持媒体输入的模型均可识别数据网址和 HTTPS 网址,部分模型插件还扩展了对其他媒体来源的支持。例如,借助 Vertex AI 插件,您还可以使用 Cloud Storage (gs://
) 网址。
后续步骤
详细了解 Genkit
- 作为应用开发者,您影响生成式 AI 模型输出的主要方式是通过提示。请阅读使用 Dotprompt 管理提示,了解 Genkit 如何帮助您在代码库中开发有效的提示并对其进行管理。
- 虽然
genkit.Generate()
是所有由生成式 AI 赋能应用的核心,但在实际应用中,通常需要在调用生成式 AI 模型前后执行配套处理。为反映这一点,Genkit 引入了 flow 的概念,工作流的定义方式与函数类似,但增加了可观测性和简化部署等额外功能。如需了解详情,请参阅定义 AI 工作流。
高级 LLM 用法
您的应用可以使用一些技巧来从 LLM 获得更多好处。
- 增强 LLM 功能的一种方法是,向 LLM 提示一系列方式,让其向您请求更多信息,或请求您执行某些操作。这称为“工具调用”或“函数调用”。经过训练以支持此功能的模型可以使用格式特殊的回答来回答提示,该响应会向调用应用指明应执行某些操作并将结果连同原始提示一起发送回 LLM。Genkit 提供库函数,可自动完成工具调用实现中的提示生成和调用-回答循环元素。如需了解详情,请参阅工具调用。
- 检索增强生成 (RAG) 是一种技术,用于将特定于某个领域的信息引入模型的输出中。这通常通过在将提示传递给语言模型之前插入相关信息来实现。完整的 RAG 实现需要集成多种技术:文本嵌入生成模型、向量数据库和大语言模型。如需了解 Genkit 如何简化协调这些各种元素的过程,请参阅检索增强生成 (RAG)。