Skip to content

Add comprehensive dependency injection support with IServiceCollection extension methods - #696

Merged
joseharriaga merged 19 commits into
openai:mainfrom
mokarchi:main
Feb 25, 2026
Merged

joseharriaga merged 19 commits into
openai:mainfrom
mokarchi:main

Conversation

@mokarchi

@mokarchi mokarchi commented Sep 18, 2025 •

Copy link
Copy Markdown
Contributor

This PR implements per-client configuration and dependency injection support for the OpenAI .NET library, fully aligning with the design proposed in issue #932 and following the modern .NET / Azure SDK pattern using System.ClientModel.

The new approach replaces manual DI registrations with strongly-typed, configuration-bound settings classes for each specialized client (ChatClient, EmbeddingClient, AudioClient, ImageClient, ModerationClient).

Key Features Added

  1. Dedicated Settings Classes per Client
    Each specialized client now has its own settings class inheriting from ClientSettings

    These classes contain only the properties needed by the client's primary constructor (mainly Model and Options), and credential is handled automatically by the base ClientSettings.

    Example structure:

    [Experimental("SCME0002")]
    public sealed class ChatClientSettings : ClientSettings
    {
        public string? Model { get; set; }
        public OpenAIClientOptions? Options { get; set; } = new();
        // BindCore implemented for configuration binding
    }
  2. New Constructor for Specialized Clients
    Each specialized client now has an additional constructor that accepts its settings class:

    [Experimental("SCME0002")]
    public ChatClient(ChatClientSettings settings)
     : this(settings.Model, AuthenticationPolicy.Create(settings), settings.Options ?? new OpenAIClientOptions())
    {
    }

(Similar constructors added to EmbeddingClient, AudioClient, ImageClient, ModerationClient)

  1. Fluent DI Registration via IHostApplicationBuilder
    Extension methods on IHostApplicationBuilder for registering each client with configuration support:
builder.AddChatClient("Chat")           // sectionName = "Chat"
builder.AddEmbeddingClient("Embedding");
builder.AddAudioClient("Audio");
builder.AddImageClient("Image");
builder.AddModerationClient("Moderation");

Keyed registration is also supported:

builder.AddKeyedChatClient("premium", "PremiumChat");
  1. Configuration Integration (appsettings.json)
    Full support for Microsoft.Extensions.Configuration binding with hierarchical keys, $ref syntax, and environment variables:
{
  "Chat": {
    "Model": "gpt-4o-mini",
    "Options": {
      "OrganizationId": "org-abc123",
      "ProjectId": "proj-xyz789"
    }
  },
  "Embedding": {
    "Model": "text-embedding-3-small"
  },
  "Audio": {
    "Model": "whisper-1"
  }
}

This commit introduces new features for dependency injection in the OpenAI .NET library, allowing for easier registration and configuration of clients within ASP.NET Core applications. Key changes include:

- New extension methods for registering OpenAI clients with support for `appsettings.json` and environment variables.
- Introduction of the `OpenAIServiceOptions` class for simplified configuration.
- Updates to README.md with detailed usage instructions and examples.
- Modifications to project files to include necessary package references.
- Comprehensive unit tests to validate the new features and ensure proper functionality.
@stephentoub

Copy link
Copy Markdown
Contributor

Should this instead be left to Aspire, e.g. https://www.nuget.org/packages/Aspire.OpenAI ?

cc: @eerhardt

@KrzysztofCwalina

Copy link
Copy Markdown
Contributor

I also think configuration like this needs to be aligned with what we already have in both Aspire, .NET, and Azure. In fact, I had a sync up with @eerhardt a couple of days ago to design a consistent solution.

cc @m-nash

@mokarchi

Copy link
Copy Markdown
Contributor Author

@stephentoub @KrzysztofCwalina, I was wondering about the current status of this PR. Should I wait or make any changes?

@KrzysztofCwalina

Copy link
Copy Markdown
Contributor

@stephentoub @KrzysztofCwalina, I was wondering about the current status of this PR. Should I wait or make any changes?

@m-nash @eerhardt, @jsquire, how would you want to handle this PR? It seems like you are working features similar to it.

@mokarchi

mokarchi commented Oct 1, 2025

Copy link
Copy Markdown
Contributor Author

@eerhardt Could you review this, please?

@jsquire

jsquire commented Oct 1, 2025

Copy link
Copy Markdown
Collaborator

Hi @mokarchi. Thank you for your contribution and your interest in improving the OpenAI developer experience. Apologies for the feedback delay, but there was some coordination needed on other workstreams. As Krzysztof mentioned, we are in the process of designing an experience where clients natively integrate with the .NET configuration, options, and DI systems. Part of that work entails defining the common patterns across the OpenAI clients for DI registration, construction, and configuration and ensuring that they align closely with the .NET ecosystem.

Because we don't yet have a fully codified design, we're not able to provide the detailed feedback that would be needed to help your contribution align. As a result, we're unable to move forward at this time. We have a couple of options that you can consider for next steps:

  • We can close this PR out and leave the implementation to the team once a design is settled.
  • We can close this PR out and coordinate on a new implementation together once the design is settled.
  • We can park this PR for now and then work together to align the implementation to the design once it is available.

Please let us know how you'd like to proceed.

//cc: @m-nash for awareness.

jsquire
jsquire previously requested changes Oct 1, 2025

@jsquire jsquire left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking for now to prevent accidental merge.

@mokarchi

mokarchi commented Oct 1, 2025 •

Copy link
Copy Markdown
Contributor Author

Thank you for the update, @jsquire.
I'd like to go with the third option: parking this PR for now and working together to align the implementation once the design is available. I'm happy to iterate on this contribution to ensure it fits seamlessly with the broader patterns you're defining.

@jsquire

jsquire commented Oct 1, 2025

Copy link
Copy Markdown
Collaborator

Thank you, @mokarchi. We appreciate your flexibility and understanding.

@jsquire
jsquire requested a review from m-nash October 1, 2025 20:21
@m-nash

m-nash commented Oct 1, 2025

Copy link
Copy Markdown
Collaborator

Thank you for the update, @jsquire. I'd like to go with the third option: parking this PR for now and working together to align the implementation once the design is available. I'm happy to iterate on this contribution to ensure it fits seamlessly with the broader patterns you're defining.

Late to the party, but yeah this feels like the best path forward. Once the design is ready to share we can collaborate on the implementation.

@mokarchi
mokarchi requested a review from christothes as a code owner February 5, 2026 11:22
…ests

- Deleted ServiceCollectionExtensionsAdvanced.cs which contained methods for adding OpenAI services with enhanced configuration support.
- Removed OpenAIServiceOptionsTests.cs that tested the OpenAIServiceOptions class.
- Deleted ServiceCollectionExtensionsAdvancedTests.cs which included tests for the advanced service collection methods.
- Updated ServiceCollectionExtensionsTests.cs to reflect changes in service registration methods and added new tests for the simplified client builder methods.
@mokarchi

mokarchi commented Feb 5, 2026

Copy link
Copy Markdown
Contributor Author

Hi @m-nash, @jsquire
I've applied the changes based on the design outlined in issue #932.
Would appreciate your review and any feedback or additional requirements.
Thanks for the guidance!

@m-nash

m-nash commented Feb 7, 2026

Copy link
Copy Markdown
Collaborator

Hi @m-nash, @jsquire I've applied the changes based on the design outlined in issue #932. Would appreciate your review and any feedback or additional requirements. Thanks for the guidance!

@mokarchi You jumped on this faster than I was ready I hadn't put all the details into the issue yet. I updated issues with the rest of the details.

@mokarchi

mokarchi commented Feb 7, 2026

Copy link
Copy Markdown
Contributor Author

Hi @m-nash, @jsquire I've applied the changes based on the design outlined in issue #932. Would appreciate your review and any feedback or additional requirements. Thanks for the guidance!

@mokarchi You jumped on this faster than I was ready I hadn't put all the details into the issue yet. I updated issues with the rest of the details.

Ready for your review. let me know if anything needs tweaking or if I missed a detail.
Appreciate your help!

@m-nash m-nash left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like we are missing a few clients in here like AssistantClient, BatchClient, etc. Lets add those in as well with a settings that matches their main ctor.

Comment thread src/Custom/Audio/AudioClient.cs Outdated
Comment thread src/Custom/DependencyInjection/OpenAIHostBuilderExtensions.cs Outdated
Comment thread src/Custom/DependencyInjection/OpenAIHostBuilderExtensions.cs Outdated
Comment thread src/Custom/OpenAISpecializedClientSettings.cs Outdated
Comment thread src/Custom/OpenAISpecializedClientSettings.cs Outdated
Comment thread src/Custom/OpenAISpecializedClientSettings.cs Outdated
Comment thread src/Custom/OpenAISpecializedClientSettings.cs Outdated

@m-nash m-nash left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like we are missing a few clients in here like AssistantClient, BatchClient, etc. Lets add those in as well with a settings that matches their main ctor.

@m-nash m-nash left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One minor update but this is looking good. @joseharriaga can you do a quick review as well?

Comment thread src/Custom/OpenAIClientOptions.cs Outdated
@mokarchi

Copy link
Copy Markdown
Contributor Author

@m-nash, Ready for your review. if there's anything else, please let me know.

@m-nash m-nash left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes LGTM, thanks again @mokarchi .

@joseharriaga can you also take a look to see if anything stands out where do we typically document things like this?

@m-nash

m-nash commented Feb 12, 2026

Copy link
Copy Markdown
Collaborator

@mokarchi looks like CI fails because you forgot to run ./scripts/Export-Api.ps1. You will need to run that and add those changed api files to the PR.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds first-class configuration binding and dependency injection registration for the OpenAI .NET clients using the System.ClientModel ClientSettings pattern, enabling per-client configuration and host-builder-based registrations.

Changes:

  • Introduces *ClientSettings types per specialized client, implementing configuration binding via ClientSettings.BindCore.
  • Adds new ClientSettings-based constructors across the specialized clients.
  • Adds IHostApplicationBuilder extension methods to register clients (including keyed registrations) via AddClient<TClient,TSettings> / AddKeyedClient<TClient,TSettings>.

Reviewed changes

Copilot reviewed 38 out of 38 changed files in this pull request and generated 19 comments.

Show a summary per file
File Description
src/Custom/DependencyInjection/OpenAIHostBuilderExtensions.cs Adds IHostApplicationBuilder extension methods for registering OpenAI clients (including keyed variants).
src/Custom/OpenAIClientOptions.cs Adds configuration-section-based binding constructor used by settings classes.
src/Custom/Chat/ChatClientSettings.cs Adds settings type to bind Model and nested Options for ChatClient.
src/Custom/Chat/ChatClient.cs Adds settings-based constructor for ChatClient.
src/Custom/Embeddings/EmbeddingClientSettings.cs Adds settings type to bind Model and nested Options for EmbeddingClient.
src/Custom/Embeddings/EmbeddingClient.cs Adds settings-based constructor for EmbeddingClient.
src/Custom/Audio/AudioClientSettings.cs Adds settings type to bind Model and nested Options for AudioClient.
src/Custom/Audio/AudioClient.cs Adds settings-based constructor for AudioClient.
src/Custom/Images/ImageClientSettings.cs Adds settings type to bind Model and nested Options for ImageClient.
src/Custom/Images/ImageClient.cs Adds settings-based constructor for ImageClient.
src/Custom/Moderations/ModerationClientSettings.cs Adds settings type to bind Model and nested Options for ModerationClient.
src/Custom/Moderations/ModerationClient.cs Adds settings-based constructor for ModerationClient.
src/Custom/Responses/ResponsesClientSettings.cs Adds settings type to bind Model and nested Options for ResponsesClient.
src/Custom/Responses/ResponsesClient.cs Adds settings-based constructor for ResponsesClient and a small whitespace-only change.
src/Custom/Assistants/AssistantClientSettings.cs Adds settings type to bind nested Options for AssistantClient.
src/Custom/Assistants/AssistantClient.cs Adds settings-based constructor for AssistantClient.
src/Custom/Batch/BatchClientSettings.cs Adds settings type to bind nested Options for BatchClient.
src/Custom/Batch/BatchClient.cs Adds settings-based constructor for BatchClient.
src/Custom/Containers/ContainerClientSettings.cs Adds settings type to bind nested Options for ContainerClient.
src/Custom/Containers/ContainerClient.cs Adds settings-based constructor for ContainerClient.
src/Custom/Conversations/ConversationClientSettings.cs Adds settings type to bind nested Options for ConversationClient.
src/Custom/Conversations/ConversationClient.cs Adds settings-based constructor for ConversationClient.
src/Custom/Evals/EvaluationClientSettings.cs Adds settings type to bind nested Options for EvaluationClient.
src/Custom/Evals/EvaluationClient.cs Adds settings-based constructor for EvaluationClient.
src/Custom/Files/OpenAIFileClientSettings.cs Adds settings type to bind nested Options for OpenAIFileClient.
src/Custom/Files/OpenAIFileClient.cs Adds settings-based constructor for OpenAIFileClient.
src/Custom/FineTuning/FineTuningClientSettings.cs Adds settings type to bind nested Options for FineTuningClient.
src/Custom/FineTuning/FineTuningClient.cs Adds settings-based constructor for FineTuningClient.
src/Custom/Graders/GraderClientSettings.cs Adds settings type to bind nested Options for GraderClient.
src/Custom/Graders/GraderClient.cs Adds settings-based constructor for GraderClient.
src/Custom/Models/OpenAIModelClientSettings.cs Adds settings type to bind nested Options for OpenAIModelClient.
src/Custom/Models/OpenAIModelClient.cs Adds settings-based constructor for OpenAIModelClient.
src/Custom/Realtime/RealtimeClientSettings.cs Adds settings type to bind nested Options for RealtimeClient.
src/Custom/Realtime/RealtimeClient.cs Adds settings-based constructor for RealtimeClient.
src/Custom/VectorStores/VectorStoreClientSettings.cs Adds settings type to bind nested Options for VectorStoreClient.
src/Custom/VectorStores/VectorStoreClient.cs Adds settings-based constructor for VectorStoreClient.
src/Custom/Videos/VideoClientSettings.cs Adds settings type to bind nested Options for VideoClient.
src/Custom/Videos/VideoClient.cs Adds settings-based constructor for VideoClient.

Comment thread src/Custom/DependencyInjection/OpenAIHostBuilderExtensions.cs Outdated
Comment thread src/Custom/Audio/AudioClient.cs Outdated
Comment thread src/Custom/VectorStores/VectorStoreClient.cs Outdated
Comment thread src/Custom/FineTuning/FineTuningClient.cs Outdated
Comment thread src/Custom/Graders/GraderClient.cs
Comment thread src/Custom/Realtime/RealtimeClient.cs Outdated
Comment thread src/Custom/Models/OpenAIModelClient.cs Outdated
Comment thread src/Custom/Responses/ResponsesClient.cs Outdated
Comment thread src/Custom/Files/OpenAIFileClient.cs Outdated
Comment thread src/Custom/Conversations/ConversationClient.cs Outdated
Comment thread src/Custom/DependencyInjection/OpenAIHostBuilderExtensions.cs
@mokarchi

Copy link
Copy Markdown
Contributor Author

@joseharriaga Thanks for the thorough review and all the detailed feedback! I've now applied all the requested changes.

@mokarchi

Copy link
Copy Markdown
Contributor Author

@m-nash @joseharriaga

  1. I ran ./scripts/Export-Api.ps1 It completed successfully and updated the API surface files. I committed and pushed them However, CI is still failing.
  2. With all previous feedback applied, I believe the PR is now complete and ready. If there are no more comments or adjustments needed from your side, please feel free to merge whenever convenient or let me know if anything else remains.

mokarchi and others added 2 commits February 20, 2026 18:31
…tests

Replaced the duplicated constructor body implementations in all 18 client
settings constructors with simple delegation to the existing constructors
that already contain the body logic. This uses ?. notation to safely
forward values from the settings object and lets the target constructor
handle all validation.

Added 64 new tests in ClientSettingsConstructorTests covering:
- GetClientSettings<T> binding from in-memory configuration
- Null settings throws ArgumentNullException for all 18 clients
- Valid settings constructs all 18 clients successfully
- Missing required fields (model, credential) throw appropriately
- Custom endpoint propagation through settings

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@m-nash

m-nash commented Feb 24, 2026

Copy link
Copy Markdown
Collaborator

@mokarchi mokarchi#4

Refactor settings constructors to delegate to existing ctors and add tests
@joseharriaga

Copy link
Copy Markdown
Collaborator

Hi, @mokarchi ! It looks like the API listings under the "api" folder are out of date. Could you re-run the .scripts/Export-Api script?

@mokarchi

Copy link
Copy Markdown
Contributor Author

Hi, @mokarchi ! It looks like the API listings under the "api" folder are out of date. Could you re-run the .scripts/Export-Api script?

I ran, but no changes were generated in the API files

Re-run ./scripts/Export-Api.ps1 to update the API listing files to match
the current GenAPI tooling output format used by the repo.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@m-nash

m-nash commented Feb 25, 2026

Copy link
Copy Markdown
Collaborator

@mokarchi mokarchi#5

Regenerate API surface files with Export-Api.ps1

@m-nash m-nash left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@joseharriaga mind taking one last look

@joseharriaga
joseharriaga merged commit 58dadcb into openai:main Feb 25, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants