Skip to content

Commit

Permalink
[24.x][Copilot] Add authorization interface for managed resources + U…
Browse files Browse the repository at this point in the history
…se managed deployment instead of deployment when setting first party authorization (#1294)

<!-- Thank you for submitting a Pull Request. If you're new to
contributing to BCApps please read our pull request guideline below
* https://github.com/microsoft/BCApps/Contributing.md
-->
#### Summary <!-- Provide a general summary of your changes -->
Cherry-picks [[Copilot] Add authorization interface for managed
resources](a78f587)
and [[Copilot] Use managed deployment instead of deployment when setting
first party
authorization](6daca64)
and [[Copilot] First party authorization throws error when checking if
configured](#1295)

#### Work Item(s) <!-- Add the issue number here after the #. The issue
needs to be open and approved. Submitting PRs with no linked issues or
unapproved issues is highly discouraged. -->
Fixes
[AB#537820](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/537820)
  • Loading branch information
encimita authored Jun 25, 2024
1 parent de30eb3 commit ea642f9
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ codeunit 7767 "AOAI Authorization"
Deployment: Text;
[NonDebuggable]
ApiKey: SecretText;
[NonDebuggable]
ManagedResourceDeployment: Text;
ResourceUtilization: Enum "AOAI Resource Utilization";

[NonDebuggable]
procedure IsConfigured(CallerModule: ModuleInfo): Boolean
Expand All @@ -32,27 +35,50 @@ codeunit 7767 "AOAI Authorization"
begin
NavApp.GetCurrentModuleInfo(CurrentModule);

if Deployment = '' then
exit(false);
case ResourceUtilization of
Enum::"AOAI Resource Utilization"::"First Party":
exit((ManagedResourceDeployment <> '') and ALCopilotFunctions.IsPlatformAuthorizationConfigured(CallerModule.Publisher(), CurrentModule.Publisher()));
Enum::"AOAI Resource Utilization"::"Self-Managed":
exit((Deployment <> '') and (Endpoint <> '') and (not ApiKey.IsEmpty()));
Enum::"AOAI Resource Utilization"::"Microsoft Managed":
exit((Deployment <> '') and (Endpoint <> '') and (not ApiKey.IsEmpty()) and (ManagedResourceDeployment <> '') and AzureOpenAiImpl.IsTenantAllowlistedForFirstPartyCopilotCalls());
end;

if (Endpoint = '') and ApiKey.IsEmpty() then
exit(AzureOpenAiImpl.IsTenantAllowlistedForFirstPartyCopilotCalls()
or ALCopilotFunctions.IsPlatformAuthorizationConfigured(CallerModule.Publisher(), CurrentModule.Publisher()));
exit(false);
end;

if (Endpoint = '') or ApiKey.IsEmpty() then
exit(false);
[NonDebuggable]
procedure SetMicrosoftManagedAuthorization(NewEndpoint: Text; NewDeployment: Text; NewApiKey: SecretText; NewManagedResourceDeployment: Text)
begin
ClearVariables();

exit(true);
ResourceUtilization := Enum::"AOAI Resource Utilization"::"Microsoft Managed";
Endpoint := NewEndpoint;
Deployment := NewDeployment;
ApiKey := NewApiKey;
ManagedResourceDeployment := NewManagedResourceDeployment;
end;

[NonDebuggable]
procedure SetAuthorization(NewEndpoint: Text; NewDeployment: Text; NewApiKey: SecretText)
procedure SetSelfManagedAuthorization(NewEndpoint: Text; NewDeployment: Text; NewApiKey: SecretText)
begin
ClearVariables();

ResourceUtilization := Enum::"AOAI Resource Utilization"::"Self-Managed";
Endpoint := NewEndpoint;
Deployment := NewDeployment;
ApiKey := NewApiKey;
end;

[NonDebuggable]
procedure SetFirstPartyAuthorization(NewDeployment: Text)
begin
ClearVariables();

ResourceUtilization := Enum::"AOAI Resource Utilization"::"First Party";
ManagedResourceDeployment := NewDeployment;
end;

[NonDebuggable]
procedure GetEndpoint(): SecretText
begin
Expand All @@ -70,4 +96,24 @@ codeunit 7767 "AOAI Authorization"
begin
exit(ApiKey);
end;

[NonDebuggable]
procedure GetManagedResourceDeployment(): SecretText
begin
exit(ManagedResourceDeployment);
end;

procedure GetResourceUtilization(): Enum "AOAI Resource Utilization"
begin
exit(ResourceUtilization);
end;

local procedure ClearVariables()
begin
Clear(Endpoint);
Clear(ApiKey);
Clear(Deployment);
Clear(ManagedResourceDeployment);
Clear(ResourceUtilization);
end;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// ------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// ------------------------------------------------------------------------------------------------
namespace System.AI;

/// <summary>
/// The supported utilization models for Azure OpenAI resources.
/// </summary>
enum 7771 "AOAI Resource Utilization"
{
Access = Internal;
Extensible = false;

/// <summary>
/// The first party utilization (only available for Microsoft first party apps).
/// </summary>
value(0; "First Party")
{
}

/// <summary>
/// The Microsoft managed utilization (the resource used for the LLM call is provided and managed by Microsoft).
/// </summary>
/// <remarks>A valid resource is still required to validate that the developer has access to Azure OpenAI.</remarks>
value(1; "Microsoft Managed")
{
}

/// <summary>
/// The Self-managed utilization (the resource used for the LLM call is the one provided by the developer).
/// </summary>
value(2; "Self-Managed")
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,25 @@ codeunit 7771 "Azure OpenAI"
exit(AzureOpenAIImpl.IsInitialized(CopilotCapability, ModelType, CallerModuleInfo));
end;

/// <summary>
/// Sets the managed Azure OpenAI API authorization to use for a specific model type.
/// This will send the Azure OpenAI call to the deployment specified in <paramref name="ManagedResourceDeployment"/>, and will use the other parameters to verify that you have access to Azure OpenAI.
/// </summary>
/// <param name="ModelType">The model type to set authorization for.</param>
/// <param name="Endpoint">The endpoint to use to verify access to Azure OpenAI. This is used only for verification, not for actual Azure OpenAI calls.</param>
/// <param name="Deployment">The deployment to use to verify access to Azure OpenAI. This is used only for verification, not for actual Azure OpenAI calls.</param>
/// <param name="ApiKey">The API key to use to verify access to Azure OpenAI. This is used only for verification, not for actual Azure OpenAI calls.</param>
/// <param name="ManagedResourceDeployment">The managed deployment to use for the model type.</param>
/// <remarks> NOTE: This function is currently only available to selected partners.
/// Endpoint would look like: https://resource-name.openai.azure.com/
/// Deployment would look like: gpt-35-turbo-16k
/// </remarks>
[NonDebuggable]
procedure SetManagedResourceAuthorization(ModelType: Enum "AOAI Model Type"; Endpoint: Text; Deployment: Text; ApiKey: SecretText; ManagedResourceDeployment: Text)
begin
AzureOpenAIImpl.SetManagedResourceAuthorization(ModelType, Endpoint, Deployment, ApiKey, ManagedResourceDeployment);
end;

/// <summary>
/// Sets the Azure OpenAI API authorization to use for a specific model type and endpoint.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,22 +173,44 @@ codeunit 7772 "Azure OpenAI Impl"

[NonDebuggable]
procedure SetAuthorization(ModelType: Enum "AOAI Model Type"; Deployment: Text)
var
ApiKey: SecretText;
begin
SetAuthorization(ModelType, '', Deployment, ApiKey);
case ModelType of
Enum::"AOAI Model Type"::"Text Completions":
TextCompletionsAOAIAuthorization.SetFirstPartyAuthorization(Deployment);
Enum::"AOAI Model Type"::Embeddings:
EmbeddingsAOAIAuthorization.SetFirstPartyAuthorization(Deployment);
Enum::"AOAI Model Type"::"Chat Completions":
ChatCompletionsAOAIAuthorization.SetFirstPartyAuthorization(Deployment);
else
Error(InvalidModelTypeErr);
end;
end;

[NonDebuggable]
procedure SetAuthorization(ModelType: Enum "AOAI Model Type"; Endpoint: Text; Deployment: Text; ApiKey: SecretText)
begin
case ModelType of
Enum::"AOAI Model Type"::"Text Completions":
TextCompletionsAOAIAuthorization.SetAuthorization(Endpoint, Deployment, ApiKey);
TextCompletionsAOAIAuthorization.SetSelfManagedAuthorization(Endpoint, Deployment, ApiKey);
Enum::"AOAI Model Type"::Embeddings:
EmbeddingsAOAIAuthorization.SetAuthorization(Endpoint, Deployment, ApiKey);
EmbeddingsAOAIAuthorization.SetSelfManagedAuthorization(Endpoint, Deployment, ApiKey);
Enum::"AOAI Model Type"::"Chat Completions":
ChatCompletionsAOAIAuthorization.SetAuthorization(Endpoint, Deployment, ApiKey);
ChatCompletionsAOAIAuthorization.SetSelfManagedAuthorization(Endpoint, Deployment, ApiKey);
else
Error(InvalidModelTypeErr);
end;
end;

[NonDebuggable]
procedure SetManagedResourceAuthorization(ModelType: Enum "AOAI Model Type"; Endpoint: Text; Deployment: Text; ApiKey: SecretText; ManagedResourceDeployment: Text)
begin
case ModelType of
Enum::"AOAI Model Type"::"Text Completions":
TextCompletionsAOAIAuthorization.SetMicrosoftManagedAuthorization(Endpoint, Deployment, ApiKey, ManagedResourceDeployment);
Enum::"AOAI Model Type"::Embeddings:
EmbeddingsAOAIAuthorization.SetMicrosoftManagedAuthorization(Endpoint, Deployment, ApiKey, ManagedResourceDeployment);
Enum::"AOAI Model Type"::"Chat Completions":
ChatCompletionsAOAIAuthorization.SetMicrosoftManagedAuthorization(Endpoint, Deployment, ApiKey, ManagedResourceDeployment);
else
Error(InvalidModelTypeErr);
end;
Expand Down Expand Up @@ -224,7 +246,7 @@ codeunit 7772 "Azure OpenAI Impl"
PayloadText: Text;
UnwrappedPrompt: Text;
begin
GuiCheck(CallerModuleInfo);
GuiCheck(TextCompletionsAOAIAuthorization);

CheckCapabilitySet();
CheckEnabled(CallerModuleInfo);
Expand Down Expand Up @@ -258,7 +280,7 @@ codeunit 7772 "Azure OpenAI Impl"
Payload: JsonObject;
PayloadText: Text;
begin
GuiCheck(CallerModuleInfo);
GuiCheck(EmbeddingsAOAIAuthorization);

CheckCapabilitySet();
CheckEnabled(CallerModuleInfo);
Expand Down Expand Up @@ -312,7 +334,7 @@ codeunit 7772 "Azure OpenAI Impl"
MetapromptTokenCount: Integer;
PromptTokenCount: Integer;
begin
GuiCheck(CallerModuleInfo);
GuiCheck(ChatCompletionsAOAIAuthorization);

CheckCapabilitySet();
CheckEnabled(CallerModuleInfo);
Expand Down Expand Up @@ -478,9 +500,17 @@ codeunit 7772 "Azure OpenAI Impl"
ALCopilotFunctions: DotNet ALCopilotFunctions;
ALCopilotOperationResponse: DotNet ALCopilotOperationResponse;
Error: Text;
EmptySecretText: SecretText;
begin
ClearLastError();
ALCopilotAuthorization := ALCopilotAuthorization.Create(AOAIAuthorization.GetEndpoint(), AOAIAuthorization.GetDeployment(), AOAIAuthorization.GetApiKey());
case AOAIAuthorization.GetResourceUtilization() of
Enum::"AOAI Resource Utilization"::"Microsoft Managed":
ALCopilotAuthorization := ALCopilotAuthorization.Create(EmptySecretText, AOAIAuthorization.GetManagedResourceDeployment(), EmptySecretText);
Enum::"AOAI Resource Utilization"::"First Party":
ALCopilotAuthorization := ALCopilotAuthorization.Create(EmptySecretText, AOAIAuthorization.GetManagedResourceDeployment(), EmptySecretText);
else
ALCopilotAuthorization := ALCopilotAuthorization.Create(AOAIAuthorization.GetEndpoint(), AOAIAuthorization.GetDeployment(), AOAIAuthorization.GetApiKey());
end;

case ModelType of
Enum::"AOAI Model Type"::"Text Completions":
Expand Down Expand Up @@ -508,14 +538,15 @@ codeunit 7772 "Azure OpenAI Impl"
Telemetry.LogMessage('0000LT4', StrSubstNo(TelemetryTokenCountLbl, Metaprompt, Prompt, Metaprompt + Prompt), Verbosity::Normal, DataClassification::SystemMetadata, TelemetryScope::All, CustomDimensions);
end;

local procedure GuiCheck(CallerModuleInfo: ModuleInfo)
var
CurrentModuleInfo: ModuleInfo;
local procedure GuiCheck(AOAIAuthorization: Codeunit "AOAI Authorization")
begin
NavApp.GetCallerModuleInfo(CurrentModuleInfo);
if GuiAllowed() then
exit;

if AOAIAuthorization.GetResourceUtilization() = Enum::"AOAI Resource Utilization"::"Self-Managed" then
exit;

if (not GuiAllowed()) and (CallerModuleInfo.Publisher = CurrentModuleInfo.Publisher) then
Error(CapabilityBackgroundErr);
Error(CapabilityBackgroundErr);
end;

local procedure AddTelemetryCustomDimensions(var CustomDimensions: Dictionary of [Text, Text]; CallerModuleInfo: ModuleInfo)
Expand Down

0 comments on commit ea642f9

Please sign in to comment.