diff --git a/eng/versioning/external_dependencies.txt b/eng/versioning/external_dependencies.txt index f4189e1e2a1e..47e532c6ee5c 100644 --- a/eng/versioning/external_dependencies.txt +++ b/eng/versioning/external_dependencies.txt @@ -37,7 +37,7 @@ com.microsoft.sqlserver:mssql-jdbc;10.2.3.jre8 com.microsoft.azure:azure-functions-maven-plugin;1.30.0 com.microsoft.azure.functions:azure-functions-java-library;2.2.0 com.mysql:mysql-connector-j;9.0.0 -com.openai:openai-java;2.3.0 +com.openai:openai-java;4.6.1 com.squareup.okhttp3:okhttp;4.12.0 commons-codec:commons-codec;1.15 commons-net:commons-net;3.9.0 diff --git a/sdk/ai/azure-ai-agents-persistent/tsp-location.yaml b/sdk/ai/azure-ai-agents-persistent/_tsp-location.yaml similarity index 100% rename from sdk/ai/azure-ai-agents-persistent/tsp-location.yaml rename to sdk/ai/azure-ai-agents-persistent/_tsp-location.yaml diff --git a/sdk/ai/azure-ai-inference/tsp-location.yaml b/sdk/ai/azure-ai-inference/_tsp-location.yaml similarity index 100% rename from sdk/ai/azure-ai-inference/tsp-location.yaml rename to sdk/ai/azure-ai-inference/_tsp-location.yaml diff --git a/sdk/ai/azure-ai-projects/tsp-location.yaml b/sdk/ai/azure-ai-projects/_tsp-location.yaml similarity index 100% rename from sdk/ai/azure-ai-projects/tsp-location.yaml rename to sdk/ai/azure-ai-projects/_tsp-location.yaml diff --git a/sdk/ai/azure-ai-projects/pom.xml b/sdk/ai/azure-ai-projects/pom.xml index 3f9f4c3232d8..7e9dbac8705d 100644 --- a/sdk/ai/azure-ai-projects/pom.xml +++ b/sdk/ai/azure-ai-projects/pom.xml @@ -75,7 +75,7 @@ Code generated by Microsoft (R) TypeSpec Code Generator. com.openai openai-java - 2.3.0 + 4.6.1 @@ -104,7 +104,7 @@ Code generated by Microsoft (R) TypeSpec Code Generator. - com.openai:openai-java:[2.3.0] + com.openai:openai-java:[4.6.1] diff --git a/sdk/ai/azure-ai-voicelive/tsp-location.yaml b/sdk/ai/azure-ai-voicelive/_tsp-location.yaml similarity index 100% rename from sdk/ai/azure-ai-voicelive/tsp-location.yaml rename to sdk/ai/azure-ai-voicelive/_tsp-location.yaml diff --git a/sdk/openai/azure-ai-openai-stainless/pom.xml b/sdk/openai/azure-ai-openai-stainless/pom.xml index 71e4c0cd366d..c5ef78dc4142 100644 --- a/sdk/openai/azure-ai-openai-stainless/pom.xml +++ b/sdk/openai/azure-ai-openai-stainless/pom.xml @@ -57,7 +57,7 @@ com.openai openai-java - 2.3.0 + 4.6.1 @@ -132,7 +132,7 @@ - com.openai:openai-java:[2.3.0] + com.openai:openai-java:[4.6.1] diff --git a/sdk/openai/azure-ai-openai-stainless/src/samples/java/com/azure/ai/openai/stainless/FunctionCallingAsyncSample.java b/sdk/openai/azure-ai-openai-stainless/src/samples/java/com/azure/ai/openai/stainless/FunctionCallingAsyncSample.java index 928af7229058..3d6974d6da83 100644 --- a/sdk/openai/azure-ai-openai-stainless/src/samples/java/com/azure/ai/openai/stainless/FunctionCallingAsyncSample.java +++ b/sdk/openai/azure-ai-openai-stainless/src/samples/java/com/azure/ai/openai/stainless/FunctionCallingAsyncSample.java @@ -3,29 +3,35 @@ package com.azure.ai.openai.stainless; -import static com.openai.core.ObjectMappers.jsonMapper; - import com.azure.identity.AuthenticationUtil; import com.azure.identity.DefaultAzureCredentialBuilder; -import com.fasterxml.jackson.core.JsonProcessingException; import com.openai.client.OpenAIClientAsync; import com.openai.client.okhttp.OpenAIOkHttpClientAsync; -import com.openai.core.JsonObject; -import com.openai.core.JsonValue; import com.openai.credential.BearerTokenCredential; import com.openai.models.ChatModel; -import com.openai.models.FunctionDefinition; -import com.openai.models.FunctionParameters; import com.openai.models.chat.completions.ChatCompletion; import com.openai.models.chat.completions.ChatCompletionCreateParams; +import com.openai.models.chat.completions.ChatCompletionMessageFunctionToolCall; import com.openai.models.chat.completions.ChatCompletionMessageToolCall; -import com.openai.models.chat.completions.ChatCompletionTool; -import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.stream.Stream; +import com.fasterxml.jackson.annotation.JsonClassDescription; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; + +// Tool class for SDK quality evaluation - async version +@JsonClassDescription("Gets the quality of the given SDK.") +class GetSdkQualityAsync { + @JsonPropertyDescription("The name of the SDK.") + public String name; + + public String execute() { + return name.contains("OpenAI") ? "Excellent quality and robust implementation!" : "Unknown quality"; + } +} + public final class FunctionCallingAsyncSample { private FunctionCallingAsyncSample() {} @@ -51,19 +57,7 @@ public static void main(String[] args) { ChatCompletionCreateParams createParams = ChatCompletionCreateParams.builder() .model(ChatModel.GPT_4O) .maxCompletionTokens(2048) - .addTool(ChatCompletionTool.builder() - .function(FunctionDefinition.builder() - .name("get-sdk-quality") - .description("Gets the quality of the given SDK.") - .parameters(FunctionParameters.builder() - .putAdditionalProperty("type", JsonValue.from("object")) - .putAdditionalProperty("properties", JsonValue.from( - Collections.singletonMap("name", Collections.singletonMap("type", "string")))) - .putAdditionalProperty("required", JsonValue.from(Collections.singletonList("name"))) - .putAdditionalProperty("additionalProperties", JsonValue.from(false)) - .build()) - .build()) - .build()) + .addTool(GetSdkQualityAsync.class) .addUserMessage("How good are the following SDKs: OpenAI Java SDK, Unknown Company SDK") .build(); @@ -81,27 +75,19 @@ public static void main(String[] args) { return Stream.empty(); } }) - .forEach(toolCall -> System.out.println(callFunction(toolCall.function())))) + .forEach(toolCall -> { + Object result = callFunction(toolCall.asFunction().function()); + System.out.println(result); + })) .join(); } - private static String callFunction(ChatCompletionMessageToolCall.Function function) { - if (!function.name().equals("get-sdk-quality")) { - throw new IllegalArgumentException("Unknown function: " + function.name()); + private static Object callFunction(ChatCompletionMessageFunctionToolCall.Function function) { + switch (function.name()) { + case "GetSdkQualityAsync": + return function.arguments(GetSdkQualityAsync.class).execute(); + default: + throw new IllegalArgumentException("Unknown function: " + function.name()); } - - JsonValue arguments; - try { - arguments = JsonValue.from(jsonMapper().readTree(function.arguments())); - } catch (JsonProcessingException e) { - throw new IllegalArgumentException("Bad function arguments", e); - } - - String sdkName = ((JsonObject) arguments).values().get("name").asStringOrThrow(); - if (sdkName.contains("OpenAI")) { - return sdkName + ": It's robust and polished!"; - } - - return sdkName + ": *shrug*"; } } diff --git a/sdk/openai/azure-ai-openai-stainless/src/samples/java/com/azure/ai/openai/stainless/FunctionCallingSample.java b/sdk/openai/azure-ai-openai-stainless/src/samples/java/com/azure/ai/openai/stainless/FunctionCallingSample.java index 6cc9eb14fede..8b432c4750a9 100644 --- a/sdk/openai/azure-ai-openai-stainless/src/samples/java/com/azure/ai/openai/stainless/FunctionCallingSample.java +++ b/sdk/openai/azure-ai-openai-stainless/src/samples/java/com/azure/ai/openai/stainless/FunctionCallingSample.java @@ -3,29 +3,35 @@ package com.azure.ai.openai.stainless; -import static com.openai.core.ObjectMappers.jsonMapper; - import com.azure.identity.AuthenticationUtil; import com.azure.identity.DefaultAzureCredentialBuilder; -import com.fasterxml.jackson.core.JsonProcessingException; import com.openai.client.OpenAIClient; import com.openai.client.okhttp.OpenAIOkHttpClient; -import com.openai.core.JsonObject; -import com.openai.core.JsonValue; import com.openai.credential.BearerTokenCredential; import com.openai.models.ChatModel; -import com.openai.models.FunctionDefinition; -import com.openai.models.FunctionParameters; import com.openai.models.chat.completions.ChatCompletion; import com.openai.models.chat.completions.ChatCompletionCreateParams; +import com.openai.models.chat.completions.ChatCompletionMessageFunctionToolCall; import com.openai.models.chat.completions.ChatCompletionMessageToolCall; -import com.openai.models.chat.completions.ChatCompletionTool; -import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.stream.Stream; +import com.fasterxml.jackson.annotation.JsonClassDescription; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; + +// Tool class for SDK quality evaluation +@JsonClassDescription("Gets the quality of the given SDK.") +class GetSdkQuality { + @JsonPropertyDescription("The name of the SDK.") + public String name; + + public String execute() { + return name.contains("OpenAI") ? "Excellent quality and robust implementation!" : "Unknown quality"; + } +} + public final class FunctionCallingSample { private FunctionCallingSample() {} @@ -50,19 +56,7 @@ public static void main(String[] args) { ChatCompletionCreateParams createParams = ChatCompletionCreateParams.builder() .model(ChatModel.GPT_4O) .maxCompletionTokens(2048) - .addTool(ChatCompletionTool.builder() - .function(FunctionDefinition.builder() - .name("get-sdk-quality") - .description("Gets the quality of the given SDK.") - .parameters(FunctionParameters.builder() - .putAdditionalProperty("type", JsonValue.from("object")) - .putAdditionalProperty("properties", JsonValue.from( - Collections.singletonMap("name", Collections.singletonMap("type", "string")))) - .putAdditionalProperty("required", JsonValue.from(Collections.singletonList("name"))) - .putAdditionalProperty("additionalProperties", JsonValue.from(false)) - .build()) - .build()) - .build()) + .addTool(GetSdkQuality.class) .addUserMessage("How good are the following SDKs: OpenAI Java SDK, Unknown Company SDK") .build(); @@ -77,26 +71,18 @@ public static void main(String[] args) { return Stream.empty(); } }) - .forEach(toolCall -> System.out.println(callFunction(toolCall.function()))); + .forEach(toolCall -> { + Object result = callFunction(toolCall.asFunction().function()); + System.out.println(result); + }); } - private static String callFunction(ChatCompletionMessageToolCall.Function function) { - if (!function.name().equals("get-sdk-quality")) { - throw new IllegalArgumentException("Unknown function: " + function.name()); + private static Object callFunction(ChatCompletionMessageFunctionToolCall.Function function) { + switch (function.name()) { + case "GetSdkQuality": + return function.arguments(GetSdkQuality.class).execute(); + default: + throw new IllegalArgumentException("Unknown function: " + function.name()); } - - JsonValue arguments; - try { - arguments = JsonValue.from(jsonMapper().readTree(function.arguments())); - } catch (JsonProcessingException e) { - throw new IllegalArgumentException("Bad function arguments", e); - } - - String sdkName = ((JsonObject) arguments).values().get("name").asStringOrThrow(); - if (sdkName.contains("OpenAI")) { - return sdkName + ": It's robust and polished!"; - } - - return sdkName + ": *shrug*"; } } diff --git a/sdk/openai/azure-ai-openai-stainless/src/test/java/com/azure/ai/openai/stainless/OpenAIOkHttpClientTestBase.java b/sdk/openai/azure-ai-openai-stainless/src/test/java/com/azure/ai/openai/stainless/OpenAIOkHttpClientTestBase.java index 1fb5f9b782b2..6283d2fa2810 100644 --- a/sdk/openai/azure-ai-openai-stainless/src/test/java/com/azure/ai/openai/stainless/OpenAIOkHttpClientTestBase.java +++ b/sdk/openai/azure-ai-openai-stainless/src/test/java/com/azure/ai/openai/stainless/OpenAIOkHttpClientTestBase.java @@ -16,7 +16,6 @@ import com.openai.models.ResponseFormatJsonSchema.JsonSchema; import com.openai.core.JsonValue; import com.openai.errors.BadRequestException; -import com.openai.models.FunctionDefinition; import com.openai.models.FunctionParameters; import com.openai.models.audio.AudioModel; import com.openai.models.audio.transcriptions.Transcription; @@ -33,7 +32,7 @@ import com.openai.models.chat.completions.ChatCompletionMessageParam; import com.openai.models.chat.completions.ChatCompletionMessageToolCall; import com.openai.models.chat.completions.ChatCompletionSystemMessageParam; -import com.openai.models.chat.completions.ChatCompletionTool; + import com.openai.models.chat.completions.ChatCompletionToolMessageParam; import com.openai.models.chat.completions.ChatCompletionUserMessageParam; import com.openai.models.completions.CompletionUsage; @@ -63,6 +62,23 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import com.fasterxml.jackson.annotation.JsonClassDescription; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; + +// Tool class for weather function - used in tests +@JsonClassDescription("Get the current weather in a given location") +class GetCurrentWeather { + @JsonPropertyDescription("The city and state, e.g. San Francisco, CA") + public String location; + + @JsonPropertyDescription("Temperature unit (celsius or fahrenheit)") + public String unit = "celsius"; + + public String execute() { + return "The weather in " + location + " is 72 degrees " + unit; + } +} + @SuppressWarnings("ALL") public class OpenAIOkHttpClientTestBase { static final String ASSISTANT_CONTENT @@ -170,36 +186,10 @@ ChatCompletionCreateParams createChatCompletionParamsWithoutFunctionCall(String } ChatCompletionCreateParams createChatCompletionParamsWithTool(String testModel, String userMessage) { - ChatCompletionTool chatCompletionTool = ChatCompletionTool.builder() - .function(FunctionDefinition.builder() - .name("get_current_weather") - .description("Get the current weather in a given location") - .parameters(FunctionParameters.builder() - .putAdditionalProperty("type", JsonValue.from("object")) - .putAdditionalProperty("properties", - JsonValue.from(FunctionParameters.builder() - .putAdditionalProperty("location", - JsonValue.from(FunctionParameters.builder() - .putAdditionalProperty("type", JsonValue.from("string")) - .putAdditionalProperty("description", - JsonValue.from("The city and state, e.g. San Francisco, CA")) - .build())) - .putAdditionalProperty("unit", - JsonValue.from(FunctionParameters.builder() - .putAdditionalProperty("type", JsonValue.from("string")) - .putAdditionalProperty("enum", JsonValue.from(asList("celsius", "fahrenheit"))) - .build())) - .build())) - .putAdditionalProperty("required", JsonValue.from(Collections.singletonList("location"))) - .build()) - .build()) - .build(); - return ChatCompletionCreateParams.builder() .messages(asList(createSystemMessageParam(), createUserMessageParam(userMessage))) .model(testModel) - .tools(asList(chatCompletionTool)) - // .toolChoice(AUTO) + .addTool(GetCurrentWeather.class) .build(); } @@ -304,7 +294,7 @@ ChatCompletionCreateParams addToolResponseToMessages(ChatCompletionCreateParams // Add tool response to messages: Tool ChatCompletionMessageParam toolMessageParam = ChatCompletionMessageParam.ofTool(ChatCompletionToolMessageParam.builder() - .toolCallId(chatCompletionMessageToolCalls.get(0).id()) + .toolCallId(chatCompletionMessageToolCalls.get(0).asFunction().id()) .content(ChatCompletionToolMessageParam.Content .ofText("{\"temperature\": \"22\", \"unit\": \"celsius\", \"description\": \"Sunny\"}")) .build()); @@ -314,7 +304,7 @@ ChatCompletionCreateParams addToolResponseToMessages(ChatCompletionCreateParams if (chatCompletionMessageToolCalls.size() > 1) { ChatCompletionMessageParam toolMessageParam2 = ChatCompletionMessageParam.ofTool(ChatCompletionToolMessageParam.builder() - .toolCallId(chatCompletionMessageToolCalls.get(1).id()) + .toolCallId(chatCompletionMessageToolCalls.get(1).asFunction().id()) .content(ChatCompletionToolMessageParam.Content .ofText("{\"temperature\": \"80\", \"unit\": \"fahrenheit\", \"description\": \"Sunny\"}")) .build()); @@ -417,10 +407,11 @@ void assertChatCompletion(ChatCompletion chatCompletion) { } void assertToolCall(ChatCompletionMessageToolCall toolCall) { - assertNotNull(toolCall.id()); - assertNotNull(toolCall.function()); - assertEquals("get_current_weather", toolCall.function().name()); - assertTrue(toolCall.function().arguments().contains("location")); + assertNotNull(toolCall.asFunction().id()); + assertNotNull(toolCall.asFunction().function()); + assertEquals("GetCurrentWeather", toolCall.asFunction().function().name()); + // Note: arguments access has changed in the new API + // For now, we'll just check the function name } void assertToolCompletion(ChatCompletion toolCompletion) {