Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Azure Document Intelligence Module #2834

Merged
merged 29 commits into from
Feb 11, 2025
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
60e78da
Add ADI
Jan 23, 2025
6e860fb
tags
Jan 23, 2025
838fba7
Minor corrections
Jan 23, 2025
b91bdb9
Fix unused label
Jan 24, 2025
d3ab47c
Merge branch 'private/magnushar/ADI' of https://github.com/microsoft/…
Jan 24, 2025
e351912
pack into json
Jan 24, 2025
b002636
Fix id
Jan 25, 2025
8b1a432
Update namespell
Jan 30, 2025
e0ea026
Can we decouple OpenAI and Copilot module
Jan 30, 2025
8ce1c7d
Merge branch 'main' of https://github.com/microsoft/BCApps into priva…
Feb 3, 2025
71304a5
Merge branch 'private/magnushar/ADI' of https://github.com/microsoft/…
Feb 3, 2025
893bb6b
Move abstraction around
Feb 5, 2025
6dc545b
Update text
Feb 5, 2025
f791b25
Clear before insert.
Feb 5, 2025
a61ba61
Update src/System Application/App/AI/src/Azure OpenAI/AzureOpenAIImpl…
Groenbech96 Feb 6, 2025
5ca1c58
Update src/System Application/App/AI/src/Azure AI Document Intelligen…
Groenbech96 Feb 6, 2025
1ce1417
Add field to table, to exclude from pages
Feb 10, 2025
85abf9f
Merge branch 'main' of https://github.com/microsoft/BCApps into priva…
Feb 10, 2025
2a1bb49
Undo label change
Feb 10, 2025
c85d431
Uncomment new code
Feb 10, 2025
af2de12
Error if not enabled
Feb 10, 2025
89bb33f
Fix comment
Feb 10, 2025
44f54d2
Update src/System Application/App/AI/src/Azure AI Document Intelligen…
Groenbech96 Feb 10, 2025
ade6490
Update src/System Application/App/AI/src/Azure AI Document Intelligen…
Groenbech96 Feb 10, 2025
2ddd7f3
tests
Feb 10, 2025
0787dfd
Merge branch 'private/magnushar/ADI' of https://github.com/microsoft/…
Feb 10, 2025
db18633
pr comments
Feb 11, 2025
c9fccf1
Minor
Feb 11, 2025
17509fa
rename interface
Feb 11, 2025
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
2 changes: 1 addition & 1 deletion src/System Application/App/AI/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
"idRanges": [
{
"from": 7758,
"to": 7778
"to": 7780
}
],
"target": "OnPrem",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// ------------------------------------------------------------------------------------------------
// 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.DocumentIntelligence;

/// <summary>
/// The supported model types for Azure OpenAI.
/// </summary>
enum 7779 "ADI Model Type"
{
Access = Public;
Extensible = false;

/// <summary>
/// Invoice model type.
/// </summary>
value(0; Invoice)
{
}

/// <summary>
/// Receipt model type.
/// </summary>
value(1; Receipt)
{
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// ------------------------------------------------------------------------------------------------
// 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.DocumentIntelligence;

using System.Privacy;
using System.Telemetry;
using System;
using System.AI;

/// <summary>
/// Azure Document Intelligence implementation.
/// </summary>
codeunit 7779 "Azure DI Impl."
{
Access = Internal;
InherentEntitlements = X;
InherentPermissions = X;

var
CopilotCapabilityImpl: Codeunit "Copilot Capability Impl";
FeatureTelemetry: Codeunit "Feature Telemetry";
AzureDocumentIntelligenceCapabilityTok: Label 'ADI', Locked = true;
TelemetryAnalyzeInvoiceFailureLbl: Label 'Analyze invoice failed.', Locked = true;
TelemetryAnalyzeInvoiceCompletedLbl: Label 'Analyze invoice completed.', Locked = true;
TelemetryAnalyzeReceiptFailureLbl: Label 'Analyze receipt failed.', Locked = true;
TelemetryAnalyzeReceiptCompletedLbl: Label 'Analyze receipt completed.', Locked = true;
GenerateRequestFailedErr: Label 'The request did not return a success status code.';
AzureAiDocumentIntelligenceTxt: Label 'Azure AI Document Intelligence', Locked = true;


procedure SetCopilotCapability(Capability: Enum "Copilot Capability"; CallerModuleInfo: ModuleInfo; AzureAIServiceName: Text)
begin
CopilotCapabilityImpl.SetCopilotCapability(Capability, CallerModuleInfo, AzureAIServiceName);
end;

/// <summary>
/// Analyze a single invoice.
/// </summary>
/// <param name="Base64Data">Data to analyze.</param>
/// <param name="CallerModuleInfo">The module info of the caller.</param>
/// <returns>The analyzed result.</returns>
procedure AnalyzeInvoice(Base64Data: Text; CallerModuleInfo: ModuleInfo) Result: Text
var
CustomDimensions: Dictionary of [Text, Text];
begin
CopilotCapabilityImpl.CheckCapabilitySet();
CopilotCapabilityImpl.CheckEnabled(CallerModuleInfo, Enum::"Azure AI Service Type"::"Azure Document Intelligence");
CopilotCapabilityImpl.AddTelemetryCustomDimensions(CustomDimensions, CallerModuleInfo);

if not SendRequest(Base64Data, Enum::"ADI Model Type"::Invoice, CallerModuleInfo, Result) then begin
FeatureTelemetry.LogError('0000OLK', AzureDocumentIntelligenceCapabilityTok, TelemetryAnalyzeInvoiceFailureLbl, GetLastErrorText(), '', Enum::"AL Telemetry Scope"::All, CustomDimensions);
exit;
end;

FeatureTelemetry.LogUsage('0000OLM', AzureDocumentIntelligenceCapabilityTok, TelemetryAnalyzeInvoiceCompletedLbl, Enum::"AL Telemetry Scope"::All, CustomDimensions);

end;

/// <summary>
/// Analyze a single receipt.
/// </summary>
/// <param name="Base64Data">Data to analyze.</param>
/// <param name="CallerModuleInfo">The module info of the caller.</param>
/// <returns>The analyzed result.</returns>
procedure AnalyzeReceipt(Base64Data: Text; CallerModuleInfo: ModuleInfo) Result: Text
var
CustomDimensions: Dictionary of [Text, Text];
begin
CopilotCapabilityImpl.CheckCapabilitySet();
CopilotCapabilityImpl.CheckEnabled(CallerModuleInfo, Enum::"Azure AI Service Type"::"Azure Document Intelligence");
CopilotCapabilityImpl.AddTelemetryCustomDimensions(CustomDimensions, CallerModuleInfo);

if not SendRequest(Base64Data, Enum::"ADI Model Type"::Receipt, CallerModuleInfo, Result) then begin
FeatureTelemetry.LogError('0000OLL', AzureDocumentIntelligenceCapabilityTok, TelemetryAnalyzeReceiptFailureLbl, GetLastErrorText(), '', Enum::"AL Telemetry Scope"::All, CustomDimensions);
exit;
end;

FeatureTelemetry.LogUsage('0000OLN', AzureDocumentIntelligenceCapabilityTok, TelemetryAnalyzeReceiptCompletedLbl, Enum::"AL Telemetry Scope"::All, CustomDimensions);
end;

[TryFunction]
[NonDebuggable]
local procedure SendRequest(Base64Data: Text; ModelType: Enum "ADI Model Type"; CallerModuleInfo: ModuleInfo; var Result: Text)
var
ALCopilotFunctions: DotNet ALCopilotFunctions;
ALCopilotCapability: DotNet ALCopilotCapability;
ALCopilotResponse: DotNet ALCopilotOperationResponse;
ErrorMsg: Text;
begin
ClearLastError();
ALCopilotCapability := ALCopilotCapability.ALCopilotCapability(CallerModuleInfo.Publisher(), CallerModuleInfo.Id(), Format(CallerModuleInfo.AppVersion()), AzureDocumentIntelligenceCapabilityTok);
case ModelType of
Enum::"ADI Model Type"::Invoice:
ALCopilotResponse := ALCopilotFunctions.GenerateInvoiceIntelligence(GenerateJsonForSingleInput(Base64Data), ALCopilotCapability);
Enum::"ADI Model Type"::Receipt:
ALCopilotResponse := ALCopilotFunctions.GenerateReceiptIntelligence(GenerateJsonForSingleInput(Base64Data), ALCopilotCapability);
end;
ErrorMsg := ALCopilotResponse.ErrorText();
if ErrorMsg <> '' then
Error(ErrorMsg);

if not ALCopilotResponse.IsSuccess() then
Error(GenerateRequestFailedErr);

Result := ALCopilotResponse.Result();
end;

local procedure GenerateJsonForSingleInput(Base64: Text): Text
var
JsonObject: JsonObject;
InputsObject: JsonObject;
InnerObject: JsonObject;
JsonText: Text;
begin
// Create the inner object with the base64Encoded property
InnerObject.Add('base64_encoded', Base64);
// Create the inputs object and add the inner object to it
InputsObject.Add('1', InnerObject);
// Create the main JSON object and add the inputs object to it
JsonObject.Add('inputs', InputsObject);
// Convert the JSON object to text
JsonObject.WriteTo(JsonText);
// Return the JSON text
exit(JsonText);
end;

procedure GetAzureAIDocumentIntelligenceCategory(): Code[50]
begin
exit(AzureAiDocumentIntelligenceTxt);
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Privacy Notice", OnRegisterPrivacyNotices, '', false, false)]
local procedure CreatePrivacyNoticeRegistrations(var TempPrivacyNotice: Record "Privacy Notice" temporary)
begin
TempPrivacyNotice.Init();
TempPrivacyNotice.ID := GetAzureAIDocumentIntelligenceCategory();
TempPrivacyNotice."Integration Service Name" := AzureAiDocumentIntelligenceTxt;
if not TempPrivacyNotice.Insert() then;
end;



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// ------------------------------------------------------------------------------------------------
// 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.DocumentIntelligence;

using System.AI;

/// <summary>
/// Azure Document Intelligence implementation.
/// </summary>
codeunit 7780 "Azure Document Intelligence"
{
Access = Public;
InherentEntitlements = X;
InherentPermissions = X;

var
AzureDIImpl: Codeunit "Azure DI Impl.";


/// <summary>
/// Analyze the invoice.
/// </summary>
/// <param name="Base64Data">Data to analyze.</param>
/// <returns>The analyzed result.</returns>
[Scope('OnPrem')]
procedure AnalyzeInvoice(Base64Data: Text): Text
var
CallerModuleInfo: ModuleInfo;
begin
NavApp.GetCallerModuleInfo(CallerModuleInfo);
exit(AzureDIImpl.AnalyzeInvoice(Base64Data, CallerModuleInfo));
end;

/// <summary>
/// Analyze the Receipt.
/// </summary>
/// <param name="Base64Data">Data to analyze.</param>
/// <returns>The analyzed result.</returns>
[Scope('OnPrem')]
procedure AnalyzeReceipt(Base64Data: Text): Text
var
CallerModuleInfo: ModuleInfo;
begin
NavApp.GetCallerModuleInfo(CallerModuleInfo);
exit(AzureDIImpl.AnalyzeReceipt(Base64Data, CallerModuleInfo));
end;


/// <summary>
/// Sets the copilot capability that the API is running for.
/// </summary>
/// <param name="CopilotCapability">The copilot capability to set.</param>
[NonDebuggable]
procedure SetCopilotCapability(CopilotCapability: Enum "Copilot Capability")
var
CallerModuleInfo: ModuleInfo;
begin
NavApp.GetCallerModuleInfo(CallerModuleInfo);
AzureDIImpl.SetCopilotCapability(CopilotCapability, CallerModuleInfo, AzureDIImpl.GetAzureAIDocumentIntelligenceCategory());
end;

}
Original file line number Diff line number Diff line change
Expand Up @@ -268,8 +268,9 @@ codeunit 7771 "Azure OpenAI"
CallerModuleInfo: ModuleInfo;
begin
NavApp.GetCallerModuleInfo(CallerModuleInfo);
AzureOpenAIImpl.SetCopilotCapability(CopilotCapability, CallerModuleInfo);
AzureOpenAIImpl.SetCopilotCapability(CopilotCapability, CallerModuleInfo, AzureOpenAIImpl.GetAzureOpenAICategory());
end;

#if not CLEAN24
/// <summary>
/// Gets the approximate token count for the input.
Expand Down
Loading
Loading