Skip to content

Commit 20c8252

Browse files
feat: [vertexai] add fromFunctionResponse in PartMaker (#10272)
PiperOrigin-RevId: 600847017 Co-authored-by: Jaycee Li <jayceeli@google.com>
1 parent e761894 commit 20c8252

File tree

3 files changed

+114
-1
lines changed

3 files changed

+114
-1
lines changed

java-vertexai/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ If you are using Maven with [BOM][libraries-bom], add this to your pom.xml file:
1818
<dependency>
1919
<groupId>com.google.cloud</groupId>
2020
<artifactId>libraries-bom</artifactId>
21-
<version>26.30.0</version>
21+
<version>26.29.0</version>
2222
<type>pom</type>
2323
<scope>import</scope>
2424
</dependency>

java-vertexai/google-cloud-vertexai/src/main/java/com/google/cloud/vertexai/generativeai/preview/PartMaker.java

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,14 @@
1818

1919
import com.google.cloud.vertexai.api.Blob;
2020
import com.google.cloud.vertexai.api.FileData;
21+
import com.google.cloud.vertexai.api.FunctionResponse;
2122
import com.google.cloud.vertexai.api.Part;
2223
import com.google.protobuf.ByteString;
24+
import com.google.protobuf.NullValue;
25+
import com.google.protobuf.Struct;
26+
import com.google.protobuf.Value;
2327
import java.net.URI;
28+
import java.util.Map;
2429

2530
/** Helper class to create {@link com.google.cloud.vertexai.api.Part} */
2631
public class PartMaker {
@@ -77,4 +82,55 @@ public static Part fromMimeTypeAndData(String mimeType, Object partData) {
7782
}
7883
return part;
7984
}
85+
86+
/**
87+
* Make a {@link com.google.cloud.vertexai.api.Part} from the output of {@link
88+
* com.google.cloud.vertexai.api.FunctionCall}.
89+
*
90+
* @param name a string represents the name of the {@link
91+
* com.google.cloud.vertexai.api.FunctionDeclaration}
92+
* @param response a structured JSON object containing any output from the function call
93+
*/
94+
public static Part fromFunctionResponse(String name, Struct response) {
95+
return Part.newBuilder()
96+
.setFunctionResponse(FunctionResponse.newBuilder().setName(name).setResponse(response))
97+
.build();
98+
}
99+
100+
/**
101+
* Make a {@link com.google.cloud.vertexai.api.Part} from the result output of {@link
102+
* com.google.cloud.vertexai.api.FunctionCall}.
103+
*
104+
* @param name a string represents the name of the {@link
105+
* com.google.cloud.vertexai.api.FunctionDeclaration}
106+
* @param response a map containing the output from the function call, supported output type:
107+
* String, Double, Boolean, null
108+
*/
109+
public static Part fromFunctionResponse(String name, Map<String, Object> response) {
110+
Struct.Builder structBuilder = Struct.newBuilder();
111+
response.forEach(
112+
(key, value) -> {
113+
if (value instanceof String) {
114+
String stringValue = (String) value;
115+
structBuilder.putFields(key, Value.newBuilder().setStringValue(stringValue).build());
116+
} else if (value instanceof Double) {
117+
Double doubleValue = (Double) value;
118+
structBuilder.putFields(key, Value.newBuilder().setNumberValue(doubleValue).build());
119+
} else if (value instanceof Boolean) {
120+
Boolean boolValue = (Boolean) value;
121+
structBuilder.putFields(key, Value.newBuilder().setBoolValue(boolValue).build());
122+
} else if (value == null) {
123+
structBuilder.putFields(
124+
key, Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build());
125+
} else {
126+
throw new IllegalArgumentException(
127+
"The value in the map can only be one of the following format: "
128+
+ "String, Double, Boolean, null.");
129+
}
130+
});
131+
132+
return Part.newBuilder()
133+
.setFunctionResponse(FunctionResponse.newBuilder().setName(name).setResponse(structBuilder))
134+
.build();
135+
}
80136
}

java-vertexai/google-cloud-vertexai/src/test/java/com/google/cloud/vertexai/generativeai/preview/PartMakerTest.java

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,16 @@
1717
package com.google.cloud.vertexai.generativeai.preview;
1818

1919
import static com.google.common.truth.Truth.assertThat;
20+
import static org.junit.Assert.assertThrows;
2021

2122
import com.google.cloud.vertexai.api.Part;
2223
import com.google.protobuf.ByteString;
24+
import com.google.protobuf.Struct;
25+
import com.google.protobuf.Value;
2326
import java.net.URI;
2427
import java.net.URISyntaxException;
28+
import java.util.HashMap;
29+
import java.util.Map;
2530
import org.junit.Test;
2631
import org.junit.runner.RunWith;
2732
import org.junit.runners.JUnit4;
@@ -72,4 +77,56 @@ public void fromMimeTypeAndData_dataInURI() throws URISyntaxException {
7277
assertThat(part.getFileData().getMimeType()).isEqualTo("image/png");
7378
assertThat(part.getFileData().getFileUri()).isEqualTo(fileUri.toString());
7479
}
80+
81+
@Test
82+
public void testFromFunctionResponseWithStruct() {
83+
String functionName = "getCurrentWeather";
84+
Struct functionResponse =
85+
Struct.newBuilder()
86+
.putFields("currentWeather", Value.newBuilder().setStringValue("Super nice!").build())
87+
.putFields("currentTemperature", Value.newBuilder().setNumberValue(85.0).build())
88+
.putFields("isRaining", Value.newBuilder().setBoolValue(false).build())
89+
.build();
90+
91+
Part part = PartMaker.fromFunctionResponse(functionName, functionResponse);
92+
93+
assertThat(part.getFunctionResponse().getName()).isEqualTo("getCurrentWeather");
94+
assertThat(part.getFunctionResponse().getResponse()).isEqualTo(functionResponse);
95+
}
96+
97+
@Test
98+
public void testFromFunctionResponseWithMap() {
99+
String functionName = "getCurrentWeather";
100+
Map<String, Object> functionResponse = new HashMap<>();
101+
functionResponse.put("currentWeather", "Super nice!");
102+
functionResponse.put("currentTemperature", 85.0);
103+
functionResponse.put("isRaining", false);
104+
functionResponse.put("other", null);
105+
106+
Part part = PartMaker.fromFunctionResponse(functionName, functionResponse);
107+
108+
assertThat(part.getFunctionResponse().getName()).isEqualTo("getCurrentWeather");
109+
110+
Map<String, Value> fieldsMap = part.getFunctionResponse().getResponse().getFieldsMap();
111+
assertThat(fieldsMap.get("currentWeather").getStringValue()).isEqualTo("Super nice!");
112+
assertThat(fieldsMap.get("currentTemperature").getNumberValue()).isEqualTo(85.0);
113+
assertThat(fieldsMap.get("isRaining").getBoolValue()).isEqualTo(false);
114+
assertThat(fieldsMap.get("other").hasNullValue()).isEqualTo(true);
115+
}
116+
117+
@Test
118+
public void testFromFunctionResponseWithInvalidMap() {
119+
String functionName = "getCurrentWeather";
120+
Map<String, Object> invalidResponse = new HashMap<>();
121+
invalidResponse.put("currentWeather", new byte[] {1, 2, 3});
122+
IllegalArgumentException thrown =
123+
assertThrows(
124+
IllegalArgumentException.class,
125+
() -> PartMaker.fromFunctionResponse(functionName, invalidResponse));
126+
assertThat(thrown)
127+
.hasMessageThat()
128+
.isEqualTo(
129+
"The value in the map can only be one of the following format: "
130+
+ "String, Double, Boolean, null.");
131+
}
75132
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy