Azure OpenAI provides enterprise-grade AI capabilities with enhanced security, compliance, and regional availability. This guide walks you through implementing Azure OpenAI chat completions in your .NET applications, focusing on the key differences from the standard OpenAI implementation.
Why Choose Azure OpenAI?
Azure OpenAI offers several advantages over the standard OpenAI API:
- Enterprise Security: Built-in Azure security features and compliance certifications
- Data Residency: Control over where your data is processed and stored
- Network Isolation: Virtual network integration and private endpoints
- SLA Guarantees: Enterprise-grade service level agreements
- Integrated Billing: Unified billing with other Azure services
Prerequisites
Before starting, ensure you have:
- An Azure subscription with OpenAI access approved
- Azure OpenAI resource created in your subscription
- Visual Studio or VS Code with .NET SDK
- Azure CLI (optional, for deployment)
Step 1: Create Azure OpenAI Resource
First, create an Azure OpenAI resource through the Azure Portal:
# Using Azure CLI
az cognitiveservices account create \
--name "my-openai-resource" \
--resource-group "my-resource-group" \
--kind "OpenAI" \
--sku "S0" \
--location "eastus"
Step 2: Deploy a Model
Deploy a GPT model in your Azure OpenAI resource:
# Deploy GPT-4 model
az cognitiveservices account deployment create \
--name "my-openai-resource" \
--resource-group "my-resource-group" \
--deployment-name "gpt-4-deployment" \
--model-name "gpt-4" \
--model-version "0613" \
--model-format "OpenAI"
Step 3: Install Required NuGet Packages
dotnet add package Azure.AI.OpenAI
dotnet add package Azure.Identity
Step 4: Basic Implementation
Here’s a complete implementation using Azure OpenAI:
using Azure;
using Azure.AI.OpenAI;
using Azure.Identity;
namespace AzureOpenAIExample
{
class Program
{
private static readonly string endpoint = "https://your-resource.openai.azure.com/";
private static readonly string deploymentName = "gpt-4-deployment";
static async Task Main(string[] args)
{
// Option 1: Using API Key
var client = new OpenAIClient(
new Uri(endpoint),
new AzureKeyCredential("your-api-key")
);
// Option 2: Using Azure AD Authentication (Recommended)
// var client = new OpenAIClient(
// new Uri(endpoint),
// new DefaultAzureCredential()
// );
await RunChatExample(client);
}
static async Task RunChatExample(OpenAIClient client)
{
var messages = new List<ChatRequestMessage>
{
new ChatRequestSystemMessage("You are a helpful AI assistant.")
};
Console.WriteLine("Azure OpenAI Chat (type 'exit' to quit):");
while (true)
{
Console.Write("You: ");
var userInput = Console.ReadLine();
if (userInput?.ToLower() == "exit")
break;
messages.Add(new ChatRequestUserMessage(userInput));
try
{
var chatCompletionsOptions = new ChatCompletionsOptions(deploymentName, messages)
{
Temperature = 0.7f,
MaxTokens = 500,
NucleusSamplingFactor = 0.95f,
FrequencyPenalty = 0,
PresencePenalty = 0
};
Response<ChatCompletions> response = await client.GetChatCompletionsAsync(chatCompletionsOptions);
ChatResponseMessage responseMessage = response.Value.Choices[0].Message;
Console.WriteLine($"Assistant: {responseMessage.Content}");
messages.Add(new ChatRequestAssistantMessage(responseMessage.Content));
}
catch (RequestFailedException ex)
{
Console.WriteLine($"Error: {ex.Message}");
Console.WriteLine($"Error Code: {ex.ErrorCode}");
}
}
}
}
}
Step 5: Advanced Configuration
Authentication with Azure Active Directory
For production applications, use Azure AD authentication:
using Azure.Identity;
public class AzureOpenAIService
{
private readonly OpenAIClient _client;
private readonly string _deploymentName;
public AzureOpenAIService(string endpoint, string deploymentName)
{
var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions
{
ManagedIdentityClientId = Environment.GetEnvironmentVariable("AZURE_CLIENT_ID")
});
_client = new OpenAIClient(new Uri(endpoint), credential);
_deploymentName = deploymentName;
}
public async Task<string> GetCompletionAsync(string prompt)
{
var messages = new List<ChatRequestMessage>
{
new ChatRequestUserMessage(prompt)
};
var options = new ChatCompletionsOptions(_deploymentName, messages)
{
Temperature = 0.3f,
MaxTokens = 1000
};
var response = await _client.GetChatCompletionsAsync(options);
return response.Value.Choices[0].Message.Content;
}
}
Configuration Management
Use Azure App Configuration or Key Vault for secure configuration:
// appsettings.json
{
"AzureOpenAI": {
"Endpoint": "https://your-resource.openai.azure.com/",
"DeploymentName": "gpt-4-deployment",
"MaxTokens": 1000,
"Temperature": 0.7
}
}
// Configuration class
public class AzureOpenAIOptions
{
public string Endpoint { get; set; } = string.Empty;
public string DeploymentName { get; set; } = string.Empty;
public int MaxTokens { get; set; } = 1000;
public float Temperature { get; set; } = 0.7f;
}
// Dependency injection setup
public void ConfigureServices(IServiceCollection services)
{
services.Configure<AzureOpenAIOptions>(
Configuration.GetSection("AzureOpenAI"));
services.AddSingleton<OpenAIClient>(provider =>
{
var options = provider.GetRequiredService<IOptions<AzureOpenAIOptions>>().Value;
return new OpenAIClient(
new Uri(options.Endpoint),
new DefaultAzureCredential()
);
});
services.AddTransient<IAzureOpenAIService, AzureOpenAIService>();
}
Step 6: Streaming Responses
For real-time applications, implement streaming responses:
public async Task GetStreamingCompletionAsync(string prompt)
{
var messages = new List<ChatRequestMessage>
{
new ChatRequestUserMessage(prompt)
};
var options = new ChatCompletionsOptions(_deploymentName, messages)
{
Temperature = 0.7f,
MaxTokens = 1000
};
await foreach (StreamingChatCompletionsUpdate chatUpdate in
_client.GetChatCompletionsStreaming(options))
{
if (chatUpdate.Role.HasValue)
{
Console.Write($"{chatUpdate.Role.Value}: ");
}
if (!string.IsNullOrEmpty(chatUpdate.ContentUpdate))
{
Console.Write(chatUpdate.ContentUpdate);
}
}
Console.WriteLine();
}
Step 7: Error Handling and Retry Logic
Implement robust error handling for production use:
using Polly;
using Polly.Extensions.Http;
public class ResilientAzureOpenAIService
{
private readonly OpenAIClient _client;
private readonly IAsyncPolicy<Response<ChatCompletions>> _retryPolicy;
public ResilientAzureOpenAIService(OpenAIClient client)
{
_client = client;
_retryPolicy = Policy
.Handle<RequestFailedException>(ex =>
ex.Status == 429 || // Rate limit
ex.Status >= 500) // Server errors
.WaitAndRetryAsync(
retryCount: 3,
sleepDurationProvider: retryAttempt =>
TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
onRetry: (outcome, timespan, retryCount, context) =>
{
Console.WriteLine($"Retry {retryCount} after {timespan} seconds");
});
}
public async Task<string> GetCompletionWithRetryAsync(string prompt)
{
var messages = new List<ChatRequestMessage>
{
new ChatRequestUserMessage(prompt)
};
var options = new ChatCompletionsOptions("gpt-4-deployment", messages);
var response = await _retryPolicy.ExecuteAsync(async () =>
{
return await _client.GetChatCompletionsAsync(options);
});
return response.Value.Choices[0].Message.Content;
}
}
Step 8: Monitoring and Logging
Integrate with Azure Application Insights:
using Microsoft.Extensions.Logging;
using System.Diagnostics;
public class MonitoredAzureOpenAIService
{
private readonly OpenAIClient _client;
private readonly ILogger<MonitoredAzureOpenAIService> _logger;
private readonly ActivitySource _activitySource;
public MonitoredAzureOpenAIService(
OpenAIClient client,
ILogger<MonitoredAzureOpenAIService> logger)
{
_client = client;
_logger = logger;
_activitySource = new ActivitySource("AzureOpenAI");
}
public async Task<string> GetCompletionAsync(string prompt)
{
using var activity = _activitySource.StartActivity("GetCompletion");
activity?.SetTag("prompt.length", prompt.Length);
var stopwatch = Stopwatch.StartNew();
try
{
_logger.LogInformation("Starting OpenAI completion request");
var messages = new List<ChatRequestMessage>
{
new ChatRequestUserMessage(prompt)
};
var options = new ChatCompletionsOptions("gpt-4-deployment", messages);
var response = await _client.GetChatCompletionsAsync(options);
stopwatch.Stop();
var completion = response.Value.Choices[0].Message.Content;
_logger.LogInformation(
"Completion successful. Duration: {Duration}ms, " +
"Input tokens: {InputTokens}, Output tokens: {OutputTokens}",
stopwatch.ElapsedMilliseconds,
response.Value.Usage.PromptTokens,
response.Value.Usage.CompletionTokens);
activity?.SetTag("success", true);
activity?.SetTag("duration_ms", stopwatch.ElapsedMilliseconds);
activity?.SetTag("input_tokens", response.Value.Usage.PromptTokens);
activity?.SetTag("output_tokens", response.Value.Usage.CompletionTokens);
return completion;
}
catch (Exception ex)
{
stopwatch.Stop();
_logger.LogError(ex,
"OpenAI completion failed after {Duration}ms",
stopwatch.ElapsedMilliseconds);
activity?.SetTag("success", false);
activity?.SetTag("error", ex.Message);
throw;
}
}
}
Security Best Practices
- Use Azure AD Authentication: Avoid API keys in production
- Implement Network Security: Use private endpoints and virtual networks
- Monitor Usage: Set up alerts for unusual activity
- Rotate Keys: Regularly rotate API keys if used
- Limit Access: Use Azure RBAC for fine-grained permissions
Cost Optimization
public class CostOptimizedAzureOpenAIService
{
private readonly OpenAIClient _client;
private readonly IMemoryCache _cache;
public async Task<string> GetCompletionWithCachingAsync(string prompt)
{
// Check cache first
var cacheKey = $"openai:{prompt.GetHashCode()}";
if (_cache.TryGetValue(cacheKey, out string cachedResponse))
{
return cachedResponse;
}
// Optimize prompt to reduce tokens
var optimizedPrompt = OptimizePrompt(prompt);
var messages = new List<ChatRequestMessage>
{
new ChatRequestUserMessage(optimizedPrompt)
};
var options = new ChatCompletionsOptions("gpt-4-deployment", messages)
{
MaxTokens = 500, // Limit response length
Temperature = 0.3f // Lower temperature for more consistent results
};
var response = await _client.GetChatCompletionsAsync(options);
var completion = response.Value.Choices[0].Message.Content;
// Cache for future requests
_cache.Set(cacheKey, completion, TimeSpan.FromHours(1));
return completion;
}
private string OptimizePrompt(string prompt)
{
// Remove unnecessary whitespace and optimize for token efficiency
return prompt.Trim().Replace(" ", " ");
}
}
Conclusion
Azure OpenAI provides a robust, enterprise-ready platform for integrating AI capabilities into your .NET applications. By following these patterns and best practices, you can build scalable, secure, and cost-effective AI-powered solutions.
Key takeaways:
- Use Azure AD authentication for production security
- Implement proper error handling and retry logic
- Monitor usage and performance with Application Insights
- Optimize costs through caching and prompt engineering
- Follow Azure security best practices
With Azure OpenAI, you get the power of OpenAI’s models with the enterprise features and compliance guarantees of Azure, making it an ideal choice for business-critical applications.
Ready to Build Something Amazing?
Let's discuss how Aviron Labs can help bring your ideas to life with custom software solutions.
Get in Touch