Add responseMimeType option in VertexAiGeminiChatOptions

- Add test
This commit is contained in:
KimMinjeong
2024-08-08 01:00:48 +09:00
committed by Mark Pollack
parent 189468127c
commit bc55bc7196
4 changed files with 71 additions and 7 deletions

View File

@@ -359,6 +359,9 @@ public class VertexAiGeminiChatModel extends AbstractToolCallSupport implements
if (options.getStopSequences() != null) {
generationConfigBuilder.addAllStopSequences(options.getStopSequences());
}
if (options.getResponseMimeType() != null) {
generationConfigBuilder.setResponseMimeType(options.getResponseMimeType());
}
return generationConfigBuilder.build();
}

View File

@@ -77,6 +77,12 @@ public class VertexAiGeminiChatOptions implements FunctionCallingOptions, ChatOp
* Gemini model name.
*/
private @JsonProperty("modelName") String model;
/**
* Optional. Output response mimetype of the generated candidate text.
* - text/plain: (default) Text output.
* - application/json: JSON response in the candidates.
*/
private @JsonProperty("responseMimeType") String responseMimeType;
/**
* Tool Function Callbacks to register with the ChatModel.
@@ -151,6 +157,12 @@ public class VertexAiGeminiChatOptions implements FunctionCallingOptions, ChatOp
return this;
}
public Builder withResponseMimeType(String mimeType) {
Assert.notNull(mimeType, "mimeType must not be null");
this.options.setResponseMimeType(mimeType);
return this;
}
public Builder withFunctionCallbacks(List<FunctionCallback> functionCallbacks) {
this.options.functionCallbacks = functionCallbacks;
return this;
@@ -251,6 +263,14 @@ public class VertexAiGeminiChatOptions implements FunctionCallingOptions, ChatOp
this.model = modelName;
}
public String getResponseMimeType() {
return this.responseMimeType;
}
public String setResponseMimeType(String mimeType) {
return this.responseMimeType = mimeType;
}
public List<FunctionCallback> getFunctionCallbacks() {
return this.functionCallbacks;
}
@@ -290,6 +310,7 @@ public class VertexAiGeminiChatOptions implements FunctionCallingOptions, ChatOp
result = prime * result + ((candidateCount == null) ? 0 : candidateCount.hashCode());
result = prime * result + ((maxOutputTokens == null) ? 0 : maxOutputTokens.hashCode());
result = prime * result + ((model == null) ? 0 : model.hashCode());
result = prime * result + ((responseMimeType == null) ? 0 : responseMimeType.hashCode());
result = prime * result + ((functionCallbacks == null) ? 0 : functionCallbacks.hashCode());
result = prime * result + ((functions == null) ? 0 : functions.hashCode());
return result;
@@ -346,6 +367,13 @@ public class VertexAiGeminiChatOptions implements FunctionCallingOptions, ChatOp
}
else if (!model.equals(other.model))
return false;
if (responseMimeType == null) {
if (other.responseMimeType != null)
return false;
}
else if (!responseMimeType.equals(other.responseMimeType)) {
return false;
}
if (functionCallbacks == null) {
if (other.functionCallbacks != null)
return false;
@@ -365,13 +393,13 @@ public class VertexAiGeminiChatOptions implements FunctionCallingOptions, ChatOp
public String toString() {
return "VertexAiGeminiChatOptions [stopSequences=" + stopSequences + ", temperature=" + temperature + ", topP="
+ topP + ", topK=" + topK + ", candidateCount=" + candidateCount + ", maxOutputTokens="
+ maxOutputTokens + ", model=" + model + ", functionCallbacks=" + functionCallbacks + ", functions="
+ functions + ", getClass()=" + getClass() + ", getStopSequences()=" + getStopSequences()
+ ", getTemperature()=" + getTemperature() + ", getTopP()=" + getTopP() + ", getTopK()=" + getTopK()
+ ", getCandidateCount()=" + getCandidateCount() + ", getMaxOutputTokens()=" + getMaxOutputTokens()
+ ", getModel()=" + getModel() + ", getFunctionCallbacks()=" + getFunctionCallbacks()
+ ", getFunctions()=" + getFunctions() + ", hashCode()=" + hashCode() + ", toString()="
+ super.toString() + "]";
+ maxOutputTokens + ", model=" + model + ", responseMimeType=" + responseMimeType
+ ", functionCallbacks=" + functionCallbacks + ", functions=" + functions + ", getClass()=" + getClass()
+ ", getStopSequences()=" + getStopSequences() + ", getTemperature()=" + getTemperature()
+ ", getTopP()=" + getTopP() + ", getTopK()=" + getTopK() + ", getCandidateCount()="
+ getCandidateCount() + ", getMaxOutputTokens()=" + getMaxOutputTokens() + ", getModel()=" + getModel()
+ ", getFunctionCallbacks()=" + getFunctionCallbacks() + ", getFunctions()=" + getFunctions()
+ ", hashCode()=" + hashCode() + ", toString()=" + super.toString() + "]";
}
@Override
@@ -389,6 +417,7 @@ public class VertexAiGeminiChatOptions implements FunctionCallingOptions, ChatOp
options.setMaxOutputTokens(fromOptions.getMaxOutputTokens());
options.setModel(fromOptions.getModel());
options.setFunctionCallbacks(fromOptions.getFunctionCallbacks());
options.setResponseMimeType(fromOptions.getResponseMimeType());
options.setFunctions(fromOptions.getFunctions());
return options;
}

View File

@@ -191,4 +191,35 @@ public class CreateGeminiRequestTests {
.isEqualTo("Overridden function description");
}
@Test
public void createRequestWithGenerationConfigOptions() {
var client = new VertexAiGeminiChatModel(vertexAI,
VertexAiGeminiChatOptions.builder()
.withModel("DEFAULT_MODEL")
.withTemperature(66.6f)
.withMaxOutputTokens(100)
.withTopK(10.0f)
.withTopP(5.0f)
.withStopSequences(List.of("stop1", "stop2"))
.withCandidateCount(1)
.withResponseMimeType("application/json")
.build());
GeminiRequest request = client.createGeminiRequest(new Prompt("Test message content"));
assertThat(request.contents()).hasSize(1);
assertThat(request.model().getSystemInstruction()).isNotPresent();
assertThat(request.model().getModelName()).isEqualTo("DEFAULT_MODEL");
assertThat(request.model().getGenerationConfig().getTemperature()).isEqualTo(66.6f);
assertThat(request.model().getGenerationConfig().getMaxOutputTokens()).isEqualTo(100);
assertThat(request.model().getGenerationConfig().getTopK()).isEqualTo(10.0f);
assertThat(request.model().getGenerationConfig().getTopP()).isEqualTo(5.0f);
assertThat(request.model().getGenerationConfig().getCandidateCount()).isEqualTo(1);
assertThat(request.model().getGenerationConfig().getStopSequences(0)).isEqualTo("stop1");
assertThat(request.model().getGenerationConfig().getStopSequences(1)).isEqualTo("stop2");
assertThat(request.model().getGenerationConfig().getResponseMimeType()).isEqualTo("application/json");
}
}

View File

@@ -67,6 +67,7 @@ The prefix `spring.ai.vertex.ai.gemini.chat` is the property prefix that lets yo
| Property | Description | Default
| spring.ai.vertex.ai.gemini.chat.options.model | Supported https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/gemini[Vertex AI Gemini Chat model] to use include the (1.0 ) `gemini-pro`, `gemini-pro-vision` (deprecated) and the new `gemini-1.5-pro-001`, `gemini-1.5-flash-001` models. | gemini-1.5-pro-001
| spring.ai.vertex.ai.gemini.chat.options.responseMimeType | Output response mimetype of the generated candidate text. | `text/plain`: (default) Text output or `application/json`: JSON response.
| spring.ai.vertex.ai.gemini.chat.options.temperature | Controls the randomness of the output. Values can range over [0.0,1.0], inclusive. A value closer to 1.0 will produce responses that are more varied, while a value closer to 0.0 will typically result in less surprising responses from the generative. This value specifies default to be used by the backend while making the call to the generative. | 0.8
| spring.ai.vertex.ai.gemini.chat.options.topK | The maximum number of tokens to consider when sampling. The generative uses combined Top-k and nucleus sampling. Top-k sampling considers the set of topK most probable tokens. | -
| spring.ai.vertex.ai.gemini.chat.options.topP | The maximum cumulative probability of tokens to consider when sampling. The generative uses combined Top-k and nucleus sampling. Nucleus sampling considers the smallest set of tokens whose probability sum is at least topP. | -