Dynamics 365 Business Central: Microsoft standard AI features and prompts.

The new Dynamics 365 Business Central 23.2 release unlocks the new Copilot Developer Toolkit (more info here) for creating generative-AI experiences inside the ERP on online sandboxes.

The advantages of using this toolkit include:

  • Designing solutions that adhere to Responsible AI principles.
  • Creating a unified Copilot experience.
  • Accelerating time to market.

You can now spin up a 23.2 sandbox and then start creating generative-AI features with the new UI or test Microsoft standard generative-AI features, like the new bank account reconcilitation feature, that was enhanced with:

  • AI-powered transaction matching that complements rule-based matching and further reduces the remaining unmatched transactions that require review.
  • AI-powered G/L account suggestions where Copilot suggests the most likely ledger account to post any residual transactions to and offers the opportunity to remember a specific transaction description for the next reconciliation.

In the past months when talking about introducing generative-AI features in Dynamics 365 Business Central I’ve always emphasized the concept of Prompts and Prompt Engineering.

A prompt is a natural language request submitted to a language model to receive a response back. Prompts can contain questions, instructions, contextual information, examples, and partial input for the model in order to have a response that is relevant and complete for the context. Prompt engineering is the process where you guide generative artificial intelligence (generative AI) solutions to generate desired outputs by working on prompts.

A common AI prompt process is the following:

I always say that prompt is key in AI. Without a good prompt, you don’t have good responses and I thin you already know the pattern:

After the last events and talks showing these features, lots of you asked for having prompt samples from Microsoft.

At the moment, there are no shared prompt samples from Microsoft because creating a prompt depends on the context and on the use-case. Lots of you also asked if it’s possible to have the prompt used by Microsoft for the standard AI features actually released on Business Central.

If you inspect the source code of the AI-based bank account reconciliation feature and expecially the BankRecAIMatchingImpl codeunit, you can see that there’s a GenerateMatchProposals procedure with the following call:

CompletionTaskTxt := BankRecAIMatchingImpl.BuildBankRecCompletionTask(true);

The BuildBankRecCompletionTask procedure is used to generate part of the AI prompt needed for the bank account reconciliation in the following way:

[NonDebuggable]
procedure BuildBankRecCompletionTask(IncludeFewShotExample: Boolean): Text
var
CompletionTaskTxt: Text;
CompletionTaskPartTxt: Text;
CompletionTaskBuildingFromKeyVaultFailed: Boolean;
begin
if GetAzureKeyVaultSecret(CompletionTaskPartTxt, 'BankAccRecAIMatching1') then
CompletionTaskTxt := CompletionTaskPartTxt
else
CompletionTaskBuildingFromKeyVaultFailed := true;

if GetAzureKeyVaultSecret(CompletionTaskPartTxt, 'BankAccRecAIMatching2') then
CompletionTaskTxt += CompletionTaskPartTxt
else
CompletionTaskBuildingFromKeyVaultFailed := true;

if GetAzureKeyVaultSecret(CompletionTaskPartTxt, 'BankAccRecAIMatching3') then
CompletionTaskTxt += CompletionTaskPartTxt
else
CompletionTaskBuildingFromKeyVaultFailed := true;

if GetAzureKeyVaultSecret(CompletionTaskPartTxt, 'BankAccRecAIMatching4') then
CompletionTaskTxt += CompletionTaskPartTxt
else
CompletionTaskBuildingFromKeyVaultFailed := true;

if GetAzureKeyVaultSecret(CompletionTaskPartTxt, 'BankAccRecAIMatching5') then
CompletionTaskTxt += CompletionTaskPartTxt
else
CompletionTaskBuildingFromKeyVaultFailed := true;

if GetAzureKeyVaultSecret(CompletionTaskPartTxt, 'BankAccRecAIMatching6') then
CompletionTaskTxt += CompletionTaskPartTx
else
CompletionTaskBuildingFromKeyVaultFailed := true;

if CompletionTaskBuildingFromKeyVaultFailed then begin
Session.LogMessage('0000LFJ', TelemetryConstructingPromptFailedErr, Verbosity::Error, DataClassification::SystemMetadata, TelemetryScope::All, 'Category', FeatureName());
Error(ConstructingPromptFailedErr);
end;

As you can see in the above code, the procedure retrieves the various parts of the prompt by using the GetAzureKeyVaultSecret procedure, that simply retrieves the string from an Azure KeyVault secret in a Microsoft’s Azure keyVault instance. The prompt is not defined in clear in the source code.

The BuildBankRecCompletionTask procedure also provides a sample for the prompt (useful to train the model response):

if (IncludeFewShotExample) then begin
CompletionTaskTxt += '\n**Example 1**:\n';
CompletionTaskTxt += 'Statement Line: Id: 1, Description: A, Amount: 100, Date: 2023-07-01\n';
CompletionTaskTxt += 'Ledger Entry: Id: 11, DocumentNo: 111, Description: A, Amount: 100, Date: 2023-07-01\n';
CompletionTaskTxt += 'Matches: (1, [11])\n';
CompletionTaskTxt += '\n**Example 2**:\n';
CompletionTaskTxt += 'Statement Line: Id: 2, Description: B, Amount: 200, Date: 2023-07-02\n';
CompletionTaskTxt += 'Ledger Entry: Id: 22, DocumentNo: 222, Description: B, Amount: 100, Date: 2023-07-02\n';
CompletionTaskTxt += 'Ledger Entry: Id: 23, DocumentNo: 223, Description: B, Amount: 100, Date: 2023-07-02\n';
CompletionTaskTxt += 'Matches: (2, [22, 23])\n\n';
CompletionTaskTxt += '\n**Example 3**:\n';
CompletionTaskTxt += 'Statement Line: Id: 3, Description: C, Amount: 237, Date: 2023-07-02\n';
CompletionTaskTxt += 'Ledger Entry: Id: 32, DocumentNo: 322, Description: D, Amount: 205, Date: 2023-07-02\n';
CompletionTaskTxt += 'Ledger Entry: Id: 33, DocumentNo: 323, Description: E, Amount: 237, Date: 2023-07-02\n';
CompletionTaskTxt += 'Matches: (3, [33])\n\n';
CompletionTaskTxt += '\n**Example 4**:\n';
CompletionTaskTxt += 'Statement Line: Id: 4, Description: F, Amount: 248, Date: 2023-07-02\n';
CompletionTaskTxt += 'Ledger Entry: Id: 42, DocumentNo: 422, Description: G, Amount: 248, Date: 2023-07-02\n';
CompletionTaskTxt += 'Ledger Entry: Id: 43, DocumentNo: 423, Description: H, Amount: 248, Date: 2023-07-03\n';
CompletionTaskTxt += '\n**Example 5**:\n';
CompletionTaskTxt += 'Statement Line: Id: 5, Description: I 522, Amount: 248, Date: 2023-07-02\n';
CompletionTaskTxt += 'Statement Line: Id: 6, Description: I 522, Amount: 100, Date: 2023-07-05\n';
CompletionTaskTxt += 'Ledger Entry: Id: 52, DocumentNo: 522, Description: J, Amount: 348, Date: 2023-07-02\n';
CompletionTaskTxt += 'Matches: (5, [52]), (6, [52])\n\n';
end;

The full prompt is then created with the following call:

CompletionPromptTxt := BankRecAIMatchingImpl.BuildBankRecCompletionPrompt(CompletionTaskTxt, BankRecStatementLinesTxt, BankRecLedgerEntriesTxt);

and here the BuildBankRecCompletionPrompt procedure definition:

procedure BuildBankRecCompletionPrompt(taskPrompt: Text; StatementLines: Text; LedgerLines: Text): Text
begin
LedgerLines += '"""\n**Matches**:'; // close the ledger lines section
StatementLines += '"""\n'; // close the statement lines section
exit(taskPrompt + StatementLines + LedgerLines);
end;

What can you see here is that:

  • The Microsoft prompt is protected as an Azure KeyVault secret.
  • Prompt can be often be long and complex and must be fine-tuned during time, so it’s always better to avoid storing it into the source code but load it from a KeyVault or from a blob storage file (I personally adopt this second option in all my apps when I have a complex prompt that must be refined during time).
  • Providing samples inside the prompt text can help the AI model on giving better responses.

Regarding Microsoft’s prompts, there are no plans at the moment to make that prompts available and shared to everyone. Prompts are not part of the Business Central open source code initiative and Microsoft has plans to fine-tune their prompts during time accordingly to the AI feature usage (that’s the reason why they are handled externally and in a secret way). This is aligned also with all the Microsoft’s Copilot features in all other products.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.