在 Java 中构建 Gen AI 功能从未如此简单
Source: Dev.to
请提供您希望翻译的具体文本内容,我将为您翻译成简体中文并保持原有的格式。
介绍
构建 Java 生成式 AI 应用过去是一项复杂且充斥大量样板代码的工作。你需要与原始 HTTP 客户端搏斗,手动编写 JSON 负载,解析流式响应,管理 API 密钥,并拼接可观测性——这些都要在编写任何实际 AI 逻辑之前完成。那些日子已经结束。
Genkit Java 是一个开源框架,使得在 Java 中构建 AI 驱动的应用像定义一个函数一样简单。将其与 Google 的 Gemini 模型和 Google Cloud Run 结合使用,你可以在几分钟内而不是几天内,从零开始部署一个生产级的生成式 AI 服务。
这是一个完整、可运行的示例。克隆它,设置你的 API 密钥,然后运行。
谁适合阅读?
如果你是 Java 开发者,你可能已经看到生成式 AI 革命主要在 Python 和 TypeScript 生态中展开。工具、框架、教程——全部倾向于这些生态系统。Java 开发者只能自行从零构建,或使用冗长、底层的 SDK。
示例展示的内容
一个演示通过 Genkit 使用 Gemini 驱动的翻译 AI 流程的 Java 应用程序。示例重点包括:
- 类型化的流输入 – 一个使用
@JsonProperty注解的TranslateRequest类。 - 结构化的 LLM 输出 – Gemini 直接返回
TranslateResponseJava 对象(无需手动 JSON 解析)。 - 类型化的流输出 – 流向调用方返回完整类型的
TranslateResponse。
所有代码都集中在一个 Java 文件以及两个模型类中。没有 Spring Boot,没有大量注解,也没有 XML 配置——只有简洁、可读、类型安全的代码。
前置条件
| 工具 | 最低版本 |
|---|---|
| Java | 21+(推荐使用 Eclipse Temurin) |
| Maven | 3.6+ |
| Node.js | 18+(用于 Genkit CLI) |
| Google GenAI API 密钥 | 可在 Google AI Studio 免费获取 |
| Google Cloud SDK | 仅在部署到 Cloud Run 时需要 |
安装 Genkit CLI
Genkit CLI 是用于开发和测试 AI 流程的命令行伴侣。
npm install -g genkit验证安装:
genkit --versionCLI 为 Dev UI 提供动力,并提供无缝的开发体验(下面会详细说明)。
项目结构
genkit-java-getting-started/
├── src/
│ └── main/
│ ├── java/
│ │ └── com/example/
│ │ ├── App.java # 主应用程序
│ │ ├── TranslateRequest.java # 类型化流输入
│ │ └── TranslateResponse.java # 类型化流 + LLM 输出
│ └── resources/
│ └── logback.xml # 日志配置
├── pom.xml # 包含 Genkit + Jib 的 Maven 配置
├── run.sh # 快速启动脚本
└── README.md # 本文档快速入门
git clone https://github.com/xavidop/genkit-java-getting-started.git
cd genkit-java-getting-started
export GOOGLE_API_KEY=your-api-key-here
genkit start -- mvn compile exec:java就是这样——两条命令。你的 AI 驱动的 Java 服务器将在 http://localhost:8080 运行,Genkit 开发 UI 可在 http://localhost:4000 访问。
你也可以直接运行应用:
mvn compile exec:java模型类
TranslateRequest.java – 流输入
package com.example;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
/**
* Input for the translate flow.
*/
public class TranslateRequest {
@JsonProperty(required = true)
@JsonPropertyDescription("The text to translate")
private String text;
@JsonProperty(required = true)
@JsonPropertyDescription("The target language (e.g., Spanish, French, Japanese)")
private String language;
public TranslateRequest() {}
public TranslateRequest(String text, String language) {
this.text = text;
this.language = language;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
@Override
public String toString() {
return String.format("TranslateRequest{text='%s', language='%s'}", text, language);
}
}TranslateResponse.java – 流输出 & LLM 结构化输出
package com.example;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
/**
* Structured output for the translate flow.
*/
public class TranslateResponse {
@JsonProperty(required = true)
@JsonPropertyDescription("The original text that was translated")
private String originalText;
@JsonProperty(required = true)
@JsonPropertyDescription("The translated text")
private String translatedText;
@JsonProperty(required = true)
@JsonPropertyDescription("The target language")
private String language;
public TranslateResponse() {}
public TranslateResponse(String originalText, String translatedText, String language) {
this.originalText = originalText;
this.translatedText = translatedText;
this.language = language;
}
public String getOriginalText() {
return originalText;
}
public void setOriginalText(String originalText) {
this.originalText = originalText;
}
public String getTranslatedText() {
return translatedText;
}
public void setTranslatedText(String translatedText) {
this.translatedText = translatedText;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
@Override
public String toString() {
return String.format(
"TranslateResponse{originalText='%s', translatedText='%s', language='%s'}",
originalText, translatedText, language);
}
}注意:
@JsonPropertyDescription注解至关重要。Genkit 会将它们作为 JSON 架构的一部分传递给 Gemini,使模型能够准确了解每个字段的含义。
现在,你拥有一个干净、可直接运行的 Java 项目,演示了类型化输入、结构化 LLM 输出,以及使用 Genkit 的最小样板开发体验。祝编码愉快!
Genkit Java 设置
Genkit genkit = Genkit.builder()
.options(GenkitOptions.builder()
.devMode(true)
.reflectionPort(3100)
.build())
.plugin(GoogleGenAIPlugin.create())
.plugin(jetty)
.build();- GoogleGenAIPlugin 会自动读取你的
GOOGLE_API_KEY。 - JettyPlugin 负责处理 HTTP。
- Genkit 将所有组件串联起来。
定义 translate 流程
genkit.defineFlow(
"translate",
TranslateRequest.class, // typed input
TranslateResponse.class, // typed output
(ctx, request) -> {
String prompt = String.format(
"Translate the following text to %s.\n\nText: %s",
request.getLanguage(),
request.getText()
);
return genkit.generate(
GenerateOptions.builder()
.model("googleai/gemini-3-flash-preview")
.prompt(prompt)
.outputClass(TranslateResponse.class) // Gemini returns a typed object!
.config(GenerationConfig.builder()
.temperature(0.1)
.build())
.build()
);
}
);正在发生什么?
| 步骤 | 说明 |
|---|---|
TranslateRequest.class 作为流的输入 | Genkit 会自动将传入的 JSON 反序列化为 TranslateRequest 对象——无需手动 Map.get() 强制转换。 |
TranslateResponse.class 作为流的输出 | 流返回一个类型化对象,Genkit 会将其序列化为 JSON 作为 HTTP 响应返回。 |
outputClass(TranslateResponse.class) 在生成调用中 | Genkit 将从 TranslateResponse 推导出的 JSON schema 发送给 Gemini。Gemini 返回结构化 JSON,Genkit 再将其反序列化回 TranslateResponse 对象——无需手动解析。 |
单个 defineFlow 调用 | • 在 Genkit 的内部注册表中注册该流 • 将其暴露为 POST /api/flows/translate 端点• 在 Dev UI 中可见 • 自动添加完整的 OpenTelemetry 跟踪 • 自动追踪 token 使用量、延迟和错误率 |
对比 使用 Spring Boot 编写控制器 + 服务 + DTO + 配置 + 异常处理器来实现相同功能时,Genkit 可以消除所有这些样板代码。
开发体验
- 浏览所有流程 – 例如,查看
translate流程及其类型化的输入/输出模式。 - 交互式运行流程 – 填写
TranslateRequestJSON,点击 Run,即可即时看到TranslateResponse(无需curl)。 - 检查追踪 – 查看调用了哪个模型、其输入/输出、执行时间以及 token 使用情况。
- 查看已注册的模型和工具 – 列出所有可用的 Gemini 模型以及您定义的自定义工具。
- 测试工具调用 – 实时观察 Gemini 决定调用您的工具。
- 管理数据集和评估 – 创建测试数据集并评估 AI 输出。
使用 Jib 构建和部署
该项目使用 Jib 直接从 Maven 构建并推送容器镜像——无需 Dockerfile,也不需要 Docker 守护进程。
# Set your GCP project
export PROJECT_ID=$(gcloud config get-value project)
export REGION=us-central1
# Build the container image and push it to Google Container Registry
# (Jib does everything from Maven, no Docker needed!)
mvn compile jib:build -Djib.to.image=gcr.io/$PROJECT_ID/genkit-java-app
# Deploy to Cloud Run
gcloud run deploy genkit-java-app \
--image gcr.io/$PROJECT_ID/genkit-java-app \
--region $REGION \
--platform managed \
--allow-unauthenticated \
--set-env-vars "GOOGLE_API_KEY=$GOOGLE_API_KEY" \
--memory 512Mi \
--cpu 1为什么使用 Jib?
- 无需 Dockerfile – 镜像直接从 Maven 项目构建。
- 无需 Docker 守护进程 – 机器上不必安装 Docker。
- 快速重建 – 依赖、类和资源分层;仅重建已更改的层。
- 可复现的构建 – 确定性强,独立于本地 Docker 环境。
- 直接推送 – 镜像直接发送到 GCR/Artifact Registry,无需本地
docker push。
可选:构建本地 Docker 镜像(需要 Docker)
mvn compile jib:dockerBuild -Djib.to.image=genkit-java-appSource: …
测试 Translate 流程
服务器启动后,发送 TranslateRequest JSON 负载并接收结构化的 TranslateResponse。
示例请求
curl -X POST http://localhost:8080/api/flows/translate \
-H "Content-Type: application/json" \
-d '{"text":"Building AI applications has never been easier","language":"Spanish"}'示例响应
{
"originalText": "Building AI applications has never been easier",
"translatedText": "Construir aplicaciones de IA nunca ha sido tan fácil",
"language": "Spanish"
}尝试其他语言
法语
curl -X POST http://localhost:8080/api/flows/translate \
-H "Content-Type: application/json" \
-d '{"text":"Genkit makes Java AI development simple","language":"French"}'日语
curl -X POST http://localhost:8080/api/flows/translate \
-H "Content-Type: application/json" \
-d '{"text":"Hello world","language":"Japanese"}'注意: 响应始终是一个 结构化的 JSON 对象,而不是原始字符串。这是使用
outputClass(TranslateResponse.class)的结果:Gemini 返回结构化数据,Genkit 会自动将其反序列化为你的 Java 类。
生产级特性
当您使用 Genkit 时,您获得的不仅仅是 API 调用的薄包装:
OpenTelemetry 跟踪 用于每一次流程执行
- 按流程和模型调用的延迟跟踪
- 令牌使用情况(输入 / 输出 / “思考” 令牌)
- 错误率和失败跟踪
- 完整的跨度层级,展示执行路径
模型切换 – 只需一行代码即可更换底层模型:
// Switch from Gemini to OpenAI
.plugin(OpenAIPlugin.create());
// Or use Anthropic Claude
.plugin(AnthropicPlugin.create());Genkit 提供了一个面向生产的框架,用于构建、测试和部署 AI 驱动的 Java 应用程序,具备最小的样板代码和最大的可观测性。
Genkit Java 入门
// Or run locally with Ollama
.plugin(OllamaPlugin.create())Genkit 支持 10+ 模型提供商、向量数据库(Pinecone、Weaviate、PostgreSQL)、Firebase 集成等。对于 Java 开发者来说,这正是 Genkit 大显身手的地方:flows、generate 调用,甚至 LLM 响应都是完整类型化的。
定义类型化 Flow
// The flow takes a TranslateRequest and returns a TranslateResponse
genkit.defineFlow(
"translate",
TranslateRequest.class,
TranslateResponse.class,
/* … */
);生成类型化响应
// The LLM returns a TranslateResponse directly—no string parsing required
genkit.generate(
GenerateOptions.builder()
.outputClass(TranslateResponse.class)
.build()
);Genkit 根据你的 @JsonProperty 和 @JsonPropertyDescription 注解生成 JSON 架构并发送给 Gemini,从而模型返回的结构化数据可以直接映射到你的 Java 类。无需对象强制转换、无需 response.getText() + objectMapper.readValue(),也不会出现运行时意外。
本项目涵盖内容
- RAG – 检索增强生成,使用向量存储(Firestore、Pinecone、pgvector、Weaviate)
- 多代理编排 – 协调多个 AI 代理
- 聊天会话 – 多轮对话并保持会话持久性
- 评估 – 类 RAGAS 的指标,用于衡量 AI 输出质量
- MCP 集成 – 连接到模型上下文协议(Model Context Protocol)服务器
- Spring Boot – 对现有 Spring 应用使用 Spring 插件而非 Jetty
- Firebase – 以 Cloud Functions 部署,并使用 Firestore 向量搜索
深入了解完整的 Genkit Java 文档和 samples 目录,以进一步探索。
为什么使用 Genkit Java?
- 类型化的输入/输出消除解析错误。
- 结构化的 LLM 响应直接映射到 Java 类。
- 内置可观测性,便于调试。
- 无缝部署到云平台。
结果: 使用最少的代码构建强大的生成式 AI 应用。
您可以在 GitHub 仓库 中找到此示例的完整代码。
祝编码愉快!