diff --git a/core/src/main/java/com/google/adk/models/ChatCompletionsResponse.java b/core/src/main/java/com/google/adk/models/ChatCompletionsResponse.java deleted file mode 100644 index fe5cdd116..000000000 --- a/core/src/main/java/com/google/adk/models/ChatCompletionsResponse.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright 2026 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.adk.models; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; -import java.util.Map; - -/** - * Data Transfer Objects for Chat Completion and Chat Completion Chunk API responses. - * - *

These classes are used for deserializing JSON responses from the `/chat/completions` endpoint. - */ -@JsonIgnoreProperties(ignoreUnknown = true) -final class ChatCompletionsResponse { - - private ChatCompletionsResponse() {} - - @JsonIgnoreProperties(ignoreUnknown = true) - static class ChatCompletion { - public String id; - public List choices; - public Long created; - public String model; - public String object; - - @JsonProperty("service_tier") - public String serviceTier; - - @JsonProperty("system_fingerprint") - public String systemFingerprint; - - public Usage usage; - } - - @JsonIgnoreProperties(ignoreUnknown = true) - static class Choice { - @JsonProperty("finish_reason") - public String finishReason; - - public Integer index; - public Logprobs logprobs; - public Message message; - } - - @JsonIgnoreProperties(ignoreUnknown = true) - static class ChatCompletionChunk { - public String id; - public List choices; - public Long created; - public String model; - public String object; - - @JsonProperty("service_tier") - public String serviceTier; - - @JsonProperty("system_fingerprint") - public String systemFingerprint; - - public Usage usage; - } - - @JsonIgnoreProperties(ignoreUnknown = true) - static class ChunkChoice { - @JsonProperty("finish_reason") - public String finishReason; - - public Integer index; - public Logprobs logprobs; - public Message delta; - } - - @JsonIgnoreProperties(ignoreUnknown = true) - static class Message { - public String content; - public String refusal; - public String role; - - @JsonProperty("tool_calls") - public List toolCalls; - - // function_call is not supported in ChatCompletionChunk and ChatCompletion support is - // deprecated. - @JsonProperty("function_call") - public Function functionCall; // Fallback for deprecated top-level function calls - - public List annotations; - public Audio audio; - } - - @JsonIgnoreProperties(ignoreUnknown = true) - static class ToolCall { - // Index is only used in ChatCompletionChunk. - public Integer index; - public String id; - public String type; - public Function function; - public Custom custom; - - @JsonProperty("extra_content") - public Map extraContent; - } - - @JsonIgnoreProperties(ignoreUnknown = true) - static class Function { - public String name; - public String arguments; // JSON string - } - - @JsonIgnoreProperties(ignoreUnknown = true) - static class Custom { - public String input; - public String name; - } - - @JsonIgnoreProperties(ignoreUnknown = true) - static class Logprobs { - public List content; - public List refusal; - } - - @JsonIgnoreProperties(ignoreUnknown = true) - @JsonInclude(JsonInclude.Include.NON_NULL) - static class TokenLogprob { - public String token; - public List bytes; - public Double logprob; - - @JsonProperty("top_logprobs") - public List topLogprobs; - } - - @JsonIgnoreProperties(ignoreUnknown = true) - static class Usage { - @JsonProperty("completion_tokens") - public Integer completionTokens; - - @JsonProperty("prompt_tokens") - public Integer promptTokens; - - @JsonProperty("total_tokens") - public Integer totalTokens; - - @JsonProperty("thoughts_token_count") - public Integer thoughtsTokenCount; // Gemini-specific extension - - @JsonProperty("completion_tokens_details") - public CompletionTokensDetails completionTokensDetails; - - @JsonProperty("prompt_tokens_details") - public PromptTokensDetails promptTokensDetails; - } - - @JsonIgnoreProperties(ignoreUnknown = true) - static class CompletionTokensDetails { - @JsonProperty("accepted_prediction_tokens") - public Integer acceptedPredictionTokens; - - @JsonProperty("audio_tokens") - public Integer audioTokens; - - @JsonProperty("reasoning_tokens") - public Integer reasoningTokens; - - @JsonProperty("rejected_prediction_tokens") - public Integer rejectedPredictionTokens; - } - - @JsonIgnoreProperties(ignoreUnknown = true) - static class PromptTokensDetails { - @JsonProperty("audio_tokens") - public Integer audioTokens; - - @JsonProperty("cached_tokens") - public Integer cachedTokens; - } - - @JsonIgnoreProperties(ignoreUnknown = true) - static class Annotation { - public String type; - - @JsonProperty("url_citation") - public UrlCitation urlCitation; - } - - @JsonIgnoreProperties(ignoreUnknown = true) - static class UrlCitation { - @JsonProperty("end_index") - public Integer endIndex; - - @JsonProperty("start_index") - public Integer startIndex; - - public String title; - public String url; - } - - @JsonIgnoreProperties(ignoreUnknown = true) - static class Audio { - public String id; - public String data; - - @JsonProperty("expires_at") - public Long expiresAt; - - public String transcript; - } -} diff --git a/core/src/main/java/com/google/adk/models/chat/ChatCompletionsCommon.java b/core/src/main/java/com/google/adk/models/chat/ChatCompletionsCommon.java new file mode 100644 index 000000000..730f53af2 --- /dev/null +++ b/core/src/main/java/com/google/adk/models/chat/ChatCompletionsCommon.java @@ -0,0 +1,88 @@ +/* + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.adk.models.chat; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Map; + +/** Shared models for Chat Completions Request and Response. */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +final class ChatCompletionsCommon { + + private ChatCompletionsCommon() {} + + /** + * See + * https://developers.openai.com/api/reference/resources/chat#(resource)%20chat.completions%20%3E%20(model)%20chat_completion_message_tool_call%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + @JsonInclude(JsonInclude.Include.NON_NULL) + static class ToolCall { + /** See class definition for more details. */ + public Integer index; + + /** See class definition for more details. */ + public String id; + + /** See class definition for more details. */ + public String type; + + /** See class definition for more details. */ + public Function function; + + /** See class definition for more details. */ + public Custom custom; + + /** + * Used to supply additional parameters for specific models, for example: + * https://ai.google.dev/gemini-api/docs/openai#thinking + */ + @JsonProperty("extra_content") + public Map extraContent; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat#(resource)%20chat.completions%20%3E%20(model)%20chat_completion_message_function_tool_call%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + @JsonInclude(JsonInclude.Include.NON_NULL) + static class Function { + /** See class definition for more details. */ + public String name; + + /** See class definition for more details. */ + public String arguments; // JSON string + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat#(resource)%20chat.completions%20%3E%20(model)%20chat_completion_custom_tool%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + @JsonInclude(JsonInclude.Include.NON_NULL) + static class Custom { + /** See class definition for more details. */ + public String input; + + /** See class definition for more details. */ + public String name; + } +} diff --git a/core/src/main/java/com/google/adk/models/chat/ChatCompletionsRequest.java b/core/src/main/java/com/google/adk/models/chat/ChatCompletionsRequest.java new file mode 100644 index 000000000..4b6747fb1 --- /dev/null +++ b/core/src/main/java/com/google/adk/models/chat/ChatCompletionsRequest.java @@ -0,0 +1,728 @@ +/* + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.adk.models.chat; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.List; +import java.util.Map; + +/** + * Data Transfer Objects for Chat Completion API requests. + * + *

See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +final class ChatCompletionsRequest { + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20messages%20%3E%20(schema) + */ + public List messages; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20model%20%3E%20(schema) + */ + public String model; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20audio%20%3E%20(schema) + */ + public AudioParam audio; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20frequency_penalty%20%3E%20(schema) + */ + @JsonProperty("frequency_penalty") + public Double frequencyPenalty; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20logit_bias%20%3E%20(schema) + */ + @JsonProperty("logit_bias") + public Map logitBias; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20logprobs%20%3E%20(schema) + */ + public Boolean logprobs; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20max_completion_tokens%20%3E%20(schema) + */ + @JsonProperty("max_completion_tokens") + public Integer maxCompletionTokens; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20metadata%20%3E%20(schema) + */ + public Map metadata; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20modalities%20%3E%20(schema) + */ + public List modalities; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20n%20%3E%20(schema) + */ + public Integer n; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20parallel_tool_calls%20%3E%20(schema) + */ + @JsonProperty("parallel_tool_calls") + public Boolean parallelToolCalls; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20prediction%20%3E%20(schema) + */ + public Prediction prediction; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20presence_penalty%20%3E%20(schema) + */ + @JsonProperty("presence_penalty") + public Double presencePenalty; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20prompt_cache_key%20%3E%20(schema) + */ + @JsonProperty("prompt_cache_key") + public String promptCacheKey; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20prompt_cache_retention%20%3E%20(schema) + */ + @JsonProperty("prompt_cache_retention") + public String promptCacheRetention; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20reasoning_effort%20%3E%20(schema) + */ + @JsonProperty("reasoning_effort") + public String reasoningEffort; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20response_format%20%3E%20(schema) + */ + @JsonProperty("response_format") + public ResponseFormat responseFormat; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20safety_identifier%20%3E%20(schema) + */ + @JsonProperty("safety_identifier") + public String safetyIdentifier; + + /** + * Deprecated. Use temperature instead. See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20seed%20%3E%20(schema) + */ + public Long seed; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20service_tier%20%3E%20(schema) + */ + @JsonProperty("service_tier") + public String serviceTier; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20stop%20%3E%20(schema) + */ + public StopCondition stop; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20store%20%3E%20(schema) + */ + public Boolean store; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20stream%20%3E%20(schema) + */ + public Boolean stream; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20stream_options%20%3E%20(schema) + */ + @JsonProperty("stream_options") + public StreamOptions streamOptions; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20temperature%20%3E%20(schema) + */ + public Double temperature; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20tool_choice%20%3E%20(schema) + */ + @JsonProperty("tool_choice") + public ToolChoice toolChoice; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20tools%20%3E%20(schema) + */ + public List tools; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20top_logprobs%20%3E%20(schema) + */ + @JsonProperty("top_logprobs") + public Integer topLogprobs; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20top_p%20%3E%20(schema) + */ + @JsonProperty("top_p") + public Double topP; + + /** + * Deprecated, use safety_identifier and prompt_cache_key instead. See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20user%20%3E%20(schema) + */ + public String user; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20verbosity%20%3E%20(schema) + */ + public String verbosity; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20web_search_options%20%3E%20(schema) + */ + @JsonProperty("web_search_options") + public WebSearchOptions webSearchOptions; + + /** + * Additional body parameters used for specific models, for example: + * https://ai.google.dev/gemini-api/docs/openai#extra-body + */ + @JsonProperty("extra_body") + public Map extraBody; + + /** + * A catch-all class for message parameters. See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20messages%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + @JsonInclude(JsonInclude.Include.NON_NULL) + static class Message { + /** See class definition for more details. */ + public String role; + + /** See class definition for more details. */ + public MessageContent content; + + /** See class definition for more details. */ + public String name; + + /** See class definition for more details. */ + @JsonProperty("tool_calls") + public List toolCalls; + + /** Deprecated. Use tool_calls instead.See class definition for more details. */ + @JsonProperty("function_call") + public FunctionCall functionCall; + + /** See class definition for more details. */ + @JsonProperty("tool_call_id") + public String toolCallId; + + /** See class definition for more details. */ + public Audio audio; + + /** See class definition for more details. */ + public String refusal; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat#(resource)%20chat.completions%20%3E%20(model)%20chat_completion_content_part_text%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + @JsonInclude(JsonInclude.Include.NON_NULL) + static class ContentPart { + /** See class definition for more details. */ + public String type; + + /** See class definition for more details. */ + public String text; + + /** See class definition for more details. */ + public String refusal; + + /** See class definition for more details. */ + @JsonProperty("image_url") + public ImageUrl imageUrl; + + /** See class definition for more details. */ + @JsonProperty("input_audio") + public InputAudio inputAudio; + + /** See class definition for more details. */ + public File file; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat#(resource)%20chat.completions%20%3E%20(model)%20chat_completion_content_part_text%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + @JsonInclude(JsonInclude.Include.NON_NULL) + static class ImageUrl { + /** See class definition for more details. */ + public String url; + + /** See class definition for more details. */ + public String detail; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat#(resource)%20chat.completions%20%3E%20(model)%20chat_completion_content_part_text%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + @JsonInclude(JsonInclude.Include.NON_NULL) + static class InputAudio { + /** See class definition for more details. */ + public String data; + + /** See class definition for more details. */ + public String format; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20messages%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + @JsonInclude(JsonInclude.Include.NON_NULL) + static class File { + /** See class definition for more details. */ + @JsonProperty("file_data") + public String fileData; + + /** See class definition for more details. */ + @JsonProperty("file_id") + public String fileId; + + /** See class definition for more details. */ + public String filename; + } + + /** + * Deprecated. Function call details replaced by tool_calls. See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20messages%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + @JsonInclude(JsonInclude.Include.NON_NULL) + static class FunctionCall { + /** See class definition for more details. */ + public String name; + + /** See class definition for more details. */ + public String arguments; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20audio%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + @JsonInclude(JsonInclude.Include.NON_NULL) + static class AudioParam { + /** See class definition for more details. */ + public String format; + + /** See class definition for more details. */ + public VoiceConfig voice; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20audio%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + @JsonInclude(JsonInclude.Include.NON_NULL) + static class Audio { + /** See class definition for more details. */ + public String id; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20prediction%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + @JsonInclude(JsonInclude.Include.NON_NULL) + static class Prediction { + /** See class definition for more details. */ + public String type; + + /** See class definition for more details. */ + public Object content; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20stream_options%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + @JsonInclude(JsonInclude.Include.NON_NULL) + static class StreamOptions { + /** See class definition for more details. */ + @JsonProperty("include_obfuscation") + public Boolean includeObfuscation; + + /** See class definition for more details. */ + @JsonProperty("include_usage") + public Boolean includeUsage; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20tools%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + @JsonInclude(JsonInclude.Include.NON_NULL) + static class Tool { + /** See class definition for more details. */ + public String type; + + /** See class definition for more details. */ + public FunctionDefinition function; + + /** See class definition for more details. */ + public CustomTool custom; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20tools%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + @JsonInclude(JsonInclude.Include.NON_NULL) + static class FunctionDefinition { + /** See class definition for more details. */ + public String name; + + /** See class definition for more details. */ + public String description; + + /** See class definition for more details. */ + public Map parameters; + + /** See class definition for more details. */ + public Boolean strict; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(model)%20chat_completion_custom_tool%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + @JsonInclude(JsonInclude.Include.NON_NULL) + static class CustomTool { + /** See class definition for more details. */ + public String name; + + /** See class definition for more details. */ + public String description; + + /** See class definition for more details. */ + public Object format; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20web_search_options%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + @JsonInclude(JsonInclude.Include.NON_NULL) + static class WebSearchOptions { + /** See class definition for more details. */ + @JsonProperty("search_context_size") + public String searchContextSize; + + /** See class definition for more details. */ + @JsonProperty("user_location") + public UserLocation userLocation; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20web_search_options%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + @JsonInclude(JsonInclude.Include.NON_NULL) + static class UserLocation { + /** See class definition for more details. */ + public String type; + + /** See class definition for more details. */ + public ApproximateLocation approximate; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20web_search_options%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + @JsonInclude(JsonInclude.Include.NON_NULL) + static class ApproximateLocation { + /** See class definition for more details. */ + public String city; + + /** See class definition for more details. */ + public String country; + + /** See class definition for more details. */ + public String region; + + /** See class definition for more details. */ + public String timezone; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20response_format%20%3E%20(schema) + */ + interface ResponseFormat {} + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20response_format%20%3E%20(schema) + */ + static class ResponseFormatText implements ResponseFormat { + public String type = "text"; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20response_format%20%3E%20(schema) + */ + static class ResponseFormatJsonObject implements ResponseFormat { + public String type = "json_object"; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20response_format%20%3E%20(schema) + */ + static class ResponseFormatJsonSchema implements ResponseFormat { + public String type = "json_schema"; + + @JsonProperty("json_schema") + public JsonSchema jsonSchema; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20response_format%20%3E%20(schema) + */ + static class JsonSchema { + /** See class definition for more details. */ + public String name; + + /** See class definition for more details. */ + public String description; + + /** See class definition for more details. */ + public Map schema; + + /** See class definition for more details. */ + public Boolean strict; + } + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20tool_choice%20%3E%20(schema) + */ + interface ToolChoice {} + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20tool_choice%20%3E%20(schema) + */ + static class ToolChoiceMode implements ToolChoice { + private final String mode; + + public ToolChoiceMode(String mode) { + this.mode = mode; + } + + @JsonValue + public String getMode() { + return mode; + } + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20tool_choice%20%3E%20(schema) + */ + static class NamedToolChoice implements ToolChoice { + /** See class definition for more details. */ + public String type = "function"; + + /** See class definition for more details. */ + public FunctionName function; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20tool_choice%20%3E%20(schema) + */ + static class FunctionName { + /** See class definition for more details. */ + public String name; + } + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20tool_choice%20%3E%20(schema) + */ + static class NamedToolChoiceCustom implements ToolChoice { + /** See class definition for more details. */ + public String type = "custom"; + + /** See class definition for more details. */ + public CustomName custom; + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20tool_choice%20%3E%20(schema) + */ + static class CustomName { + /** See class definition for more details. */ + public String name; + } + } + + /** + * Wrapper class for stop. See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20stop%20%3E%20(schema) + */ + static class StopCondition { + private final String stringValue; + private final List listValue; + + @JsonCreator + public StopCondition(String stringValue) { + this.stringValue = stringValue; + this.listValue = null; + } + + @JsonCreator + public StopCondition(List listValue) { + this.stringValue = null; + this.listValue = listValue; + } + + @JsonValue + public Object getValue() { + return stringValue != null ? stringValue : listValue; + } + } + + /** + * Wrapper class for messages. See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20messages%20%3E%20(schema) + */ + static class MessageContent { + private final String stringValue; + private final List listValue; + + @JsonCreator + public MessageContent(String stringValue) { + this.stringValue = stringValue; + this.listValue = null; + } + + @JsonCreator + public MessageContent(List listValue) { + this.stringValue = null; + this.listValue = listValue; + } + + @JsonValue + public Object getValue() { + return stringValue != null ? stringValue : listValue; + } + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create#(resource)%20chat.completions%20%3E%20(method)%20create%20%3E%20(params)%200.non_streaming%20%3E%20(param)%20audio%20%3E%20(schema) + */ + static class VoiceConfig { + private final String stringValue; + private final Map mapValue; + + @JsonCreator + public VoiceConfig(String stringValue) { + this.stringValue = stringValue; + this.mapValue = null; + } + + @JsonCreator + public VoiceConfig(Map mapValue) { + this.stringValue = null; + this.mapValue = mapValue; + } + + @JsonValue + public Object getValue() { + return stringValue != null ? stringValue : mapValue; + } + } +} diff --git a/core/src/main/java/com/google/adk/models/chat/ChatCompletionsResponse.java b/core/src/main/java/com/google/adk/models/chat/ChatCompletionsResponse.java new file mode 100644 index 000000000..75a96e6ee --- /dev/null +++ b/core/src/main/java/com/google/adk/models/chat/ChatCompletionsResponse.java @@ -0,0 +1,327 @@ +/* + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.adk.models.chat; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; + +/** + * Data Transfer Objects for Chat Completion and Chat Completion Chunk API responses. + * + *

See https://developers.openai.com/api/reference/resources/chat + */ +@JsonIgnoreProperties(ignoreUnknown = true) +final class ChatCompletionsResponse { + + private ChatCompletionsResponse() {} + + /** + * See + * https://developers.openai.com/api/reference/resources/chat#(resource)%20chat.completions%20%3E%20(model)%20chat_completion%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + static class ChatCompletion { + /** See class definition for more details. */ + public String id; + + /** See class definition for more details. */ + public List choices; + + /** See class definition for more details. */ + public Long created; + + /** See class definition for more details. */ + public String model; + + /** See class definition for more details. */ + public String object; + + /** See class definition for more details. */ + @JsonProperty("service_tier") + public String serviceTier; + + /** Deprecated. See class definition for more details. */ + @JsonProperty("system_fingerprint") + public String systemFingerprint; + + /** See class definition for more details. */ + public Usage usage; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat#(resource)%20chat.completions%20%3E%20(model)%20chat_completion%20%3E%20(schema)%20%3E%20(property)%20choices + */ + @JsonIgnoreProperties(ignoreUnknown = true) + static class Choice { + /** See class definition for more details. */ + @JsonProperty("finish_reason") + public String finishReason; + + /** See class definition for more details. */ + public Integer index; + + /** See class definition for more details. */ + public Logprobs logprobs; + + /** See class definition for more details. */ + public Message message; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat#(resource)%20chat.completions%20%3E%20(model)%20chat_completion_chunk%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + static class ChatCompletionChunk { + /** See class definition for more details. */ + public String id; + + /** See class definition for more details. */ + public List choices; + + /** See class definition for more details. */ + public Long created; + + /** See class definition for more details. */ + public String model; + + /** See class definition for more details. */ + public String object; + + /** See class definition for more details. */ + @JsonProperty("service_tier") + public String serviceTier; + + /** Deprecated. See class definition for more details. */ + @JsonProperty("system_fingerprint") + public String systemFingerprint; + + /** See class definition for more details. */ + public Usage usage; + } + + /** + * Used for streaming responses. See + * https://developers.openai.com/api/reference/resources/chat#(resource)%20chat.completions%20%3E%20(model)%20chat_completion_chunk%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + static class ChunkChoice { + /** See class definition for more details. */ + @JsonProperty("finish_reason") + public String finishReason; + + /** See class definition for more details. */ + public Integer index; + + /** See class definition for more details. */ + public Logprobs logprobs; + + /** See class definition for more details. */ + public Message delta; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat#(resource)%20chat.completions%20%3E%20(model)%20chat_completion_message%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + static class Message { + /** See class definition for more details. */ + public String content; + + /** See class definition for more details. */ + public String refusal; + + /** See class definition for more details. */ + public String role; + + /** See class definition for more details. */ + @JsonProperty("tool_calls") + public List toolCalls; + + /** Deprecated. Use tool_calls instead. See class definition for more details. */ + @JsonProperty("function_call") + public ChatCompletionsCommon.Function functionCall; + + /** See class definition for more details. */ + public List annotations; + + /** See class definition for more details. */ + public Audio audio; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat#(resource)%20chat.completions%20%3E%20(model)%20chat_completion_logprobs%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + static class Logprobs { + /** See class definition for more details. */ + public List content; + + /** See class definition for more details. */ + public List refusal; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat#(resource)%20chat.completions%20%3E%20(model)%20chat_completion_token_logprob%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + @JsonInclude(JsonInclude.Include.NON_NULL) + static class TokenLogprob { + /** See class definition for more details. */ + public String token; + + /** See class definition for more details. */ + public List bytes; + + /** See class definition for more details. */ + public Double logprob; + + /** See class definition for more details. */ + @JsonProperty("top_logprobs") + public List topLogprobs; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/completions#(resource)%20completions%20%3E%20(model)%20completion_usage%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + static class Usage { + /** See class definition for more details. */ + @JsonProperty("completion_tokens") + public Integer completionTokens; + + /** See class definition for more details. */ + @JsonProperty("prompt_tokens") + public Integer promptTokens; + + /** See class definition for more details. */ + @JsonProperty("total_tokens") + public Integer totalTokens; + + /** See class definition for more details. */ + @JsonProperty("thoughts_token_count") + public Integer thoughtsTokenCount; + + /** See class definition for more details. */ + @JsonProperty("completion_tokens_details") + public CompletionTokensDetails completionTokensDetails; + + /** See class definition for more details. */ + @JsonProperty("prompt_tokens_details") + public PromptTokensDetails promptTokensDetails; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/completions#(resource)%20completions%20%3E%20(model)%20completion_usage%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + static class CompletionTokensDetails { + /** See class definition for more details. */ + @JsonProperty("accepted_prediction_tokens") + public Integer acceptedPredictionTokens; + + /** See class definition for more details. */ + @JsonProperty("audio_tokens") + public Integer audioTokens; + + /** See class definition for more details. */ + @JsonProperty("reasoning_tokens") + public Integer reasoningTokens; + + /** See class definition for more details. */ + @JsonProperty("rejected_prediction_tokens") + public Integer rejectedPredictionTokens; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/completions#(resource)%20completions%20%3E%20(model)%20completion_usage%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + static class PromptTokensDetails { + /** See class definition for more details. */ + @JsonProperty("audio_tokens") + public Integer audioTokens; + + /** See class definition for more details. */ + @JsonProperty("cached_tokens") + public Integer cachedTokens; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat#(resource)%20chat.completions%20%3E%20(model)%20chat_completion_message%20%3E%20(schema)%20%3E%20(property)%20annotations + */ + @JsonIgnoreProperties(ignoreUnknown = true) + static class Annotation { + /** See class definition for more details. */ + public String type; + + /** See class definition for more details. */ + @JsonProperty("url_citation") + public UrlCitation urlCitation; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat#(resource)%20chat.completions%20%3E%20(model)%20chat_completion_message%20%3E%20(schema)%20%3E%20(property)%20annotations%20%3E%20(items)%20%3E%20(property)%20url_citation + */ + @JsonIgnoreProperties(ignoreUnknown = true) + static class UrlCitation { + /** See class definition for more details. */ + @JsonProperty("end_index") + public Integer endIndex; + + /** See class definition for more details. */ + @JsonProperty("start_index") + public Integer startIndex; + + /** See class definition for more details. */ + public String title; + + /** See class definition for more details. */ + public String url; + } + + /** + * See + * https://developers.openai.com/api/reference/resources/chat#(resource)%20chat.completions%20%3E%20(model)%20chat_completion_audio%20%3E%20(schema) + */ + @JsonIgnoreProperties(ignoreUnknown = true) + static class Audio { + /** See class definition for more details. */ + public String id; + + /** See class definition for more details. */ + public String data; + + /** See class definition for more details. */ + @JsonProperty("expires_at") + public Long expiresAt; + + /** See class definition for more details. */ + public String transcript; + } +} diff --git a/core/src/test/java/com/google/adk/models/chat/ChatCompletionsRequestTest.java b/core/src/test/java/com/google/adk/models/chat/ChatCompletionsRequestTest.java new file mode 100644 index 000000000..9dc63c5d6 --- /dev/null +++ b/core/src/test/java/com/google/adk/models/chat/ChatCompletionsRequestTest.java @@ -0,0 +1,221 @@ +/* + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.adk.models.chat; + +import static com.google.common.truth.Truth.assertThat; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.ImmutableList; +import java.util.HashMap; +import java.util.Map; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public final class ChatCompletionsRequestTest { + + private ObjectMapper objectMapper; + + @Before + public void setUp() { + objectMapper = new ObjectMapper(); + } + + @Test + public void testSerializeChatCompletionRequest_standard() throws Exception { + ChatCompletionsRequest request = new ChatCompletionsRequest(); + request.model = "gemini-3-flash-preview"; + + ChatCompletionsRequest.Message message = new ChatCompletionsRequest.Message(); + message.role = "user"; + message.content = new ChatCompletionsRequest.MessageContent("Hello"); + request.messages = ImmutableList.of(message); + + String json = objectMapper.writeValueAsString(request); + + assertThat(json).contains("\"model\":\"gemini-3-flash-preview\""); + assertThat(json).contains("\"role\":\"user\""); + assertThat(json).contains("\"content\":\"Hello\""); + } + + @Test + public void testSerializeChatCompletionRequest_withExtraBody() throws Exception { + ChatCompletionsRequest request = new ChatCompletionsRequest(); + request.model = "gemini-3-flash-preview"; + + ChatCompletionsRequest.Message message = new ChatCompletionsRequest.Message(); + message.role = "user"; + message.content = new ChatCompletionsRequest.MessageContent("Explain to me how AI works"); + request.messages = ImmutableList.of(message); + + Map thinkingConfig = new HashMap<>(); + thinkingConfig.put("thinking_level", "low"); + thinkingConfig.put("include_thoughts", true); + + Map google = new HashMap<>(); + google.put("thinking_config", thinkingConfig); + + Map extraBody = new HashMap<>(); + extraBody.put("google", google); + + request.extraBody = extraBody; + + String json = objectMapper.writeValueAsString(request); + + assertThat(json).contains("\"extra_body\":{"); + assertThat(json).contains("\"thinking_level\":\"low\""); + assertThat(json).contains("\"include_thoughts\":true"); + } + + @Test + public void testSerializeChatCompletionRequest_withToolCallsAndExtraContent() throws Exception { + ChatCompletionsRequest request = new ChatCompletionsRequest(); + request.model = "gemini-3-flash-preview"; + + ChatCompletionsRequest.Message userMessage = new ChatCompletionsRequest.Message(); + userMessage.role = "user"; + userMessage.content = new ChatCompletionsRequest.MessageContent("Check flight status"); + + ChatCompletionsRequest.Message modelMessage = new ChatCompletionsRequest.Message(); + modelMessage.role = "model"; + + ChatCompletionsCommon.ToolCall toolCall = new ChatCompletionsCommon.ToolCall(); + toolCall.id = "function-call-1"; + toolCall.type = "function"; + + ChatCompletionsCommon.Function function = new ChatCompletionsCommon.Function(); + function.name = "check_flight"; + function.arguments = "{\"flight\":\"AA100\"}"; + toolCall.function = function; + + Map google = new HashMap<>(); + google.put("thought_signature", ""); + + Map extraContent = new HashMap<>(); + extraContent.put("google", google); + + toolCall.extraContent = extraContent; + + modelMessage.toolCalls = ImmutableList.of(toolCall); + + ChatCompletionsRequest.Message toolMessage = new ChatCompletionsRequest.Message(); + toolMessage.role = "tool"; + toolMessage.name = "check_flight"; + toolMessage.toolCallId = "function-call-1"; + toolMessage.content = new ChatCompletionsRequest.MessageContent("{\"status\":\"delayed\"}"); + + request.messages = ImmutableList.of(userMessage, modelMessage, toolMessage); + + String json = objectMapper.writeValueAsString(request); + + assertThat(json).contains("\"role\":\"user\""); + assertThat(json).contains("\"role\":\"model\""); + assertThat(json).contains("\"role\":\"tool\""); + assertThat(json).contains("\"extra_content\":{"); + assertThat(json).contains("\"thought_signature\":\"\""); + assertThat(json).contains("\"tool_call_id\":\"function-call-1\""); + } + + @Test + public void testSerializeChatCompletionRequest_comprehensive() throws Exception { + ChatCompletionsRequest request = new ChatCompletionsRequest(); + request.model = "gemini-3-flash-preview"; + + // Developer message with name + ChatCompletionsRequest.Message devMsg = new ChatCompletionsRequest.Message(); + devMsg.role = "developer"; + devMsg.content = new ChatCompletionsRequest.MessageContent("System instruction"); + devMsg.name = "system-bot"; + + request.messages = ImmutableList.of(devMsg); + + // Response Format JSON Schema + ChatCompletionsRequest.ResponseFormatJsonSchema format = + new ChatCompletionsRequest.ResponseFormatJsonSchema(); + format.jsonSchema = new ChatCompletionsRequest.ResponseFormatJsonSchema.JsonSchema(); + format.jsonSchema.name = "MySchema"; + format.jsonSchema.strict = true; + request.responseFormat = format; + + // Tool Choice Named + ChatCompletionsRequest.NamedToolChoice choice = new ChatCompletionsRequest.NamedToolChoice(); + choice.function = new ChatCompletionsRequest.NamedToolChoice.FunctionName(); + choice.function.name = "my_function"; + request.toolChoice = choice; + + String json = objectMapper.writeValueAsString(request); + + // Assert Developer Message + assertThat(json).contains("\"role\":\"developer\""); + assertThat(json).contains("\"name\":\"system-bot\""); + assertThat(json).contains("\"content\":\"System instruction\""); + + // Assert Response Format + assertThat(json).contains("\"response_format\":{"); + assertThat(json).contains("\"type\":\"json_schema\""); + assertThat(json).contains("\"name\":\"MySchema\""); + assertThat(json).contains("\"strict\":true"); + + // Assert Tool Choice + assertThat(json).contains("\"tool_choice\":{"); + assertThat(json).contains("\"type\":\"function\""); + assertThat(json).contains("\"name\":\"my_function\""); + } + + @Test + public void testSerializeChatCompletionRequest_withToolChoiceMode() throws Exception { + ChatCompletionsRequest request = new ChatCompletionsRequest(); + request.model = "gemini-3-flash-preview"; + + request.toolChoice = new ChatCompletionsRequest.ToolChoiceMode("none"); + + String json = objectMapper.writeValueAsString(request); + + assertThat(json).contains("\"tool_choice\":\"none\""); + } + + @Test + public void testSerializeChatCompletionRequest_withStopAndVoice() throws Exception { + ChatCompletionsRequest request = new ChatCompletionsRequest(); + request.model = "gemini-3-flash-preview"; + + request.stop = new ChatCompletionsRequest.StopCondition("STOP"); + + ChatCompletionsRequest.AudioParam audio = new ChatCompletionsRequest.AudioParam(); + audio.voice = new ChatCompletionsRequest.VoiceConfig("alloy"); + request.audio = audio; + + String json = objectMapper.writeValueAsString(request); + + assertThat(json).contains("\"stop\":\"STOP\""); + assertThat(json).contains("\"voice\":\"alloy\""); + } + + @Test + public void testSerializeChatCompletionRequest_withStopList() throws Exception { + ChatCompletionsRequest request = new ChatCompletionsRequest(); + request.model = "gemini-3-flash-preview"; + + request.stop = new ChatCompletionsRequest.StopCondition(ImmutableList.of("STOP1", "STOP2")); + + String json = objectMapper.writeValueAsString(request); + + assertThat(json).contains("\"stop\":[\"STOP1\",\"STOP2\"]"); + } +} diff --git a/core/src/test/java/com/google/adk/models/ChatCompletionsResponseTest.java b/core/src/test/java/com/google/adk/models/chat/ChatCompletionsResponseTest.java similarity index 96% rename from core/src/test/java/com/google/adk/models/ChatCompletionsResponseTest.java rename to core/src/test/java/com/google/adk/models/chat/ChatCompletionsResponseTest.java index 53fcdfbdf..52134476c 100644 --- a/core/src/test/java/com/google/adk/models/ChatCompletionsResponseTest.java +++ b/core/src/test/java/com/google/adk/models/chat/ChatCompletionsResponseTest.java @@ -14,13 +14,13 @@ * limitations under the License. */ -package com.google.adk.models; +package com.google.adk.models.chat; import static com.google.common.truth.Truth.assertThat; import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.adk.models.ChatCompletionsResponse.ChatCompletion; -import com.google.adk.models.ChatCompletionsResponse.ChatCompletionChunk; +import com.google.adk.models.chat.ChatCompletionsResponse.ChatCompletion; +import com.google.adk.models.chat.ChatCompletionsResponse.ChatCompletionChunk; import java.util.Map; import org.junit.Before; import org.junit.Test; @@ -245,7 +245,7 @@ public void testDeserializeChatCompletion_withCustomToolCall() throws Exception objectMapper.readValue(json, ChatCompletionsResponse.ChatCompletion.class); assertThat(completion.choices.get(0).message.toolCalls).hasSize(1); - ChatCompletionsResponse.ToolCall toolCall = completion.choices.get(0).message.toolCalls.get(0); + ChatCompletionsCommon.ToolCall toolCall = completion.choices.get(0).message.toolCalls.get(0); assertThat(toolCall.type).isEqualTo("custom"); assertThat(toolCall.custom.name).isEqualTo("custom_tool"); assertThat(toolCall.custom.input).isEqualTo("{\"arg\":\"val\"}"); @@ -310,7 +310,7 @@ public void testDeserializeChatCompletionChunk_withToolCallDelta() throws Except ChatCompletionChunk chunk = objectMapper.readValue(json, ChatCompletionChunk.class); assertThat(chunk.choices.get(0).delta.toolCalls).hasSize(1); - ChatCompletionsResponse.ToolCall toolCall = chunk.choices.get(0).delta.toolCalls.get(0); + ChatCompletionsCommon.ToolCall toolCall = chunk.choices.get(0).delta.toolCalls.get(0); assertThat(toolCall.index).isEqualTo(1); assertThat(toolCall.id).isEqualTo("call_abc"); assertThat(toolCall.type).isEqualTo("function");