Skip to content

Commit d8dda38

Browse files
authored
Add option to use Azure OpenAI for translations (#750)
### Summary & Motivation Add support for Azure OpenAI as an alternative to standard OpenAI for translations in the Developer CLI. - Add Azure OpenAI client integration for custom endpoints - Enhance API key validation to support both standard OpenAI (sk-...) and Azure OpenAI keys - Add interactive prompt for Azure OpenAI endpoint URL when Azure key is detected - Store Azure OpenAI endpoint in secrets alongside the API key ### Checklist - [x] I have added tests, or done manual regression tests - [x] I have updated the documentation, if necessary
2 parents 28319c2 + e532314 commit d8dda38

File tree

2 files changed

+42
-13
lines changed

2 files changed

+42
-13
lines changed

developer-cli/Commands/TranslateCommand.cs

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
using System.ClientModel;
12
using System.CommandLine;
23
using System.CommandLine.NamingConventionBinder;
34
using System.Text;
5+
using Azure.AI.OpenAI;
46
using Karambolo.PO;
57
using OpenAI.Chat;
68
using PlatformPlatform.DeveloperCli.Installation;
@@ -298,35 +300,61 @@ private sealed class OpenAiTranslationService
298300
private readonly ChatClient _client;
299301
public readonly Gpt4OUsageStatistics UsageStatistics = new();
300302

301-
private OpenAiTranslationService(string apiKey)
303+
private OpenAiTranslationService(ChatClient chatClient)
302304
{
303-
_client = new ChatClient(ModelName, apiKey);
305+
_client = chatClient;
304306
}
305307

306308
public static OpenAiTranslationService Create()
307309
{
308-
var apiKey = GetApiKey();
309-
return new OpenAiTranslationService(apiKey);
310+
var (apiKey, endpoint) = GetApiKeyAndEndpoint();
311+
312+
ChatClient chatClient;
313+
if (endpoint is null)
314+
{
315+
// Use standard OpenAI client for default endpoint
316+
chatClient = new ChatClient(ModelName, apiKey);
317+
}
318+
else
319+
{
320+
// Use Azure OpenAI client for custom endpoints
321+
var azureClient = new AzureOpenAIClient(new Uri(endpoint), new ApiKeyCredential(apiKey));
322+
chatClient = azureClient.GetChatClient(ModelName);
323+
}
324+
325+
return new OpenAiTranslationService(chatClient);
310326
}
311327

312-
private static string GetApiKey()
328+
private static (string apiKey, string? endpoint) GetApiKeyAndEndpoint()
313329
{
314330
const string apiKeySecretName = "OpenAIApiKey";
331+
const string endpointSecretName = "OpenAIEndpoint";
332+
315333
var apiKey = SecretHelper.GetSecret(apiKeySecretName);
316-
if (!string.IsNullOrWhiteSpace(apiKey))
334+
var endpoint = SecretHelper.GetSecret(endpointSecretName);
335+
336+
if (apiKey is not null)
317337
{
318-
return apiKey;
338+
return (apiKey, endpoint);
319339
}
320340

321-
AnsiConsole.MarkupLine("OpenAPI Key is missing.");
322-
apiKey = AnsiConsole.Ask<string>("[yellow]Please enter your OpenAPI Key.[/]");
323-
if (!string.IsNullOrWhiteSpace(apiKey))
341+
AnsiConsole.MarkupLine("OpenAI Key is missing.");
342+
apiKey = AnsiConsole.Prompt(
343+
new TextPrompt<string>("[yellow]Enter your OpenAI Key. Use a standard OpenAI key (sk-...) or an Azure OpenAI key ([a-z0-9]{32})[/]")
344+
.Validate(key => key.Length >= 32 ? ValidationResult.Success() : ValidationResult.Error("Open AI Keys starts with 'sk-' and must be at least 51 characters long and Azure Open AI key must be 32 characters long.")));
345+
346+
if (!apiKey.StartsWith("sk-"))
324347
{
325-
SecretHelper.SetSecret(apiKeySecretName, apiKey);
326-
return apiKey;
348+
AnsiConsole.MarkupLine("[green]API Key is not a standard OpenAI key. Azure OpenAI key detected.[/]");
349+
endpoint = AnsiConsole.Prompt(
350+
new TextPrompt<string>("[yellow]Please enter the Azure OpenAI endpoint URL (e.g. https://<your-resource-name>.openai.azure.com)[/]")
351+
.Validate(url => Uri.TryCreate(url, UriKind.Absolute, out _)));
352+
SecretHelper.SetSecret(endpointSecretName, endpoint);
327353
}
328354

329-
throw new InvalidOperationException("Invalid OpenAPI Key provided.");
355+
SecretHelper.SetSecret(apiKeySecretName, apiKey);
356+
357+
return (apiKey, endpoint);
330358
}
331359

332360
public async Task<POSingularEntry> Translate(

developer-cli/DeveloperCli.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
</PropertyGroup>
1313

1414
<ItemGroup>
15+
<PackageReference Include="Azure.AI.OpenAI" Version="2.1.0" />
1516
<PackageReference Include="Azure.Identity" Version="1.13.2" />
1617
<PackageReference Include="Azure.ResourceManager" Version="1.13.0" />
1718
<PackageReference Include="Bogus" Version="35.6.1" />

0 commit comments

Comments
 (0)