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

[Copilot] Number Series improvements #2052

Merged
Merged
Show file tree
Hide file tree
Changes from 5 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
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 @@ -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,33 @@ 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);
ProcessNoSeries(i, NoSeriesCodes, Json);
end;

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 +479,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 +527,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 @@ -76,6 +76,28 @@
{
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.")));

Check failure on line 91 in src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesGenerationDetail.Table.al

View workflow job for this annotation

GitHub Actions / Build System Application Modules (Default) / System Application Modules (Default)

AL0185 Table 'Table Metadata' is missing

Check failure on line 91 in src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesGenerationDetail.Table.al

View workflow job for this annotation

GitHub Actions / Build Business Foundation (Translated) / Business Foundation (Translated)

AL0185 Table 'Table Metadata' is missing

Check failure on line 91 in src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesGenerationDetail.Table.al

View workflow job for this annotation

GitHub Actions / Build Business Foundation (Clean) / Business Foundation (Clean)

AL0185 Table 'Table Metadata' is missing

Check failure on line 91 in src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesGenerationDetail.Table.al

View workflow job for this annotation

GitHub Actions / Build System Application Modules (Clean) / System Application Modules (Clean)

AL0185 Table 'Table Metadata' is missing

Check failure on line 91 in src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesGenerationDetail.Table.al

View workflow job for this annotation

GitHub Actions / Build Business Foundation (Default) / Business Foundation (Default)

AL0185 Table 'Table Metadata' is missing
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.")));

Check failure on line 98 in src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesGenerationDetail.Table.al

View workflow job for this annotation

GitHub Actions / Build System Application Modules (Default) / System Application Modules (Default)

AL0185 Table 'Field' is missing

Check failure on line 98 in src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesGenerationDetail.Table.al

View workflow job for this annotation

GitHub Actions / Build Business Foundation (Translated) / Business Foundation (Translated)

AL0185 Table 'Field' is missing

Check failure on line 98 in src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesGenerationDetail.Table.al

View workflow job for this annotation

GitHub Actions / Build Business Foundation (Clean) / Business Foundation (Clean)

AL0185 Table 'Field' is missing

Check failure on line 98 in src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesGenerationDetail.Table.al

View workflow job for this annotation

GitHub Actions / Build System Application Modules (Clean) / System Application Modules (Clean)

AL0185 Table 'Field' is missing

Check failure on line 98 in src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesGenerationDetail.Table.al

View workflow job for this annotation

GitHub Actions / Build Business Foundation (Default) / Business Foundation (Default)

AL0185 Table 'Field' is missing
Editable = false;
}
}

keys
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,41 +28,76 @@ page 333 "No. Series Generation Sub"
{
ApplicationArea = All;
ToolTip = 'Specifies the value of the Series Code field.';
Enabled = IsEnabled;
}
field(Description; Rec.Description)
{
ApplicationArea = All;
ToolTip = 'Specifies the value of the Description field.';
Enabled = IsEnabled;
}
field("Starting No."; Rec."Starting No.")
{
ApplicationArea = All;
ToolTip = 'Specifies the value of the Starting No. field.';
Enabled = IsEnabled;
}
field("Increment-by No."; Rec."Increment-by No.")
{
ApplicationArea = All;
ToolTip = 'Specifies the value of the Increment-by No. field.';
Enabled = IsEnabled;
}
field("Ending No."; Rec."Ending No.")
{
ApplicationArea = All;
ToolTip = 'Specifies the value of the Ending No. field.';
Enabled = IsEnabled;
}
field("Warning No."; Rec."Warning No.")
{
ApplicationArea = All;
ToolTip = 'Specifies the value of the Warning No. field.';
Enabled = IsEnabled;
}
field("Starting Date"; Rec."Starting Date")
{
ApplicationArea = All;
ToolTip = 'Specifies the value of the Starting Date field.';
Enabled = IsEnabled;
}
field(Message; Rec.Message)
{
ApplicationArea = All;
ToolTip = 'Specifies the value of the Message field.';
Style = Attention;
Editable = false;
}
field("Setup Table Name"; Rec."Setup Table Name")
{
ApplicationArea = All;
ToolTip = 'Specifies the value of the Setup Table Name field.';
Enabled = IsEnabled;
}
field("Setup Field Name"; Rec."Setup Field Name")
{
ApplicationArea = All;
ToolTip = 'Specifies the value of the Setup Field Name field.';
Enabled = IsEnabled;
}

}
}
}

var
IsEnabled: Boolean;

trigger OnAfterGetRecord()
begin
IsEnabled := not Rec.Exists;
end;

internal procedure Load(var GeneratedNoSeries: Record "No. Series Generation Detail")
begin
GeneratedNoSeries.Reset();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ codeunit 331 "No. Series Cop. Add Intent" implements "AOAI Function"
AzureKeyVault: Codeunit "Azure Key Vault";
Telemetry: Codeunit Telemetry;
ToolsImpl: Codeunit "No. Series Cop. Tools Impl.";
ExistingNoSeriesJArr: JsonArray;
FunctionNameLbl: Label 'CreateNewNumberSeries', Locked = true;
DateSpecificPlaceholderLbl: Label '{current_date}', Locked = true;
CustomPatternsPlaceholderLbl: Label '{custom_patterns}', Locked = true;
Expand All @@ -28,6 +29,7 @@ codeunit 331 "No. Series Cop. Add Intent" implements "AOAI Function"
TelemetryTool1PromptRetrievalErr: Label 'Unable to retrieve the prompt for No. Series Copilot Tool 1 from Azure Key Vault.', Locked = true;
TelemetryTool1DefinitionRetrievalErr: Label 'Unable to retrieve the definition for No. Series Copilot Tool 1 from Azure Key Vault.', Locked = true;
ToolLoadingErr: Label 'Unable to load the No. Series Copilot Tool 1. Please try again later.';
ExistingNoSeriesMessageLbl: Label 'Number series already configured. If you wish to modify the existing series, please use the `Modify number series` prompt.';

procedure GetName(): Text
begin
Expand Down Expand Up @@ -148,8 +150,10 @@ codeunit 331 "No. Series Cop. Add Intent" implements "AOAI Function"
exit;

FieldRef := RecRef.Field(Field."No.");
if Format(FieldRef.Value) <> '' then
if Format(FieldRef.Value) <> '' then begin
SaveExistingNoSeries(TempTableMetadata, FieldRef);
exit; // No need to generate number series if it already created and configured
end;

TempSetupTable := TempTableMetadata;
if TempSetupTable.Insert() then;
Expand All @@ -158,6 +162,42 @@ codeunit 331 "No. Series Cop. Add Intent" implements "AOAI Function"
TempNoSeriesField.Insert();
end;

local procedure SaveExistingNoSeries(TempTableMetadata: Record "Table Metadata" temporary; FieldRef: FieldRef)
var
NoSeries: Record "No. Series";
NoSeriesLine: Record "No. Series Line";
NoSeriesManagement: Codeunit "No. Series";
ExistingNoSeriesJObj: JsonObject;
begin
if not NoSeries.Get(Format(FieldRef.Value)) then
exit;

NoSeriesManagement.GetNoSeriesLine(NoSeriesLine, NoSeries.Code, Today(), false);

Clear(ExistingNoSeriesJObj);
ExistingNoSeriesJObj.Add('seriesCode', NoSeries.Code);
ExistingNoSeriesJObj.Add('description', NoSeries.Description);
ExistingNoSeriesJObj.Add('startingNo', NoSeriesLine."Starting No.");
ExistingNoSeriesJObj.Add('endingNo', NoSeriesLine."Ending No.");
ExistingNoSeriesJObj.Add('warningNo', NoSeriesLine."Warning No.");
ExistingNoSeriesJObj.Add('incrementByNo', NoSeriesLine."Increment-by No.");
ExistingNoSeriesJObj.Add('tableId', TempTableMetadata.ID);
ExistingNoSeriesJObj.Add('fieldId', FieldRef.Number);
ExistingNoSeriesJObj.Add('nextYear', false);
ExistingNoSeriesJObj.Add('exists', true);
ExistingNoSeriesJObj.Add('message', ExistingNoSeriesMessageLbl);

ExistingNoSeriesJArr.Add(ExistingNoSeriesJObj);
end;

procedure GetExistingNoSeries() ExistingNoSeries: Text
begin
if ExistingNoSeriesJArr.Count() = 0 then
exit('');

ExistingNoSeriesJArr.WriteTo(ExistingNoSeries);
end;

[NonDebuggable]
local procedure GetToolPrompt() Prompt: Text
begin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,13 +234,18 @@ codeunit 336 "No. Series Cop. Tools Impl."
foreach Entity in Entities do begin
String1 := RecordMatchMgtCopy.RemoveShortWords(RemoveTextPart(TableMetadata.Caption, ' Setup') + ' ' + RemoveTextParts(Field.FieldName, GetNoSeriesAbbreviations()));
String2 := RecordMatchMgtCopy.RemoveShortWords(Entity);
Score := RecordMatchMgtCopy.CalculateStringNearness(String1, String2, 1, 100) / 100;
Score := RecordMatchMgtCopy.CalculateStringNearness(String1, String2, GetMatchLengthThreshold(), 100) / 100;
if Score >= RequiredNearness() then
exit(true);
end;
exit(false);
end;

local procedure GetMatchLengthThreshold(): Decimal
begin
exit(2);
end;

local procedure RequiredNearness(): Decimal
begin
exit(0.9)
Expand Down
Loading