Skip to content

Commit 87f170a

Browse files
authored
[OpenAI] Migrate azure-ai-openai to depends on openai-java (Azure#44936)
Add experience package, azure-ai-openai-stainless as the temp companion package. Merge to azure-ai-openai when release is ready
1 parent 3e9dd24 commit 87f170a

46 files changed

Lines changed: 3672 additions & 1 deletion

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

eng/versioning/external_dependencies.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ com.microsoft.sqlserver:mssql-jdbc;10.2.3.jre8
3838
com.microsoft.azure:azure-functions-maven-plugin;1.30.0
3939
com.microsoft.azure.functions:azure-functions-java-library;2.2.0
4040
com.mysql:mysql-connector-j;9.0.0
41+
com.openai:openai-java;1.3.1
4142
com.squareup.okhttp3:okhttp;4.12.0
4243
commons-codec:commons-codec;1.15
4344
commons-net:commons-net;3.9.0

eng/versioning/version_client.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ com.azure:azure-ai-metricsadvisor-perf;1.0.0-beta.1;1.0.0-beta.1
4747
com.azure:azure-ai-openai;1.0.0-beta.16;1.0.0-beta.17
4848
com.azure:azure-ai-openai-assistants;1.0.0-beta.5;1.0.0-beta.6
4949
com.azure:azure-ai-openai-realtime;1.0.0-beta.1;1.0.0-beta.1
50+
com.azure:azure-ai-openai-stainless;1.0.0-beta.1;1.0.0-beta.1
5051
com.azure:azure-ai-personalizer;1.0.0-beta.1;1.0.0-beta.2
5152
com.azure:azure-ai-textanalytics;5.5.6;5.6.0-beta.1
5253
com.azure:azure-ai-textanalytics-perf;1.0.0-beta.1;1.0.0-beta.1

sdk/openai/Clone-And-Build.ps1

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
##################################################################
2+
# This script is used for testing openai-build.yml locally only. #
3+
##################################################################
4+
5+
# Define repository details
6+
$repoUrl = "https://github.com/openai/openai-java.git"
7+
$branchName = "release-please--branches--main--changes--next"
8+
9+
# Clone the repository and checkout the specified branch
10+
Write-Host "Cloning repository: $repoUrl"
11+
git clone $repoUrl openai-java
12+
cd openai-java
13+
Write-Host "Checking out branch: $branchName"
14+
git checkout $branchName
15+
16+
# Define the path to the build.gradle.kts file
17+
$buildGradlePath = './build.gradle.kts'
18+
19+
# Read the contents of the build.gradle.kts file
20+
$buildGradleContent = Get-Content -Path $buildGradlePath
21+
22+
# Extract the version number from the build.gradle.kts file
23+
$versionLine = $buildGradleContent | Select-String -Pattern 'version\s*=\s*\"([^\"]+)\"'
24+
if ($versionLine -match 'version\s*=\s*\"([^\"]+)\"') {
25+
$version = $matches[1]
26+
Write-Host "Current version: $version"
27+
} else {
28+
Write-Host "Version not found"
29+
exit 1
30+
}
31+
32+
# Define the new version with '-SNAPSHOT' appended
33+
$newVersion = "$version-SNAPSHOT"
34+
Write-Host "New version: $newVersion"
35+
36+
# Update the version in the build.gradle.kts file
37+
$updatedContent = $buildGradleContent -replace 'version\s*=\s*\"([^\"]+)\"', "version = `"$newVersion`""
38+
Set-Content -Path $buildGradlePath -Value $updatedContent
39+
40+
# Build the project and publish to the local Maven repository
41+
Write-Host "Building the project and publishing to the local Maven repository"
42+
./gradlew clean build -x test publishToMavenLocal
43+
44+
# Define the path to the external_dependencies.txt file
45+
$dependenciesFilePath = './../../../eng/versioning/external_dependencies.txt'
46+
47+
# Update the version in the external_dependencies.txt file
48+
$newVersionInExternalDependenciesFile = "com.openai:openai-java;$newVersion"
49+
$dependenciesContent = Get-Content -Path $dependenciesFilePath -Raw
50+
$updatedDependenciesContent = $dependenciesContent -replace 'com.openai:openai-java;[0-9.]+', $newVersionInExternalDependenciesFile
51+
Set-Content -Path $dependenciesFilePath -Value $updatedDependenciesContent
52+
53+
# Run the version update script
54+
Write-Host "Running the version update script"
55+
cd ../../../
56+
python eng/versioning/update_versions.py --bt client --ut external_dependency --sr
57+
58+
# Navigate back to the sdk/openai directory
59+
cd .\sdk\openai

sdk/openai/aisource.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
extends:
2+
template: /eng/pipelines/templates/stages/archetype-sdk-tests.yml
3+
parameters:
4+
ServiceDirectory: openai
5+
DisableAzureResourceCreation: true
6+
PreSteps:
7+
- template: /sdk/openai/openai-build.yml
8+
Artifacts:
9+
- name: azure-ai-openai-stainless
10+
groupId: com.azure
11+
safeName: azureaiopenaistainless
12+
CloudConfig:
13+
Public:
14+
ServiceConnection: azure-sdk-tests-openai
15+
EnvVars:
16+
AZURE_OPENAI_ENDPOINT: $(AOAI-ENDPOINT-SWEDENCENTRAL)
17+
AZURE_OPENAI_KEY: $(AOAI-API-KEY-SWEDENCENTRAL)
18+
NON_AZURE_OPENAI_KEY: $(OPENAI-API-KEY)
19+
AZURE_TEST_RUN_LIVE: 'true'
20+
MatrixFilters:
21+
- TestFromSource=^$|false
22+
- AZURE_TEST_HTTP_CLIENTS=netty|okhttp
23+
- pool=^(?!.*(win)).*

sdk/openai/azure-ai-openai-assistants/README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Azure OpenAI: OpenAI Assistants client library for Java
22

3+
> [!IMPORTANT]
4+
> This client library won't receive updates in its current form.
5+
> To use newer OpenAI features, please use the official [OpenAI Java library][openai_java]
6+
> For Azure specific functionality, we are providing migration guides in azure-ai-openai-stainless.
7+
38
The Azure OpenAI Assistants client library for Java is an adaptation of OpenAI's REST APIs that provides an idiomatic interface
49
and rich integration with the rest of the Azure SDK ecosystem. It will connect to Azure OpenAI resources *or* to the
510
non-Azure OpenAI inference endpoint, making it a great choice for even non-Azure OpenAI development.
@@ -354,4 +359,4 @@ For details on contributing to this repository, see the [contributing guide](htt
354359
[azure_subscription]: https://azure.microsoft.com/free/
355360
[azure_identity]: https://github.com/Azure/azure-sdk-for-java/blob/main/sdk/identity/azure-identity
356361
[function_tool_call_full_sample]: https://github.com/Azure/azure-sdk-for-java/blob/main/sdk/openai/azure-ai-openai-assistants/src/samples/java/com/azure/ai/openai/assistants/FunctionToolCallSample.java
357-
362+
[openai_java]: https://github.com/openai/openai-java
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Release History
2+
3+
## 1.0.0-beta.1 (Unreleased)
4+
5+
This package is not intended for production use. It is intended to test Azure capabilities with OpenAI.
6+
This package is temporary and will be deleted after the companion library is ready to release.
Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
# Migration Guide from Azure OpenAI Java SDK to OpenAI Java SDK
2+
3+
## Overview
4+
5+
The [Azure OpenAI Java SDK's latest release][latest_aoai_sdk_release] is the last in the current shape of the SDK. Currently, we recommend users to make use of the [OpenAI Java SDK][openai_java], which can be used to access Azure OpenAI services too. We are currently working on providing classes and types to more easily interact with the service. On the meantime please use this migration guide to access the latest features of OpenAI.
6+
7+
## Client Instantiation & Authentication
8+
9+
### Project setup
10+
11+
Replace the import to `azure-ai-openai` with any of the [dependency import](https://github.com/openai/openai-java?tab=readme-ov-file#installation) that suits your setup.
12+
13+
### Authentication
14+
15+
#### OpenAI
16+
17+
For authenticating a client for OpenAI usage:
18+
19+
```java
20+
OpenAIClient client = OpenAIOkHttpClient.builder()
21+
.credential(BearerTokenCredential.create(System.getenv("OPENAI_KEY")))
22+
.build();
23+
```
24+
25+
#### Azure OpenAI Entra ID
26+
27+
Make sure you have correctly included in your project [Azure Identity][azure_identity] and your [Azure OpenAI][azure_openai_access] endpoint, then:
28+
29+
```java
30+
OpenAIClient client = OpenAIOkHttpClient.builder()
31+
.baseUrl(System.getenv("AZURE_OPENAI_ENDPOINT"))
32+
// Set the Azure Entra ID
33+
.credential(BearerTokenCredential.create(AuthenticationUtil.getBearerTokenSupplier(
34+
new DefaultAzureCredentialBuilder().build(), "https://cognitiveservices.azure.com/.default")))
35+
.build();
36+
```
37+
38+
#### Azure key authentication
39+
40+
For this mode of authentication you will need your service `key` and `endpoint`. Check your access to your [Azure OpenAI resource][azure_openai_access]:
41+
42+
```java
43+
OpenAIClient client = OpenAIOkHttpClient.builder()
44+
.baseUrl(System.getenv("AZURE_OPENAI_ENDPOINT"))
45+
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_KEY")))
46+
.build();
47+
```
48+
49+
### Azure OpenAI Service version pinning
50+
51+
To supply the version of the service you want to use of the Azure OpenAI service, do the following:
52+
53+
```java
54+
import com.openai.azure.AzureOpenAIServiceVersion;
55+
import com.openai.client.okhttp.OpenAIOkHttpClient;
56+
57+
OpenAIOkHttpClient.Builder clientBuilder = new OpenAIOkHttpClient.Builder()
58+
.azureServiceVersion(AzureOpenAIServiceVersion.latestStableVersion())
59+
// continue your client setup normally from this point onwards
60+
```
61+
62+
> [!NOTE] If the `AzureOpenAIServiceVersion` is omitted in the `ClientBuilder` setup, the latest review version in the [OpenAI Java SDK] will be used by default.
63+
64+
### Sync & Async client
65+
66+
In order to use the To use the sync client:
67+
68+
```java
69+
OpenAIClient client = OpenAIOkHttpClient.builder()
70+
.baseUrl(System.getenv("AZURE_OPENAI_ENDPOINT"))
71+
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_KEY")))
72+
.build();
73+
```
74+
75+
And for async:
76+
77+
```java
78+
OpenAIClientAsync client = OpenAIOkHttpClientAsync.builder()
79+
.baseUrl(System.getenv("AZURE_OPENAI_ENDPOINT"))
80+
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_KEY")))
81+
.build();
82+
```
83+
84+
One notable difference between the async Azure OpenAI Java SDK and the OpenAI SDK, is that the former uses [reactor](https://projectreactor.io/) and the latter [CompletableFutures](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html).
85+
86+
## Using the SDK
87+
88+
While using the [OpenAI Java SDK][openai_java], all the officially supported fields for the [OpenAI service][openai_openapi] should be supported. So for the latest features, please visit their documentation as it becomes available.
89+
90+
For fields that are "Azure-specific", we will provide guidelines on how to work with available types in the interim. We are planning on having better typed support in the near future.
91+
92+
Every [OpenAI Java SDK][openai_java] type has `Map<String, JsonValue>` named `additionalProperties` in which all fields that are not exclusively [OpenAI service related][openai_openapi] are populated. All the fields that are Azure OpenAI specific (i.e. content filter, Azure AI Search, etc.) will be populated in the aforementioned `Map<String, JsonValue>`. Next, you will find what we believe to be the more common scenarios, and how to provide/access these Azure OpenAI specific fields, while working with the [OpenAI Java SDK][openai_java].
93+
94+
> [!TIP]
95+
> We strongly recommend keeping an eye on our `samples` and `test` folders.
96+
> We use those tests to regularly validate the Azure OpenAI service.
97+
98+
### OYD: Chat Completions
99+
100+
To supply your Azure AI Search fields, you should setup your request as follows:
101+
102+
```java
103+
OpenAIClient client = createClient(apiType, apiVersion);
104+
ChatCompletionCreateParams params = createParamsBuilder(testModel)
105+
.messages(asList(createSystemMessageParam(),
106+
createUserMessageParam("<your_prompt>")))
107+
.additionalBodyProperties(createExtraBodyForByod())
108+
.build();
109+
ChatCompletion completion = client.chat().completions().create(params);
110+
111+
// Then the definition for the method where the Azure fields are added:
112+
Map<String, JsonValue> createExtraBodyForByod() {
113+
Map<String, JsonValue> authentication = new HashMap<>();
114+
authentication.put("type", JsonValue.from("api_key"));
115+
authentication.put("key", JsonValue.from(System.getenv("AZURE_SEARCH_API_KEY")));
116+
117+
Map<String, JsonValue> parameters = new HashMap<>();
118+
parameters.put("endpoint", JsonValue.from(System.getenv("AZURE_SEARCH_ENDPOINT")));
119+
parameters.put("index_name", JsonValue.from(System.getenv("AZURE_OPENAI_SEARCH_INDEX")));
120+
parameters.put("authentication", JsonValue.from(authentication));
121+
parameters.put("fields_mapping", JsonValue.from(Collections.singletonMap("title_field", "title")));
122+
parameters.put("query_type", JsonValue.from("simple"));
123+
124+
Map<String, JsonValue> dataSource = new HashMap<>();
125+
dataSource.put("type", JsonValue.from("azure_search"));
126+
dataSource.put("parameters", JsonValue.from(parameters));
127+
128+
Map<String, JsonValue> extraBody = new HashMap<>();
129+
extraBody.put("data_sources", JsonValue.from(asList(dataSource)));
130+
return extraBody;
131+
}
132+
```
133+
134+
In order to access the returned Azure fields you can do the following:
135+
136+
```java
137+
Map<String, JsonValue> additionalProperties = choice.message()._additionalProperties();
138+
139+
assertTrue(additionalProperties.containsKey("end_turn"));
140+
141+
assertTrue(additionalProperties.containsKey("context"));
142+
Map<String, JsonValue> context = (Map<String, JsonValue>) additionalProperties.get("context").asObject().get();
143+
assertNotNull(context);
144+
assertTrue(context.containsKey("intent"));
145+
assertFalse(CoreUtils.isNullOrEmpty((String) context.get("intent").asString().get()));
146+
assertTrue(context.containsKey("citations"));
147+
assertTrue(((List<JsonValue>) context.get("citations").asArray().get()).size() > 0);
148+
```
149+
150+
For more graceful handling, we suggest using `computeIfPresent` or `getOrDefault`.
151+
152+
### Streaming Chat Completions
153+
154+
For streaming with a sync client you can now do the following:
155+
156+
```java
157+
OpenAIClient client = createClient(apiType, apiVersion);
158+
159+
StringBuilder responseBuilder = new StringBuilder();
160+
try (StreamResponse<ChatCompletionChunk> streamChunks = client.chat().completions().createStreaming(
161+
createChatCompletionParams(testModel, "Tell a story about a cat and a dog who are best friends. "
162+
+ "It should be at least 100 words long, but at most 120. Be strict about these limits."))) {
163+
streamChunks.stream()
164+
.map(it -> (!it.choices().isEmpty()) ? it.choices().get(0).delta().content().orElse("") : "")
165+
.forEach(System.out::print);
166+
}
167+
```
168+
169+
Of in an async scenario:
170+
171+
```java
172+
OpenAIClientAsync client = //...
173+
174+
client.chat()
175+
.completions()
176+
.createStreaming(createChatCompletionParams(testModel,
177+
"Tell a story about a cat and a dog who are best friends. "
178+
+ "It should be at least 100 words long, but at most 120. Be strict about these limits."))
179+
.subscribe(it -> {
180+
String delta = !it.choices().isEmpty() ? it.choices().get(0).delta().content().orElse("") : "";
181+
System.out.print(delta);
182+
});
183+
```
184+
185+
### Responses
186+
187+
To use `Responses` with the [OpenAI Java SDK][openai_java], you can do the following:
188+
189+
```java
190+
OpenAIClient client = // ...
191+
client.responses().create(...)
192+
```
193+
194+
### Assistants
195+
196+
`Assistants` is still a beta feature. If you want to use it with the [OpenAI Java SDK][openai_java], you can do the following:
197+
198+
```java
199+
OpenAIClient client = // ...
200+
client.beta().assistants().create(...)
201+
```
202+
203+
204+
## Issues
205+
206+
For issues with the [OpenAI Java SDK][openai_java], please follow the guidelines in the repository for opening issues.
207+
208+
<!-- LINKS -->
209+
[azure_identity]: https://github.com/Azure/azure-sdk-for-java/blob/main/sdk/identity/azure-identity
210+
[azure_openai_access]: https://learn.microsoft.com/azure/cognitive-services/openai/overview#how-do-i-get-access-to-azure-openai
211+
[openai_java]: https://github.com/openai/openai-java
212+
[openai_openapi]: https://github.com/openai/openai-openapi
213+
[latest_aoai_sdk_release]: https://github.com/Azure/azure-sdk-for-java/blob/main/sdk/openai/azure-ai-openai/CHANGELOG.md#100-beta16-2025-03-26
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Azure tests for OpenAI Stainless client library for Java
2+
3+
This package is not intended for production use. It is intended to test Azure capabilities with OpenAI.
4+
5+
For a migration guide on how to use Azure OpenAI services features with the [OpenAI Official Java SDK](https://github.com/openai/openai-java), please see the [migration guide](https://github.com/Azure/azure-sdk-for-java/blob/main/sdk/openai/azure-ai-openai-stainless/MIGRATION.md).
6+
7+
# Getting started
8+
9+
# Key concepts
10+
11+
# Examples
12+
13+
# Troubleshooting
14+
15+
# Next steps
16+
17+
# Contributing

0 commit comments

Comments
 (0)