From 92833c9bf273afa3be1bc60b2322b0169bace3c7 Mon Sep 17 00:00:00 2001 From: Dmitry Katson Date: Wed, 23 Oct 2024 04:29:51 -0500 Subject: [PATCH] [Number Series Copilot] Bug Fixes in Intent Understanding and Field Validation (#2111) #### Summary This PR addresses three critical bugs in the Number Series Copilot: 1. **Bug 1: Incorrect Intent Mapping for "Generate" Command** - The system was misinterpreting the "generate" command, often preparing Number Series for the next period instead of creating a new one. The fix involves updating the tools definition and prompt to clarify the distinction between creating new Number Series and generating Number Series for the next period. 2. **Bug 2: Incorrect Field Check for Existing Number Series** - The system was incorrectly performing checks on all fields for existing Number Series. The fix modifies the behavior to exclude pre-existing Number Series from the field validation checks, ensuring that only mandatory fields are validated for AI generated series. 3. **Bug 3: Blank Fields Causing Validation Errors** - The system was generating Number Series without values for optional fields, causing validation errors. The fix refines the validation logic so that only mandatory fields are checked, allowing optional fields to remain blank if necessary. **Steps to Implement:** 1. Refactor the LLM prompt and tools definition to improve the understanding of user intent between creating and preparing Number Series for different periods. 2. Update the logic to exclude field checks for existing Number Series and restrict checks to mandatory fields. **Acceptance Criteria:** - Users can create Number Series without mistakenly triggering next-period Number Series generation when using the word "generate." - Existing Number Series are excluded from unnecessary checks, and only mandatory fields are validated for new series. These fixes aim to enhance the accuracy and reliability of the Number Series Copilot, ensuring it correctly interprets user commands and validates the necessary fields. #### Work Item(s) Fixes #2106 Fixes [AB#550892](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/550892), [AB#544073](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/544073) --- .../NoSeriesCopilotObjects.permissionset.al | 15 ++++ .../Copilot/NoSeriesCopilotImpl.Codeunit.al | 74 +++++++++++++------ .../src/Copilot/NoSeriesGeneration.Page.al | 16 ++-- .../NoSeriesTextMatchImpl.Codeunit.al} | 32 ++++++-- .../Tools/NoSeriesCopAddIntent.Codeunit.al | 6 +- .../Tools/NoSeriesCopChangeIntent.Codeunit.al | 6 +- .../Tools/NoSeriesCopNxtYrIntent.Codeunit.al | 4 +- .../Tools/NoSeriesCopToolsImpl.Codeunit.al | 21 ++---- .../NoSeriesCopilotRegister.Codeunit.al | 2 +- 9 files changed, 118 insertions(+), 58 deletions(-) create mode 100644 src/Business Foundation/App/NoSeriesCopilot/Permissions/NoSeriesCopilotObjects.permissionset.al rename src/Business Foundation/App/NoSeriesCopilot/src/Copilot/{Tools/RecordMatchImpl.Codeunit.al => Search/Classic/NoSeriesTextMatchImpl.Codeunit.al} (83%) diff --git a/src/Business Foundation/App/NoSeriesCopilot/Permissions/NoSeriesCopilotObjects.permissionset.al b/src/Business Foundation/App/NoSeriesCopilot/Permissions/NoSeriesCopilotObjects.permissionset.al new file mode 100644 index 0000000000..db8cdf26b4 --- /dev/null +++ b/src/Business Foundation/App/NoSeriesCopilot/Permissions/NoSeriesCopilotObjects.permissionset.al @@ -0,0 +1,15 @@ +// ------------------------------------------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// ------------------------------------------------------------------------------------------------ + +namespace Microsoft.Foundation.NoSeries; + +permissionset 330 "No. Series Copilot - Objects" +{ + Access = Internal; + Assignable = false; + Permissions = + codeunit "No. Series Copilot Impl." = X, + codeunit "No. Series Text Match Impl." = X; +} \ No newline at end of file diff --git a/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesCopilotImpl.Codeunit.al b/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesCopilotImpl.Codeunit.al index 22c284f72e..c4f485c914 100644 --- a/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesCopilotImpl.Codeunit.al +++ b/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesCopilotImpl.Codeunit.al @@ -150,7 +150,7 @@ codeunit 324 "No. Series Copilot Impl." Telemetry: Codeunit Telemetry; ToolsSelectionPrompt: Text; begin - if not AzureKeyVault.GetAzureKeyVaultSecret('NoSeriesCopilotToolsSelectionPrompt', ToolsSelectionPrompt) then begin + if not AzureKeyVault.GetAzureKeyVaultSecret('NoSeriesCopilotToolsSelectionPromptV2', ToolsSelectionPrompt) then begin Telemetry.LogMessage('0000NDY', TelemetryToolsSelectionPromptRetrievalErr, Verbosity::Error, DataClassification::SystemMetadata); Error(ToolLoadingErr); end; @@ -346,43 +346,69 @@ codeunit 324 "No. Series Copilot Impl." for i := 0 to Json.GetCollectionCount() - 1 do begin Json.GetObjectFromCollectionByIndex(i, NoSeriesObj); Json.InitializeObject(NoSeriesObj); - CheckTextPropertyExistAndCheckIfNotEmpty('seriesCode', Json); - CheckMaximumLengthOfPropertyValue('seriesCode', Json, 20); - CheckTextPropertyExistAndCheckIfNotEmpty('description', Json); - CheckTextPropertyExistAndCheckIfNotEmpty('startingNo', Json); - CheckMaximumLengthOfPropertyValue('startingNo', Json, 20); - CheckTextPropertyExistAndCheckIfNotEmpty('endingNo', Json); - CheckMaximumLengthOfPropertyValue('endingNo', Json, 20); - CheckTextPropertyExistAndCheckIfNotEmpty('warningNo', Json); - CheckMaximumLengthOfPropertyValue('warningNo', Json, 20); - CheckIntegerPropertyExistAndCheckIfNotEmpty('incrementByNo', Json); - CheckIntegerPropertyExistAndCheckIfNotEmpty('tableId', Json); - CheckIntegerPropertyExistAndCheckIfNotEmpty('fieldId', Json); + CheckMandatoryProperties(Json); end; end; + local procedure CheckMandatoryProperties(var Json: Codeunit Json) + begin + if not CheckIfNumberSeriesIsGenerated(Json) then + exit; + + CheckJsonTextProperty('seriesCode', Json, true); + CheckMaximumLengthOfPropertyValue('seriesCode', Json, 20); + CheckJsonTextProperty('description', Json, true); + CheckJsonTextProperty('startingNo', Json, true); + CheckMaximumLengthOfPropertyValue('startingNo', Json, 20); + CheckJsonTextProperty('endingNo', Json, false); + CheckMaximumLengthOfPropertyValue('endingNo', Json, 20); + CheckJsonTextProperty('warningNo', Json, false); + CheckMaximumLengthOfPropertyValue('warningNo', Json, 20); + CheckJsonIntegerProperty('incrementByNo', Json, false); + CheckJsonIntegerProperty('tableId', Json, true); + CheckJsonIntegerProperty('fieldId', Json, true); + end; + + local procedure CheckIfNumberSeriesIsGenerated(var Json: Codeunit Json): Boolean + var + IsExists: Boolean; + begin + Json.GetBoolPropertyValueFromJObjectByName('exists', IsExists); + exit(not IsExists); + end; + local procedure CheckIfArrayIsNotEmpty(NumberOfGeneratedNoSeries: Integer) begin if NumberOfGeneratedNoSeries = 0 then Error(EmptyCompletionErr); end; - local procedure CheckTextPropertyExistAndCheckIfNotEmpty(propertyName: Text; var Json: Codeunit Json) + local procedure CheckJsonTextProperty(propertyName: Text; var Json: Codeunit Json; IsRequired: Boolean) var value: Text; begin Json.GetStringPropertyValueByName(propertyName, value); - if value = '' then - Error(IncorrectCompletionErr, propertyName); + if not IsRequired then + exit; + + if value <> '' then + exit; + + Error(IncorrectCompletionErr, propertyName); end; - local procedure CheckIntegerPropertyExistAndCheckIfNotEmpty(propertyName: Text; var Json: Codeunit Json) + local procedure CheckJsonIntegerProperty(propertyName: Text; var Json: Codeunit Json; IsRequired: Boolean) var PropertyValue: Integer; begin Json.GetIntegerPropertyValueFromJObjectByName(propertyName, PropertyValue); - if PropertyValue = 0 then - Error(IncorrectCompletionErr, propertyName); + if not IsRequired then + exit; + + if PropertyValue <> 0 then + exit; + + Error(IncorrectCompletionErr, propertyName); end; local procedure CheckMaximumLengthOfPropertyValue(propertyName: Text; var Json: Codeunit Json; maxLength: Integer) @@ -390,8 +416,10 @@ codeunit 324 "No. Series Copilot Impl." value: Text; begin Json.GetStringPropertyValueByName(propertyName, value); - if StrLen(value) > maxLength then - Error(TextLengthIsOverMaxLimitErr, propertyName, maxLength); + if StrLen(value) <= maxLength then + exit; + + Error(TextLengthIsOverMaxLimitErr, propertyName, maxLength); end; local procedure ReadGeneratedNumberSeriesJArray(Completion: Text) NoSeriesJArray: JsonArray @@ -445,14 +473,12 @@ codeunit 324 "No. Series Copilot Impl." var NoSeriesCode: Text; NoSeriesObj: Text; - IsExists: Boolean; begin Json.GetObjectFromCollectionByIndex(i, NoSeriesObj); Json.InitializeObject(NoSeriesObj); - Json.GetBoolPropertyValueFromJObjectByName('exists', IsExists); Json.GetStringPropertyValueByName('seriesCode', NoSeriesCode); - if NoSeriesCodes.Contains(NoSeriesCode) and (not IsExists) then begin + if NoSeriesCodes.Contains(NoSeriesCode) and (CheckIfNumberSeriesIsGenerated(Json)) then begin Json.RemoveJObjectFromCollection(i); exit; end; diff --git a/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesGeneration.Page.al b/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesGeneration.Page.al index 7dee646d97..e4db90211b 100644 --- a/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesGeneration.Page.al +++ b/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesGeneration.Page.al @@ -114,23 +114,23 @@ page 332 "No. Series Generation" { Caption = 'Prepare for next year'; - action(SetupForNextYear) + action(PrepareForNextYear) { - Caption = 'Set up number series for the next year'; + Caption = 'Prepare number series for the next year'; ToolTip = 'Sample prompt for setting up number series for the next year.'; trigger OnAction() begin - InputText := SetupForNextYearLbl; + InputText := PrepareForNextYearLbl; CurrPage.Update(); end; } - action(SetupModuleForNextYear) + action(PrepareModuleForNextYear) { - Caption = 'Set up number series for the [sales] module for the next year'; + Caption = 'Prepare number series for the [sales] module for the next year'; ToolTip = 'Sample prompt for setting up number series for a specific module for the next year. Replace [sales] with the module you want to set up number series for.'; trigger OnAction() begin - InputText := SetupModuleForNextYearLbl; + InputText := PrepareModuleForNextYearLbl; CurrPage.Update(); end; } @@ -178,8 +178,8 @@ page 332 "No. Series Generation" CreateNoSeriesForModuleWithPatternLbl: Label 'Create number series for [specify here] module in the format '; CreateNoSeriesForCompanyLbl: Label 'Create numbers series for the new company'; ChangeNumberLbl: Label 'Change the [specify here] number to '; - SetupForNextYearLbl: Label 'Set up number series for the next year'; - SetupModuleForNextYearLbl: Label 'Set up number series for the [specify here] module for the next year'; + PrepareForNextYearLbl: Label 'Prepare number series for the next year'; + PrepareModuleForNextYearLbl: Label 'Prepare number series for the [specify here] module for the next year'; trigger OnAfterGetCurrRecord() begin diff --git a/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Tools/RecordMatchImpl.Codeunit.al b/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Search/Classic/NoSeriesTextMatchImpl.Codeunit.al similarity index 83% rename from src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Tools/RecordMatchImpl.Codeunit.al rename to src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Search/Classic/NoSeriesTextMatchImpl.Codeunit.al index ae9b640c59..43a891d0a8 100644 --- a/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Tools/RecordMatchImpl.Codeunit.al +++ b/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Search/Classic/NoSeriesTextMatchImpl.Codeunit.al @@ -5,12 +5,24 @@ namespace Microsoft.Foundation.NoSeries; -codeunit 337 "Record Match Impl." +codeunit 337 "No. Series Text Match Impl." { Access = Internal; InherentPermissions = X; InherentEntitlements = X; + procedure IsRelevant(FirstString: Text; SecondString: Text): Boolean + var + Score: Decimal; + begin + FirstString := RemoveShortWords(FirstString); + SecondString := RemoveShortWords(SecondString); + + Score := CalculateStringNearness(FirstString, SecondString, GetMatchLengthTreshold(), 100) / 100; + + exit(Score >= RequiredNearness()); + end; + /// /// Computes a nearness score between strings. Nearness is based on repeatedly finding longest common substrings. /// Substring matches below Threshold are not considered. @@ -21,7 +33,7 @@ codeunit 337 "Record Match Impl." /// Substring matches below Threshold are not considered /// Max value returned by this procedure /// A number between 0 and NormalizingFactor, representing how much of the strings was matched - procedure CalculateStringNearness(FirstString: Text; SecondString: Text; Threshold: Integer; NormalizingFactor: Integer): Integer + local procedure CalculateStringNearness(FirstString: Text; SecondString: Text; Threshold: Integer; NormalizingFactor: Integer): Integer var Result: Text; TotalMatchedChars: Integer; @@ -98,11 +110,11 @@ codeunit 337 "Record Match Impl." exit(MinThreshold <= Length); end; - procedure RemoveShortWords(OriginalText: Text[250]): Text[250]; + local procedure RemoveShortWords(OriginalText: Text): Text; var Words: List of [Text]; - Word: Text[250]; - Result: Text[250]; + Word: Text; + Result: Text; begin Words := OriginalText.Split(' '); // split the text by spaces into a list of words foreach Word in Words do // loop through each word in the list @@ -112,4 +124,14 @@ codeunit 337 "Record Match Impl." OriginalText := Result; // assign the result back to the text parameter exit(OriginalText); end; + + local procedure GetMatchLengthTreshold(): Decimal + begin + exit(2); + end; + + local procedure RequiredNearness(): Decimal + begin + exit(0.9) + end; } \ No newline at end of file diff --git a/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Tools/NoSeriesCopAddIntent.Codeunit.al b/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Tools/NoSeriesCopAddIntent.Codeunit.al index b2377be60d..164b896655 100644 --- a/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Tools/NoSeriesCopAddIntent.Codeunit.al +++ b/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Tools/NoSeriesCopAddIntent.Codeunit.al @@ -28,6 +28,7 @@ codeunit 331 "No. Series Cop. Add Intent" implements "AOAI Function" NumberOfAddedTablesPlaceholderLbl: Label '{number_of_tables}', Locked = true; 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; + ToolProgressDialogTextLbl: Label 'Searching for tables with number series related to your query'; 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.'; @@ -62,7 +63,9 @@ codeunit 331 "No. Series Cop. Add Intent" implements "AOAI Function" NewNoSeriesPrompt, CustomPatternsPromptList, TablesYamlList, EmptyList : List of [Text]; NumberOfToolResponses, i, ActualTablesChunkSize : Integer; NumberOfAddedTables: Integer; + Progress: Dialog; begin + Progress.Open(ToolProgressDialogTextLbl); GetTablesRequireNoSeries(Arguments, TempSetupTable, TempNoSeriesField); ToolsImpl.GetUserSpecifiedOrExistingNumberPatternsGuidelines(Arguments, CustomPatternsPromptList, EmptyList, false); @@ -80,7 +83,8 @@ codeunit 331 "No. Series Cop. Add Intent" implements "AOAI Function" .Replace(NumberOfAddedTablesPlaceholderLbl, Format(ActualTablesChunkSize))); ToolResults.Add(ToolsImpl.ConvertListToText(NewNoSeriesPrompt), ActualTablesChunkSize); - end + end; + Progress.Close(); end; local procedure GetTablesRequireNoSeries(var Arguments: JsonObject; var TempSetupTable: Record "Table Metadata" temporary; var TempNoSeriesField: Record "Field" temporary) diff --git a/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Tools/NoSeriesCopChangeIntent.Codeunit.al b/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Tools/NoSeriesCopChangeIntent.Codeunit.al index b4dfc2698a..4c78718f90 100644 --- a/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Tools/NoSeriesCopChangeIntent.Codeunit.al +++ b/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Tools/NoSeriesCopChangeIntent.Codeunit.al @@ -32,6 +32,7 @@ codeunit 334 "No. Series Cop. Change Intent" implements "AOAI Function" NumberOfAddedTablesPlaceholderLbl: Label '{number_of_tables}', Locked = true; TelemetryTool2PromptRetrievalErr: Label 'Unable to retrieve the prompt for No. Series Copilot Tool 2 from Azure Key Vault.', Locked = true; TelemetryTool2DefinitionRetrievalErr: Label 'Unable to retrieve the definition for No. Series Copilot Tool 2 from Azure Key Vault.', Locked = true; + ToolProgressDialogTextLbl: Label 'Searching for tables with number series related to your query'; ToolLoadingErr: Label 'Unable to load the No. Series Copilot Tool 2. Please try again later.'; procedure GetName(): Text @@ -71,12 +72,14 @@ codeunit 334 "No. Series Cop. Change Intent" implements "AOAI Function" ChangeNoSeriesPrompt, CustomPatternsPromptList, TablesYamlList, ExistingNoSeriesToChangeList : List of [Text]; NumberOfToolResponses, i, ActualTablesChunkSize : Integer; NumberOfChangedTables: Integer; + Progress: Dialog; begin if not CheckIfUserSpecifiedNoSeriesToChange(Arguments) then begin NoSeriesCopilotImpl.SendNotification(GetLastErrorText()); exit; end; + Progress.Open(ToolProgressDialogTextLbl); GetTablesWithNoSeries(Arguments, TempSetupTable, TempNoSeriesField, ExistingNoSeriesToChangeList); ToolsImpl.GetUserSpecifiedOrExistingNumberPatternsGuidelines(Arguments, CustomPatternsPromptList, ExistingNoSeriesToChangeList, UpdateForNextYear); @@ -97,7 +100,8 @@ codeunit 334 "No. Series Cop. Change Intent" implements "AOAI Function" .Replace(NumberOfAddedTablesPlaceholderLbl, Format(ActualTablesChunkSize))); ToolResults.Add(ToolsImpl.ConvertListToText(ChangeNoSeriesPrompt), ActualTablesChunkSize); - end + end; + Progress.Close(); end; [TryFunction] diff --git a/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Tools/NoSeriesCopNxtYrIntent.Codeunit.al b/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Tools/NoSeriesCopNxtYrIntent.Codeunit.al index 21d5effda1..9babc47e9f 100644 --- a/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Tools/NoSeriesCopNxtYrIntent.Codeunit.al +++ b/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Tools/NoSeriesCopNxtYrIntent.Codeunit.al @@ -17,7 +17,7 @@ codeunit 349 "No. Series Cop. Nxt Yr. Intent" implements "AOAI Function" var Telemetry: Codeunit Telemetry; - FunctionNameLbl: Label 'GenerateNextYearNumberSeries', Locked = true; + FunctionNameLbl: Label 'PrepareNextYearNumberSeries', Locked = true; TelemetryTool3DefinitionRetrievalErr: Label 'Unable to retrieve the definition for No. Series Copilot Tool 3 from Azure Key Vault.', Locked = true; ToolLoadingErr: Label 'Unable to load the No. Series Copilot Tool 3. Please try again later.'; @@ -45,7 +45,7 @@ codeunit 349 "No. Series Cop. Nxt Yr. Intent" implements "AOAI Function" var AzureKeyVault: Codeunit "Azure Key Vault"; begin - if not AzureKeyVault.GetAzureKeyVaultSecret('NoSeriesCopilotTool3Definition', Definition) then begin + if not AzureKeyVault.GetAzureKeyVaultSecret('NoSeriesCopilotTool3DefinitionV2', Definition) then begin Telemetry.LogMessage('0000ND9', TelemetryTool3DefinitionRetrievalErr, Verbosity::Error, DataClassification::SystemMetadata); Error(ToolLoadingErr); end; diff --git a/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Tools/NoSeriesCopToolsImpl.Codeunit.al b/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Tools/NoSeriesCopToolsImpl.Codeunit.al index 7fc97a5beb..c132c22a73 100644 --- a/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Tools/NoSeriesCopToolsImpl.Codeunit.al +++ b/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Tools/NoSeriesCopToolsImpl.Codeunit.al @@ -225,32 +225,21 @@ codeunit 336 "No. Series Cop. Tools Impl." procedure IsRelevant(TableMetadata: Record "Table Metadata"; Field: Record "Field"; Entities: List of [Text]): Boolean var - RecordMatchMgtCopy: Codeunit "Record Match Impl."; + TextMatchImpl: Codeunit "No. Series Text Match Impl."; Entity: Text[250]; String1: Text[250]; String2: Text[250]; - Score: Decimal; begin 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, GetMatchLengthThreshold(), 100) / 100; - if Score >= RequiredNearness() then + String1 := RemoveTextPart(TableMetadata.Name, '& ') + ' ' + Field.FieldName; + String2 := Entity; + + if TextMatchImpl.IsRelevant(String1, String2) then exit(true); end; exit(false); end; - local procedure GetMatchLengthThreshold(): Decimal - begin - exit(2); - end; - - local procedure RequiredNearness(): Decimal - begin - exit(0.9) - end; - procedure GenerateChunkedTablesListInYamlFormat(var TablesYamlList: List of [Text]; var TempSetupTable: Record "Table Metadata" temporary; var TempNoSeriesField: Record "Field" temporary; var NumberOfAddedTables: Integer) begin Clear(TablesYamlList); diff --git a/src/Business Foundation/App/NoSeriesCopilot/src/Register/NoSeriesCopilotRegister.Codeunit.al b/src/Business Foundation/App/NoSeriesCopilot/src/Register/NoSeriesCopilotRegister.Codeunit.al index c206500036..cbab6bd7b7 100644 --- a/src/Business Foundation/App/NoSeriesCopilot/src/Register/NoSeriesCopilotRegister.Codeunit.al +++ b/src/Business Foundation/App/NoSeriesCopilot/src/Register/NoSeriesCopilotRegister.Codeunit.al @@ -41,6 +41,6 @@ codeunit 327 "No. Series Copilot Register" end; var - LearnMoreUrlTxt: Label 'https://go.microsoft.com/fwlink/?linkid=[id]', Locked = true; //TODO: replace 'id' when docs page is ready + LearnMoreUrlTxt: Label 'https://go.microsoft.com/fwlink/?linkid=2294514', Locked = true; } \ No newline at end of file