Skip to content

Commit

Permalink
[25.0][Suggest No. Series] Enable feature and sync version with versi…
Browse files Browse the repository at this point in the history
…on from MAIN branch. (#2069)

<!-- 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 -->
Backporting all changes from the MAIN version and enabling the feature.

#### 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 #659
Fixes
[AB#503148](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/503148)
  • Loading branch information
JesperSchulz authored Sep 19, 2024
1 parent d711966 commit f66dd6c
Show file tree
Hide file tree
Showing 12 changed files with 380 additions and 279 deletions.
110 changes: 54 additions & 56 deletions src/Business Foundation/App/NoSeriesCopilot/app.json
Original file line number Diff line number Diff line change
@@ -1,57 +1,55 @@
{
"id": "7efce506-def2-4195-9d1e-bc538e729242",
"name": "No. Series Suggestions",
"publisher": "Microsoft",
"brief": "",
"description": "",
"version": "25.0.0.0",
"privacyStatement": "https://go.microsoft.com/fwlink/?linkid=724009",
"EULA": "https://go.microsoft.com/fwlink/?linkid=2009120",
"help": "https://go.microsoft.com/fwlink/?linkid=2103698",
"url": "https://go.microsoft.com/fwlink/?linkid=724011",
"logo": "",
"dependencies": [
{
"id": "63ca2fa4-4f03-4f2b-a480-172fef340d3f",
"name": "System Application",
"publisher": "Microsoft",
"version": "25.0.0.0"
},
{
"id": "d098b816-22fd-477f-9602-9122f5465527",
"name": "No. Series",
"publisher": "Microsoft",
"version": "25.0.0.0"
}
],
"internalsVisibleTo": [
{
"id": "ecb647bf-6fae-45b9-b136-28aa313f5e97",
"name": "No. Series Suggestions Test Library",
"publisher": "Microsoft"
}
],
"screenshots": [

],
"platform": "25.0.0.0",
"target": "OnPrem",
"idRanges": [
{
"from": 1,
"to": 9999
}
],
"features": [
"TranslationFile",
"GenerateCaptions",
"NoImplicitWith",
"NoPromotedActionProperties"
],
"resourceExposurePolicy": {
"allowDebugging": true,
"allowDownloadingSource": true,
"includeSourceInSymbolFile": true
},
"contextSensitiveHelpUrl": "https://learn.microsoft.com/dynamics365/business-central/"
}
"id": "7efce506-def2-4195-9d1e-bc538e729242",
"name": "No. Series Suggestions",
"publisher": "Microsoft",
"brief": "",
"description": "",
"version": "25.0.0.0",
"privacyStatement": "https://go.microsoft.com/fwlink/?linkid=724009",
"EULA": "https://go.microsoft.com/fwlink/?linkid=2009120",
"help": "https://go.microsoft.com/fwlink/?linkid=2103698",
"url": "https://go.microsoft.com/fwlink/?linkid=724011",
"logo": "",
"dependencies": [
{
"id": "63ca2fa4-4f03-4f2b-a480-172fef340d3f",
"name": "System Application",
"publisher": "Microsoft",
"version": "25.0.0.0"
},
{
"id": "d098b816-22fd-477f-9602-9122f5465527",
"name": "No. Series",
"publisher": "Microsoft",
"version": "25.0.0.0"
}
],
"internalsVisibleTo": [
{
"id": "ecb647bf-6fae-45b9-b136-28aa313f5e97",
"name": "No. Series Suggestions Test Library",
"publisher": "Microsoft"
}
],
"screenshots": [],
"platform": "25.0.0.0",
"target": "OnPrem",
"idRanges": [
{
"from": 1,
"to": 9999
}
],
"features": [
"TranslationFile",
"GenerateCaptions",
"NoImplicitWith",
"NoPromotedActionProperties"
],
"resourceExposurePolicy": {
"allowDebugging": true,
"allowDownloadingSource": true,
"includeSourceInSymbolFile": true
},
"contextSensitiveHelpUrl": "https://learn.microsoft.com/dynamics365/business-central/"
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ codeunit 324 "No. Series Copilot Impl."

var
IncorrectCompletionErr: Label 'Incorrect completion. The property %1 is empty', Comment = '%1 = property name';
EmptyCompletionErr: Label 'Incorrect completion. The completion is empty.';
IncorrectCompletionNumberOfGeneratedNoSeriesErr: Label 'Incorrect completion. The number of generated number series is incorrect. Expected %1, but got %2', Comment = '%1 = Expected Number, %2 = Actual Number';
TextLengthIsOverMaxLimitErr: Label 'The property %1 exceeds the maximum length of %2', Comment = '%1 = property name, %2 = maximum length';
DateSpecificPlaceholderLbl: Label '{current_date}', Locked = true;
Expand Down Expand Up @@ -68,6 +69,7 @@ codeunit 324 "No. Series Copilot Impl."

procedure ApplyGeneratedNoSeries(var GeneratedNoSeries: Record "No. Series Generation Detail")
begin
GeneratedNoSeries.SetRange(Exists, false);
if GeneratedNoSeries.FindSet() then
repeat
InsertNoSeriesWithLines(GeneratedNoSeries);
Expand Down Expand Up @@ -171,7 +173,7 @@ codeunit 324 "No. Series Copilot Impl."
if not AzureOpenAI.IsEnabled(Enum::"Copilot Capability"::"No. Series Copilot") then
exit;

AzureOpenAI.SetAuthorization(Enum::"AOAI Model Type"::"Chat Completions", AOAIDeployments.GetGPT4oMiniLatest());
AzureOpenAI.SetAuthorization(Enum::"AOAI Model Type"::"Chat Completions", AOAIDeployments.GetGPT4oLatest());
AzureOpenAI.SetCopilotCapability(Enum::"Copilot Capability"::"No. Series Copilot");
AOAIChatCompletionParams.SetMaxTokens(MaxOutputTokens());
AOAIChatCompletionParams.SetTemperature(0);
Expand All @@ -189,13 +191,13 @@ codeunit 324 "No. Series Copilot Impl."
CompletionAnswerTxt := AOAIChatMessages.GetLastMessage(); // the model can answer to rephrase the question, if the user input is not clear

if AOAIOperationResponse.IsFunctionCall() then
CompletionAnswerTxt := GenerateNoSeriesUsingToolResult(AzureOpenAI, InputText, AOAIOperationResponse);
CompletionAnswerTxt := GenerateNoSeriesUsingToolResult(AzureOpenAI, InputText, AOAIOperationResponse, AddNoSeriesIntent.GetExistingNoSeries());

exit(CompletionAnswerTxt);
end;

[NonDebuggable]
local procedure GenerateNoSeriesUsingToolResult(var AzureOpenAI: Codeunit "Azure OpenAI"; InputText: Text; var AOAIOperationResponse: Codeunit "AOAI Operation Response"): Text
local procedure GenerateNoSeriesUsingToolResult(var AzureOpenAI: Codeunit "Azure OpenAI"; InputText: Text; var AOAIOperationResponse: Codeunit "AOAI Operation Response"; ExistingNoSeriesArray: Text): Text
var
AOAIChatCompletionParams: Codeunit "AOAI Chat Completion Params";
AOAIChatMessages: Codeunit "AOAI Chat Messages";
Expand All @@ -209,6 +211,9 @@ codeunit 324 "No. Series Copilot Impl."
FunctionResponses: List of [Codeunit "AOAI Function Response"];
Progress: Dialog;
begin
if ExistingNoSeriesArray <> '' then
FinalResults.Add(ExistingNoSeriesArray);

FunctionResponses := AOAIOperationResponse.GetFunctionResponses();

foreach AOAIFunctionResponse in FunctionResponses do begin
Expand Down Expand Up @@ -237,7 +242,6 @@ codeunit 324 "No. Series Copilot Impl."
Progress.Close();
end;
end;

exit(ConcatenateToolResponse(FinalResults));
end;

Expand Down Expand Up @@ -337,6 +341,7 @@ codeunit 324 "No. Series Copilot Impl."
begin
ReadGeneratedNumberSeriesJArray(GeneratedNoSeriesArrayText).WriteTo(NoSeriesArrText);
Json.InitializeCollection(NoSeriesArrText);
CheckIfArrayIsNotEmpty(Json.GetCollectionCount());

for i := 0 to Json.GetCollectionCount() - 1 do begin
Json.GetObjectFromCollectionByIndex(i, NoSeriesObj);
Expand All @@ -356,6 +361,12 @@ codeunit 324 "No. Series Copilot Impl."
end;
end;

local procedure CheckIfArrayIsNotEmpty(NumberOfGeneratedNoSeries: Integer)
begin
if NumberOfGeneratedNoSeries = 0 then
Error(EmptyCompletionErr);
end;

local procedure CheckTextPropertyExistAndCheckIfNotEmpty(propertyName: Text; var Json: Codeunit Json)
var
value: Text;
Expand Down Expand Up @@ -420,47 +431,32 @@ codeunit 324 "No. Series Copilot Impl."
var
Json: Codeunit Json;
i: Integer;
NoSeriesObj: Text;
NoSeriesCodes: List of [Text];
NoSeriesCode: Text;
begin
Json.InitializeCollection(NoSeriesArrText);

for i := 0 to Json.GetCollectionCount() - 1 do begin
Json.GetObjectFromCollectionByIndex(i, NoSeriesObj);
Json.InitializeObject(NoSeriesObj);
Json.GetStringPropertyValueByName('seriesCode', NoSeriesCode);
if NoSeriesCodes.Contains(NoSeriesCode) then begin
Json.ReplaceOrAddJPropertyInJObject('seriesCode', GenerateNewSeriesCodeValue(NoSeriesCodes, NoSeriesCode));
NoSeriesObj := Json.GetObjectAsText();
Json.ReplaceJObjectInCollection(i, NoSeriesObj);
end;
NoSeriesCodes.Add(NoSeriesCode);
end;
for i := 0 to Json.GetCollectionCount() - 1 do
ProcessNoSeries(i, NoSeriesCodes, Json);

NoSeriesArrText := Json.GetCollectionAsText()
end;

local procedure GenerateNewSeriesCodeValue(var NoSeriesCodes: List of [Text]; var NoSeriesCode: Text): Text
local procedure ProcessNoSeries(i: Integer; var NoSeriesCodes: List of [Text]; var Json: Codeunit Json)
var
NewNoSeriesCode: Text;
begin
repeat
NewNoSeriesCode := CopyStr(NoSeriesCode, 1, 18) + '-' + RandomCharacter();
until not NoSeriesCodes.Contains(NewNoSeriesCode);

NoSeriesCode := NewNoSeriesCode;
exit(NewNoSeriesCode);
end;

local procedure RandomCharacter(): Char
NoSeriesCode: Text;
NoSeriesObj: Text;
IsExists: Boolean;
begin
exit(RandIntInRange(33, 126)); // ASCII: ! (33) to ~ (126)
end;
Json.GetObjectFromCollectionByIndex(i, NoSeriesObj);
Json.InitializeObject(NoSeriesObj);
Json.GetBoolPropertyValueFromJObjectByName('exists', IsExists);
Json.GetStringPropertyValueByName('seriesCode', NoSeriesCode);

local procedure RandIntInRange(MinInt: Integer; MaxInt: Integer): Integer
begin
exit(MinInt - 1 + Random(MaxInt - MinInt + 1));
if NoSeriesCodes.Contains(NoSeriesCode) and (not IsExists) then begin
Json.RemoveJObjectFromCollection(i);
exit;
end;
NoSeriesCodes.Add(NoSeriesCode);
end;

local procedure InsertGeneratedNoSeries(var GeneratedNoSeries: Record "No. Series Generation Detail"; NoSeriesObj: Text; GenerationNo: Integer)
Expand All @@ -482,7 +478,9 @@ codeunit 324 "No. Series Copilot Impl."
Json.GetValueAndSetToRecFieldNo(RecRef, 'tableId', GeneratedNoSeries.FieldNo("Setup Table No."));
Json.GetValueAndSetToRecFieldNo(RecRef, 'fieldId', GeneratedNoSeries.FieldNo("Setup Field No."));
Json.GetValueAndSetToRecFieldNo(RecRef, 'nextYear', GeneratedNoSeries.FieldNo("Is Next Year"));
RecRef.Insert(true);
Json.GetValueAndSetToRecFieldNo(RecRef, 'exists', GeneratedNoSeries.FieldNo(Exists));
Json.GetValueAndSetToRecFieldNo(RecRef, 'message', GeneratedNoSeries.FieldNo(Message));
if RecRef.Insert(true) then;

ValidateGeneratedNoSeries(RecRef);
end;
Expand Down Expand Up @@ -528,7 +526,7 @@ codeunit 324 "No. Series Copilot Impl."

local procedure MaxModelTokens(): Integer
begin
exit(16385); //gpt-4o-mini-latest
exit(16385); //gpt-4o-latest
end;

procedure IsCopilotVisible(): Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,36 @@ namespace Microsoft.Foundation.NoSeries;

pageextension 324 "No. Series Ext." extends "No. Series"
{
// TODO: Enable when all green lights have been given.
// actions
// {
// addfirst(Prompting)
// {
// action("Generate With Copilot Prompting")
// {
// Caption = 'Generate';
// ToolTip = 'Generate No. Series using Copilot';
// Image = Sparkle;
// ApplicationArea = All;
// Visible = CopilotActionsVisible;
actions
{
addfirst(Prompting)
{
action("Generate With Copilot Prompting")
{
Caption = 'Generate';
ToolTip = 'Generate No. Series using Copilot';
Image = Sparkle;
ApplicationArea = All;
Visible = CopilotActionsVisible;

// trigger OnAction()
// var
// NoSeriesCopilotImpl: Codeunit "No. Series Copilot Impl.";
// begin
// NoSeriesCopilotImpl.GetNoSeriesSuggestions();
// end;
// }
// }
// }
trigger OnAction()
var
NoSeriesCopilotImpl: Codeunit "No. Series Copilot Impl.";
begin
NoSeriesCopilotImpl.GetNoSeriesSuggestions();
end;
}
}
}

// trigger OnOpenPage()
// var
// NumberSeriesCopilotImpl: Codeunit "No. Series Copilot Impl.";
// begin
// CopilotActionsVisible := NumberSeriesCopilotImpl.IsCopilotVisible();
// end;
trigger OnOpenPage()
var
NumberSeriesCopilotImpl: Codeunit "No. Series Copilot Impl.";
begin
CopilotActionsVisible := NumberSeriesCopilotImpl.IsCopilotVisible();
end;

// var
// CopilotActionsVisible: Boolean;
var
CopilotActionsVisible: Boolean;

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

namespace Microsoft.Foundation.NoSeries;

using System.Reflection;

table 392 "No. Series Generation Detail"
{
TableType = Temporary;
Expand Down Expand Up @@ -76,6 +78,28 @@ table 392 "No. Series Generation Detail"
{
Caption = 'Starting Date';
}
field(13; "Exists"; Boolean)
{
Caption = 'Exists';
}
field(14; Message; Text[1024])
{
Caption = 'Message';
}
field(20; "Setup Table Name"; Text[80])
{
Caption = 'Setup Table';
FieldClass = FlowField;
CalcFormula = lookup("Table Metadata".Caption where(ID = field("Setup Table No.")));
Editable = false;
}
field(21; "Setup Field Name"; Text[250])
{
Caption = 'Setup Field';
FieldClass = FlowField;
CalcFormula = lookup(Field."Field Caption" where(TableNo = field("Setup Table No."), "No." = field("Setup Field No.")));
Editable = false;
}
}

keys
Expand Down Expand Up @@ -129,4 +153,4 @@ table 392 "No. Series Generation Detail"

Rec."Starting Date" := CalcDate('<-CY+1Y>', Today);
end;
}
}
Loading

0 comments on commit f66dd6c

Please sign in to comment.