Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cli/azd/extensions/azure.ai.finetune/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# `azd` Demo Extension
# `azd` Finetune Extension

An AZD Demo extension
An AZD Finetune extension
15 changes: 15 additions & 0 deletions cli/azd/extensions/azure.ai.finetune/internal/cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,15 @@ func ensureEnvironment(ctx context.Context, flags *initFlags, azdClient *azdext.
return nil, fmt.Errorf("failed to set AZURE_ACCOUNT_NAME in azd environment: %w", err)
}

_, err = azdClient.Environment().SetValue(ctx, &azdext.SetEnvRequest{
EnvName: existingEnv.Name,
Key: "AZURE_PROJECT_NAME",
Value: foundryProject.AiProjectName,
})
if err != nil {
return nil, fmt.Errorf("failed to set AZURE_PROJECT_NAME in azd environment: %w", err)
}

_, err = azdClient.Environment().SetValue(ctx, &azdext.SetEnvRequest{
EnvName: existingEnv.Name,
Key: "AZURE_LOCATION",
Expand Down Expand Up @@ -513,6 +522,12 @@ func ensureAzureContext(
Value: fpDetails.AiAccountName,
})

_, err = azdClient.Environment().SetValue(ctx, &azdext.SetEnvRequest{
EnvName: env.Name,
Key: "AZURE_PROJECT_NAME",
Value: fpDetails.AiProjectName,
})

location := *projectResp.Location

// Set the location in the environment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,28 @@ package factory
import (
"context"
"fmt"
"net/http"

"azure.ai.finetune/internal/providers"
azureprovider "azure.ai.finetune/internal/providers/azure"
openaiprovider "azure.ai.finetune/internal/providers/openai"
"azure.ai.finetune/internal/utils"
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/cognitiveservices/armcognitiveservices"
"github.com/azure/azure-dev/cli/azd/pkg/azdext"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/azure"
"github.com/openai/openai-go/v3/option"
)

const (
// OpenAI API version for Azure cognitive services
apiVersion = "2025-04-01-preview"
DefaultApiVersion = "2025-11-15-preview"
// Azure cognitive services endpoint URL pattern
azureCognitiveServicesEndpoint = "https://%s.cognitiveservices.azure.com/openai"
DefaultCognitiveServicesEndpoint = "https://%s.services.ai.azure.com/api/projects/%s"
DefaultAzureFinetuningScope = "https://ai.azure.com/.default"
)

func GetOpenAIClientFromAzdClient(ctx context.Context, azdClient *azdext.AzdClient) (*openai.Client, error) {
Expand Down Expand Up @@ -53,17 +56,57 @@ func GetOpenAIClientFromAzdClient(ctx context.Context, azdClient *azdext.AzdClie
// Get Azure credentials and endpoint - TODO
// You'll need to get these from your environment or config
accountName := envValueMap[utils.EnvAzureAccountName]
endpoint := fmt.Sprintf(azureCognitiveServicesEndpoint, accountName)
projectName := envValueMap[utils.EnvAzureOpenAIProjectName]
endpoint := envValueMap[utils.EnvFinetuningRoute]
if endpoint == "" {
endpoint = fmt.Sprintf(DefaultCognitiveServicesEndpoint, accountName, projectName)
}

apiVersion := envValueMap[utils.EnvAPIVersion]
if apiVersion == "" {
apiVersion = DefaultApiVersion
}

scope := envValueMap[utils.EnvFineturningTokenScope]
if scope == "" {
scope = DefaultAzureFinetuningScope
}
// Create OpenAI client
client := openai.NewClient(
//azure.WithEndpoint(endpoint, apiVersion),
option.WithBaseURL(endpoint),
option.WithQuery("api-version", apiVersion),
azure.WithTokenCredential(credential),
WithTokenCredential(credential, scope),
)
return &client, nil
}

// WithTokenCredential configures this client to authenticate using an [Azure Identity] TokenCredential.
// This function should be paired with a call to [WithEndpoint] to point to your Azure OpenAI instance.
//
// [Azure Identity]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity
func WithTokenCredential(tokenCredential azcore.TokenCredential, scope string) option.RequestOption {
bearerTokenPolicy := runtime.NewBearerTokenPolicy(tokenCredential, []string{scope}, nil)
// add in a middleware that uses the bearer token generated from the token credential
return option.WithMiddleware(func(req *http.Request, next option.MiddlewareNext) (*http.Response, error) {
pipeline := runtime.NewPipeline("azopenai-extensions", version, runtime.PipelineOptions{}, &policy.ClientOptions{
InsecureAllowCredentialWithHTTP: true, // allow for plain HTTP proxies, etc..
PerRetryPolicies: []policy.Policy{
bearerTokenPolicy,
policyAdapter(next),
},
})

req2, err := runtime.NewRequestFromRequest(req)

if err != nil {
return nil, err
}

return pipeline.Do(req2)
})
}

// NewFineTuningProvider creates a FineTuningProvider based on provider type
func NewFineTuningProvider(ctx context.Context, azdClient *azdext.AzdClient) (providers.FineTuningProvider, error) {
client, err := GetOpenAIClientFromAzdClient(ctx, azdClient)
Expand All @@ -82,3 +125,11 @@ func NewModelDeploymentProvider(subscriptionId string, credential azcore.TokenCr
}
return azureprovider.NewAzureProvider(clientFactory), err
}

type policyAdapter option.MiddlewareNext

func (mp policyAdapter) Do(req *policy.Request) (*http.Response, error) {
return (option.MiddlewareNext)(mp)(req.Raw())
}

const version = "v.0.1.0"
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@ import (
)

const (
EnvAzureTenantID = "AZURE_TENANT_ID"
EnvAzureSubscriptionID = "AZURE_SUBSCRIPTION_ID"
EnvAzureLocation = "AZURE_LOCATION"
EnvAzureAccountName = "AZURE_ACCOUNT_NAME"
EnvAzureTenantID = "AZURE_TENANT_ID"
EnvAzureSubscriptionID = "AZURE_SUBSCRIPTION_ID"
EnvAzureLocation = "AZURE_LOCATION"
EnvAzureAccountName = "AZURE_ACCOUNT_NAME"
EnvAzureOpenAIProjectName = "AZURE_PROJECT_NAME"
EnvAPIVersion = "AZURE_API_VERSION"
EnvFinetuningRoute = "AZURE_FINETUNING_ROUTE"
EnvFineturningTokenScope = "AZURE_FINETUNING_TOKEN_SCOPE"
)

// GetEnvironmentValues retrieves Azure environment configuration from azd client.
Expand Down
Loading