主题
Google Vertex AI Gemini
Vertex AI 是 Google Cloud 的全托管 AI 开发平台,提供对 Google 大型生成式模型的访问,包括较早的一代(PaLM2)与较新的一代(Gemini)。
要使用 Vertex AI,必须先创建一个 Google Cloud Platform 账户。
开始使用
创建 Google Cloud 账户
如果你是 Google Cloud 新手,可以在下页的 Get set up on Google Cloud 下拉菜单下,点击 [create an account] 按钮创建一个新账户:
在你的 Google Cloud Platform 账户内创建一个项目。
在你的 Google Cloud 账户内创建一个新项目,并按下述步骤启用 Vertex AI API:
记下你的 PROJECT_ID,因为后续的 API 调用会需要它。
选择 Google Cloud 认证策略
你的应用向 Google Cloud 服务与 API 认证的方式有几种。例如,你可以创建一个 服务账号,并将环境变量 GOOGLE_APPLICATION_CREDENTIALS 设为指向包含你凭据的 JSON 文件路径。
你可以在这里了解所有认证策略。但为了本地测试的简便,我们将通过 gcloud 工具进行认证。
安装 Google Cloud CLI(可选)
要在本地访问你的云项目,你可以按安装说明安装 gcloud 工具。对于 GNU/Linux 操作系统,安装步骤如下:
- 下载 SDK:
bash
curl -O https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-467.0.0-linux-x86_64.tar.gz- 解压归档:
bash
tar -xf google-cloud-cli-467.0.0-linux-x86_64.tar.gz- 运行安装脚本:
bash
cd google-cloud-sdk/
./install.sh- 运行以下命令以设置默认项目与认证凭据:
bash
gcloud auth application-default login该认证方式同时兼容 vertex-ai(嵌入模型、PaLM2)与 vertex-ai-gemini(Gemini)两个包。
添加依赖
要开始使用,将以下依赖添加到你的项目的 pom.xml:
xml
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-vertex-ai-gemini</artifactId>
<version>1.22.0-beta32</version>
</dependency>或添加到项目的 build.gradle:
groovy
implementation 'dev.langchain4j:langchain4j-vertex-ai-gemini:1.22.0-beta32'试用示例代码:
PROJECT_ID 字段代表你在创建新的 Google Cloud 项目时所设置的变量。
java
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.ImageContent;
import dev.langchain4j.data.message.TextContent;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.output.Response;
import dev.langchain4j.model.vertexai.gemini.VertexAiGeminiChatModel;
public class GeminiProVisionWithImageInput {
private static final String PROJECT_ID = "YOUR-PROJECT-ID";
private static final String LOCATION = "us-central1";
private static final String MODEL_NAME = "gemini-1.5-flash";
private static final String CAT_IMAGE_URL = "https://upload.wikimedia.org/" +
"wikipedia/commons/e/e9/" +
"Felis_silvestris_silvestris_small_gradual_decrease_of_quality.png";
public static void main(String[] args) {
ChatModel visionModel = VertexAiGeminiChatModel.builder()
.project(PROJECT_ID)
.location(LOCATION)
.modelName(MODEL_NAME)
.build();
ChatResponse response = visionModel.chat(
UserMessage.from(
ImageContent.from(CAT_IMAGE_URL),
TextContent.from("What do you see?")
)
);
System.out.println(response.aiMessage().text());
}
}借助 VertexAiGeminiStreamingChatModel 类,流式也受支持:
java
var model = VertexAiGeminiStreamingChatModel.builder()
.project(PROJECT_ID)
.location(LOCATION)
.modelName(GEMINI_1_5_PRO)
.build();
model.chat("Why is the sky blue?", new StreamingChatResponseHandler() {
@Override
public void onPartialResponse(String partialResponse) {
System.print(partialResponse);
}
@Override
public void onCompleteResponse(ChatResponse completeResponse){
System.print(completeResponse);
}
@Override
public void onError(Throwable error) {
error.printStackTrace();
}
});你可以使用 LambdaStreamingResponseHandler 的便捷函数 onPartialResponse() 与 onPartialResponseAndError():
java
model.chat("Why is the sky blue?", onPartialResponse(System.out::print));
model.chat("Why is the sky blue?", onPartialResponseAndError(System.out::print, Throwable::printStackTrace));可用模型
| 模型名 | 描述 | 输入 | 属性 |
|---|---|---|---|
gemini-1.5-flash | 为大批量、高质量、高性价比的应用提供速度与效率。 | 文本、代码、图像、音频、视频、含音频的视频、PDF | 最大输入词元:1,048,576,最大输出词元:8,192 |
gemini-1.5-pro | 支持文本或聊天提示词,给出文本或代码响应。支持直到最大输入词元上限的长上下文理解。 | 文本、代码、图像、音频、视频、含音频的视频、PDF | 最大输入词元:2,097,152,最大输出词元:8,192 |
gemini-1.0-pro | 面向大范围纯文本任务表现最佳的模型。 | 文本 | 最大输入词元:32,760,最大输出词元:8,192 |
gemini-1.0-pro-vision | 处理广泛应用时表现最佳的图像与视频理解模型。 | 文本、图像、音频、视频、含音频的视频、PDF | 最大输入词元:16,384,最大输出词元:2,048 |
gemini-1.0-ultra | 最强能力的文本模型,针对复杂任务(包括指令、代码与推理)优化。 | 文本 | 最大输入词元:8,192,最大输出词元:2,048 |
gemini-1.0-ultra-vision | 最强能力的多模态视觉模型。针对支持文本、图像与视频的联合输入而优化。 | 文本、代码、图像、音频、视频、含音频的视频、PDF | 最大输入词元:8,192,最大输出词元:2,048 |
你可以在 Gemini 模型文档页了解更多关于这些模型的信息
请注意,2024 年 3 月,Ultra 版本通过允许名单私有访问。因此你可能会收到类似这样的异常:
text
Caused by: io.grpc.StatusRuntimeException:
FAILED_PRECONDITION: Project `1234567890` is not allowed to use Publisher Model
`projects/{YOUR_PROJECT_ID}/locations/us-central1/publishers/google/models/gemini-ultra`配置
java
ChatModel model = VertexAiGeminiChatModel.builder()
.project(PROJECT_ID) // your Google Cloud project ID
.location(LOCATION) // the region where AI inference should take place
.modelName(MODEL_NAME) // the model used
.logRequests(true) // log input requests
.logResponses(true) // log output responses
.maxOutputTokens(8192) // the maximum number of tokens to generate (up to 8192)
.temperature(0.7) // temperature (between 0 and 2)
.topP(0.95) // topP (between 0 and 1) — cumulative probability of the most probable tokens
.topK(3) // topK (positive integer) — pick a token among the most probable ones
.seed(1234) // seed for the random number generator
.maxRetries(2) // maximum number of retries
.responseMimeType("application/json") // to get JSON structured outputs
.responseSchema(/*...*/) // structured output following the provided schema
.safetySettings(/*...*/) // specify safety settings to filter inappropriate content
.useGoogleSearch(true) // to ground responses with Google Search results
.vertexSearchDatastore(name)// to ground responses with data backed documents
// from a custom Vertex AI Search datastore
.toolCallingMode(/*...*/) // AUTO (automatic), ANY (from a list of functions), NONE
.allowedFunctionNames(/*...*/) // when using ANY tool calling mode,
// specify the allowed function names to be called
.listeners(/*...*/) // list of listeners to receive model events
.credentials(credentials) // custom Google Cloud credentials
.build();相同的参数也可用于流式聊天模型。
更多示例
Gemini 是一个多模态模型,它不仅接受文本,还接受图像、音频与视频文件以及 PDF 作为输入。
描述图像内容
java
ChatModel model = VertexAiGeminiChatModel.builder()
.project(PROJECT_ID)
.location(LOCATION)
.modelName(GEMINI_1_5_PRO)
.build();
UserMessage userMessage = UserMessage.from(
ImageContent.from(CAT_IMAGE_URL),
TextContent.from("What do you see? Reply in one word.")
);
ChatResponse response = model.chat(userMessage);该 URL 可以是一个网络 URL,也可以指向存储在 Google Cloud Storage 桶中的文件,例如 gs://my-bucket/my-image.png。
你也可以把图像内容作为 Base64 编码字符串传入:
java
String base64Data = Base64.getEncoder().encodeToString(readBytes(CAT_IMAGE_URL));
UserMessage userMessage = UserMessage.from(
ImageContent.from(base64Data, "image/png"),
TextContent.from("What do you see? Reply in one word.")
);就 PDF 文档提问
java
var model = VertexAiGeminiChatModel.builder()
.project(PROJECT_ID)
.location(LOCATION)
.modelName(GEMINI_1_5_PRO)
.logRequests(true)
.logResponses(true)
.build();
UserMessage message = UserMessage.from(
PdfFileContent.from(Paths.get("src/test/resources/gemini-doc-snapshot.pdf").toUri()),
TextContent.from("Provide a summary of the document")
);
ChatResponse response = model.chat(message);工具调用
java
ChatModel model = VertexAiGeminiChatModel.builder()
.project(PROJECT_ID)
.location(LOCATION)
.modelName(GEMINI_1_5_PRO)
.build();
ToolSpecification weatherToolSpec = ToolSpecification.builder()
.name("getWeatherForecast")
.description("Get the weather forecast for a location")
.parameters(JsonObjectSchema.builder()
.addStringProperty("location", "the location to get the weather forecast for")
.required("location")
.build())
.build();
ChatRequest request = ChatRequest.builder()
.messages(UserMessage.from("What is the weather in Paris?"))
.toolSpecifications(weatherToolSpec)
.build();
ChatResponse response = model.chat(request);模型会回复一个工具执行请求,而非文本消息。 你的职责是通过向模型回发一个 ToolExecutionResultMessage,为该执行请求提供结果, 模型随后便能回复一个文本响应。
并行函数调用也受支持——当模型在单个响应中请求发起多个工具执行请求时。
结合 AiServices 的工具支持
你可以用 AiServices 创建由工具驱动的助手。 下例展示了一个用于做数学计算的 Calculator 工具、一个用来指定助手契约的 Assistant 接口, 然后我们把 AiServices 配置为使用 Gemini,附带聊天记忆与计算器工具。
java
static class Calculator {
@Tool("Adds two given numbers")
double add(double a, double b) {
return a + b;
}
@Tool("Multiplies two given numbers")
String multiply(double a, double b) {
return String.valueOf(a * b);
}
}
interface Assistant {
String chat(String userMessage);
}
Calculator calculator = new Calculator();
Assistant assistant = AiServices.builder(Assistant.class)
.chatModel(model)
.chatMemory(MessageWindowChatMemory.withMaxMessages(10))
.tools(calculator)
.build();
String answer = assistant.chat("How much is 74589613588 + 4786521789?");用 Google 搜索结果接地响应
LLM 未必知道所有问题的答案!对于其最后一次训练结束之后发生的近期事件或信息更是如此。可以用 Google 搜索的最新结果来为 Gemini 的回答_接地(ground)_:
java
var modelWithSearch = VertexAiGeminiChatModel.builder()
.project(PROJECT_ID)
.location(LOCATION)
.modelName("gemini-1.5-flash-001")
.useGoogleSearch(true)
.build();
String resp = modelWithSearch.chat("What is the score of yesterday's football match from Paris Saint Germain?");用 Vertex AI Search 结果接地响应
在处理私有的内部信息、文档、数据时,你可以使用 Vertex AI Search 数据存储来存放这些文档。随后你可以用这些文档为 Gemini 的回答接地:
java
var modelWithSearch = VertexAiGeminiChatModel.builder()
.project(PROJECT_ID)
.location(LOCATION)
.modelName("gemini-1.5-flash-001")
.vertexSearchDatastore("name_of_the_datastore")
.build();JSON 结构化输出
你可以要求 Gemini 只返回有效的 JSON 输出:
java
var modelWithResponseMimeType = VertexAiGeminiChatModel.builder()
.project(PROJECT_ID)
.location(LOCATION)
.modelName("gemini-1.5-flash-001")
.responseMimeType("application/json")
.build();
String userMessage = "Return JSON with two fields: name and surname of Klaus Heisler.";
String jsonResponse = modelWithResponseMimeType.chat(userMessage).content().text();
// {"name": "Klaus", "surname": "Heisler"}带 JSON schema 的严格 JSON 结构化输出
使用 responseMimeType("application/json) 时,若你的提示词没有精确描述所需的 JSON 输出,模型在响应方式上仍可能有些"发挥"。为确保更严格的 JSON 结构化输出,你可以为响应指定一个 JSON schema:
java
Schema schema = Schema.newBuilder()
.setType(Type.OBJECT)
.putProperties("name", Schema.newBuilder()
.setType(Type.STRING)
.build())
.putProperties("address", Schema.newBuilder()
.setType(Type.OBJECT)
.putProperties("street",
Schema.newBuilder().setType(Type.STRING).build())
.putProperties("zipcode",
Schema.newBuilder().setType(Type.STRING).build())
.build())
.build();
var model = VertexAiGeminiChatModel.builder()
.project(PROJECT_ID)
.location(LOCATION)
.modelName(GEMINI_1_5_PRO)
.responseMimeType("application/json")
.responseSchema(Schema)
.build();有一个便捷方法可为某个 Java 类生成 schema:
java
class Artist {
public String artistName;
int artistAge;
protected boolean artistAdult;
private String artistAddress;
public Pet[] pets;
}
class Pet {
public String name;
}
Schema schema = SchemaHelper.fromClass(Artist.class);
var model = VertexAiGeminiChatModel.builder()
.project(PROJECT_ID)
.location(LOCATION)
.modelName(GEMINI_1_5_PRO)
.responseMimeType("application/json")
.responseSchema(schema)
.build();另一个方法可从 JSON schema 字符串创建 schema:SchemaHelper.fromJson(...)。
Gemini 既支持 JSON 对象,也支持数组作为结构化输出,但对作为输出的 JSON 字符串枚举还有一个特殊情况,在要求 Gemini 做分类任务(例如情感分析)时尤为有趣:
java
var model = VertexAiGeminiChatModel.builder()
.project(PROJECT_ID)
.location(LOCATION)
.modelName(GEMINI_1_5_PRO)
.logRequests(true)
.logResponses(true)
.responseSchema(Schema.newBuilder()
.setType(Type.STRING)
.addAllEnum(Arrays.asList("POSITIVE", "NEUTRAL", "NEGATIVE"))
.build())
.build();在这种情况下,隐式的响应 mime 类型被设为 text/x.enum(它并非一个官方注册的 mime 类型)。
指定安全设置
如果你想过滤或屏蔽有害内容,可以用不同的阈值设置安全选项。
java
HashMap<HarmCategory, SafetyThreshold> safetySettings = new HashMap<>();
safetySettings.put(HARM_CATEGORY_HARASSMENT, BLOCK_LOW_AND_ABOVE);
safetySettings.put(HARM_CATEGORY_DANGEROUS_CONTENT, BLOCK_ONLY_HIGH);
safetySettings.put(HARM_CATEGORY_SEXUALLY_EXPLICIT, BLOCK_MEDIUM_AND_ABOVE);
var model = VertexAiGeminiChatModel.builder()
.project(PROJECT_ID)
.location(LOCATION)
.modelName("gemini-1.5-flash-001")
.safetySettings(safetySettings)
.logRequests(true)
.logResponses(true)
.build();自定义认证
你可以提供自定义的 Google Cloud 凭据:
java
import com.google.auth.oauth2.GoogleCredentials;
import java.io.FileInputStream;
GoogleCredentials credentials = GoogleCredentials.fromStream(
new FileInputStream("path/to/service-account-key.json"));
var model = VertexAiGeminiChatModel.builder()
.project(PROJECT_ID)
.location(LOCATION)
.modelName("gemini-1.5-flash-001")
.credentials(credentials)
.build();