Summary
Implement AzureFoundryService as a concrete provider of IAiService, integrated via the existing AiServiceFactory + AiProvider keyed DI architecture. This is a priority item: it must be ready before the Azure MeetUp Torino (see #118), where it will be presented as a real-world Azure AI Foundry integration within XPoster.
Context
AiServiceFactory already supports keyed DI resolution by AiProvider enum. OpenAiService is the only active implementation today. AzureFoundryService is the next provider to implement — it does not replace OpenAI but acts as an alternative provider selectable via configuration.
The AiProvider.AzureFoundry enum value is expected to already exist (or must be added) in src/Abstraction/AiProvider.cs.
Implementation Plan
1. src/Models/AzureFoundryOptions.cs
Strongly-typed configuration bound from the AzureFoundry configuration section:
public sealed class AzureFoundryOptions
{
public string Endpoint { get; set; } = string.Empty;
public string ApiKey { get; set; } = string.Empty;
public string DeploymentName { get; set; } = string.Empty;
public string ImageDeploymentName { get; set; } = string.Empty;
public string ApiVersion { get; set; } = "2024-02-01";
public double SummaryTemperature { get; set; } = 0.5;
public int SummaryMaxTokensPerChar { get; set; } = 5;
public int SummarySafetyMarginChars { get; set; } = 50;
public string SummarySystemPromptTemplate { get; set; } = "...";
public string SummaryUserPromptTemplate { get; set; } = "...";
public string ImagePromptSystemTemplate { get; set; } = "...";
public string ImagePromptUserTemplate { get; set; } = "...";
public int ImagePromptMaxTokens { get; set; } = 60;
public double ImagePromptTemperature { get; set; } = 0.7;
}
Add AzureFoundryOptionsValidator.cs — validate that Endpoint, ApiKey, and DeploymentName are not empty when AiProvider.AzureFoundry is active.
2. src/Services/AzureFoundryService.cs
Implement IAiService using the Azure AI Foundry REST API (OpenAI-compatible endpoint):
GetSummaryAsync — POST to {Endpoint}/openai/deployments/{DeploymentName}/chat/completions?api-version={ApiVersion}
GetImagePromptAsync — same endpoint, image prompt templates
GenerateImageAsync — POST to {Endpoint}/openai/deployments/{ImageDeploymentName}/images/generations?api-version={ApiVersion} (DALL-E compatible)
Use IHttpClientFactory. Set api-key header from AzureFoundryOptions.ApiKey.
3. Program.cs
builder.Services.AddKeyedTransient<IAiService, AzureFoundryService>(AiProvider.AzureFoundry);
builder.Services.Configure<AzureFoundryOptions>(builder.Configuration.GetSection("AzureFoundry"));
builder.Services.AddSingleton<IValidateOptions<AzureFoundryOptions>, AzureFoundryOptionsValidator>();
4. AiServiceFactory.cs
Add AiProvider.AzureFoundry to the supported providers set.
5. Configuration files
src/local.settings.json.example:
"AzureFoundry__Endpoint": "",
"AzureFoundry__ApiKey": "",
"AzureFoundry__DeploymentName": "",
"AzureFoundry__ImageDeploymentName": ""
6. docs/azure-foundry-setup.md — Setup Guide
Create a step-by-step guide explaining how to provision Azure AI Foundry and retrieve all required parameters to configure AzureFoundryService. The guide must cover:
- How to create an Azure AI Foundry resource in the Azure Portal
- How to create a project and deploy a model (chat completion + image generation)
- How to retrieve the Endpoint URL, API Key, Deployment Name, and API Version
- Where to store these values (App Settings / Key Vault)
- How to switch XPoster to use
AzureFoundryService via the AiProvider configuration key
- Troubleshooting: common errors (wrong API version, missing deployment, quota limits)
Acceptance Criteria
Tests to Add
tests/Services/AzureFoundryServiceTests.cs:
GetSummaryAsync_WhenTextExceedsLimit_CallsApiAndReturnsTrimmedContent
GetSummaryAsync_WhenApiReturns429_ReturnsEmptyString
GetSummaryAsync_WhenApiReturnsNonSuccess_ReturnsEmptyString
GetImagePromptAsync_WhenApiReturnsValidResponse_ReturnsPrompt
GenerateImageAsync_WhenApiReturnsValidResponse_ReturnsByteArray
GenerateImageAsync_WhenApiReturnsNonSuccess_ReturnsEmptyByteArray
Related
Summary
Implement
AzureFoundryServiceas a concrete provider ofIAiService, integrated via the existingAiServiceFactory+AiProviderkeyed DI architecture. This is a priority item: it must be ready before the Azure MeetUp Torino (see #118), where it will be presented as a real-world Azure AI Foundry integration within XPoster.Context
AiServiceFactoryalready supports keyed DI resolution byAiProviderenum.OpenAiServiceis the only active implementation today.AzureFoundryServiceis the next provider to implement — it does not replace OpenAI but acts as an alternative provider selectable via configuration.The
AiProvider.AzureFoundryenum value is expected to already exist (or must be added) insrc/Abstraction/AiProvider.cs.Implementation Plan
1.
src/Models/AzureFoundryOptions.csStrongly-typed configuration bound from the
AzureFoundryconfiguration section:Add
AzureFoundryOptionsValidator.cs— validate thatEndpoint,ApiKey, andDeploymentNameare not empty whenAiProvider.AzureFoundryis active.2.
src/Services/AzureFoundryService.csImplement
IAiServiceusing the Azure AI Foundry REST API (OpenAI-compatible endpoint):GetSummaryAsync— POST to{Endpoint}/openai/deployments/{DeploymentName}/chat/completions?api-version={ApiVersion}GetImagePromptAsync— same endpoint, image prompt templatesGenerateImageAsync— POST to{Endpoint}/openai/deployments/{ImageDeploymentName}/images/generations?api-version={ApiVersion}(DALL-E compatible)Use
IHttpClientFactory. Setapi-keyheader fromAzureFoundryOptions.ApiKey.3.
Program.cs4.
AiServiceFactory.csAdd
AiProvider.AzureFoundryto the supported providers set.5. Configuration files
src/local.settings.json.example:6.
docs/azure-foundry-setup.md— Setup GuideCreate a step-by-step guide explaining how to provision Azure AI Foundry and retrieve all required parameters to configure
AzureFoundryService. The guide must cover:AzureFoundryServicevia theAiProviderconfiguration keyAcceptance Criteria
AzureFoundryServiceimplementsIAiServiceand compilesAzureFoundryOptionsbound fromAzureFoundryconfiguration section; no literals hardcoded in the service classAiServiceFactoryresolvesAzureFoundryServicewhen called withAiProvider.AzureFoundryAiServiceFactoryresolvesOpenAiServicewhen called withAiProvider.OpenAi— existing behaviour unchangedGetSummaryAsync,GetImagePromptAsync,GenerateImageAsyncimplemented and functionaldocs/azure-foundry-setup.mdwritten and completelocal.settings.json.exampleTests to Add
tests/Services/AzureFoundryServiceTests.cs:Related
AzureFoundryServicemust be at minimum scaffolded before the event)AiServiceFactory+ keyed DI pattern (see also Add PerplexityService implementation of IAiService using Perplexity Chat Completions API #91 —PerplexityAiService)