Update Google VertexAI Gemini to 26.41.0

- update the Gemini function calling ITs to include a system message with dedicated calling instructions.
 - fix a type with few Gemini ChatModel enum names.
 - re-enable all Gemini ITs.
This commit is contained in:
Christian Tzolov
2024-06-13 12:43:18 +02:00
parent 2306db4a30
commit dbccfda7c5
7 changed files with 50 additions and 66 deletions

View File

@@ -102,9 +102,9 @@ public class VertexAiGeminiChatModel
GEMINI_PRO("gemini-pro"),
GEMINI_PRO_1_5_PRO("gemini-1.5-pro-preview-0514"),
GEMINI_1_5_PRO("gemini-1.5-pro-preview-0514"),
GEMINI_PRO_1_5_FLASH("gemini-1.5-flash-preview-0514");
GEMINI_1_5_FLASH("gemini-1.5-flash-preview-0514");
ChatModel(String value) {
this.value = value;

View File

@@ -15,37 +15,37 @@
*/
package org.springframework.ai.vertexai.gemini.function;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.google.cloud.vertexai.Transport;
import com.google.cloud.vertexai.VertexAI;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatModel;
import reactor.core.publisher.Flux;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.model.Generation;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.model.Generation;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.model.function.FunctionCallbackWrapper;
import org.springframework.ai.model.function.FunctionCallbackWrapper.Builder.SchemaType;
import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatModel;
import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatOptions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
import static org.assertj.core.api.Assertions.assertThat;
import com.google.cloud.vertexai.Transport;
import com.google.cloud.vertexai.VertexAI;
import reactor.core.publisher.Flux;
@SpringBootTest
@EnabledIfEnvironmentVariable(named = "VERTEX_AI_GEMINI_PROJECT_ID", matches = ".*")
@@ -57,27 +57,19 @@ public class VertexAiGeminiChatModelFunctionCallingIT {
@Autowired
private VertexAiGeminiChatModel chatModel;
@AfterEach
public void afterEach() {
try {
Thread.sleep(3000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
@Test
@Disabled("Google Vertex AI degraded support for parallel function calls")
public void functionCallExplicitOpenApiSchema() {
UserMessage userMessage = new UserMessage(
"What's the weather like in San Francisco, in Paris and in Tokyo, Japan?"
+ " Use Celsius units. Answer for all requested locations.");
// " Use Celsius units. Use Multi-turn function calling. Provide answer for all
// requested locations.");
var systemMessage = new SystemMessage("""
Use Multi-turn function calling.
Answer for all listed locations.
If the information was not fetched call the function again. Repeat at most 3 times.
""");
List<Message> messages = new ArrayList<>(List.of(userMessage));
UserMessage userMessage = new UserMessage(
"What's the weather like in San Francisco, Paris and in Tokyo? Perform multiple funciton execution if necessary. Return the temperature in Celsius.");
List<Message> messages = new ArrayList<>(List.of(systemMessage, userMessage));
String openApiSchema = """
{
@@ -98,7 +90,7 @@ public class VertexAiGeminiChatModelFunctionCallingIT {
""";
var promptOptions = VertexAiGeminiChatOptions.builder()
.withModel(VertexAiGeminiChatModel.ChatModel.GEMINI_PRO)
.withModel(VertexAiGeminiChatModel.ChatModel.GEMINI_1_5_FLASH)
// .withModel(VertexAiGeminiModelCall.ChatModel.GEMINI_PRO_1_5_PRO)
.withFunctionCallbacks(List.of(FunctionCallbackWrapper.builder(new MockWeatherService())
.withName("get_current_weather")
@@ -111,11 +103,7 @@ public class VertexAiGeminiChatModelFunctionCallingIT {
logger.info("Response: {}", response);
// System.out.println(response.getResult().getOutput().getContent());
assertThat(response.getResult().getOutput().getContent()).containsAnyOf("30.0", "30");
assertThat(response.getResult().getOutput().getContent()).containsAnyOf("10.0", "10");
assertThat(response.getResult().getOutput().getContent()).containsAnyOf("15.0", "15");
assertThat(response.getResult().getOutput().getContent()).contains("30", "10", "15");
}
@Test
@@ -126,8 +114,8 @@ public class VertexAiGeminiChatModelFunctionCallingIT {
List<Message> messages = new ArrayList<>(List.of(userMessage));
var promptOptions = VertexAiGeminiChatOptions.builder()
// .withModel(VertexAiGeminiModelCall.ChatModel.GEMINI_PRO_1_5_PRO)
.withModel(VertexAiGeminiChatModel.ChatModel.GEMINI_PRO.getValue())
.withModel(VertexAiGeminiChatModel.ChatModel.GEMINI_1_5_PRO)
// .withModel(VertexAiGeminiChatModel.ChatModel.GEMINI_PRO)
.withFunctionCallbacks(List.of(
FunctionCallbackWrapper.builder(new MockWeatherService())
.withSchemaType(SchemaType.OPEN_API_SCHEMA)
@@ -160,15 +148,18 @@ public class VertexAiGeminiChatModelFunctionCallingIT {
@Test
public void functionCallTestInferredOpenApiSchemaStream() {
UserMessage userMessage = new UserMessage("What's the weather like in San Francisco in Celsius units?");
// UserMessage userMessage = new UserMessage(
// "What's the weather like in San Francisco, in Paris and in Tokyo, Japan? Use
// Multi-turn function calling. Provide answer for all requested locations.");
var systemMessage = new SystemMessage("""
Use Multi-turn function calling.
Answer for all listed locations.
If the information was not fetched call the function again. Repeat at most 3 times.
""");
UserMessage userMessage = new UserMessage(
"What's the weather like in San Francisco, Paris and in Tokyo? Perform multiple funciton execution if necessary. Return the temperature in Celsius.");
List<Message> messages = new ArrayList<>(List.of(userMessage));
List<Message> messages = new ArrayList<>(List.of(systemMessage, userMessage));
var promptOptions = VertexAiGeminiChatOptions.builder()
.withModel(VertexAiGeminiChatModel.ChatModel.GEMINI_PRO)
.withModel(VertexAiGeminiChatModel.ChatModel.GEMINI_1_5_FLASH)
.withFunctionCallbacks(List.of(FunctionCallbackWrapper.builder(new MockWeatherService())
.withSchemaType(SchemaType.OPEN_API_SCHEMA)
.withName("getCurrentWeather")
@@ -189,9 +180,7 @@ public class VertexAiGeminiChatModelFunctionCallingIT {
logger.info("Response: {}", responseString);
// assertThat(responseString).containsAnyOf("15.0", "15");
assertThat(responseString).containsAnyOf("30.0", "30");
// assertThat(responseString).containsAnyOf("10.0", "10");
assertThat(responseString).contains("30", "10", "15");
}
@@ -227,7 +216,7 @@ public class VertexAiGeminiChatModelFunctionCallingIT {
public VertexAiGeminiChatModel vertexAiEmbedding(VertexAI vertexAi) {
return new VertexAiGeminiChatModel(vertexAi,
VertexAiGeminiChatOptions.builder()
.withModel(VertexAiGeminiChatModel.ChatModel.GEMINI_PRO)
.withModel(VertexAiGeminiChatModel.ChatModel.GEMINI_1_5_PRO)
.withTemperature(0.9f)
.build());
}

View File

@@ -21,16 +21,11 @@ import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.google.cloud.vertexai.Transport;
import com.google.cloud.vertexai.VertexAI;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Flux;
import org.springframework.ai.chat.client.AdvisedRequest;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.RequestResponseAdvisor;
@@ -46,10 +41,14 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Description;
import com.google.cloud.vertexai.Transport;
import com.google.cloud.vertexai.VertexAI;
import reactor.core.publisher.Flux;
/**
* @author Christian Tzolov
*/
@Disabled("Vertex AI Gemini function calling is very unstable.")
@SpringBootTest
@EnabledIfEnvironmentVariable(named = "VERTEX_AI_GEMINI_PROJECT_ID", matches = ".*")
@EnabledIfEnvironmentVariable(named = "VERTEX_AI_GEMINI_LOCATION", matches = ".*")
@@ -99,7 +98,7 @@ public class VertexAiGeminiPaymentTransactionIT {
logger.info("" + content);
}
@RepeatedTest(10)
@RepeatedTest(5)
public void streamingPaymentStatuses() {
Flux<String> streamContent = this.chatClient.prompt()
@@ -120,11 +119,9 @@ public class VertexAiGeminiPaymentTransactionIT {
// Quota rate
try {
Thread.sleep(20000);
Thread.sleep(2000);
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@@ -189,7 +186,7 @@ public class VertexAiGeminiPaymentTransactionIT {
return new VertexAiGeminiChatModel(vertexAi,
VertexAiGeminiChatOptions.builder()
.withModel(VertexAiGeminiChatModel.ChatModel.GEMINI_PRO_1_5_FLASH)
.withModel(VertexAiGeminiChatModel.ChatModel.GEMINI_1_5_FLASH)
// .withModel(VertexAiGeminiChatModel.ChatModel.GEMINI_PRO_1_5_PRO)
.withTemperature(0.1f)
// .withResponseMimeType(ResponseMimeType.JSON)

View File

@@ -140,7 +140,7 @@
<jackson.version>2.16.1</jackson.version>
<djl.version>0.26.0</djl.version>
<onnxruntime.version>1.17.0</onnxruntime.version>
<com.google.cloud.version>26.39.0</com.google.cloud.version>
<com.google.cloud.version>26.41.0</com.google.cloud.version>
<qdrant.version>1.9.1</qdrant.version>
<spring-retry.version>2.0.5</spring-retry.version>
<ibm.sdk.version>9.20.0</ibm.sdk.version>

View File

@@ -56,8 +56,8 @@ class FunctionCallWithFunctionBeanIT {
contextRunner.withPropertyValues("spring.ai.vertex.ai.gemini.chat.options.model="
// + VertexAiGeminiChatModel.ChatModel.GEMINI_PRO.getValue())
+ VertexAiGeminiChatModel.ChatModel.GEMINI_PRO_1_5_PRO.getValue())
// + VertexAiGeminiChatModel.ChatModel.GEMINI_PRO_1_5_FLASH.getValue())
// + VertexAiGeminiChatModel.ChatModel.GEMINI_PRO_1_5_PRO.getValue())
+ VertexAiGeminiChatModel.ChatModel.GEMINI_1_5_FLASH.getValue())
.run(context -> {
VertexAiGeminiChatModel chatModel = context.getBean(VertexAiGeminiChatModel.class);
@@ -70,7 +70,7 @@ class FunctionCallWithFunctionBeanIT {
var userMessage = new UserMessage(
// "What's the weather like in San Francisco, Paris and in Tokyo?
// Please let me know how many function calls you've preformed.");
"What's the weather like in San Francisco, Paris and in Tokyo?");
"What's the weather like in San Francisco, Paris and in Tokyo? Perform multiple funciton execution if necessary. Return the temperature in Celsius.");
ChatResponse response = chatModel.call(new Prompt(List.of(systemMessage, userMessage),
VertexAiGeminiChatOptions.builder().withFunction("weatherFunction").build()));
@@ -82,8 +82,6 @@ class FunctionCallWithFunctionBeanIT {
assertThat(response.getResult().getOutput().getContent()).contains("30", "10", "15");
Thread.sleep(10000);
response = chatModel.call(new Prompt(List.of(systemMessage, userMessage),
VertexAiGeminiChatOptions.builder().withFunction("weatherFunction3").build()));

View File

@@ -55,7 +55,7 @@ public class FunctionCallWithFunctionWrapperIT {
void functionCallTest() {
contextRunner
.withPropertyValues("spring.ai.vertex.ai.gemini.chat.options.model="
+ VertexAiGeminiChatModel.ChatModel.GEMINI_PRO_1_5_FLASH.getValue())
+ VertexAiGeminiChatModel.ChatModel.GEMINI_1_5_FLASH.getValue())
.run(context -> {
VertexAiGeminiChatModel chatModel = context.getBean(VertexAiGeminiChatModel.class);

View File

@@ -51,7 +51,7 @@ public class FunctionCallWithPromptFunctionIT {
void functionCallTest() {
contextRunner
.withPropertyValues("spring.ai.vertex.ai.gemini.chat.options.model="
+ VertexAiGeminiChatModel.ChatModel.GEMINI_PRO_1_5_FLASH.getValue())
+ VertexAiGeminiChatModel.ChatModel.GEMINI_1_5_FLASH.getValue())
.run(context -> {
VertexAiGeminiChatModel chatModel = context.getBean(VertexAiGeminiChatModel.class);