Skip to content

fix for wrong OpenAIClientOptions used with keyed OpenAIClient(s) - #11003

Merged
Eric Erhardt (eerhardt) merged 3 commits into
microsoft:mainfrom
Steinblock:main
Aug 19, 2025
Merged

fix for wrong OpenAIClientOptions used with keyed OpenAIClient(s)#11003
Eric Erhardt (eerhardt) merged 3 commits into
microsoft:mainfrom
Steinblock:main

Conversation

@Steinblock

@SteinblockJürgen Steinblock (Steinblock) commented Aug 18, 2025

Copy link
Copy Markdown
Contributor

with keyed OpenAIClients

builder.AddKeyedOpenAIClient("openai");
builder.AddKeyedOpenAIClient("ionos");

assuming that at least one keyed OpenAIClient has a differnt endpoint,

{
"ConnectionStrings": {
"openai": "Key={account_key};"
"ionos": "Endpoint=https://{openai_rest_api_url};Key={account_key};"
}
}

getting the client with

var client = serviceProvider.GetRequiredKeyedService<OpenAIClient>("ionos")

the client uses the key from the connectionstring but it still has the default enpoint https://api.openai.com/v1

The issue is that ConfigureOpenAI ignores the serviceKey and always get's the default OpenAIClientOptions instead of the one created with optionsName = servicekey.

This makes using keyed OpenAIClients virtually impossible because the main reason having multiple OpenAIClients is having different endpoints.

Description

Please include a summary of the changes and the related issue. Please also include relevant motivation and context. List any dependencies that are required for this change.

Fixes # (issue)

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No
  • Did you add public API?
    • Yes
      • If yes, did you have an API Review for it?
        • Yes
        • No
      • Did you add <remarks /> and <code /> elements on your triple slash comments?
        • Yes
        • No
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
      • If yes, have you done a threat model and had a security review?
        • Yes
        • No
    • No
  • Does the change require an update in our Aspire docs?

with keyed OpenAIClients
```
builder.AddKeyedOpenAIClient("openai");
builder.AddKeyedOpenAIClient("ionos");
```
assuming that at least one keyed OpenAIClient has a differnt endpoint,
```
{
"ConnectionStrings": {
"openai": "Key={account_key};"
"ionos": "Endpoint=https://{openai_rest_api_url};Key={account_key};"
}
}
```
getting the client with
```
var client = serviceProvider.GetRequiredKeyedService<OpenAIClient>("ionos")
```
the client uses the key from the connectionstring but it still has the default enpoint https://api.openai.com/v1
The issue is that ConfigureOpenAI ignores the serviceKey and always get's the default OpenAIClientOptions instead of the one created with optionsName = servicekey.
This makes using keyed OpenAIClients virtually impossible because the main reason having multiple OpenAIClients is having different endpoints.
@github-actionsgithub-actionsBot added the area-integrations Issues pertaining to Aspire Integrations packages label Aug 18, 2025
@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label Aug 18, 2025
@Steinblock

Copy link
Copy Markdown
ContributorAuthor

@dotnet-policy-service agree

@eerhardt

Copy link
Copy Markdown
Member

Can you add tests for this?

@Kumima

Copy link
Copy Markdown
Contributor

Fixing #9543
Is this better? And did you take a look at the azure related stuff?

options=serviceProvider.GetRequiredService<IOptionsMonitor<OpenAIClientOptions>>().Get(serviceKey??Options.DefaultName);

According to: openai/openai-dotnet#215
Tests can be tricky using reflection.

@Steinblock

Copy link
Copy Markdown
ContributorAuthor

Eric Erhardt (@eerhardt) I added a test case that is failing without my changes and passing afterwards.

As Kumima (@Kumima) mentioned, testing this is tricky because OpenAIClient doesn't expose the endpoint.

I don't really like the test because I usually only test the public interface of a class but I could not figure out how to workaround this so I opted for using reflection to get the endpoint.

Kumima (@Kumima)

This would work as well.

var options = serviceProvider
.GetRequiredService<IOptionsMonitor<OpenAIClientOptions>>()
.Get(serviceKey ?? Options.Options.DefaultName);

@eerhardtEric Erhardt (eerhardt) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM. Thanks for the fix!

@eerhardt
Eric Erhardt (eerhardt) merged commit 79d4eed into microsoft:mainAug 19, 2025
292 checks passed
@dotnet-policy-servicedotnet-policy-serviceBot added this to the 9.5 milestone Aug 19, 2025
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Sep 19, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-integrationsIssues pertaining to Aspire Integrations packagescommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@Steinblock@eerhardt@Kumima