Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
12 changes: 12 additions & 0 deletions src/System Application/App/AI/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,18 @@
"name": "Client Type Management",
"publisher": "Microsoft",
"version": "27.0.0.0"
},
{
"id": "e31ad830-3d46-472e-afeb-1d3d35247943",
"name": "BLOB Storage",
"publisher": "Microsoft",
"version": "27.0.0.0"
},
{
"id": "0846d207-5dec-4c1b-afd8-6a25e1e14b9d",
"name": "Base64 Convert",
"publisher": "Microsoft",
"version": "27.0.0.0"
}
],
"screenshots": [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
// ------------------------------------------------------------------------------------------------

namespace System.AI;
using System.Environment;
using System.Utilities;

/// <summary>
/// Helper functions for the AOAI Chat Message table.
Expand Down Expand Up @@ -59,6 +61,70 @@ codeunit 7763 "AOAI Chat Messages"
AOAIChatMessagesImpl.AddUserMessage(NewMessage, NewName);
end;

/// <summary>
/// Adds a user message containing text and an image from a URL to the chat messages history.
/// </summary>
/// <param name="UserText">The text part of the message.</param>
/// <param name="ImageUrl">The URL of the image (HTTPS recommended).</param>
/// <param name="DetailLevel">The detail level for image processing.</param>
[NonDebuggable]
procedure AddUserMessage(UserText: Text; ImageUrl: Text; DetailLevel: Enum "AOAI Image Detail Level")
begin
AOAIChatMessagesImpl.AddUserMessage(UserText, ImageUrl, DetailLevel);
end;

/// <summary>
/// Adds a user message containing text and an image from a stream to the chat messages history.
/// The image stream will be Base64 encoded.
/// </summary>
/// <param name="UserText">The text part of the message.</param>
/// <param name="ImageStream">The InStream containing the image data.</param>
/// <param name="FileExtension">The file extension of the image (e.g., 'png', 'jpg') used to determine the MIME type.</param>
/// <param name="DetailLevel">The detail level for image processing.</param>
[NonDebuggable]
procedure AddUserMessage(UserText: Text; var ImageStream: InStream; FileExtension: Text; DetailLevel: Enum "AOAI Image Detail Level")
begin
AOAIChatMessagesImpl.AddUserMessage(UserText, ImageStream, FileExtension, DetailLevel);
end;

/// <summary>
/// Adds a user message containing text and images from a MediaSet to the chat messages history.
/// </summary>
/// <param name="UserText">The text part of the message.</param>
/// <param name="MediaSetId">The Guid of the MediaSet containing the images.</param>
/// <param name="DetailLevel">The detail level for image processing.</param>
[NonDebuggable]
procedure AddUserMessage(UserText: Text; MediaSetId: Guid; DetailLevel: Enum "AOAI Image Detail Level")
begin
AOAIChatMessagesImpl.AddUserMessage(UserText, MediaSetId, DetailLevel);
end;


/// <summary>
/// Adds a user message containing text and an image from a Tenant Media record to the chat messages history.
/// </summary>
/// <param name="UserText">The text part of the message.</param>
/// <param name="TenantMedia">The Tenant Media record containing the image.</param>
/// <param name="DetailLevel">The detail level for image processing.</param>
[NonDebuggable]
procedure AddUserMessage(UserText: Text; TenantMedia: Record "Tenant Media"; DetailLevel: Enum "AOAI Image Detail Level")
begin
AOAIChatMessagesImpl.AddUserMessage(UserText, TenantMedia, DetailLevel);
end;

/// <summary>
/// Adds a user message containing text and an image from a Temp Blob to the chat messages history.
/// </summary>
/// <param name="UserText">The text part of the message.</param>
/// <param name="TempBlob">The Temp Blob codeunit containing the image data.</param>
/// <param name="FileExtension">The file extension of the image in the Temp Blob (e.g., 'png', 'jpg').</param>
/// <param name="DetailLevel">The detail level for image processing.</param>
[NonDebuggable]
procedure AddUserMessage(UserText: Text; var TempBlob: Codeunit "Temp Blob"; FileExtension: Text; DetailLevel: Enum "AOAI Image Detail Level")
begin
AOAIChatMessagesImpl.AddUserMessage(UserText, TempBlob, FileExtension, DetailLevel);
end;

/// <summary>
/// Adds a assistant message to the chat messages history.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace System.AI;

using System.Azure.KeyVault;
using System.Environment;
using System.Utilities;
using System.Telemetry;

codeunit 7764 "AOAI Chat Messages Impl"
Expand Down Expand Up @@ -69,6 +70,76 @@ codeunit 7764 "AOAI Chat Messages Impl"
AddMessage(NewMessage, NewName, Enum::"AOAI Chat Roles"::User);
end;

[NonDebuggable]
procedure AddUserMessage(UserText: Text; ImageUrl: Text; DetailLevel: Enum "AOAI Image Detail Level")
var
AOAIImagesImpl: Codeunit "AOAI Images Impl";
ContentAsText: Text;
begin
Initialize();
ContentAsText := AOAIImagesImpl.PrepareUserMessageContentFromUrl(UserText, ImageUrl, DetailLevel);
if ContentAsText = '' then
exit;

AddMessage(ContentAsText, '', Enum::"AOAI Chat Roles"::User);
end;

[NonDebuggable]
procedure AddUserMessage(UserText: Text; var ImageStream: InStream; FileExtension: Text; DetailLevel: Enum "AOAI Image Detail Level")
var
AOAIImagesImpl: Codeunit "AOAI Images Impl";
ContentAsText: Text;
begin
Initialize();
ContentAsText := AOAIImagesImpl.PrepareUserMessageContentFromStream(UserText, ImageStream, FileExtension, DetailLevel);
if ContentAsText = '' then
exit;

AddMessage(ContentAsText, '', Enum::"AOAI Chat Roles"::User);
end;

[NonDebuggable]
procedure AddUserMessage(UserText: Text; MediaSetId: Guid; DetailLevel: Enum "AOAI Image Detail Level")
var
AOAIImagesImpl: Codeunit "AOAI Images Impl";
ContentAsText: Text;
begin
Initialize();
ContentAsText := AOAIImagesImpl.PrepareUserMessageContentFromMediaSet(UserText, MediaSetId, DetailLevel);
if ContentAsText = '' then
exit;

AddMessage(ContentAsText, '', Enum::"AOAI Chat Roles"::User);
end;

[NonDebuggable]
procedure AddUserMessage(UserText: Text; TenantMedia: Record "Tenant Media"; DetailLevel: Enum "AOAI Image Detail Level")
var
AOAIImagesImpl: Codeunit "AOAI Images Impl";
ContentAsText: Text;
begin
Initialize();
ContentAsText := AOAIImagesImpl.PrepareUserMessageContentFromMediaRecord(UserText, TenantMedia, DetailLevel);
if ContentAsText = '' then
exit;

AddMessage(ContentAsText, '', Enum::"AOAI Chat Roles"::User);
end;

[NonDebuggable]
procedure AddUserMessage(UserText: Text; var TempBlob: Codeunit "Temp Blob"; FileExtension: Text; DetailLevel: Enum "AOAI Image Detail Level")
var
AOAIImagesImpl: Codeunit "AOAI Images Impl";
ContentAsText: Text;
begin
Initialize();
ContentAsText := AOAIImagesImpl.PrepareUserMessageContentFromTempBlob(UserText, TempBlob, FileExtension, DetailLevel);
if ContentAsText = '' then
exit;

AddMessage(ContentAsText, '', Enum::"AOAI Chat Roles"::User);
end;

[NonDebuggable]
procedure AddAssistantMessage(NewMessage: Text)
begin
Expand Down Expand Up @@ -239,10 +310,11 @@ codeunit 7764 "AOAI Chat Messages Impl"
Message := WrapUserMessages(AzureOpenAIImpl.RemoveProhibitedCharacters(Message))
else
Message := AzureOpenAIImpl.RemoveProhibitedCharacters(Message);

if ToolCalls.Count() > 0 then
MessageJsonObject.Add('tool_calls', ToolCalls)
else
MessageJsonObject.Add('content', Message);
AddContentToMessage(Message, MessageJsonObject);

if Name <> '' then
MessageJsonObject.Add('name', Name);
Expand All @@ -258,6 +330,38 @@ codeunit 7764 "AOAI Chat Messages Impl"
MessagesTokenCount := AOAIToken.GetGPT4TokenCount(TotalMessages);
end;

local procedure AddContentToMessage(Message: Text; var MessageJsonObject: JsonObject)
begin
AddTextContentToMessage(Message, MessageJsonObject);
AddImageContentToMessage(Message, MessageJsonObject);
end;

local procedure AddTextContentToMessage(Message: Text; var MessageJsonObject: JsonObject)
begin
if CheckIfImageContent(Message) then
exit;

MessageJsonObject.Add('content', Message);
end;

local procedure AddImageContentToMessage(Message: Text; var MessageJsonObject: JsonObject)
var
AOAIImagesImpl: Codeunit "AOAI Images Impl";
begin
if not CheckIfImageContent(Message) then
exit;

MessageJsonObject.Add('content', AOAIImagesImpl.ReadImageContent(Message));
end;

local procedure CheckIfImageContent(Message: Text): Boolean
var
AOAIImagesImpl: Codeunit "AOAI Images Impl";
begin
exit(AOAIImagesImpl.CheckIfImageContent(Message));
end;


local procedure Initialize()
begin
if Initialized then
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// ------------------------------------------------------------------------------------------------
// 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;

/// <summary>
/// Specifies the detail level for image processing in vision-enabled models.
/// </summary>
enum 7770 "AOAI Image Detail Level"
{
Extensible = true;
Access = Public;

value(0; low)
{
Caption = 'low';
}
value(1; high)
{
Caption = 'high';
}
value(2; auto)
{
Caption = 'auto';
}
}
Loading
Loading