diff --git a/src/Infrastructure/BotSharp.Abstraction/Files/IBotSharpFileService.cs b/src/Infrastructure/BotSharp.Abstraction/Files/IBotSharpFileService.cs index 9c27d7ff6..272abf0df 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Files/IBotSharpFileService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Files/IBotSharpFileService.cs @@ -3,7 +3,8 @@ namespace BotSharp.Abstraction.Files; public interface IBotSharpFileService { string GetDirectory(string conversationId); - IEnumerable GetConversationFiles(string conversationId, string messageId); + IEnumerable GetChatImages(string conversationId, List conversations, int offset = 2); + IEnumerable GetMessageFiles(string conversationId, IEnumerable messageIds, bool imageOnly = false); string? GetMessageFile(string conversationId, string messageId, string fileName); void SaveMessageFiles(string conversationId, string messageId, List files); @@ -17,4 +18,11 @@ public interface IBotSharpFileService /// bool DeleteMessageFiles(string conversationId, IEnumerable messageIds, string targetMessageId, string? newMessageId = null); bool DeleteConversationFiles(IEnumerable conversationIds); + + /// + /// Get file bytes and content type from data, e.g., "data:image/png;base64,aaaaaaaaa" + /// + /// + /// + (string, byte[]) GetFileInfoFromData(string data); } diff --git a/src/Infrastructure/BotSharp.Abstraction/Files/Models/BotSharpFile.cs b/src/Infrastructure/BotSharp.Abstraction/Files/Models/BotSharpFile.cs index f679d52e1..de226f58c 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Files/Models/BotSharpFile.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Files/Models/BotSharpFile.cs @@ -4,14 +4,14 @@ namespace BotSharp.Abstraction.Files.Models; public class BotSharpFile { [JsonPropertyName("file_name")] - public string FileName { get; set; } + public string FileName { get; set; } = string.Empty; + /// + /// File data, e.g., "data:image/png;base64,aaaaaaaa" + /// [JsonPropertyName("file_data")] - public string FileData { get; set; } + public string FileData { get; set; } = string.Empty; - [JsonPropertyName("content_type")] - public string ContentType { get; set; } - - [JsonPropertyName("file_size")] - public int FileSize { get; set; } + [JsonPropertyName("file_url")] + public string FileUrl { get; set; } = string.Empty; } diff --git a/src/Infrastructure/BotSharp.Abstraction/Files/Models/MessageFileModel.cs b/src/Infrastructure/BotSharp.Abstraction/Files/Models/MessageFileModel.cs new file mode 100644 index 000000000..3ec63fd83 --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Files/Models/MessageFileModel.cs @@ -0,0 +1,32 @@ +namespace BotSharp.Abstraction.Files.Models; + +public class MessageFileModel +{ + [JsonPropertyName("message_id")] + public string MessageId { get; set; } + + [JsonPropertyName("file_url")] + public string FileUrl { get; set; } + + [JsonPropertyName("file_storage_url")] + public string FileStorageUrl { get; set; } + + [JsonPropertyName("file_name")] + public string FileName { get; set; } + + [JsonPropertyName("file_type")] + public string FileType { get; set; } + + [JsonPropertyName("content_type")] + public string ContentType { get; set; } + + public MessageFileModel() + { + + } + + public override string ToString() + { + return $"File name: {FileName}, File type: {FileType}, Content type: {ContentType}"; + } +} diff --git a/src/Infrastructure/BotSharp.Abstraction/Files/Models/OutputFileModel.cs b/src/Infrastructure/BotSharp.Abstraction/Files/Models/OutputFileModel.cs deleted file mode 100644 index 962b01e10..000000000 --- a/src/Infrastructure/BotSharp.Abstraction/Files/Models/OutputFileModel.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace BotSharp.Abstraction.Files.Models; - -public class OutputFileModel -{ - [JsonPropertyName("file_url")] - public string FileUrl { get; set; } - - [JsonPropertyName("file_name")] - public string FileName { get; set; } - - [JsonPropertyName("file_type")] - public string FileType { get; set; } -} diff --git a/src/Infrastructure/BotSharp.Abstraction/MLTasks/ILlmProviderService.cs b/src/Infrastructure/BotSharp.Abstraction/MLTasks/ILlmProviderService.cs index 75fd60e65..120304d2c 100644 --- a/src/Infrastructure/BotSharp.Abstraction/MLTasks/ILlmProviderService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/MLTasks/ILlmProviderService.cs @@ -6,6 +6,6 @@ public interface ILlmProviderService { LlmModelSetting GetSetting(string provider, string model); List GetProviders(); - LlmModelSetting GetProviderModel(string provider, string id); + LlmModelSetting GetProviderModel(string provider, string id, bool multiModal = false); List GetProviderModels(string provider); } diff --git a/src/Infrastructure/BotSharp.Abstraction/MLTasks/Settings/LlmModelSetting.cs b/src/Infrastructure/BotSharp.Abstraction/MLTasks/Settings/LlmModelSetting.cs index 1faf3c52a..b86578fe5 100644 --- a/src/Infrastructure/BotSharp.Abstraction/MLTasks/Settings/LlmModelSetting.cs +++ b/src/Infrastructure/BotSharp.Abstraction/MLTasks/Settings/LlmModelSetting.cs @@ -27,6 +27,11 @@ public class LlmModelSetting public string Endpoint { get; set; } public LlmModelType Type { get; set; } = LlmModelType.Chat; + /// + /// If true, allow sending images/vidoes to this model + /// + public bool MultiModal { get; set; } + /// /// Prompt cost per 1K token /// diff --git a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj index 8d05c40b1..0ddc52e83 100644 --- a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj +++ b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj @@ -159,6 +159,7 @@ + diff --git a/src/Infrastructure/BotSharp.Core/Files/BotSharpFileService.cs b/src/Infrastructure/BotSharp.Core/Files/BotSharpFileService.cs index ad687274e..d7e961be4 100644 --- a/src/Infrastructure/BotSharp.Core/Files/BotSharpFileService.cs +++ b/src/Infrastructure/BotSharp.Core/Files/BotSharpFileService.cs @@ -1,3 +1,4 @@ +using Microsoft.AspNetCore.StaticFiles; using System.IO; using System.Threading; @@ -7,16 +8,22 @@ public class BotSharpFileService : IBotSharpFileService { private readonly BotSharpDatabaseSettings _dbSettings; private readonly IServiceProvider _services; + private readonly ILogger _logger; private readonly string _baseDir; + private readonly IEnumerable _allowedTypes = new List { "image/png", "image/jpeg" }; private const string CONVERSATION_FOLDER = "conversations"; private const string FILE_FOLDER = "files"; + private const int MIN_OFFSET = 1; + private const int MAX_OFFSET = 5; public BotSharpFileService( BotSharpDatabaseSettings dbSettings, + ILogger logger, IServiceProvider services) { _dbSettings = dbSettings; + _logger = logger; _services = services; _baseDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, dbSettings.FileRepository); } @@ -31,29 +38,67 @@ public string GetDirectory(string conversationId) return dir; } - public IEnumerable GetConversationFiles(string conversationId, string messageId) + public IEnumerable GetChatImages(string conversationId, List conversations, int offset = 2) { - var outputFiles = new List(); - var dir = GetConversationFileDirectory(conversationId, messageId); - if (string.IsNullOrEmpty(dir)) + var files = new List(); + if (string.IsNullOrEmpty(conversationId) || conversations.IsNullOrEmpty()) + { + return files; + } + + if (offset <= 0) + { + offset = MIN_OFFSET; + } + else if (offset > MAX_OFFSET) { - return outputFiles; + offset = MAX_OFFSET; } - foreach (var file in Directory.GetFiles(dir)) + var messageIds = conversations.Select(x => x.MessageId).Distinct().TakeLast(offset).ToList(); + files = GetMessageFiles(conversationId, messageIds, imageOnly: true).ToList(); + return files; + } + + public IEnumerable GetMessageFiles(string conversationId, IEnumerable messageIds, bool imageOnly = false) + { + var files = new List(); + if (messageIds.IsNullOrEmpty()) return files; + + foreach (var messageId in messageIds) { - var fileName = Path.GetFileNameWithoutExtension(file); - var extension = Path.GetExtension(file); - var fileType = extension.Substring(1); - var model = new OutputFileModel() + var dir = GetConversationFileDirectory(conversationId, messageId); + if (string.IsNullOrEmpty(dir)) { - FileUrl = $"/conversation/{conversationId}/message/{messageId}/file/{fileName}", - FileName = fileName, - FileType = fileType - }; - outputFiles.Add(model); + continue; + } + + foreach (var file in Directory.GetFiles(dir)) + { + var contentType = GetFileContentType(file); + if (imageOnly && !_allowedTypes.Contains(contentType)) + { + continue; + } + + var fileName = Path.GetFileNameWithoutExtension(file); + var extension = Path.GetExtension(file); + var fileType = extension.Substring(1); + + var model = new MessageFileModel() + { + MessageId = messageId, + FileUrl = $"/conversation/{conversationId}/message/{messageId}/file/{fileName}", + FileStorageUrl = file, + FileName = fileName, + FileType = fileType, + ContentType = contentType + }; + files.Add(model); + } } - return outputFiles; + + return files; } public string? GetMessageFile(string conversationId, string messageId, string fileName) @@ -75,19 +120,26 @@ public void SaveMessageFiles(string conversationId, string messageId, List conversationIds) return true; } + public (string, byte[]) GetFileInfoFromData(string data) + { + if (string.IsNullOrEmpty(data)) + { + return (string.Empty, new byte[0]); + } + + var typeStartIdx = data.IndexOf(':'); + var typeEndIdx = data.IndexOf(';'); + var contentType = data.Substring(typeStartIdx + 1, typeEndIdx - typeStartIdx - 1); + + var base64startIdx = data.IndexOf(','); + var base64Str = data.Substring(base64startIdx + 1); + + return (contentType, Convert.FromBase64String(base64Str)); + } + #region Private methods private string GetConversationFileDirectory(string? conversationId, string? messageId, bool createNewDir = false) { @@ -170,54 +239,16 @@ private string GetConversationFileDirectory(string? conversationId, string? mess return dir; } - private byte[] GetFileBytes(string data) - { - if (string.IsNullOrEmpty(data)) - { - return new byte[0]; - } - - var startIdx = data.IndexOf(','); - var base64Str = data.Substring(startIdx + 1); - return Convert.FromBase64String(base64Str); - } - - private string GetFileType(string data) + private string GetFileContentType(string filePath) { - if (string.IsNullOrEmpty(data)) + string contentType; + var provider = new FileExtensionContentTypeProvider(); + if (!provider.TryGetContentType(filePath, out contentType)) { - return string.Empty; + contentType = string.Empty; } - var startIdx = data.IndexOf(':'); - var endIdx = data.IndexOf(';'); - var fileType = data.Substring(startIdx + 1, endIdx - startIdx - 1); - return fileType; - } - - private string ParseFileFormat(string type) - { - var parsed = string.Empty; - switch (type) - { - case "image/png": - parsed = ".png"; - break; - case "image/jpeg": - case "image/jpg": - parsed = ".jpeg"; - break; - case "application/pdf": - parsed = ".pdf"; - break; - case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": - parsed = ".xlsx"; - break; - case "text/plain": - parsed = ".txt"; - break; - } - return parsed; + return contentType; } #endregion } diff --git a/src/Infrastructure/BotSharp.Core/Infrastructures/CompletionProvider.cs b/src/Infrastructure/BotSharp.Core/Infrastructures/CompletionProvider.cs index c55ed9a8c..ace1e6642 100644 --- a/src/Infrastructure/BotSharp.Core/Infrastructures/CompletionProvider.cs +++ b/src/Infrastructure/BotSharp.Core/Infrastructures/CompletionProvider.cs @@ -35,10 +35,13 @@ public static object GetCompletion(IServiceProvider services, public static IChatCompletion GetChatCompletion(IServiceProvider services, string? provider = null, string? model = null, + string? modelId = null, + bool multiModal = false, AgentLlmConfig? agentConfig = null) { var completions = services.GetServices(); - (provider, model) = GetProviderAndModel(services, provider: provider, model: model, agentConfig: agentConfig); + (provider, model) = GetProviderAndModel(services, provider: provider, model: model, modelId: modelId, + multiModal: multiModal, agentConfig: agentConfig); var completer = completions.FirstOrDefault(x => x.Provider == provider); if (completer == null) @@ -47,7 +50,7 @@ public static IChatCompletion GetChatCompletion(IServiceProvider services, logger.LogError($"Can't resolve completion provider by {provider}"); } - completer.SetModelName(model); + completer?.SetModelName(model); return completer; } @@ -55,6 +58,8 @@ public static IChatCompletion GetChatCompletion(IServiceProvider services, private static (string, string) GetProviderAndModel(IServiceProvider services, string? provider = null, string? model = null, + string? modelId = null, + bool multiModal = false, AgentLlmConfig? agentConfig = null) { var agentSetting = services.GetRequiredService(); @@ -73,11 +78,11 @@ private static (string, string) GetProviderAndModel(IServiceProvider services, { model = state.GetState("model", model ?? "gpt-35-turbo-4k"); } - else if (state.ContainsState("model_id")) + else if (state.ContainsState("model_id") || !string.IsNullOrEmpty(modelId)) { - var modelId = state.GetState("model_id"); + var modelIdentity = state.ContainsState("model_id") ? state.GetState("model_id") : modelId; var llmProviderService = services.GetRequiredService(); - model = llmProviderService.GetProviderModel(provider, modelId)?.Name; + model = llmProviderService.GetProviderModel(provider, modelIdentity, multiModal)?.Name; } } diff --git a/src/Infrastructure/BotSharp.Core/Infrastructures/LlmProviderService.cs b/src/Infrastructure/BotSharp.Core/Infrastructures/LlmProviderService.cs index eb92ac519..7d92a6877 100644 --- a/src/Infrastructure/BotSharp.Core/Infrastructures/LlmProviderService.cs +++ b/src/Infrastructure/BotSharp.Core/Infrastructures/LlmProviderService.cs @@ -44,10 +44,10 @@ public List GetProviderModels(string provider) ?.Models ?? new List(); } - public LlmModelSetting GetProviderModel(string provider, string id) + public LlmModelSetting GetProviderModel(string provider, string id, bool multiModal = false) { var models = GetProviderModels(provider) - .Where(x => x.Id == id) + .Where(x => x.Id == id && x.MultiModal == multiModal) .ToList(); var random = new Random(); diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs index 6bdac0eff..6046c5bbd 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs @@ -17,18 +17,18 @@ public async Task InvokeAgent(string agentId, List dialog return false; } - var provide = agent.LlmConfig.Provider; + var provider = agent.LlmConfig.Provider; var model = agent.LlmConfig.Model; - if (provide == null || model == null) + if (provider == null || model == null) { var agentSettings = _services.GetRequiredService(); - provide = agentSettings.LlmConfig.Provider; + provider = agentSettings.LlmConfig.Provider; model = agentSettings.LlmConfig.Model; } var chatCompletion = CompletionProvider.GetChatCompletion(_services, - provider: provide, + provider: provider, model: model); var message = dialogs.Last(); diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/FileController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/FileController.cs index a24357a2a..cfae602ca 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/FileController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/FileController.cs @@ -38,10 +38,11 @@ public IActionResult UploadAttachments([FromRoute] string conversationId, } [HttpGet("/conversation/{conversationId}/files/{messageId}")] - public IEnumerable GetConversationFiles([FromRoute] string conversationId, [FromRoute] string messageId) + public IEnumerable GetMessageFiles([FromRoute] string conversationId, [FromRoute] string messageId) { var fileService = _services.GetRequiredService(); - return fileService.GetConversationFiles(conversationId, messageId); + var files = fileService.GetMessageFiles(conversationId, new List { messageId }); + return files?.Select(x => MessageFileViewModel.Transform(x))?.ToList() ?? new List(); } [HttpGet("/conversation/{conversationId}/message/{messageId}/file/{fileName}")] diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/InstructModeController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/InstructModeController.cs index 985526d97..a884fd7e1 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/InstructModeController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/InstructModeController.cs @@ -11,10 +11,12 @@ namespace BotSharp.OpenAPI.Controllers; public class InstructModeController : ControllerBase { private readonly IServiceProvider _services; + private readonly ILogger _logger; - public InstructModeController(IServiceProvider services) + public InstructModeController(IServiceProvider services, ILogger logger) { _services = services; + _logger = logger; } [HttpPost("/instruct/{agentId}")] @@ -72,4 +74,32 @@ public async Task ChatCompletion([FromBody] IncomingMessageModel input) }); return message.Content; } + + [HttpPost("/instruct/multi-modal")] + public async Task MultiModalCompletion([FromBody] IncomingMessageModel input) + { + var state = _services.GetRequiredService(); + input.States.ForEach(x => state.SetState(x.Key, x.Value, activeRounds: x.ActiveRounds, source: StateSource.External)); + + try + { + var completion = CompletionProvider.GetChatCompletion(_services, provider: "openai", modelId: "gpt-4", multiModal: true); + var message = await completion.GetChatCompletions(new Agent() + { + Id = Guid.Empty.ToString(), + }, new List + { + new RoleDialogModel(AgentRole.User, input.Text) + { + Files = input.Files + } + }); + return message.Content; + } + catch (Exception ex) + { + _logger.LogError($"Error in analyzing files. {ex.Message}"); + return $"Error in analyzing files."; + } + } } diff --git a/src/Infrastructure/BotSharp.OpenAPI/Using.cs b/src/Infrastructure/BotSharp.OpenAPI/Using.cs index f3ba775f9..8771b81c0 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Using.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Using.cs @@ -28,4 +28,5 @@ global using BotSharp.Abstraction.Files; global using BotSharp.OpenAPI.ViewModels.Conversations; global using BotSharp.OpenAPI.ViewModels.Users; -global using BotSharp.OpenAPI.ViewModels.Agents; \ No newline at end of file +global using BotSharp.OpenAPI.ViewModels.Agents; +global using BotSharp.OpenAPI.ViewModels.Files; \ No newline at end of file diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Files/MessageFileViewModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Files/MessageFileViewModel.cs new file mode 100644 index 000000000..a9eb33bdd --- /dev/null +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Files/MessageFileViewModel.cs @@ -0,0 +1,34 @@ +using System.Text.Json.Serialization; + +namespace BotSharp.OpenAPI.ViewModels.Files; + +public class MessageFileViewModel +{ + [JsonPropertyName("file_url")] + public string FileUrl { get; set; } + + [JsonPropertyName("file_name")] + public string FileName { get; set; } + + [JsonPropertyName("file_type")] + public string FileType { get; set; } + + [JsonPropertyName("content_type")] + public string ContentType { get; set; } + + public MessageFileViewModel() + { + + } + + public static MessageFileViewModel Transform(MessageFileModel model) + { + return new MessageFileViewModel + { + FileUrl = model.FileUrl, + FileName = model.FileName, + FileType = model.FileType, + ContentType = model.ContentType + }; + } +} diff --git a/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/ChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/ChatCompletionProvider.cs index 07a3ff8f7..d884e3867 100644 --- a/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/ChatCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/ChatCompletionProvider.cs @@ -4,14 +4,19 @@ using BotSharp.Abstraction.Agents.Models; using BotSharp.Abstraction.Conversations; using BotSharp.Abstraction.Conversations.Models; +using BotSharp.Abstraction.Files; +using BotSharp.Abstraction.Files.Models; using BotSharp.Abstraction.Loggers; using BotSharp.Abstraction.MLTasks; +using BotSharp.Abstraction.Utilities; using BotSharp.Plugin.AzureOpenAI.Settings; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; +using System.IO; using System.Linq; +using System.Runtime.InteropServices.ComTypes; using System.Threading.Tasks; namespace BotSharp.Plugin.AzureOpenAI.Providers; @@ -218,6 +223,17 @@ public async Task GetChatCompletionsStreamingAsync(Agent agent, List conversations) { var agentService = _services.GetRequiredService(); + var fileService = _services.GetRequiredService(); + var state = _services.GetRequiredService(); + var settingsService = _services.GetRequiredService(); + var settings = settingsService.GetSetting(Provider, _model); + var allowMultiModal = settings != null && settings.MultiModal; + + var chatFiles = new List(); + if (allowMultiModal) + { + chatFiles = fileService.GetChatImages(state.GetConversationId(), conversations, offset: 2).ToList(); + } var chatCompletionsOptions = new ChatCompletionsOptions(); @@ -279,19 +295,52 @@ public async Task GetChatCompletionsStreamingAsync(Agent agent, List() { - // To display Planner name in log - Name = message.FunctionName, + new ChatMessageTextContentItem(text) }; - if (!string.IsNullOrEmpty(message.ImageUrl)) + var files = chatFiles.Where(x => x.MessageId == message.MessageId).ToList(); + if (!files.IsNullOrEmpty()) + { + foreach (var file in files) + { + using var stream = File.OpenRead(file.FileStorageUrl); + chatItems.Add(new ChatMessageImageContentItem(stream, file.ContentType, ChatMessageImageDetailLevel.Low)); + } + } + + if (allowMultiModal && !message.Files.IsNullOrEmpty()) { - var uri = new Uri(message.ImageUrl); - userMessage.MultimodalContentItems.Add( - new ChatMessageImageContentItem(uri, ChatMessageImageDetailLevel.Low)); + foreach (var file in message.Files) + { + if (!string.IsNullOrEmpty(file.FileUrl)) + { + var uri = new Uri(file.FileUrl); + chatItems.Add(new ChatMessageImageContentItem(uri, ChatMessageImageDetailLevel.Low)); + } + else if (!string.IsNullOrEmpty(file.FileData)) + { + var (contentType, bytes) = fileService.GetFileInfoFromData(file.FileData); + using var stream = new MemoryStream(bytes, 0, bytes.Length); + chatItems.Add(new ChatMessageImageContentItem(stream, contentType, ChatMessageImageDetailLevel.Low)); + } + } } + //if (!string.IsNullOrEmpty(message.ImageUrl)) + //{ + // var uri = new Uri(message.ImageUrl); + // userMessage.MultimodalContentItems.Add( + // new ChatMessageImageContentItem(uri, ChatMessageImageDetailLevel.Low)); + //} + + var userMessage = new ChatRequestUserMessage(chatItems) + { + // To display Planner name in log + Name = message.FunctionName, + }; + chatCompletionsOptions.Messages.Add(userMessage); } else if (message.Role == ChatRole.Assistant) @@ -301,7 +350,7 @@ public async Task GetChatCompletionsStreamingAsync(Agent agent, List(); + //var state = _services.GetRequiredService(); var temperature = float.Parse(state.GetState("temperature", "0.0")); var samplingFactor = float.Parse(state.GetState("sampling_factor", "0.0")); chatCompletionsOptions.Temperature = temperature;