providers/azure.ps1
<#
Azure OpenAI Powershai Provider Este arquivo implementa o provider do Azure OpenAI. Link úteis: - https://ai.azure.com/ - https://learn.microsoft.com/en-us/azure/ai-services/openai/reference - Latest GA APIs: https://learn.microsoft.com/en-us/azure/ai-services/openai/reference#api-specs - https://learn.microsoft.com/en-us/azure/ai-services/openai/api-version-deprecation A API do Azure OpenAI difere um pouco da OpenAI base devido ao formato da URL. Na OpenAI, a url é fixa, mudando apenas o token. No Azure OpenAI, a URL depende de nomes configurados pelo usuário. POST https://YOUR_RESOURCE_NAME.openai.azure.com/openai/deployments/YOUR_DEPLOYMENT_NAME/completions?api-version=2024-06-01 Variaveis que precisamos: - ResourceName - DeploymentName - ApiVersion TAmbém, além da autenticação por API Key, há a autenticação usando EntraID. Nesta primeira versão, não iremos implementar autenticação por EntraID. Também, para não conflitar com o módulo powershell oficial do Azure, que costuma ter comandos Az*, Azure*, iremos usar o nomes no formato AiAzure* #> <# .DESCRIPTION Configura as credenciais para acesso ao LLMs disponíveis em assinaturas do Azure Você deve fornecer, além do token, algumas informações adicionais requeridas pelo azure. Veja abaixo para entender. No Azure, basicamente, existem 2 tipos de URL que iremos usar: - URLs específicas do serviço Azure OpenAI, que contém os modelos OpenAI - URLs compatíveis com OpenAI, para outros modelos open source, como llama, phi3, etc. O primeiro caso é o formato de URL disponibilizado quando se usa um serviço Azure OpenAI. Ele geralmente possui esse formato de URL: https://<RESOURCE-NAME>.openai.azure.com/openai/deployments/DEPLOYMENT-NAME/chat/completions?api-version=API-VERSION Essas URLS dão acesso à API do Azure OpenAI, e são exclusivas para apenas estes deployments de serviços do tipo "Azure OpenAI". O segundo caso de URLs disponibilizadas pelo Azure, são essas que dão acesso Inference API do Azure. Essas URLs são geradas quando se faz o deploy de modelos da comunidade ou de outras empreas que não sejam a OpenaI. Exemplos: phi3, llama, qwen, etc. O formato é: https://DEPLOYMENT-NAME.REGIAO.models.ai.azure.com Ambas as URLs implementam o mesmo padrão de comunicação da API da OpenAI, isto é, possui um endpoint /chat/completions, etc. Porém, dependendo do tipo, há mais elementos que precisam ser configurados na URl, e por isso, é importante determinar o formato correto usado. Este cmdlet detecta automaticamente o formato e faz as configurações necessárioas. Ainda sim, é possível especificar estas informacoes separadamente, se precisar. Veja a documentação dos parâmetros para mais detalhes. Este comando aceita ambos estes formatos e, conforme o formato, ele irá configurar as chamadas da OpenAI corretamente. .LINK # Aprenda mais como funciona a API e os modelos no Azure https://learn.microsoft.com/en-us/azure/machine-learning/concept-model-catalog .LINK # Sobre a API de Inferência https://learn.microsoft.com/en-us/azure/machine-learning/reference-model-inference-api?view=azureml-api-2&tabs=pythonm #> function azure_SetCredential { param( $AiCredential ,#Nome do resource onde foi criado. Esta informação pode ser obtida no portal #Ou, pode ser uma url. Dependendo do formato, serão extraído as informações necessárias. #VOcê pode usar qualquer URL que foi gerada no portal ou no AI Studio e colar aqui que os elementos identificados serão extraídos. #Se um parâmetro obrigatório não for encontrado, um erro será retornado. #Se não informado, usa o atual preivamente configurado! [Alias('url')] $ResourceName ,#Nome do deployment (configurado no portal ou azure ai studio) #Se não informado, usa o atual preivamente configurado! $DeploymentName ,#Versão da API a ser usada #Se não informado, usa o atual preivamente configurado! $ApiVersion = "2024-06-01" ,#Força mudar a API key [switch]$ChangeApiKey ) $UrlType = "AzureOpenai" if($ResourceName -match '^https:'){ $ParsedUrl = [uri]$ResourceName if(!$ParsedUrl.Host){ throw "POWERSHAI_AZUREOPENAI_INVALID_URL: $ResourceName"; } switch -Regex ($ParsedUrl.Host){ "([^\.]+)\.openai.azure.com" { $UrlType = "AzureOpenai"; $ResourceName = $matches[1]; if($ParsedUrl.PathAndQuery -match 'deployments/(.+?)/'){ $DeploymentName = $matches[1]; } if($ParsedUrl.PathAndQuery -match 'api-version=(\d{4}-\d{2}-\d{2}(-preview)?)'){ $ApiVersion = $matches[1] } } '\.models\.ai\.azure\.com$' { $UrlType = "AzureInferenceApi"; $BaseUrl = $ResourceName } default { throw "POWERSHAI_AZUREOPENAI_INVALID_URL_DOMAIN: $Domain. Expected *.openai.azure.com,*.models.azure.com, FullUrl = $ResourceName" } } } $TempCred = NewAiCredential $TempCred.credential = HashTableMerge $AiCredential.old.credential @{ ResourceName = $ResourceName DeploymentName = $DeploymentName ApiVersion = $ApiVersion UrlType = $UrlType BaseUrl = $BaseUrl ApiKey = $ApiKey } -filter { param($k) $k.new -ne $null } $CredApiKey = $TempCred.credential.ApiKey; verbose "TempCredInfo:`n$($TempCred.credential|out-string)" if(!$CredApiKey -or $ChangeApiKey){ $Creds = Get-Credential "Azure Api key" $TempCred.credential.ApiKey = $Creds.GetNetworkCredential().Password; } Enter-AiCredential $TempCred { $null = Get-AiModels } $AiCredential.credential = $TempCred.credential; } Set-Alias Set-OpenaiToken openai_SetCredential <# .SYNOPSIS Obtém informacoes do modelo. Mesmo retorno do endpoint /info da API de Inferência do Azure. .DESCRIPTION Este endpoint funciona somente com urls compativeis com a API de Inferência do Azure. #> function Get-AiAzureApiInfo { InvokeOpenai 'info' -method GET } # Used to change request! function OpenaiAzureChangeRequest { param($Req, $OriginalParams) verbose "Changing ApiRequest"; $Credential = (Get-AiDefaultCredential).credential.credential $ResourceName = $Credential.ResourceName; $DeploymentName = $Credential.DeploymentName $ApiVersion = $Credential.ApiVersion $UrlType = $Credential.UrlType; $BaseUrl = $Credential.BaseUrl; $ApiKey = $Credential.ApiKey; if($UrlType -eq "AzureInferenceApi"){ $TokenHeader = "Authorization"; if(!$BaseUrl){ throw "POWERSHAI_AZURE_HTTPREQ_NOBASEURL"; } } else { $TokenHeader = "api-key"; } $Req.headers[$TokenHeader] = $ApiKey $Endpoint = $OriginalParams.bound.endpoint; switch -Regex ($Endpoint){ "^(models|info)$" { if($UrlType -eq "AzureInferenceApi"){ $Req.url = "$BaseUrl/info" } else { $Req.url = "https://$ResourceName.openai.azure.com/openai/models?api-version=2024-06-01" } } '^chat/completions$' { if($UrlType -eq "AzureInferenceApi"){ $Req.url = "$BaseUrl/v1/chat/completions" } else { $Req.url = "https://$ResourceName.openai.azure.com/openai/deployments/$DeploymentName/chat/completions?api-version=2024-06-01" } } '^https?:' { verbose "IsHttp endpoint. Nothing to do..."; } default { throw "POWERSHAI_AZUREOPENAI_ENDPOINT_NOTSUPPORTED: $Endpoint"; } } } function azure_FormatPrompt { param($model) return "🔵☁️ $($model): " } function azure_GetModels { $UrlData = GetCurrentProviderData -Context UrlData; if($UrlData.UrlType -eq "AzureInferenceApi"){ $info = Get-AiAzureApiInfo $info | Add-Member -Type AliasProperty -Name name -Value "model_name" return $info } openai_GetModels; } function azure_Chat { $RawParams = $ProviderFuncRawData.params; $UrlData = GetCurrentProviderData -Context UrlData; if($UrlData.UrlType -eq "AzureInferenceApi"){ $RawParams.Remove('Functions'); } $RawParams.model = "-"; openai_Chat @RawParams } return @{ RequireToken = $false TokenEnvName = "AZURE_OPENAI_API_KEY" info = @{ desc = "AzureOpenAI " url = "https://learn.microsoft.com/en-us/azure/ai-services/openai/overview" } # Req changer ReqChanger = (Get-Command OpenaiAzureChangeRequest) #Assume every openai model support tools. ToolsModels = "gpt-4*","o1-*" IsOpenaiCompatible = $true } |