Skip to content

Commit 3cd1b3f

Browse files
JeffreyCACopilot
andauthored
azure.ai.agents - filter out unsupported models and locations from init prompts (#7415)
* Filter out unsupported models and locations from init prompts Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR review feedback * Update go.mod/go.sum * Change requiredAzdVersion in extension.yaml Updated requiredAzdVersion to be greater than 1.23.13. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent a67ac9e commit 3cd1b3f

10 files changed

Lines changed: 478 additions & 61 deletions

File tree

cli/azd/extensions/azure.ai.agents/extension.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ description: Ship agents with Microsoft Foundry from your terminal. (Preview)
66
usage: azd ai agent <command> [options]
77
# NOTE: Make sure version.txt is in sync with this version.
88
version: 0.1.20-preview
9-
requiredAzdVersion: ">1.23.6"
9+
requiredAzdVersion: ">1.23.13"
1010
language: go
1111
capabilities:
1212
- custom-commands

cli/azd/extensions/azure.ai.agents/go.mod

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ require (
1010
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerregistry/armcontainerregistry v1.2.0
1111
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0
1212
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions v1.3.0
13-
github.com/azure/azure-dev/cli/azd v1.23.13
13+
github.com/azure/azure-dev/cli/azd v1.23.14
1414
github.com/braydonk/yaml v0.9.0
1515
github.com/drone/envsubst v1.0.3
1616
github.com/fatih/color v1.18.0
@@ -31,6 +31,9 @@ require (
3131
github.com/AlecAivazis/survey/v2 v2.3.7 // indirect
3232
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect
3333
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/appservice/armappservice/v2 v2.3.0 // indirect
34+
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault v1.5.0 // indirect
35+
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.4.0 // indirect
36+
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0 // indirect
3437
github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 // indirect
3538
github.com/Masterminds/semver/v3 v3.4.0 // indirect
3639
github.com/adam-lavrik/go-imath v0.0.0-20210910152346-265a42a96f0b // indirect
@@ -49,13 +52,15 @@ require (
4952
github.com/charmbracelet/x/cellbuf v0.0.15 // indirect
5053
github.com/charmbracelet/x/exp/slice v0.0.0-20260204111555-7642919e0bee // indirect
5154
github.com/charmbracelet/x/term v0.2.2 // indirect
55+
github.com/cli/browser v1.3.0 // indirect
5256
github.com/clipperhouse/displaywidth v0.9.0 // indirect
5357
github.com/clipperhouse/stringish v0.1.1 // indirect
5458
github.com/clipperhouse/uax29/v2 v2.5.0 // indirect
5559
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
5660
github.com/dlclark/regexp2 v1.11.5 // indirect
5761
github.com/go-logr/logr v1.4.3 // indirect
5862
github.com/go-logr/stdr v1.2.2 // indirect
63+
github.com/gofrs/flock v0.12.1 // indirect
5964
github.com/golang-jwt/jwt/v5 v5.3.1 // indirect
6065
github.com/golobby/container/v3 v3.3.2 // indirect
6166
github.com/gorilla/css v1.0.1 // indirect
@@ -95,6 +100,7 @@ require (
95100
go.opentelemetry.io/otel/sdk v1.42.0 // indirect
96101
go.opentelemetry.io/otel/trace v1.42.0 // indirect
97102
go.uber.org/atomic v1.11.0 // indirect
103+
go.uber.org/multierr v1.11.0 // indirect
98104
golang.org/x/crypto v0.48.0 // indirect
99105
golang.org/x/exp v0.0.0-20260112195511-716be5621a96 // indirect
100106
golang.org/x/net v0.51.0 // indirect

cli/azd/extensions/azure.ai.agents/go.sum

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,20 @@ github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerregistry/armconta
2323
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerregistry/armcontainerregistry v1.2.0/go.mod h1:E7ltexgRDmeJ0fJWv0D/HLwY2xbDdN+uv+X2uZtOx3w=
2424
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0 h1:PTFGRSlMKCQelWwxUyYVEUqseBJVemLyqWJjvMyt0do=
2525
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0/go.mod h1:LRr2FzBTQlONPPa5HREE5+RjSCTXl7BwOvYOaWTqCaI=
26+
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v3 v3.1.0 h1:2qsIIvxVT+uE6yrNldntJKlLRgxGbZ85kgtz5SNBhMw=
27+
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v3 v3.1.0/go.mod h1:AW8VEadnhw9xox+VaVd9sP7NjzOAnaZBLRH6Tq3cJ38=
28+
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault v1.5.0 h1:nnQ9vXH039UrEFxi08pPuZBE7VfqSJt343uJLw0rhWI=
29+
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault v1.5.0/go.mod h1:4YIVtzMFVsPwBvitCDX7J9sqthSj43QD1sP6fYc1egc=
2630
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/managementgroups/armmanagementgroups v1.0.0 h1:pPvTJ1dY0sA35JOeFq6TsY2xj6Z85Yo23Pj4wCCvu4o=
2731
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/managementgroups/armmanagementgroups v1.0.0/go.mod h1:mLfWfj8v3jfWKsL9G4eoBoXVcsqcIUTapmdKy7uGOp0=
2832
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 h1:Dd+RhdJn0OTtVGaeDLZpcumkIVCtA/3/Fo42+eoYvVM=
2933
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0/go.mod h1:5kakwfW5CjC9KK+Q4wjXAg+ShuIm2mBMua0ZFj2C8PE=
3034
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions v1.3.0 h1:wxQx2Bt4xzPIKvW59WQf1tJNx/ZZKPfN+EhPX3Z6CYY=
3135
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions v1.3.0/go.mod h1:TpiwjwnW/khS0LKs4vW5UmmT9OWcxaveS8U7+tlknzo=
36+
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.4.0 h1:/g8S6wk65vfC6m3FIxJ+i5QDyN9JWwXI8Hb0Img10hU=
37+
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.4.0/go.mod h1:gpl+q95AzZlKVI3xSoseF9QPrypk0hQqBiJYeB/cR/I=
38+
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0 h1:nCYfgcSyHZXJI8J0IWE5MsCGlb2xp9fJiXyxWgmOFg4=
39+
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0/go.mod h1:ucUjca2JtSZboY8IoUqyQyuuXvwbMBVwFOm0vdQPNhA=
3240
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM=
3341
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE=
3442
github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 h1:XRzhVemXdgvJqCH0sFfrBUTnUJSBrBf7++ypk+twtRs=
@@ -51,8 +59,8 @@ github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWp
5159
github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA=
5260
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
5361
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
54-
github.com/azure/azure-dev/cli/azd v1.23.13 h1:KVPI0JvIMBblO9WJnrnOM//TwIYSTFIAwkSX+Y79hjQ=
55-
github.com/azure/azure-dev/cli/azd v1.23.13/go.mod h1:skXbQLtJw3iu4ZchM0sDc5bG/KKTG2aVdOIv3cn+g9w=
62+
github.com/azure/azure-dev/cli/azd v1.23.14 h1:yfmEPu3T+FqFuHhHHX9gEc+yflAu0k1aDOkN00HlFzo=
63+
github.com/azure/azure-dev/cli/azd v1.23.14/go.mod h1:mS/n9XZcwRrTaDcFxWFfgcsmB6AuuTNarB2IDCS5QzI=
5664
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
5765
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
5866
github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o=
@@ -85,6 +93,8 @@ github.com/charmbracelet/x/exp/slice v0.0.0-20260204111555-7642919e0bee h1:B/JPE
8593
github.com/charmbracelet/x/exp/slice v0.0.0-20260204111555-7642919e0bee/go.mod h1:vqEfX6xzqW1pKKZUUiFOKg0OQ7bCh54Q2vR/tserrRA=
8694
github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
8795
github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI=
96+
github.com/cli/browser v1.3.0 h1:LejqCrpWr+1pRqmEPDGnTZOjsMe7sehifLynZJuqJpo=
97+
github.com/cli/browser v1.3.0/go.mod h1:HH8s+fOAxjhQoBUAsKuPCbqUuxZDhQ2/aD+SzsEfBTk=
8898
github.com/clipperhouse/displaywidth v0.9.0 h1:Qb4KOhYwRiN3viMv1v/3cTBlz3AcAZX3+y9OLhMtAtA=
8999
github.com/clipperhouse/displaywidth v0.9.0/go.mod h1:aCAAqTlh4GIVkhQnJpbL0T/WfcrJXHcj8C0yjYcjOZA=
90100
github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs=
@@ -112,6 +122,8 @@ github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
112122
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
113123
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
114124
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
125+
github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E=
126+
github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0=
115127
github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
116128
github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY=
117129
github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
@@ -249,6 +261,8 @@ go.opentelemetry.io/otel/trace v1.42.0 h1:OUCgIPt+mzOnaUTpOQcBiM/PLQ/Op7oq6g4Len
249261
go.opentelemetry.io/otel/trace v1.42.0/go.mod h1:f3K9S+IFqnumBkKhRJMeaZeNk9epyhnCmQh/EysQCdc=
250262
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
251263
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
264+
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
265+
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
252266
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
253267
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
254268
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=

cli/azd/extensions/azure.ai.agents/internal/cmd/init.go

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,40 @@ type InitAction struct {
5959
//azureClient *azure.AzureClient
6060
azureContext *azdext.AzureContext
6161
//composedResources []*azdext.ComposedResource
62-
console input.Console
63-
credential azcore.TokenCredential
62+
console input.Console
63+
credential azcore.TokenCredential
64+
projectConfig *azdext.ProjectConfig
65+
environment *azdext.Environment
66+
flags *initFlags
67+
models *modelSelector
68+
69+
deploymentDetails []project.Deployment
70+
httpClient *http.Client
71+
}
72+
73+
// modelSelector encapsulates the dependencies needed for model selection and
74+
// deployment resolution during init. It avoids constructing partial InitAction
75+
// structs when only the model-selection call chain is needed.
76+
type modelSelector struct {
77+
azdClient *azdext.AzdClient
78+
azureContext *azdext.AzureContext
79+
environment *azdext.Environment
80+
flags *initFlags
81+
6482
modelCatalog map[string]*azdext.AiModel
6583
locationWarningShown bool
66-
projectConfig *azdext.ProjectConfig
67-
environment *azdext.Environment
68-
flags *initFlags
69-
deploymentDetails []project.Deployment
70-
httpClient *http.Client
84+
}
85+
86+
func (a *InitAction) getModelSelector() *modelSelector {
87+
if a.models == nil {
88+
a.models = &modelSelector{
89+
azdClient: a.azdClient,
90+
azureContext: a.azureContext,
91+
environment: a.environment,
92+
flags: a.flags,
93+
}
94+
}
95+
return a.models
7196
}
7297

7398
// GitHubUrlInfo holds parsed information from a GitHub URL
@@ -79,6 +104,7 @@ type GitHubUrlInfo struct {
79104
}
80105

81106
const AiAgentHost = "azure.ai.agent"
107+
const agentsV2ModelCapability = "agentsV2"
82108

83109
// checkAiModelServiceAvailable is a temporary check to ensure the azd host supports
84110
// required gRPC services. Remove once azd core enforces requiredAzdVersion.

cli/azd/extensions/azure.ai.agents/internal/cmd/init_foundry_resources_helpers.go

Lines changed: 110 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerregistry/armcontainerregistry"
1919
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources"
2020
"github.com/azure/azure-dev/cli/azd/pkg/azdext"
21+
"github.com/azure/azure-dev/cli/azd/pkg/output"
2122
"github.com/azure/azure-dev/cli/azd/pkg/ux"
2223
"google.golang.org/grpc/codes"
2324
"google.golang.org/grpc/status"
@@ -734,23 +735,27 @@ func ensureLocation(
734735
azureContext *azdext.AzureContext,
735736
envName string,
736737
) error {
737-
if azureContext.Scope.Location != "" {
738+
allowedLocations := supportedRegionsForInit()
739+
740+
if azureContext.Scope.Location != "" && locationAllowed(azureContext.Scope.Location, allowedLocations) {
738741
return nil
739742
}
743+
if azureContext.Scope.Location != "" {
744+
fmt.Printf("%s", output.WithWarningFormat(
745+
"The current AZURE_LOCATION '%s' is not supported for this agent setup. Please choose a different location.\n",
746+
azureContext.Scope.Location,
747+
))
748+
azureContext.Scope.Location = ""
749+
}
740750

741751
fmt.Println("Select an Azure location. This determines which models are available and where your Foundry project resources will be deployed.")
742752

743-
locationResponse, err := azdClient.Prompt().PromptLocation(ctx, &azdext.PromptLocationRequest{
744-
AzureContext: azureContext,
745-
})
753+
locationName, err := promptLocationForInit(ctx, azdClient, azureContext, allowedLocations)
746754
if err != nil {
747-
if exterrors.IsCancellation(err) {
748-
return exterrors.Cancelled("location selection was cancelled")
749-
}
750-
return exterrors.FromPrompt(err, "failed to prompt for location")
755+
return err
751756
}
752757

753-
azureContext.Scope.Location = locationResponse.Location.Name
758+
azureContext.Scope.Location = locationName
754759

755760
return setEnvValue(ctx, azdClient, envName, "AZURE_LOCATION", azureContext.Scope.Location)
756761
}
@@ -776,6 +781,57 @@ func ensureSubscriptionAndLocation(
776781
return newCredential, nil
777782
}
778783

784+
func normalizeLocationName(location string) string {
785+
return strings.TrimSpace(strings.ToLower(location))
786+
}
787+
788+
func locationAllowed(location string, allowedLocations []string) bool {
789+
if len(allowedLocations) == 0 {
790+
return true
791+
}
792+
793+
normalized := normalizeLocationName(location)
794+
return slices.ContainsFunc(allowedLocations, func(allowed string) bool {
795+
return normalized == normalizeLocationName(allowed)
796+
})
797+
}
798+
799+
func promptLocationForInit(
800+
ctx context.Context,
801+
azdClient *azdext.AzdClient,
802+
azureContext *azdext.AzureContext,
803+
allowedLocations []string,
804+
) (string, error) {
805+
locationResponse, err := azdClient.Prompt().PromptLocation(ctx, &azdext.PromptLocationRequest{
806+
AzureContext: azureContext,
807+
AllowedLocations: allowedLocations,
808+
})
809+
if err != nil {
810+
if exterrors.IsCancellation(err) {
811+
return "", exterrors.Cancelled("location selection was cancelled")
812+
}
813+
return "", exterrors.FromPrompt(err, "failed to prompt for location")
814+
}
815+
816+
return locationResponse.Location.Name, nil
817+
}
818+
819+
func agentModelFilter(locations []string, excludeModelNames []string) *azdext.AiModelFilterOptions {
820+
filter := &azdext.AiModelFilterOptions{
821+
Capabilities: []string{agentsV2ModelCapability},
822+
}
823+
824+
if len(locations) > 0 {
825+
filter.Locations = locations
826+
}
827+
828+
if len(excludeModelNames) > 0 {
829+
filter.ExcludeModelNames = excludeModelNames
830+
}
831+
832+
return filter
833+
}
834+
779835
// --- Shared model helpers ---
780836

781837
// selectNewModel prompts the user to select a model from the AI catalog, filtered by location.
@@ -793,15 +849,13 @@ func selectNewModel(
793849

794850
promptReq := &azdext.PromptAiModelRequest{
795851
AzureContext: azureContext,
852+
Filter: agentModelFilter([]string{azureContext.Scope.Location}, nil),
796853
SelectOptions: &azdext.SelectOptions{
797854
Message: "Select a model",
798855
},
799856
Quota: &azdext.QuotaCheckOptions{
800857
MinRemainingCapacity: 1,
801858
},
802-
Filter: &azdext.AiModelFilterOptions{
803-
Locations: []string{azureContext.Scope.Location},
804-
},
805859
DefaultValue: defaultModel,
806860
}
807861

@@ -813,16 +867,15 @@ func selectNewModel(
813867
return modelResp.Model, nil
814868
}
815869

816-
// resolveModelDeployment resolves a model deployment without prompting, selecting the best
817-
// candidate based on default versions, SKU priority, and available quota. Both init flows
818-
// use this for the "deploy new model" path in non-interactive mode.
819-
func resolveModelDeployment(
870+
// resolveModelDeployments resolves model deployments without prompting, returning all candidates
871+
// filtered by location and quota. Both init flows use this for deployment resolution.
872+
func resolveModelDeployments(
820873
ctx context.Context,
821874
azdClient *azdext.AzdClient,
822875
azureContext *azdext.AzureContext,
823876
model *azdext.AiModel,
824877
location string,
825-
) (*azdext.AiModelDeployment, error) {
878+
) ([]*azdext.AiModelDeployment, error) {
826879
resolveResp, err := azdClient.Ai().ResolveModelDeployments(ctx, &azdext.ResolveModelDeploymentsRequest{
827880
AzureContext: azureContext,
828881
ModelName: model.Name,
@@ -834,19 +887,22 @@ func resolveModelDeployment(
834887
},
835888
})
836889
if err != nil {
837-
return nil, exterrors.FromAiService(err, exterrors.CodeModelResolutionFailed)
890+
return nil, err
838891
}
839892

840-
if len(resolveResp.Deployments) == 0 {
841-
return nil, exterrors.Dependency(
842-
exterrors.CodeModelResolutionFailed,
843-
fmt.Sprintf("no deployment candidates found for model '%s' in location '%s'", model.Name, location),
844-
"",
845-
)
893+
return resolveResp.Deployments, nil
894+
}
895+
896+
func selectBestModelDeploymentCandidate(
897+
model *azdext.AiModel,
898+
deployments []*azdext.AiModelDeployment,
899+
) *azdext.AiModelDeployment {
900+
if len(deployments) == 0 {
901+
return nil
846902
}
847903

848-
orderedCandidates := make([]*azdext.AiModelDeployment, len(resolveResp.Deployments))
849-
copy(orderedCandidates, resolveResp.Deployments)
904+
orderedCandidates := make([]*azdext.AiModelDeployment, len(deployments))
905+
copy(orderedCandidates, deployments)
850906

851907
defaultVersions := make(map[string]struct{}, len(model.Versions))
852908
for _, version := range model.Versions {
@@ -863,7 +919,34 @@ func resolveModelDeployment(
863919
continue
864920
}
865921

866-
return cloneDeploymentWithCapacity(candidate, capacity), nil
922+
return cloneDeploymentWithCapacity(candidate, capacity)
923+
}
924+
925+
return nil
926+
}
927+
928+
func resolveModelDeployment(
929+
ctx context.Context,
930+
azdClient *azdext.AzdClient,
931+
azureContext *azdext.AzureContext,
932+
model *azdext.AiModel,
933+
location string,
934+
) (*azdext.AiModelDeployment, error) {
935+
deployments, err := resolveModelDeployments(ctx, azdClient, azureContext, model, location)
936+
if err != nil {
937+
return nil, exterrors.FromAiService(err, exterrors.CodeModelResolutionFailed)
938+
}
939+
940+
if len(deployments) == 0 {
941+
return nil, exterrors.Dependency(
942+
exterrors.CodeModelResolutionFailed,
943+
fmt.Sprintf("no deployment candidates found for model '%s' in location '%s'", model.Name, location),
944+
"",
945+
)
946+
}
947+
948+
if candidate := selectBestModelDeploymentCandidate(model, deployments); candidate != nil {
949+
return candidate, nil
867950
}
868951

869952
return nil, fmt.Errorf("no deployment candidates found for model '%s' with a valid non-interactive capacity", model.Name)

0 commit comments

Comments
 (0)