diff --git a/README.md b/README.md index 74dfe944ddb..ec157942ddb 100644 --- a/README.md +++ b/README.md @@ -274,6 +274,35 @@ Client client = Client.builder() The Google Gen AI Java SDK allows you to access the service programmatically. The following code snippets are some basic usages of model inferencing. +#### Seed Live API conversation history + +Gemini 3.1 Live sessions can accept conversation history through client content +messages before realtime input begins. Enable initial history processing when +connecting: + +```java +import com.google.genai.Client; +import com.google.genai.types.HistoryConfig; +import com.google.genai.types.LiveConnectConfig; +import com.google.genai.types.Modality; + +Client client = new Client(); + +LiveConnectConfig config = + LiveConnectConfig.builder() + .responseModalities(Modality.Known.AUDIO) + .historyConfig( + HistoryConfig.builder() + .initialHistoryInClientContent(true)) + .build(); + +client.async.live.connect("gemini-3.1-flash-live-preview", config); +``` + +After the session connects, use `sendClientContent` to send the initial history +and finish it with `turnComplete(true)`. Use `sendRealtimeInput` for subsequent +conversation input. + #### Generate Content Use `generateContent` method for the most basic content generation. @@ -1027,4 +1056,4 @@ Apache 2.0 - See [LICENSE][license] for more information. [maven-version-link]: https://central.sonatype.com/artifact/com.google.genai/google-genai [javadoc-image]: https://img.shields.io/badge/JavaDoc-Online-green [javadoc-link]: https://googleapis.github.io/java-genai/javadoc/ -[license]: https://github.com/googleapis/java-genai/blob/main/LICENSE \ No newline at end of file +[license]: https://github.com/googleapis/java-genai/blob/main/LICENSE diff --git a/src/main/java/com/google/genai/LiveConverters.java b/src/main/java/com/google/genai/LiveConverters.java index 56ea4c4cc49..a3dd91fada6 100644 --- a/src/main/java/com/google/genai/LiveConverters.java +++ b/src/main/java/com/google/genai/LiveConverters.java @@ -1283,6 +1283,13 @@ ObjectNode liveConnectConfigToMldev(JsonNode fromObject, ObjectNode parentObject Common.getValueByPath(fromObject, new String[] {"translationConfig"})); } + if (Common.getValueByPath(fromObject, new String[] {"historyConfig"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"setup", "historyConfig"}, + Common.getValueByPath(fromObject, new String[] {"historyConfig"})); + } + return toObject; } @@ -1457,6 +1464,13 @@ ObjectNode liveConnectConfigToVertex(JsonNode fromObject, ObjectNode parentObjec + " Gemini Enterprise Agent Platform mode."); } + if (Common.getValueByPath(fromObject, new String[] {"historyConfig"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"setup", "historyConfig"}, + Common.getValueByPath(fromObject, new String[] {"historyConfig"})); + } + return toObject; } diff --git a/src/main/java/com/google/genai/types/LiveConnectConfig.java b/src/main/java/com/google/genai/types/LiveConnectConfig.java index f10d8d03275..4c0172a3687 100644 --- a/src/main/java/com/google/genai/types/LiveConnectConfig.java +++ b/src/main/java/com/google/genai/types/LiveConnectConfig.java @@ -173,6 +173,10 @@ public abstract class LiveConnectConfig extends JsonSerializable { @JsonProperty("translationConfig") public abstract Optional translationConfig(); + /** Configures the exchange of history between the client and the server. */ + @JsonProperty("historyConfig") + public abstract Optional historyConfig(); + /** Instantiates a builder for LiveConnectConfig. */ @ExcludeFromGeneratedCoverageReport public static Builder builder() { @@ -898,6 +902,34 @@ public Builder clearTranslationConfig() { return translationConfig(Optional.empty()); } + /** + * Setter for historyConfig. + * + *

historyConfig: Configures the exchange of history between the client and the server. + */ + @JsonProperty("historyConfig") + public abstract Builder historyConfig(HistoryConfig historyConfig); + + /** + * Setter for historyConfig builder. + * + *

historyConfig: Configures the exchange of history between the client and the server. + */ + @CanIgnoreReturnValue + public Builder historyConfig(HistoryConfig.Builder historyConfigBuilder) { + return historyConfig(historyConfigBuilder.build()); + } + + @ExcludeFromGeneratedCoverageReport + abstract Builder historyConfig(Optional historyConfig); + + /** Clears the value of historyConfig field. */ + @ExcludeFromGeneratedCoverageReport + @CanIgnoreReturnValue + public Builder clearHistoryConfig() { + return historyConfig(Optional.empty()); + } + public abstract LiveConnectConfig build(); } diff --git a/src/main/resources/META-INF/native-image/com.google.genai/auto-value/reflect-config.json b/src/main/resources/META-INF/native-image/com.google.genai/auto-value/reflect-config.json index 410815dc725..46fb26ad44c 100644 --- a/src/main/resources/META-INF/native-image/com.google.genai/auto-value/reflect-config.json +++ b/src/main/resources/META-INF/native-image/com.google.genai/auto-value/reflect-config.json @@ -2399,6 +2399,22 @@ "queryAllDeclaredMethods": true, "queryAllDeclaredConstructors": true }, + { + "name": "com.google.genai.types.AutoValue_HistoryConfig", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "queryAllDeclaredMethods": true, + "queryAllDeclaredConstructors": true + }, + { + "name": "com.google.genai.types.AutoValue_HistoryConfig$Builder", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "queryAllDeclaredMethods": true, + "queryAllDeclaredConstructors": true + }, { "name": "com.google.genai.types.AutoValue_HttpOptions", "allDeclaredConstructors": true, diff --git a/src/main/resources/META-INF/native-image/com.google.genai/google-genai/reflect-config.json b/src/main/resources/META-INF/native-image/com.google.genai/google-genai/reflect-config.json index eabb35809df..bb5947203cd 100644 --- a/src/main/resources/META-INF/native-image/com.google.genai/google-genai/reflect-config.json +++ b/src/main/resources/META-INF/native-image/com.google.genai/google-genai/reflect-config.json @@ -1380,6 +1380,13 @@ "queryAllDeclaredConstructors":true, "methods":[{"name":"dynamicRetrievalConfig","parameterTypes":[] }] }, +{ + "name":"com.google.genai.types.AutoValue_HistoryConfig", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"initialHistoryInClientContent","parameterTypes":[] }] +}, { "name":"com.google.genai.types.AutoValue_HttpOptions", "allDeclaredFields":true, @@ -1595,7 +1602,7 @@ "allDeclaredFields":true, "queryAllDeclaredMethods":true, "queryAllDeclaredConstructors":true, - "methods":[{"name":"avatarConfig","parameterTypes":[] }, {"name":"contextWindowCompression","parameterTypes":[] }, {"name":"enableAffectiveDialog","parameterTypes":[] }, {"name":"explicitVadSignal","parameterTypes":[] }, {"name":"httpOptions","parameterTypes":[] }, {"name":"inputAudioTranscription","parameterTypes":[] }, {"name":"maxOutputTokens","parameterTypes":[] }, {"name":"mediaResolution","parameterTypes":[] }, {"name":"outputAudioTranscription","parameterTypes":[] }, {"name":"proactivity","parameterTypes":[] }, {"name":"realtimeInputConfig","parameterTypes":[] }, {"name":"responseModalities","parameterTypes":[] }, {"name":"safetySettings","parameterTypes":[] }, {"name":"seed","parameterTypes":[] }, {"name":"sessionResumption","parameterTypes":[] }, {"name":"speechConfig","parameterTypes":[] }, {"name":"systemInstruction","parameterTypes":[] }, {"name":"temperature","parameterTypes":[] }, {"name":"thinkingConfig","parameterTypes":[] }, {"name":"tools","parameterTypes":[] }, {"name":"topK","parameterTypes":[] }, {"name":"topP","parameterTypes":[] }, {"name":"translationConfig","parameterTypes":[] }] + "methods":[{"name":"avatarConfig","parameterTypes":[] }, {"name":"contextWindowCompression","parameterTypes":[] }, {"name":"enableAffectiveDialog","parameterTypes":[] }, {"name":"explicitVadSignal","parameterTypes":[] }, {"name":"historyConfig","parameterTypes":[] }, {"name":"httpOptions","parameterTypes":[] }, {"name":"inputAudioTranscription","parameterTypes":[] }, {"name":"maxOutputTokens","parameterTypes":[] }, {"name":"mediaResolution","parameterTypes":[] }, {"name":"outputAudioTranscription","parameterTypes":[] }, {"name":"proactivity","parameterTypes":[] }, {"name":"realtimeInputConfig","parameterTypes":[] }, {"name":"responseModalities","parameterTypes":[] }, {"name":"safetySettings","parameterTypes":[] }, {"name":"seed","parameterTypes":[] }, {"name":"sessionResumption","parameterTypes":[] }, {"name":"speechConfig","parameterTypes":[] }, {"name":"systemInstruction","parameterTypes":[] }, {"name":"temperature","parameterTypes":[] }, {"name":"thinkingConfig","parameterTypes":[] }, {"name":"tools","parameterTypes":[] }, {"name":"topK","parameterTypes":[] }, {"name":"topP","parameterTypes":[] }, {"name":"translationConfig","parameterTypes":[] }] }, { "name":"com.google.genai.types.AutoValue_LiveConnectConstraints", @@ -3722,6 +3729,18 @@ "queryAllDeclaredConstructors":true, "methods":[{"name":"","parameterTypes":["java.lang.String"] }] }, +{ + "name":"com.google.genai.types.HistoryConfig", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true +}, +{ + "name":"com.google.genai.types.HistoryConfig$Builder", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"build","parameterTypes":[] }, {"name":"create","parameterTypes":[] }, {"name":"initialHistoryInClientContent","parameterTypes":["boolean"] }] +}, { "name":"com.google.genai.types.HttpElementLocation", "allDeclaredFields":true, @@ -4134,7 +4153,7 @@ "allDeclaredFields":true, "queryAllDeclaredMethods":true, "queryAllDeclaredConstructors":true, - "methods":[{"name":"build","parameterTypes":[] }, {"name":"create","parameterTypes":[] }, {"name":"responseModalities","parameterTypes":["java.util.List"] }, {"name":"temperature","parameterTypes":["java.lang.Float"] }, {"name":"translationConfig","parameterTypes":["com.google.genai.types.TranslationConfig"] }] + "methods":[{"name":"build","parameterTypes":[] }, {"name":"create","parameterTypes":[] }, {"name":"historyConfig","parameterTypes":["com.google.genai.types.HistoryConfig"] }, {"name":"responseModalities","parameterTypes":["java.util.List"] }, {"name":"temperature","parameterTypes":["java.lang.Float"] }, {"name":"translationConfig","parameterTypes":["com.google.genai.types.TranslationConfig"] }] }, { "name":"com.google.genai.types.LiveConnectConstraints", diff --git a/src/test/java/com/google/genai/LiveConvertersTest.java b/src/test/java/com/google/genai/LiveConvertersTest.java index 69b473ba1f7..e99d815fd37 100644 --- a/src/test/java/com/google/genai/LiveConvertersTest.java +++ b/src/test/java/com/google/genai/LiveConvertersTest.java @@ -22,6 +22,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.genai.types.Blob; +import com.google.genai.types.HistoryConfig; import com.google.genai.types.LiveClientMessage; import com.google.genai.types.LiveConnectConfig; import com.google.genai.types.LiveSendRealtimeInputParameters; @@ -189,4 +190,44 @@ public void testMultiSpeakerVoiceConfig_throws() { .createObjectNode()) // Code that should throw the exception ); } + + @Test + public void testLiveConnectConfig_HistoryConfig_mldev() { + final LiveConnectConfig config = + LiveConnectConfig.builder() + .historyConfig(HistoryConfig.builder().initialHistoryInClientContent(true)) + .build(); + final ObjectNode transformed = JsonSerializable.objectMapper.createObjectNode(); + + new LiveConverters(GEMINI_API_CLIENT) + .liveConnectConfigToMldev(JsonSerializable.toJsonNode(config), transformed); + + assertEquals( + true, + transformed + .get("setup") + .get("historyConfig") + .get("initialHistoryInClientContent") + .asBoolean()); + } + + @Test + public void testLiveConnectConfig_HistoryConfig_vertex() { + final LiveConnectConfig config = + LiveConnectConfig.builder() + .historyConfig(HistoryConfig.builder().initialHistoryInClientContent(true)) + .build(); + final ObjectNode transformed = JsonSerializable.objectMapper.createObjectNode(); + + new LiveConverters(VERTEX_AI_CLIENT) + .liveConnectConfigToVertex(JsonSerializable.toJsonNode(config), transformed); + + assertEquals( + true, + transformed + .get("setup") + .get("historyConfig") + .get("initialHistoryInClientContent") + .asBoolean()); + } }