跳到主要内容

Google AI Gemini

https://ai.google.dev/gemini-api/docs

目录

Maven 依赖

<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-google-ai-gemini</artifactId>
<version>1.18.1</version>
</dependency>

API Key

在此免费获取 API 密钥:https://ai.google.dev/gemini-api/docs/api-key

可用模型

请在文档中查看可用模型列表。

  • gemini-3-pro-preview
  • gemini-2.5-pro
  • gemini-2.5-flash
  • gemini-2.5-flash-lite
  • gemini-2.0-flash
  • gemini-2.0-flash-lite

GoogleAiGeminiChatModel

提供常用的 chat(...) 方法:

ChatModel gemini = GoogleAiGeminiChatModel.builder()
.apiKey(System.getenv("GEMINI_AI_KEY"))
.modelName("gemini-2.5-flash")
...
.build();

String response = gemini.chat("Hello Gemini!");

以及 ChatResponse chat(ChatRequest req) 方法:

ChatModel gemini = GoogleAiGeminiChatModel.builder()
.apiKey(System.getenv("GEMINI_AI_KEY"))
.modelName("gemini-2.5-flash")
.build();

ChatResponse chatResponse = gemini.chat(ChatRequest.builder()
.messages(UserMessage.from(
"How many R's are there in the word 'strawberry'?"))
.build());

String response = chatResponse.aiMessage().text();

配置

ChatModel gemini = GoogleAiGeminiChatModel.builder()
.httpClientBuilder(...)
.defaultRequestParameters(...)
.apiKey(System.getenv("GEMINI_AI_KEY"))
.baseUrl(...)
.modelName("gemini-2.5-flash")
.maxRetries(...)
.temperature(1.0)
.topP(0.95)
.topK(64)
.seed(42)
.frequencyPenalty(...)
.presencePenalty(...)
.maxOutputTokens(8192)
.timeout(Duration.ofSeconds(60))
.responseFormat(ResponseFormat.JSON) // or .responseFormat(ResponseFormat.builder()...build())
.stopSequences(List.of(...))
.toolConfig(GeminiFunctionCallingConfig.builder()...build()) // or below
.toolConfig(GeminiMode.ANY, List.of("fnOne", "fnTwo"))
.allowCodeExecution(true)
.includeCodeExecution(true)
.logRequestsAndResponses(true)
.safetySettings(List<GeminiSafetySetting> or Map<GeminiHarmCategory, GeminiHarmBlockThreshold>)
.thinkingConfig(...)
.returnThinking(true)
.sendThinking(true)
.responseLogprobs(...)
.logprobs(...)
.enableEnhancedCivicAnswers(...)
.mediaResolution(GeminiMediaResolutionLevel.MEDIA_RESOLUTION_HIGH)
.mediaResolutionPerPartEnabled(true)
.listeners(...)
.supportedCapabilities(...)
.build();

默认请求参数

除了(或除了)上方所示的各个构建器方法之外,您还可以通过 defaultRequestParameters(...) 提供单个 ChatRequestParameters 对象。这些参数会应用于模型发出的每个 请求,除非被单个 ChatRequest 的参数覆盖。

您可以传入通用的 ChatRequestParameters 或 Gemini 特有的 GoogleAiGeminiChatRequestParameters。 后者额外暴露了 Gemini 专有选项,例如 aspectRatioimageSize

GoogleAiGeminiChatRequestParameters parameters = GoogleAiGeminiChatRequestParameters.builder()
.modelName("gemini-2.5-flash")
.temperature(1.0)
.maxOutputTokens(8192)
.aspectRatio("16:9") // Gemini-specific
.imageSize("2K") // Gemini-specific
.build();

ChatModel gemini = GoogleAiGeminiChatModel.builder()
.apiKey(System.getenv("GEMINI_AI_KEY"))
.defaultRequestParameters(parameters)
.build();

当同一参数既通过 defaultRequestParameters(...) 又通过单个构建器方法 (例如 modelName(String))设置时,以单个构建器方法设置的值为准:

ChatModel gemini = GoogleAiGeminiChatModel.builder()
.apiKey(System.getenv("GEMINI_AI_KEY"))
.defaultRequestParameters(GoogleAiGeminiChatRequestParameters.builder()
.modelName("gemini-2.5-flash")
.temperature(1.0)
.build())
.temperature(0.0) // overrides temperature from defaultRequestParameters
.build();
// effective parameters: modelName=gemini-2.5-flash, temperature=0.0

GoogleAiGeminiStreamingChatModel

GoogleAiGeminiStreamingChatModel 允许逐 token 流式返回响应文本。 响应必须由 StreamingChatResponseHandler 处理。

StreamingChatModel gemini = GoogleAiGeminiStreamingChatModel.builder()
.apiKey(System.getenv("GEMINI_AI_KEY"))
.modelName("gemini-2.5-flash")
.build();

CompletableFuture<ChatResponse> futureResponse = new CompletableFuture<>();

gemini.chat("Tell me a joke about Java", new StreamingChatResponseHandler() {

@Override
public void onPartialResponse(String partialResponse) {
System.out.print(partialResponse);
}

@Override
public void onCompleteResponse(ChatResponse completeResponse) {
futureResponse.complete(completeResponse);
}

@Override
public void onError(Throwable error) {
futureResponse.completeExceptionally(error);
}
});

futureResponse.join();

工具

支持工具(即函数调用),包括并行调用。 您可以使用接受 ChatRequestchat(ChatRequest) 方法,并配置一个或多个 ToolSpecification,让 Gemini 知道它可以请求调用函数。 或者您可以使用 LangChain4j 的 AiServices 来定义它们。

以下是使用 AiServices 的天气工具示例:

record WeatherForecast(
String location,
String forecast,
int temperature) {}

class WeatherForecastService {
@Tool("Get the weather forecast for a location")
WeatherForecast getForecast(
@P("Location to get the forecast for") String location) {
if (location.equals("Paris")) {
return new WeatherForecast("Paris", "sunny", 20);
} else if (location.equals("London")) {
return new WeatherForecast("London", "rainy", 15);
} else if (location.equals("Tokyo")) {
return new WeatherForecast("Tokyo", "warm", 32);
} else {
return new WeatherForecast("Unknown", "unknown", 0);
}
}
}

interface WeatherAssistant {
String chat(String userMessage);
}

WeatherForecastService weatherForecastService =
new WeatherForecastService();

ChatModel gemini = GoogleAiGeminiChatModel.builder()
.apiKey(System.getenv("GEMINI_AI_KEY"))
.modelName("gemini-2.5-flash")
.temperature(0.0)
.build();

WeatherAssistant weatherAssistant =
AiServices.builder(WeatherAssistant.class)
.chatModel(gemini)
.tools(weatherForecastService)
.build();

String tokyoWeather = weatherAssistant.chat(
"What is the weather forecast for Tokyo?");

System.out.println("Gemini> " + tokyoWeather);
// Gemini> The weather forecast for Tokyo is warm
// with a temperature of 32 degrees.

结构化输出

有关结构化输出的更多信息见 此处

从自由形式文本中进行类型安全的数据提取

大语言模型非常擅长从非结构化文本中提取结构化信息。 在以下示例中,我们借助 AiServices 从天气预报文本中检索类型安全的 WeatherForecast 对象:

// A type-safe / strongly-typed object 
// representing the weather forecast

record WeatherForecast(
@Description("minimum temperature")
Integer minTemperature,
@Description("maximum temperature")
Integer maxTemperature,
@Description("chances of rain")
boolean rain
) { }

// An interface contract, to interact with Gemini

interface WeatherForecastAssistant {
WeatherForecast extract(String forecast);
}

// Let's extract the data:

ChatModel gemini = GoogleAiGeminiChatModel.builder()
.apiKey(System.getenv("GEMINI_AI_KEY"))
.modelName("gemini-2.5-flash")
.supportedCapabilities(RESPONSE_FORMAT_JSON_SCHEMA) // this is required to enable structured outputs feature
.build();

WeatherForecastAssistant forecastAssistant =
AiServices.builder(WeatherForecastAssistant.class)
.chatModel(gemini)
.build();

WeatherForecast forecast = forecastAssistant.extract("""
Morning: The day dawns bright and clear in Osaka, with crisp
autumn air and sunny skies. Expect temperatures to hover
around 18°C (64°F) as you head out for your morning stroll
through Namba.
Afternoon: The sun continues to shine as the city buzzes with
activity. Temperatures climb to a comfortable 22°C (72°F).
Enjoy a leisurely lunch at one of Osaka's many outdoor cafes,
or take a boat ride on the Okawa River to soak in the beautiful
scenery.
Evening: As the day fades, expect clear skies and a slight chill
in the air. Temperatures drop to 15°C (59°F). A cozy dinner at a
traditional Izakaya will be the perfect way to end your day in
Osaka.
Overall: A beautiful autumn day in Osaka awaits, perfect for
exploring the city's vibrant streets, enjoying the local cuisine,
and soaking in the sights.
Don't forget: Pack a light jacket for the evening and wear
comfortable shoes for all the walking you'll be doing.
""");

响应格式 / 响应 Schema

您可以在创建 GoogleAiGeminiChatModel 时或调用它时指定 ResponseFormat

特别是在 Json 格式的情况下,您可以选择通过创建相应的 Java 对象以编程方式定义 schema,或提供原始 json schema。

响应 Schema

让我们看一个在创建 GoogleAiGeminiChatModel 时为食谱定义 JSON schema 的示例。 在本示例中,我们使用 JsonObjectSchema 类声明 json schema。

ResponseFormat responseFormat = ResponseFormat.builder()
.type(ResponseFormatType.JSON)
.jsonSchema(JsonSchema.builder() // see [1] below
.rootElement(JsonObjectSchema.builder()
.addStringProperty("title")
.addIntegerProperty("preparationTimeMinutes")
.addProperty("ingredients", JsonArraySchema.builder()
.items(new JsonStringSchema())
.build())
.addProperty("steps", JsonArraySchema.builder()
.items(new JsonStringSchema())
.build())
.build())
.build())
.build();

ChatModel gemini = GoogleAiGeminiChatModel.builder()
.apiKey(System.getenv("GEMINI_AI_KEY"))
.modelName("gemini-2.5-flash")
.responseFormat(responseFormat)
.build();

String recipeResponse = gemini.chat("Suggest a dessert recipe with strawberries");

System.out.println(recipeResponse);

说明:

  • [1] - 可以使用 JsonSchemas.jsonSchemaFrom() 辅助方法从您的类自动生成 JsonSchema
JsonSchema jsonSchema = JsonSchemas.jsonSchemaFrom(TripItinerary.class).get();

让我们看一个在调用 GoogleAiGeminiChatModel 时为食谱定义 JSON schema 的示例:

ChatModel gemini = GoogleAiGeminiChatModel.builder()
.apiKey(System.getenv("GEMINI_AI_KEY"))
.modelName("gemini-2.5-flash")
.build();

ResponseFormat responseFormat = ...;

ChatRequest chatRequest = ChatRequest.builder()
.messages(UserMessage.from("Suggest a dessert recipe with strawberries"))
.responseFormat(responseFormat)
.build();

ChatResponse chatResponse = gemini.chat(chatRequest);

System.out.println(chatResponse.aiMessage().text());

原始响应 Schema

另一个示例展示了我们如何使用 Gemini API 的 responseJsonSchema,通过 JsonRawSchema 类提供原始 JSON schema。
请谨慎,仅使用 Gemini API 的受支持类型

String rawSchema = """
{
"type": "object",
"properties": {
"name": {
"type": "string"
},
"birthDate": {
"type": "string",
"format": "date"
},
"preferredContactTime": {
"type": "string",
"format": "time"
},
"height": {
"type": "number",
"minimum": 1.83,
"maximum": 1.88
},
"role": {
"type": "string",
"enum": ["developer", "maintainer", "researcher"]
},
"isAvailable": { "type": "boolean" },
"tags": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"maxItems": 5
},
"address": {
"type": "object",
"properties": {
"city": { "type": "string" },
"streetName": { "type": "string" },
"streetNumber": { "type": "string" }
},
"required": ["city", "streetName", "streetNumber"],
"additionalProperties": true
}
},
"required": ["name", "birthDate", "height", "role", "tags", "address"]
}
""";

JsonRawSchema jsonRawSchema = JsonRawSchema.builder().schema(rawSchema).build();
JsonSchema jsonSchema = JsonSchema.builder().rootElement(jsonRawSchema).build();

ResponseFormat responseFormat = ResponseFormat.builder()
.type(ResponseFormatType.JSON)
.jsonSchema(jsonSchema)
.build();

GoogleAiGeminiChatModel gemini = GoogleAiGeminiChatModel.builder()
.apiKey(GOOGLE_AI_GEMINI_API_KEY)
.modelName("gemini-2.5-flash-lite")
.logRequests(true)
.logResponses(true)
.responseFormat(responseFormat)
.build();

UserMessage userMessage = UserMessage.from(
"""
Tell me about a detective named Sherlock Holmes,
who was born on November 28 1852 and sees the world over six feet from the ground.
He is a trouble-seeker, an active volunteer and lives in London at 221B Baker Street.
He plays the violin and he likes to conduct various physics and chemistry experiments.
He accepts clients or prefers to be contacted at 09:00am.
""");

ChatResponse response = gemini.chat(ChatRequest.builder()
.messages(userMessage)
.build());

JSON 模式

您可以强制 Gemini 以 JSON 回复:

ChatModel gemini = GoogleAiGeminiChatModel.builder()
.apiKey(System.getenv("GEMINI_AI_KEY"))
.modelName("gemini-2.5-flash")
.responseFormat(ResponseFormat.JSON)
.build();

String roll = gemini.chat("Roll a 6-sided dice");

System.out.println(roll);
// {"roll": "3"}

系统提示可以进一步描述 JSON 输出应是什么样子。 Gemini 通常会遵循建议的 schema,但不保证。 如果您想保证应用 JSON schema,应定义响应格式,如上节所述。

Python 代码执行

除了函数调用之外,Google AI Gemini 还允许您在沙箱环境中创建并执行 Python 代码。 这在需要更高级计算或逻辑的情况下特别有用。

ChatModel gemini = GoogleAiGeminiChatModel.builder()
.apiKey(System.getenv("GEMINI_AI_KEY"))
.modelName("gemini-2.5-flash")
.allowCodeExecution(true)
.includeCodeExecutionOutput(true)
.build();

有 2 个构建器方法:

  • allowCodeExecution(true):让 Gemini 知道它可以进行一些 Python 编程
  • includeCodeExecutionOutput(true):如果您想查看它编写的实际 Python 脚本及其执行输出
ChatResponse mathQuizz = gemini.chat(
SystemMessage.from("""
You are an expert mathematician.
When asked a math problem or logic problem,
you can solve it by creating a Python program,
and execute it to return the result.
"""),
UserMessage.from("""
Implement the Fibonacci and Ackermann functions.
What is the result of `fibonacci(22)` - ackermann(3, 4)?
""")
);

Gemini 将编写一个 Python 脚本,在其服务器上执行,并返回结果。 由于我们要求查看代码和执行输出,答案将如下所示:

Code executed:
```python
def fibonacci(n):
if n <= 1:
return n
else:
return fibonacci(n-1) + fibonacci(n-2)

def ackermann(m, n):
if m == 0:
return n + 1
elif n == 0:
return ackermann(m - 1, 1)
else:
return ackermann(m - 1, ackermann(m, n - 1))

print(fibonacci(22) - ackermann(3, 4))
```
Output:
```
17586
```
The result of `fibonacci(22) - ackermann(3, 4)` is **17586**.

I implemented the Fibonacci and Ackermann functions in Python.
Then I called `fibonacci(22) - ackermann(3, 4)` and printed the result.

如果我们没有要求查看代码/输出,我们将只会收到以下文本:

The result of `fibonacci(22) - ackermann(3, 4)` is **17586**.

I implemented the Fibonacci and Ackermann functions in Python.
Then I called `fibonacci(22) - ackermann(3, 4)` and printed the result.

多模态

Gemini 是一个多模态模型,这意味着它除了文本之外,还可以接受和生成不同的_模态_。

输入模态

在输入方面,Gemini 接受:

  • 图片(ImageContent
  • 视频(VideoContent
  • 音频文件(AudioContent
  • PDF 文件(PdfFileContent

以下示例展示了如何将文本提示与图像混合:

// PNG of the cute colorful parrot mascot of the LangChain4j project
String base64Img = b64encoder.encodeToString(readBytes(
"https://avatars.githubusercontent.com/u/132277850?v=4"));

ChatModel gemini = GoogleAiGeminiChatModel.builder()
.apiKey(System.getenv("GEMINI_AI_KEY"))
.modelName("gemini-2.5-flash")
.build();

ChatResponse response = gemini.chat(
UserMessage.from(
ImageContent.from(base64Img, "image/png"),
TextContent.from("""
Do you think this logo fits well
with the project description?
""")
)
);

图像生成输出

某些 Gemini 模型(例如 gemini-2.5-flash-image)可以在响应中生成图像。生成图像时,它们存储在 AiMessage 属性中,可以使用 GeneratedImageHelper 工具类访问。

ChatModel gemini = GoogleAiGeminiChatModel.builder()
.apiKey("Your API Key")
.modelName("gemini-2.5-flash-image")
.build();

ChatResponse response = gemini.chat(UserMessage.from("A high-resolution, studio-lit product photograph of a minimalist ceramic coffee mug in matte black"));

// Extract generated images from the response
AiMessage aiMessage = response.aiMessage();
List<Image> generatedImages = GeneratedImageHelper.getGeneratedImages(aiMessage);

if (GeneratedImageHelper.hasGeneratedImages(aiMessage)) {
System.out.println("Generated " + generatedImages.size() + " image(s)");
System.out.println("Text response: " + aiMessage.text());

for (Image image : generatedImages) {
String base64Data = image.base64Data();
String mimeType = image.mimeType();

// You can now save the image, display it, or process it further
// For example, save to file:
byte[] imageBytes = Base64.getDecoder().decode(base64Data);
Files.write(Paths.get("generated_image.png"), imageBytes);
}
} else {
System.out.println("Text response: " + aiMessage.text());
}

媒体分辨率

您可以控制发送给模型的媒体(图像、视频、PDF)的分辨率。可以全局设置,也可以按部分(按图像)设置。

全局媒体分辨率

要为请求中的所有媒体部分设置媒体分辨率,请使用 .mediaResolution() 构建器方法:

ChatModel gemini = GoogleAiGeminiChatModel.builder()
.apiKey(System.getenv("GEMINI_AI_KEY"))
.modelName("gemini-2.5-flash")
.mediaResolution(GeminiMediaResolutionLevel.MEDIA_RESOLUTION_LOW) // or MEDIUM, HIGH, ULTRA_HIGH, UNSPECIFIED
.build();

按部分的媒体分辨率(Gemini 3)

使用 Gemini 3,您可以使用 ImageContent 中的 DetailLevel 为各个图像指定分辨率。 首先在构建器中启用此功能,然后在 ImageContent 上设置详细级别:

ChatModel gemini = GoogleAiGeminiChatModel.builder()
.apiKey(System.getenv("GEMINI_AI_KEY"))
.modelName("gemini-3-pro-preview")
.mediaResolutionPerPartEnabled(true)
.build();

ChatResponse response = gemini.chat(
UserMessage.from(
ImageContent.from(url1, ImageContent.DetailLevel.LOW),
ImageContent.from(url2, ImageContent.DetailLevel.HIGH),
TextContent.from("Compare these two images")
)
);

受支持的 DetailLevel 值及其到 Gemini 分辨率级别的映射:

  • LOW -> MEDIA_RESOLUTION_LOW
  • MEDIUM -> MEDIA_RESOLUTION_MEDIUM
  • HIGH -> MEDIA_RESOLUTION_HIGH
  • ULTRA_HIGH -> MEDIA_RESOLUTION_ULTRA_HIGH(最高 token 数,特定用例如计算机使用所必需)
  • AUTO -> MEDIA_RESOLUTION_UNSPECIFIED

思考(Thinking)

GoogleAiGeminiChatModelGoogleAiGeminiStreamingChatModel 都支持 thinking

以下参数也控制思考行为:

  • GeminiThinkingConfig.includeThoughtsthinkingBudget:启用思考,更多详情见 此处
  • returnThinking:控制是否在 AiMessage.thinking() 中返回思考(如果可用), 以及在使用 GoogleAiGeminiStreamingChatModel 时是否调用 StreamingChatResponseHandler.onPartialThinking()TokenStream.onPartialThinking() 回调。 默认禁用。如果启用,思考签名也将存储并返回在 AiMessage.attributes() 中。
  • sendThinking:控制是否在后续请求中将存储在 AiMessage 中的思考和签名发送给 LLM。
  • 默认禁用。
备注

请注意,当 returnThinking 未设置(为 null)且设置了 thinkingConfig 时, 思考文本将前置到 AiMessage.text() 字段中的实际响应, 并且将调用 StreamingChatResponseHandler.onPartialResponse(), 而不是 StreamingChatResponseHandler.onPartialThinking()

以下是配置思考的示例:

GeminiThinkingConfig thinkingConfig = GeminiThinkingConfig.builder()
.includeThoughts(true)
.thinkingBudget(250)
.build();

ChatModel model = GoogleAiGeminiChatModel.builder()
.apiKey(System.getenv("GOOGLE_AI_GEMINI_API_KEY"))
.modelName("gemini-2.5-flash")
.thinkingConfig(thinkingConfig)
.returnThinking(true)
.sendThinking(true)
.build();

Gemini 3 Pro

对于 Gemini 3 Pro,思考配置引入了_thinking level_,可以是 "low""high"(默认为 high)。 可以在思考配置中设置该级别:

GoogleAiGeminiChatModel modelHigh = GoogleAiGeminiChatModel.builder()
.modelName("gemini-3-pro-preview")
.apiKey(System.getenv("GOOGLE_AI_GEMINI_API_KEY"))
.thinkingConfig(GeminiThinkingConfig.builder()
.thinkingLevel(LOW) // or HIGH
.build())
.sendThinking(true)
.returnThinking(true)
.build();

您可以传入字符串 "high" / "low",或 GeminiThinkingConfig.GeminiThinkingLevel.HIGH / GeminiThinkingConfig.GeminiThinkingLevel.LOW 枚举值。

使用 Gemini 3 Pro 时,必须将 sendThinking()returnThinking() 配置为 true, 以确保 thought signatures 正确传递给模型。

Gemini Files API

Gemini Files API 允许您上传和管理供 Gemini 模型使用的媒体文件。当总请求大小超过 20 MB 时特别有用,因为文件可以单独上传并在内容生成请求中引用。

主要特性

  • 多模态支持:上传图像、音频、视频和文档
  • 存储:文件保存 48 小时
  • 容量:每个项目最多 20 GB 文件,单个文件最大 2 GB
  • 无费用:Files API 免费提供

上传文件

您可以通过两种方式上传文件:

从文件路径:

GeminiFiles filesApi = GeminiFiles.builder()
.apiKey(System.getenv("GEMINI_AI_KEY"))
.build();

// Upload from a file path
Path filePath = Paths.get("path/to/your/file.pdf");
GeminiFile uploadedFile = filesApi.uploadFile(filePath, "My Document");

System.out.println("File uploaded: " + uploadedFile.name());
System.out.println("File URI: " + uploadedFile.uri());

从字节数组:

byte[] fileBytes = Files.readAllBytes(Paths.get("path/to/file.jpg"));
GeminiFile uploadedFile = filesApi.uploadFile(
fileBytes,
"image/jpeg",
"My Image"
);

管理文件

列出所有已上传文件:

List<GeminiFile> files = filesApi.listFiles();
for (GeminiFile file : files) {
System.out.println("File: " + file.displayName() + " (" + file.name() + ")");
}

获取文件元数据:

GeminiFile file = filesApi.getMetadata("files/abc123");
System.out.println("File size: " + file.sizeBytes() + " bytes");
System.out.println("MIME type: " + file.mimeType());
System.out.println("Created: " + file.createTime());
System.out.println("Expires: " + file.expirationTime());

删除文件:

filesApi.deleteFile("files/abc123");
System.out.println("File deleted successfully");

文件状态

文件在其生命周期中可以处于不同状态:

GeminiFile file = filesApi.getMetadata("files/abc123");

if (file.isActive()) {
System.out.println("File is ready to use");
} else if (file.isProcessing()) {
System.out.println("File is still being processed");
} else if (file.isFailed()) {
System.out.println("File processing failed");
}

批处理

GoogleAiBatchChatModel

GoogleAiBatchChatModel 提供一个接口,用于以降低的成本异步处理大量聊天请求(标准定价的 50%)。它非常适合非紧急、大规模任务,具有 24 小时周转 SLO。

创建批处理任务

内联批处理创建:

GoogleAiGeminiBatchChatModel batchModel = GoogleAiGeminiBatchChatModel.builder()
.apiKey(System.getenv("GEMINI_AI_KEY"))
.modelName("gemini-2.5-flash")
.build();

// Create batch requests
List<ChatRequest> requests = List.of(
ChatRequest.builder()
.messages(UserMessage.from("What is the capital of France?"))
.build(),
ChatRequest.builder()
.messages(UserMessage.from("What is the capital of Germany?"))
.build(),
ChatRequest.builder()
.messages(UserMessage.from("What is the capital of Italy?"))
.build()
);

// Submit the batch (generic API, no Gemini-specific options)
BatchResponse<ChatResponse> response = batchModel.submit(new BatchRequest<>(requests));

// Or, to set a Gemini-specific display name and priority, use GeminiBatchRequest:
BatchResponse<ChatResponse> response = batchModel.submit(GeminiBatchRequest.from(
requests,
"Geography Questions Batch", // display name
0L // priority (optional, defaults to 0)
));

基于文件的批处理创建:

对于较大的批次,或当您需要对请求格式有更多控制时,可以从已上传的文件创建批次:

// First, upload a file with batch requests
GeminiFiles filesApi = GeminiFiles.builder()
.apiKey(System.getenv("GEMINI_AI_KEY"))
.build();

GeminiFile uploadedFile = filesApi.uploadFile(
Paths.get("batch_chat_requests.jsonl"),
"Batch Chat Requests"
);

// Wait for file to be active
while (uploadedFile.isProcessing()) {
Thread.sleep(1000);
uploadedFile = filesApi.getMetadata(uploadedFile.name());
}

// Create batch from file
BatchResponse<ChatResponse> response = batchModel.submit("My Batch Job", uploadedFile);

处理批处理响应

BatchResponse 暴露当前的 state(),以及按请求的 results()responses() / errors() 便捷视图。根据 state() 分支(使用 state().isTerminal() 判断批次是否仍在进行中):

BatchResponse<ChatResponse> response = batchModel.submit(new BatchRequest<>(requests));

if (!response.state().isTerminal()) {
System.out.println("Batch is " + response.state());
System.out.println("Batch ID: " + response.batchId());
} else if (response.state() == BatchState.SUCCEEDED) {
System.out.println("Batch completed successfully!");

// Process successful responses
for (ChatResponse chatResponse : response.responses()) {
System.out.println(chatResponse.aiMessage().text());
}

// Check for individual request errors within the batch
if (!response.errors().isEmpty()) {
System.out.println("Some requests failed:");
for (BatchError error : response.errors()) {
System.err.println("Error code: " + error.code() + ", message: " + error.message());
}
}
} else {
System.err.println("Batch " + response.state() + ": " + response.errors());
}

注意: state() == SUCCEEDED 的批次表示批处理任务已完成,但批次内的个别 请求可能已失败。errors() 列表包含任何个别请求 失败(例如超时、速率限制),而 responses() 包含成功的响应。 两者都是便捷视图,且永不为 null(没有内容可报告时为空),因此请检查 !responses().isEmpty() / !errors().isEmpty() 以优雅地处理部分失败。

将结果与请求关联

responses()errors() 是扁平视图,会丢失哪个输入产生了哪个结果的跟踪。 当您需要将每个结果映射回其原始请求时,请改用 results():它 为每个请求返回一个 BatchItemResult顺序与提交的请求相同,因此 第 i 个结果对应第 i 个请求。每个结果要么是 BatchItemResult.Success (携带 response()),要么是 BatchItemResult.Failure(携带 error()):

BatchResponse<ChatResponse> result = batchModel.submit(new BatchRequest<>(requests));
// ... poll until terminal ...

List<BatchItemResult<ChatResponse>> results = result.results();
for (int i = 0; i < results.size(); i++) {
BatchItemResult<ChatResponse> item = results.get(i);
if (item.isSuccess()) {
System.out.println("Request #" + i + " -> " + item.response().aiMessage().text());
} else {
BatchError error = item.error();
System.err.println("Request #" + i + " failed: " + error.code() + " - " + error.message());
}
}

轮询结果

由于批处理是异步的,您需要轮询结果(结果可能需要最多 24 小时处理):

BatchResponse<ChatResponse> result = batchModel.submit(new BatchRequest<>(requests));
String batchId = result.batchId();

// Poll until the batch reaches a terminal state
while (!result.state().isTerminal()) {
Thread.sleep(5000); // Wait 5 seconds between polls
result = batchModel.retrieve(batchId);
}

// Process final result
if (result.state() == BatchState.SUCCEEDED) {
System.out.println("Successful responses: " + result.responses().size());
for (ChatResponse chatResponse : result.responses()) {
System.out.println(chatResponse.aiMessage().text());
}

// Handle any individual request failures
if (!result.errors().isEmpty()) {
System.out.println("Failed requests: " + result.errors().size());
for (BatchError error : result.errors()) {
System.err.println("Error: " + error.code() + " - " + error.message());
}
}
} else {
System.err.println("Batch did not succeed: " + result.state());
}

管理批处理任务

取消批处理任务:

String batchId = // ... obtained from submit(...)

try {
batchModel.cancel(batchId);
System.out.println("Batch cancelled successfully");
} catch (HttpException e) {
System.err.println("Failed to cancel batch: " + e.getMessage());
}

删除批处理任务:

batchModel.deleteBatchJob(batchId);
System.out.println("Batch deleted successfully");

列出批处理任务:

// List first page of batch jobs
BatchPage<ChatResponse> page = batchModel.list(new BatchPagination(10, null));

for (BatchResponse<ChatResponse> batch : page.batches()) {
System.out.println("Batch: " + batch);
}

// Get next page if available
if (page.nextPageToken() != null) {
BatchPage<ChatResponse> nextPage = batchModel.list(new BatchPagination(10, page.nextPageToken()));
}

基于文件的批处理

对于高级用例,您可以将批处理请求写入 JSONL 文件并上传:

// Create a JSONL file with batch requests
Path batchFile = Files.createTempFile("batch", ".jsonl");

try (JsonLinesWriter writer = new StreamingJsonLinesWriter(batchFile)) {
List<BatchFileRequest<ChatRequest>> fileRequests = List.of(
new BatchFileRequest<>("request-1", ChatRequest.builder()
.messages(UserMessage.from("Question 1"))
.build()),
new BatchFileRequest<>("request-2", ChatRequest.builder()
.messages(UserMessage.from("Question 2"))
.build())
);

batchModel.writeBatchToFile(writer, fileRequests);
}

// Upload the file
GeminiFiles filesApi = GeminiFiles.builder()
.apiKey(System.getenv("GEMINI_AI_KEY"))
.build();

GeminiFile uploadedFile = filesApi.uploadFile(batchFile, "Batch Chat Requests");

// Create batch from file
BatchResponse<ChatResponse> response = batchModel.submit("File-Based Chat Batch", uploadedFile);

批处理任务状态

BatchState 枚举表示批处理任务可能的状态:

  • PENDING:批次已排队,等待处理
  • RUNNING:批次当前正在处理
  • SUCCEEDED:批次成功完成(终态)
  • FAILED:批次处理失败(终态)
  • CANCELLED:批次被用户取消(终态)
  • EXPIRED:批次在完成前过期(终态)
  • UNSPECIFIED:状态未知或未提供

BatchResponse.state() 使用 BatchState.isTerminal() 以检测何时可以停止轮询。

设置批处理优先级

更高优先级的批次会先于更低优先级的批次处理。通过 GeminiBatchRequest 设置优先级:

// High priority batch
BatchResponse<ChatResponse> highPriority = batchModel.submit(GeminiBatchRequest.from(
urgentRequests, "Urgent Batch", 100L));

// Low priority batch
BatchResponse<ChatResponse> lowPriority = batchModel.submit(GeminiBatchRequest.from(
backgroundRequests, "Background Batch", -50L));

配置

GoogleAiGeminiBatchChatModel 支持与 GoogleAiGeminiChatModel 相同的配置选项:

GoogleAiGeminiBatchChatModel batchModel = GoogleAiGeminiBatchChatModel.builder()
.apiKey(System.getenv("GEMINI_AI_KEY"))
.modelName("gemini-2.5-flash")
.temperature(0.7)
.topP(0.95)
.topK(40)
.maxOutputTokens(2048)
.maxRetries(3)
.timeout(Duration.ofMinutes(5))
.logRequestsAndResponses(true)
.build();

重要约束

  • 模型一致性:批次中的所有请求必须使用相同的模型
  • 大小限制:内联 API 支持总计 20MB 或以下的请求大小
  • 成本:批处理相比实时请求可降低 50% 成本
  • 周转时间:24 小时 SLO,但通常完成得更快
  • 用例:最适合大规模、非紧急任务,如数据预处理或评估

示例:完整工作流

GoogleAiGeminiBatchChatModel batchModel = GoogleAiGeminiBatchChatModel.builder()
.apiKey(System.getenv("GEMINI_AI_KEY"))
.modelName("gemini-2.5-flash")
.build();

// Prepare batch requests
List<ChatRequest> requests = new ArrayList<>();
for (int i = 0; i < 50; i++) {
requests.add(ChatRequest.builder()
.messages(UserMessage.from("Generate a creative story idea #" + i))
.build());
}

// Submit batch
BatchResponse<ChatResponse> result = batchModel.submit(GeminiBatchRequest.from(
requests, "Story Ideas Batch", 0L));
String batchId = result.batchId();

// Poll for completion
int attempts = 0;
int maxAttempts = 720; // 1 hour with 5-second intervals
while (!result.state().isTerminal()) {
if (attempts++ >= maxAttempts) {
throw new RuntimeException("Batch processing timeout");
}
Thread.sleep(5000);
result = batchModel.retrieve(batchId);
System.out.println("Status: " + result.state());
}

// Process results
if (result.state() == BatchState.SUCCEEDED) {
System.out.println("Generated " + result.responses().size() + " stories");
for (int i = 0; i < result.responses().size(); i++) {
ChatResponse chatResponse = result.responses().get(i);
System.out.println("Story #" + i + ": " + chatResponse.aiMessage().text());
}

// Report any failures
if (!result.errors().isEmpty()) {
System.err.println(result.errors().size() + " requests failed:");
for (BatchError error : result.errors()) {
System.err.println(" - Code " + error.code() + ": " + error.message());
}
}
} else {
System.err.println("Batch did not succeed: " + result.state());
}

了解更多

如果您想了解更多关于 Google AI Gemini 模型的信息,请查看其 文档