diff --git a/README.md b/README.md index b131c9344..14437028f 100644 --- a/README.md +++ b/README.md @@ -280,7 +280,7 @@ By default, Chat Copilot runs locally without authentication, using a guest user 2. **_Issue:_**: Challenges using text completion models, such as `text-davinci-003` - _Solution_: For OpenAI, see [model endpoint compatibility](https://platform.openai.com/docs/models/) for + _Solution_: For OpenAI, see [model endpoint compatibility](https://platform.openai.com/docs/models/model-endpoint-compatibility) for the complete list of current models supporting chat completions. For Azure OpenAI, see [model summary table and region availability](https://learn.microsoft.com/azure/ai-services/openai/concepts/models#model-summary-table-and-region-availability). 3. **_Issue:_** Localhost SSL certificate errors / CORS errors diff --git a/integration-tests/ChatCopilotIntegrationTests.csproj b/integration-tests/ChatCopilotIntegrationTests.csproj index a622775e5..debb176fc 100644 --- a/integration-tests/ChatCopilotIntegrationTests.csproj +++ b/integration-tests/ChatCopilotIntegrationTests.csproj @@ -15,8 +15,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/memorypipeline/CopilotChatMemoryPipeline.csproj b/memorypipeline/CopilotChatMemoryPipeline.csproj index 6ac29afdb..0906ac571 100644 --- a/memorypipeline/CopilotChatMemoryPipeline.csproj +++ b/memorypipeline/CopilotChatMemoryPipeline.csproj @@ -15,8 +15,8 @@ - - + + diff --git a/plugins/README.md b/plugins/README.md index 937c884be..28ce8162a 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -28,7 +28,7 @@ Read more about plugin authentication here: [Plugin authentication](https://plat ### Prerequisites 1. The name of your plugin. This should be identical to the `NameForHuman` in your plugin manifest. - > Please refer to OpenAI for the [manifest requirements](https://platform.openai.com/docs/plugins/getting-started/). + > Please refer to OpenAI for the [manifest requirements](https://platform.openai.com/docs/plugins/getting-started/plugin-manifest). 2. Url of your plugin. > This should be the root url to your API. Not the manifest url nor the OpenAPI spec url. 3. (Optional) Key of the plugin if it requires one. diff --git a/plugins/shared/PluginManifest.cs b/plugins/shared/PluginManifest.cs index 8ddb72998..0223233df 100644 --- a/plugins/shared/PluginManifest.cs +++ b/plugins/shared/PluginManifest.cs @@ -6,7 +6,7 @@ namespace Plugins.PluginShared; /// /// This class represents the OpenAI plugin manifest: -/// https://platform.openai.com/docs/plugins/getting-started +/// https://platform.openai.com/docs/plugins/getting-started/plugin-manifest /// public class PluginManifest { diff --git a/shared/CopilotChatShared.csproj b/shared/CopilotChatShared.csproj index ec4f16fe2..a70b39e9b 100644 --- a/shared/CopilotChatShared.csproj +++ b/shared/CopilotChatShared.csproj @@ -9,7 +9,7 @@ - + diff --git a/webapi/Controllers/ChatArchiveController.cs b/webapi/Controllers/ChatArchiveController.cs index 8bdd7b75b..a24e061a2 100644 --- a/webapi/Controllers/ChatArchiveController.cs +++ b/webapi/Controllers/ChatArchiveController.cs @@ -174,7 +174,7 @@ private async Task> GetMemoryRecordsAndAppendToEmbeddingsAsync( /// /// The chat id /// The list of chat messages in descending order of the timestamp - private async Task> GetAllChatMessagesAsync(string chatId) + private async Task> GetAllChatMessagesAsync(string chatId) { return (await this._chatMessageRepository.FindByChatIdAsync(chatId)) .OrderByDescending(m => m.Timestamp).ToList(); diff --git a/webapi/Controllers/ChatHistoryController.cs b/webapi/Controllers/ChatHistoryController.cs index d80e6e1ae..dcd81b709 100644 --- a/webapi/Controllers/ChatHistoryController.cs +++ b/webapi/Controllers/ChatHistoryController.cs @@ -98,7 +98,7 @@ public async Task CreateChatSessionAsync( await this._sessionRepository.CreateAsync(newChat); // Create initial bot message - var chatMessage = ChatMessage.CreateBotResponseMessage( + var chatMessage = CopilotChatMessage.CreateBotResponseMessage( newChat.Id, this._promptOptions.InitialBotMessage, string.Empty, // The initial bot message doesn't need a prompt. diff --git a/webapi/Controllers/DocumentController.cs b/webapi/Controllers/DocumentController.cs index e542eb3fd..01a7ea41c 100644 --- a/webapi/Controllers/DocumentController.cs +++ b/webapi/Controllers/DocumentController.cs @@ -440,11 +440,11 @@ private async Task TryStoreMemoryAsync(MemorySource memorySource) /// The target chat-id /// The document message content /// A ChatMessage object if successful, null otherwise - private async Task TryCreateDocumentUploadMessage( + private async Task TryCreateDocumentUploadMessage( Guid chatId, DocumentMessageContent documentMessageContent) { - var chatMessage = ChatMessage.CreateDocumentMessage( + var chatMessage = CopilotChatMessage.CreateDocumentMessage( this._authInfo.UserId, this._authInfo.Name, // User name chatId.ToString(), diff --git a/webapi/CopilotChatWebApi.csproj b/webapi/CopilotChatWebApi.csproj index 28f0cd0c3..102cd3799 100644 --- a/webapi/CopilotChatWebApi.csproj +++ b/webapi/CopilotChatWebApi.csproj @@ -21,18 +21,18 @@ - - - - - - - - - - - - + + + + + + + + + + + + @@ -42,7 +42,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/webapi/Extensions/ISemanticMemoryClientExtensions.cs b/webapi/Extensions/ISemanticMemoryClientExtensions.cs index 850c44516..dc391fb38 100644 --- a/webapi/Extensions/ISemanticMemoryClientExtensions.cs +++ b/webapi/Extensions/ISemanticMemoryClientExtensions.cs @@ -117,7 +117,7 @@ public static async Task StoreDocumentAsync( new DocumentUploadRequest { DocumentId = documentId, - Files = new List { new DocumentUploadRequest.UploadedFile(fileName, fileContent) }, + Files = new List { new(fileName, fileContent) }, Index = indexName, Steps = pipelineSteps, }; diff --git a/webapi/Extensions/ServiceExtensions.cs b/webapi/Extensions/ServiceExtensions.cs index 3eceb9e66..e644891ec 100644 --- a/webapi/Extensions/ServiceExtensions.cs +++ b/webapi/Extensions/ServiceExtensions.cs @@ -182,7 +182,7 @@ internal static IServiceCollection AddCorsPolicy(this IServiceCollection service public static IServiceCollection AddPersistentChatStore(this IServiceCollection services) { IStorageContext chatSessionStorageContext; - IStorageContext chatMessageStorageContext; + IStorageContext chatMessageStorageContext; IStorageContext chatMemorySourceStorageContext; IStorageContext chatParticipantStorageContext; @@ -193,7 +193,7 @@ public static IServiceCollection AddPersistentChatStore(this IServiceCollection case ChatStoreOptions.ChatStoreType.Volatile: { chatSessionStorageContext = new VolatileContext(); - chatMessageStorageContext = new VolatileContext(); + chatMessageStorageContext = new VolatileContext(); chatMemorySourceStorageContext = new VolatileContext(); chatParticipantStorageContext = new VolatileContext(); break; @@ -210,7 +210,7 @@ public static IServiceCollection AddPersistentChatStore(this IServiceCollection string directory = Path.GetDirectoryName(fullPath) ?? string.Empty; chatSessionStorageContext = new FileSystemContext( new FileInfo(Path.Combine(directory, $"{Path.GetFileNameWithoutExtension(fullPath)}_sessions{Path.GetExtension(fullPath)}"))); - chatMessageStorageContext = new FileSystemContext( + chatMessageStorageContext = new FileSystemContext( new FileInfo(Path.Combine(directory, $"{Path.GetFileNameWithoutExtension(fullPath)}_messages{Path.GetExtension(fullPath)}"))); chatMemorySourceStorageContext = new FileSystemContext( new FileInfo(Path.Combine(directory, $"{Path.GetFileNameWithoutExtension(fullPath)}_memorysources{Path.GetExtension(fullPath)}"))); @@ -228,7 +228,7 @@ public static IServiceCollection AddPersistentChatStore(this IServiceCollection #pragma warning disable CA2000 // Dispose objects before losing scope - objects are singletons for the duration of the process and disposed when the process exits. chatSessionStorageContext = new CosmosDbContext( chatStoreConfig.Cosmos.ConnectionString, chatStoreConfig.Cosmos.Database, chatStoreConfig.Cosmos.ChatSessionsContainer); - chatMessageStorageContext = new CosmosDbContext( + chatMessageStorageContext = new CosmosDbContext( chatStoreConfig.Cosmos.ConnectionString, chatStoreConfig.Cosmos.Database, chatStoreConfig.Cosmos.ChatMessagesContainer); chatMemorySourceStorageContext = new CosmosDbContext( chatStoreConfig.Cosmos.ConnectionString, chatStoreConfig.Cosmos.Database, chatStoreConfig.Cosmos.ChatMemorySourcesContainer); diff --git a/webapi/Models/Response/ChatArchive.cs b/webapi/Models/Response/ChatArchive.cs index 6ffefc7a0..f37193324 100644 --- a/webapi/Models/Response/ChatArchive.cs +++ b/webapi/Models/Response/ChatArchive.cs @@ -35,7 +35,7 @@ public class ChatArchive /// /// The chat history. It contains all the messages in the conversation with the bot. /// - public List ChatHistory { get; set; } = new List(); + public List ChatHistory { get; set; } = new List(); /// /// Chat archive's embeddings. diff --git a/webapi/Models/Response/CreateChatResponse.cs b/webapi/Models/Response/CreateChatResponse.cs index 3adcabf1e..1210ffaa4 100644 --- a/webapi/Models/Response/CreateChatResponse.cs +++ b/webapi/Models/Response/CreateChatResponse.cs @@ -22,9 +22,9 @@ public class CreateChatResponse /// Initial bot message. /// [JsonPropertyName("initialBotMessage")] - public ChatMessage InitialBotMessage { get; set; } + public CopilotChatMessage InitialBotMessage { get; set; } - public CreateChatResponse(ChatSession chatSession, ChatMessage initialBotMessage) + public CreateChatResponse(ChatSession chatSession, CopilotChatMessage initialBotMessage) { this.ChatSession = chatSession; this.InitialBotMessage = initialBotMessage; diff --git a/webapi/Models/Storage/ChatMessage.cs b/webapi/Models/Storage/CopilotChatMessage.cs similarity index 88% rename from webapi/Models/Storage/ChatMessage.cs rename to webapi/Models/Storage/CopilotChatMessage.cs index 79b69bb59..5316a9f37 100644 --- a/webapi/Models/Storage/ChatMessage.cs +++ b/webapi/Models/Storage/CopilotChatMessage.cs @@ -14,7 +14,7 @@ namespace CopilotChat.WebApi.Models.Storage; /// /// Information about a single chat message. /// -public class ChatMessage : IStorageEntity +public class CopilotChatMessage : IStorageEntity { private static readonly JsonSerializerOptions SerializerSettings = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; @@ -31,12 +31,7 @@ public enum AuthorRoles /// /// The bot. /// - Bot, - - /// - /// The participant who is not the current user nor the bot of the chat. - /// - Participant + Bot } /// @@ -133,7 +128,7 @@ public enum ChatMessageType /// Role of the author /// Type of the message /// Total token usages used to generate bot response - public ChatMessage( + public CopilotChatMessage( string userId, string userName, string chatId, @@ -164,9 +159,9 @@ public ChatMessage( /// The message /// The prompt used to generate the message /// Total token usage of response completion - public static ChatMessage CreateBotResponseMessage(string chatId, string content, string prompt, IEnumerable? citations, IDictionary? tokenUsage = null) + public static CopilotChatMessage CreateBotResponseMessage(string chatId, string content, string prompt, IEnumerable? citations, IDictionary? tokenUsage = null) { - return new ChatMessage("Bot", "Bot", chatId, content, prompt, citations, AuthorRoles.Bot, IsPlan(content) ? ChatMessageType.Plan : ChatMessageType.Message, tokenUsage); + return new CopilotChatMessage("Bot", "Bot", chatId, content, prompt, citations, AuthorRoles.Bot, IsPlan(content) ? ChatMessageType.Plan : ChatMessageType.Message, tokenUsage); } /// @@ -176,9 +171,9 @@ public static ChatMessage CreateBotResponseMessage(string chatId, string content /// The user name that uploaded the document /// The chat ID that this message belongs to /// The document message content - public static ChatMessage CreateDocumentMessage(string userId, string userName, string chatId, DocumentMessageContent documentMessageContent) + public static CopilotChatMessage CreateDocumentMessage(string userId, string userName, string chatId, DocumentMessageContent documentMessageContent) { - return new ChatMessage(userId, userName, chatId, documentMessageContent.ToString(), string.Empty, null, AuthorRoles.User, ChatMessageType.Document); + return new CopilotChatMessage(userId, userName, chatId, documentMessageContent.ToString(), string.Empty, null, AuthorRoles.User, ChatMessageType.Document); } /// @@ -243,9 +238,9 @@ public override string ToString() /// /// A json string /// A ChatMessage object - public static ChatMessage? FromString(string json) + public static CopilotChatMessage? FromString(string json) { - return JsonSerializer.Deserialize(json, SerializerSettings); + return JsonSerializer.Deserialize(json, SerializerSettings); } /// diff --git a/webapi/Plugins/Chat/ChatPlugin.cs b/webapi/Plugins/Chat/ChatPlugin.cs index d53760dbe..3e8579650 100644 --- a/webapi/Plugins/Chat/ChatPlugin.cs +++ b/webapi/Plugins/Chat/ChatPlugin.cs @@ -31,6 +31,7 @@ using Microsoft.SemanticKernel.TemplateEngine; using Microsoft.SemanticKernel.TemplateEngine.Basic; using ChatCompletionContextMessages = Microsoft.SemanticKernel.AI.ChatCompletion.ChatHistory; +using CopilotChatMessage = CopilotChat.WebApi.Models.Storage.CopilotChatMessage; namespace CopilotChat.WebApi.Plugins.Chat; @@ -249,13 +250,13 @@ private async Task GetAllowedChatHistoryAsync( { var formattedMessage = chatMessage.ToFormattedString(); - if (chatMessage.Type == ChatMessage.ChatMessageType.Document) + if (chatMessage.Type == CopilotChatMessage.ChatMessageType.Document) { continue; } // Plan object is not meaningful content in generating bot response, so shorten to intent only to save on tokens - if (chatMessage.Type == ChatMessage.ChatMessageType.Plan) + if (chatMessage.Type == CopilotChatMessage.ChatMessageType.Plan) { formattedMessage = "Bot proposed plan"; @@ -271,16 +272,16 @@ private async Task GetAllowedChatHistoryAsync( formattedMessage = $"[{chatMessage.Timestamp.ToString("G", CultureInfo.CurrentCulture)}] {formattedMessage}"; } - var promptRole = chatMessage.AuthorRole == ChatMessage.AuthorRoles.Bot ? AuthorRole.System : AuthorRole.User; + var promptRole = chatMessage.AuthorRole == CopilotChatMessage.AuthorRoles.Bot ? AuthorRole.System : AuthorRole.User; var tokenCount = chatHistory is not null ? TokenUtils.GetContextMessageTokenCount(promptRole, formattedMessage) : TokenUtils.TokenCount(formattedMessage); if (remainingToken - tokenCount >= 0) { historyText = $"{formattedMessage}\n{historyText}"; - if (chatMessage.AuthorRole == ChatMessage.AuthorRoles.Bot) + if (chatMessage.AuthorRole == CopilotChatMessage.AuthorRoles.Bot) { // Message doesn't have to be formatted for bot. This helps with asserting a natural language response from the LLM (no date or author preamble). - var botMessage = chatMessage.Type == ChatMessage.ChatMessageType.Plan ? formattedMessage : chatMessage.Content; + var botMessage = chatMessage.Type == CopilotChatMessage.ChatMessageType.Plan ? formattedMessage : chatMessage.Content; allottedChatHistory.AddAssistantMessage(botMessage.Trim()); } else @@ -333,7 +334,7 @@ public async Task ChatAsync( var chatContext = context.Clone(); chatContext.Variables.Set("knowledgeCutoff", this._promptOptions.KnowledgeCutoffDate); - ChatMessage chatMessage = await this.GetChatResponseAsync(chatId, userId, chatContext, newUserMessage, cancellationToken); + CopilotChatMessage chatMessage = await this.GetChatResponseAsync(chatId, userId, chatContext, newUserMessage, cancellationToken); context.Variables.Update(chatMessage.Content); if (chatMessage.TokenUsage != null) @@ -387,7 +388,7 @@ public async Task ProcessPlanAsync( // Save this new message to memory such that subsequent chat responses can use it await this.UpdateBotResponseStatusOnClientAsync(chatId, "Saving user message to chat history", cancellationToken); - var newUserMessage = await this.SaveNewMessageAsync(message, userId, userName, chatId, ChatMessage.ChatMessageType.Message.ToString(), cancellationToken); + var newUserMessage = await this.SaveNewMessageAsync(message, userId, userName, chatId, CopilotChatMessage.ChatMessageType.Message.ToString(), cancellationToken); // If GeneratedPlanMessageId exists on plan object, update that message with new plan state. // This signals that this plan was freshly proposed by the model and already saved as a bot response message in chat history. @@ -408,7 +409,7 @@ await this.SaveNewResponseAsync( ); } - ChatMessage chatMessage; + CopilotChatMessage chatMessage; if (deserializedPlan.State == PlanState.Rejected) { // Use a hardcoded response if user cancelled plan @@ -433,7 +434,7 @@ await this.SaveNewResponseAsync( // Add original user input that prompted plan template promptTemplate.AddUserMessage(deserializedPlan.OriginalUserInput); - chatHistoryString += "\n" + PromptUtils.FormatChatHistoryMessage(ChatMessage.AuthorRoles.User, deserializedPlan.OriginalUserInput); + chatHistoryString += "\n" + PromptUtils.FormatChatHistoryMessage(CopilotChatMessage.AuthorRoles.User, deserializedPlan.OriginalUserInput); // Add bot message proposal as prompt context message chatContext.Variables.Set("planFunctions", this._externalInformationPlugin.FormattedFunctionsString(deserializedPlan.Plan)); @@ -441,11 +442,11 @@ await this.SaveNewResponseAsync( var proposedPlanTemplate = promptTemplateFactory.Create(this._promptOptions.ProposedPlanBotMessage, new PromptTemplateConfig()); var proposedPlanBotMessage = await proposedPlanTemplate.RenderAsync(chatContext, cancellationToken); promptTemplate.AddAssistantMessage(proposedPlanBotMessage); - chatHistoryString += "\n" + PromptUtils.FormatChatHistoryMessage(ChatMessage.AuthorRoles.Bot, proposedPlanBotMessage); + chatHistoryString += "\n" + PromptUtils.FormatChatHistoryMessage(CopilotChatMessage.AuthorRoles.Bot, proposedPlanBotMessage); // Add user approval message as prompt context message promptTemplate.AddUserMessage("Yes, proceed"); - chatHistoryString += "\n" + PromptUtils.FormatChatHistoryMessage(ChatMessage.AuthorRoles.User, "Yes, proceed"); + chatHistoryString += "\n" + PromptUtils.FormatChatHistoryMessage(CopilotChatMessage.AuthorRoles.User, "Yes, proceed"); // Add user intent behind plan // TODO: [Issue #51] Consider regenerating user intent if plan was modified @@ -518,7 +519,7 @@ await this.SaveNewResponseAsync( /// ChatMessage object representing new user message. /// The cancellation token. /// The created chat message containing the model-generated response. - private async Task GetChatResponseAsync(string chatId, string userId, SKContext chatContext, ChatMessage userMessage, CancellationToken cancellationToken) + private async Task GetChatResponseAsync(string chatId, string userId, SKContext chatContext, CopilotChatMessage userMessage, CancellationToken cancellationToken) { // Render system instruction components and create the meta-prompt template var systemInstructions = await AsyncUtils.SafeInvokeAsync( @@ -639,7 +640,7 @@ private async Task RenderSystemInstructions(string chatId, SKContext con /// Chat context. /// The prompt view. /// The cancellation token. - private async Task HandleBotResponseAsync( + private async Task HandleBotResponseAsync( string chatId, string userId, SKContext chatContext, @@ -648,7 +649,7 @@ private async Task HandleBotResponseAsync( IEnumerable? citations = null, string? responseContent = null) { - ChatMessage chatMessage; + CopilotChatMessage chatMessage; if (responseContent.IsNullOrEmpty()) { // Get bot response and stream to client @@ -761,7 +762,7 @@ private async Task AcquireExternalInformationAsync(SKContext context, st /// The chat ID /// Type of the message /// The cancellation token. - private async Task SaveNewMessageAsync(string message, string userId, string userName, string chatId, string type, CancellationToken cancellationToken) + private async Task SaveNewMessageAsync(string message, string userId, string userName, string chatId, string type, CancellationToken cancellationToken) { // Make sure the chat exists. if (!await this._chatSessionRepository.TryFindByIdAsync(chatId)) @@ -769,18 +770,18 @@ private async Task SaveNewMessageAsync(string message, string userI throw new ArgumentException("Chat session does not exist."); } - var chatMessage = new ChatMessage( + var chatMessage = new CopilotChatMessage( userId, userName, chatId, message, string.Empty, null, - ChatMessage.AuthorRoles.User, + CopilotChatMessage.AuthorRoles.User, // Default to a standard message if the `type` is not recognized - Enum.TryParse(type, out ChatMessage.ChatMessageType typeAsEnum) && Enum.IsDefined(typeof(ChatMessage.ChatMessageType), typeAsEnum) + Enum.TryParse(type, out CopilotChatMessage.ChatMessageType typeAsEnum) && Enum.IsDefined(typeof(CopilotChatMessage.ChatMessageType), typeAsEnum) ? typeAsEnum - : ChatMessage.ChatMessageType.Message); + : CopilotChatMessage.ChatMessageType.Message); await this._chatMessageRepository.CreateAsync(chatMessage); return chatMessage; @@ -797,7 +798,7 @@ private async Task SaveNewMessageAsync(string message, string userI /// Total token usage of response completion /// Citations for the message /// The created chat message. - private async Task SaveNewResponseAsync( + private async Task SaveNewResponseAsync( string response, string prompt, string chatId, @@ -837,7 +838,7 @@ private async Task SaveNewResponseAsync( /// The cancellation token. private async Task UpdateChatMessageContentAsync(string updatedResponse, string messageId, string chatId, CancellationToken cancellationToken) { - ChatMessage? chatMessage = null; + CopilotChatMessage? chatMessage = null; if (!await this._chatMessageRepository.TryFindByIdAsync(messageId, chatId, callback: v => chatMessage = v)) { throw new ArgumentException($"Chat message {messageId} does not exist."); @@ -929,7 +930,7 @@ private Dictionary GetTokenUsages(SKContext chatContext, string? co /// The cancellation token. /// Citations for the message /// The created chat message - private async Task StreamResponseToClientAsync( + private async Task StreamResponseToClientAsync( string chatId, string userId, BotResponsePrompt prompt, @@ -975,7 +976,7 @@ private async Task StreamResponseToClientAsync( /// Citations for the message /// Total token usage of response completion /// The created chat message - private async Task CreateBotMessageOnClient( + private async Task CreateBotMessageOnClient( string chatId, string userId, string prompt, @@ -984,7 +985,7 @@ private async Task CreateBotMessageOnClient( IEnumerable? citations = null, Dictionary? tokenUsage = null) { - var chatMessage = ChatMessage.CreateBotResponseMessage(chatId, content, prompt, citations, tokenUsage); + var chatMessage = CopilotChatMessage.CreateBotResponseMessage(chatId, content, prompt, citations, tokenUsage); await this._messageRelayHubContext.Clients.Group(chatId).SendAsync("ReceiveMessage", chatId, userId, chatMessage, cancellationToken); return chatMessage; } @@ -994,7 +995,7 @@ private async Task CreateBotMessageOnClient( /// /// The message /// The cancellation token. - private async Task UpdateMessageOnClient(ChatMessage message, CancellationToken cancellationToken) + private async Task UpdateMessageOnClient(CopilotChatMessage message, CancellationToken cancellationToken) { await this._messageRelayHubContext.Clients.Group(message.ChatId).SendAsync("ReceiveMessageUpdate", message, cancellationToken); } diff --git a/webapi/Plugins/Utils/PromptUtils.cs b/webapi/Plugins/Utils/PromptUtils.cs index 8969266e6..3c897c557 100644 --- a/webapi/Plugins/Utils/PromptUtils.cs +++ b/webapi/Plugins/Utils/PromptUtils.cs @@ -1,6 +1,6 @@ // Copyright (c) Microsoft. All rights reserved. -using static CopilotChat.WebApi.Models.Storage.ChatMessage; +using static CopilotChat.WebApi.Models.Storage.CopilotChatMessage; namespace CopilotChat.WebApi.Plugins.Utils; diff --git a/webapi/Plugins/Utils/TokenUtils.cs b/webapi/Plugins/Utils/TokenUtils.cs index ee9086c9f..dca65c09e 100644 --- a/webapi/Plugins/Utils/TokenUtils.cs +++ b/webapi/Plugins/Utils/TokenUtils.cs @@ -127,7 +127,7 @@ internal static int GetContextMessageTokenCount(AuthorRole authorRole, string co internal static int GetContextMessagesTokenCount(ChatCompletionContextMessages chatHistory) { var tokenCount = 0; - foreach (var message in chatHistory.Messages) + foreach (var message in chatHistory) { tokenCount += GetContextMessageTokenCount(message.Role, message.Content); } diff --git a/webapi/Storage/ChatMessageRepository.cs b/webapi/Storage/ChatMessageRepository.cs index cfc0b0d08..3033c71ac 100644 --- a/webapi/Storage/ChatMessageRepository.cs +++ b/webapi/Storage/ChatMessageRepository.cs @@ -10,13 +10,13 @@ namespace CopilotChat.WebApi.Storage; /// /// A repository for chat messages. /// -public class ChatMessageRepository : Repository +public class ChatMessageRepository : Repository { /// /// Initializes a new instance of the ChatMessageRepository class. /// /// The storage context. - public ChatMessageRepository(IStorageContext storageContext) + public ChatMessageRepository(IStorageContext storageContext) : base(storageContext) { } @@ -26,7 +26,7 @@ public ChatMessageRepository(IStorageContext storageContext) /// /// The chat id. /// A list of ChatMessages matching the given chatId. - public Task> FindByChatIdAsync(string chatId) + public Task> FindByChatIdAsync(string chatId) { return base.StorageContext.QueryEntitiesAsync(e => e.ChatId == chatId); } @@ -36,7 +36,7 @@ public Task> FindByChatIdAsync(string chatId) /// /// The chat id. /// The most recent ChatMessage matching the given chatId. - public async Task FindLastByChatIdAsync(string chatId) + public async Task FindLastByChatIdAsync(string chatId) { var chatMessages = await this.FindByChatIdAsync(chatId); var first = chatMessages.MaxBy(e => e.Timestamp); diff --git a/webapi/Utilities/PluginUtils.cs b/webapi/Utilities/PluginUtils.cs index 247ef0e31..b29c44847 100644 --- a/webapi/Utilities/PluginUtils.cs +++ b/webapi/Utilities/PluginUtils.cs @@ -31,7 +31,7 @@ public static Uri GetPluginManifestUri(Uri manifestDomain) { UriBuilder uriBuilder = new(manifestDomain); - // Expected manifest path as defined by OpenAI: https://platform.openai.com/docs/plugins/getting-started + // Expected manifest path as defined by OpenAI: https://platform.openai.com/docs/plugins/getting-started/plugin-manifest uriBuilder.Path = "/.well-known/ai-plugin.json"; return uriBuilder.Uri; } diff --git a/webapp/src/components/open-api-plugins/plugin-wizard/steps/EnterManifestStep.tsx b/webapp/src/components/open-api-plugins/plugin-wizard/steps/EnterManifestStep.tsx index 3c24578ce..4a2d2ee11 100644 --- a/webapp/src/components/open-api-plugins/plugin-wizard/steps/EnterManifestStep.tsx +++ b/webapp/src/components/open-api-plugins/plugin-wizard/steps/EnterManifestStep.tsx @@ -54,7 +54,7 @@ export const EnterManifestStep: React.FC = ({ To connect a plugin, provide the website domain where your{' '}