Skip to content

Commit

Permalink
Split Plans and Personnas into seperate user settings; Added Speech e…
Browse files Browse the repository at this point in the history
…ndpoint option changes
  • Loading branch information
mattahearn committed Apr 12, 2024
1 parent 936fe11 commit 04ce7f5
Show file tree
Hide file tree
Showing 18 changed files with 256 additions and 47 deletions.
36 changes: 29 additions & 7 deletions webapi/Controllers/ChatController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using System.Threading;
using System.Threading.Tasks;
using CopilotChat.WebApi.Auth;
using CopilotChat.WebApi.Extensions;
using CopilotChat.WebApi.Hubs;
using CopilotChat.WebApi.Models.Request;
using CopilotChat.WebApi.Models.Response;
Expand All @@ -25,6 +26,7 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Graph;
Expand Down Expand Up @@ -68,6 +70,26 @@ public ChatController(
this._plugins = plugins;
}

/// <summary>
/// Updates the semantic provider and kernel services
/// </summary>
/// <param name="kernel">Semantic kernel obtained through dependency injection.</param>
/// <param name="params">Request body parameters i.e. Azure OpenAI Deployment Name.</param>
/// <returns>Results containing the response from the model.</returns>
[Route("chats/updatekernelservices")]
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<IActionResult> UpdateKernelService(
[FromServices] Kernel kernel,
[FromBody] KernelServiceParameters kp)
{
this._logger.LogDebug("Request received to update semantic kernel service.");

// SemanticKernelExtensions.ReplaceKernelServices();

return this.Ok(kernel);
}

/// <summary>
/// Invokes the chat function to get a response from the bot.
/// </summary>
Expand All @@ -87,13 +109,13 @@ public ChatController(
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status504GatewayTimeout)]
public async Task<IActionResult> ChatAsync(
[FromServices] Kernel kernel,
[FromServices] IHubContext<MessageRelayHub> messageRelayHubContext,
[FromServices] ChatSessionRepository chatSessionRepository,
[FromServices] ChatParticipantRepository chatParticipantRepository,
[FromServices] IAuthInfo authInfo,
[FromBody] Ask ask,
[FromRoute] Guid chatId)
[FromServices] Kernel kernel,
[FromServices] IHubContext<MessageRelayHub> messageRelayHubContext,
[FromServices] ChatSessionRepository chatSessionRepository,
[FromServices] ChatParticipantRepository chatParticipantRepository,
[FromServices] IAuthInfo authInfo,
[FromBody] Ask ask,
[FromRoute] Guid chatId)
{
this._logger.LogDebug("Chat message received.");

Expand Down
4 changes: 2 additions & 2 deletions webapi/Controllers/SpeechTokenController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ public async Task<ActionResult<SpeechTokenResponse>> GetAsync()
{
return new SpeechTokenResponse { IsSuccess = false };
}

string fetchTokenUri = "https://" + this._options.Region + ".api.cognitive.microsoft.com/sts/v1.0/issueToken";
//Updated to not use hardcoded string to allow GOv cloud and such to work
string fetchTokenUri = this._options.Endpoint;

TokenResult tokenResult = await this.FetchTokenAsync(fetchTokenUri, this._options.Key);
var isSuccess = tokenResult.ResponseCode != HttpStatusCode.NotFound;
Expand Down
14 changes: 8 additions & 6 deletions webapi/Controllers/UserSettingsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ public async Task<IActionResult> GetUserSettingsAsync(Guid userId)

foreach (var setting in settings)
{
UserSettings us = new(setting.UserId, setting.DarkMode, setting.PlannersAndPersonas, setting.SimplifiedChatExperience,
UserSettings us = new(setting.UserId, setting.DarkMode, setting.Planners, setting.Personas, setting.SimplifiedChatExperience,
setting.AzureContentSafety, setting.AzureAISearch, setting.ExportChatSessions, setting.LiveChatSessionSharing,
setting.FeedbackFromUser);
setting.FeedbackFromUser, setting.DeploymentGPT35, setting.DeploymentGPT4);
return this.Ok(us); // Only 1 record per user id
}

Expand All @@ -67,7 +67,6 @@ public async Task<IActionResult> GetUserSettingsAsync(Guid userId)
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> UpdateUserSettingsAsync(
[FromServices] IHubContext<MessageRelayHub> messageRelayHubContext,
[FromBody] EditUserSettingsParameters msgParameters,
[FromRoute] Guid userId)
{
Expand All @@ -79,22 +78,25 @@ public async Task<IActionResult> UpdateUserSettingsAsync(
{
// Update existing settings record for this user
setting!.DarkMode = msgParameters.darkMode;
setting!.PlannersAndPersonas = msgParameters.plannersAndPersonas;
setting!.Planners = msgParameters.planners;
setting!.Personas = msgParameters.personas;
setting!.SimplifiedChatExperience = msgParameters.simplifiedChatExperience;
setting!.AzureContentSafety = msgParameters.azureContentSafety;
setting!.AzureAISearch = msgParameters.azureAISearch;
setting!.ExportChatSessions = msgParameters.exportChatSessions;
setting!.LiveChatSessionSharing = msgParameters.liveChatSessionSharing;
setting!.FeedbackFromUser = msgParameters.feedbackFromUser;
setting!.DeploymentGPT35 = msgParameters.deploymentGPT35;
setting!.DeploymentGPT4 = msgParameters.deploymentGPT4;
await this._userSettingsRepository.UpsertAsync(setting);

return this.Ok(setting);
}

// Create a new settings record for this user
var newUserSettings = new UserSettings(msgParameters.userId, msgParameters.darkMode, msgParameters.plannersAndPersonas,
var newUserSettings = new UserSettings(msgParameters.userId, msgParameters.darkMode, msgParameters.planners, msgParameters.personas,
msgParameters.simplifiedChatExperience, msgParameters.azureContentSafety, msgParameters.azureAISearch, msgParameters.exportChatSessions,
msgParameters.liveChatSessionSharing, msgParameters.feedbackFromUser);
msgParameters.liveChatSessionSharing, msgParameters.feedbackFromUser, msgParameters.deploymentGPT35, msgParameters.deploymentGPT4);
await this._userSettingsRepository.CreateAsync(newUserSettings);

return this.Ok(newUserSettings);
Expand Down
37 changes: 36 additions & 1 deletion webapi/Extensions/SemanticKernelExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.KernelMemory;
Expand All @@ -29,6 +30,12 @@ namespace CopilotChat.WebApi.Extensions;
/// </summary>
internal static class SemanticKernelExtensions
{
public enum SemanticProvider
{
gpt35turbo = 0,
gpt4 = 1
}

/// <summary>
/// Delegate to register functions with a Semantic Kernel
/// </summary>
Expand Down Expand Up @@ -117,9 +124,37 @@ public static Kernel RegisterChatPlugin(this Kernel kernel, IServiceProvider sp)
return kernel;
}

public static WebApplicationBuilder ReplaceKernelServices(this WebApplicationBuilder builder, string deploymentName)
{
// Swap out the kernel provider service with this one to use a different Azure OpenAI Deployment Name updated by the user
ServiceDescriptor descriptorProvider = ServiceDescriptor.Singleton(typeof(SemanticKernelProvider),
sp => new SemanticKernelProvider(sp, builder.Configuration, sp.GetRequiredService<IHttpClientFactory>(), deploymentName));
builder.Services.Replace(descriptorProvider);

// Swap out the kernel service
ServiceDescriptor descriptorKernel = ServiceDescriptor.Scoped(typeof(Kernel), sp =>
{
var provider = sp.GetRequiredService<SemanticKernelProvider>();
var kernel = provider.GetCompletionKernel();

sp.GetRequiredService<RegisterFunctionsWithKernel>()(sp, kernel);

// If KernelSetupHook is not null, invoke custom kernel setup.
sp.GetService<KernelSetupHook>()?.Invoke(sp, kernel);
return kernel;
});

builder.Services.Replace(descriptorKernel);

return builder;
}

private static void InitializeKernelProvider(this WebApplicationBuilder builder)
{
builder.Services.AddSingleton(sp => new SemanticKernelProvider(sp, builder.Configuration, sp.GetRequiredService<IHttpClientFactory>()));
builder.Services.AddSingleton(sp => new SemanticKernelProvider(sp, builder.Configuration, sp.GetRequiredService<IHttpClientFactory>(), null));

// SemanticKernelProvider skp => new(skp, builder.Configuration, skp.GetRequiredService<IHttpClientFactory>(), "gpt-35-turbro");
// builder.Services.AddKeyedSingleton<SemanticKernelProvider>("gpt-35-turbro", skp);
}

/// <summary>
Expand Down
23 changes: 20 additions & 3 deletions webapi/Models/Request/EditUserSettingsParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,16 @@ public class EditUserSettingsParameters
public bool? darkMode { get; set; }

/// <summary>
/// Planners and Personas enabled?
/// Planners enabled?
/// </summary>
[JsonPropertyName("plannersAndPersonas")]
public bool? plannersAndPersonas { get; set; }
[JsonPropertyName("planners")]
public bool? planners { get; set; }

/// <summary>
/// Personas enabled?
/// </summary>
[JsonPropertyName("personas")]
public bool? personas { get; set; }

/// <summary>
/// Simplified Chat Experience?
Expand Down Expand Up @@ -67,4 +73,15 @@ public class EditUserSettingsParameters
[JsonPropertyName("feedbackFromUser")]
public bool? feedbackFromUser { get; set; }

/// <summary>
/// Azure OpenAI Deployment Name gpt-35-turbo
/// </summary>
[JsonPropertyName("deploymentGPT35")]
public bool? deploymentGPT35 { get; set; }

/// <summary>
/// Azure OpenAI Deployment Name gpt-4
/// </summary>
[JsonPropertyName("deploymentGPT4")]
public bool? deploymentGPT4 { get; set; }
}
16 changes: 16 additions & 0 deletions webapi/Models/Request/KernelServiceParameters.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Text.Json.Serialization;

Check warning on line 1 in webapi/Models/Request/KernelServiceParameters.cs

View workflow job for this annotation

GitHub Actions / check-format

A source file is missing a required header.

namespace CopilotChat.WebApi.Models.Request;

/// <summary>
/// Parameters for editing particular message.
/// </summary>
public class KernelServiceParameters
{
/// <summary>
/// Azure OpenAI Deployment Name
/// </summary>
[JsonPropertyName("deployment")]
public string? deployment { get; set; }

}
34 changes: 28 additions & 6 deletions webapi/Models/Storage/UserSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,14 @@ public class UserSettings : IStorageEntity
public bool? DarkMode { get; set; }

/// <summary>
/// Planners and Personas enabled?
/// Planners enabled?
/// </summary>
public bool? PlannersAndPersonas { get; set; }
public bool? Planners { get; set; }

/// <summary>
/// Personas enabled?
/// </summary>
public bool? Personas { get; set; }

/// <summary>
/// Simplified Chat Experience?
Expand Down Expand Up @@ -61,6 +66,16 @@ public class UserSettings : IStorageEntity
/// </summary>
public bool? FeedbackFromUser { get; set; }

/// <summary>
/// Azure OpenAI Deployment Name gpt-35-turbo
/// </summary>
public bool? DeploymentGPT35 { get; set; }

/// <summary>
/// Azure OpenAI Deployment Name gpt-4
/// </summary>
public bool? DeploymentGPT4 { get; set; }

/// <summary>
/// The partition key for the source.
/// </summary>
Expand All @@ -72,25 +87,32 @@ public class UserSettings : IStorageEntity
/// </summary>
/// <param name="userId">Settings belong to this user.</param>
/// <param name="darkMode">Is Dark Mode enabled?</param>
/// <param name="plannersAndPersonas">Planners and Personas enabled?</param>
/// <param name="planners">Planners enabled?</param>
/// <param name="personas">Personas enabled?</param>
/// <param name="simplifiedChatExperience">Simplified Chat Experience?</param>
/// <param name="azureContentSafety">Azure Content Safety enabled?</param>
/// <param name="azureAISearch">Azure AI Search enabled?</param>
/// <param name="exportChatSessions">Export Chat Sesssions enabled?</param>

Check warning on line 95 in webapi/Models/Storage/UserSettings.cs

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"Sesssions" should be "Sessions".
/// <param name="liveChatSessionSharing">Live Chat Session Sharing enabled?</param>
/// <param name="feedbackFromUser">Reinforced Learning From User Feedback enabled?</param>
public UserSettings(string userId, bool? darkMode, bool? plannersAndPersonas, bool? simplifiedChatExperience, bool? azureContentSafety,
bool? azureAISearch, bool? exportChatSessions, bool? liveChatSessionSharing, bool? feedbackFromUser)
/// <param name="deploymentGPT35">Deployment Name gpt-35-turbo</param>
/// <param name="deploymentGPT4">Deployment Name gpt-4</param>
public UserSettings(string userId, bool? darkMode, bool? planners, bool? personas, bool? simplifiedChatExperience, bool? azureContentSafety,
bool? azureAISearch, bool? exportChatSessions, bool? liveChatSessionSharing, bool? feedbackFromUser, bool? deploymentGPT35,
bool? deploymentGPT4)
{
this.Id = Guid.NewGuid().ToString();
this.UserId = userId;
this.DarkMode = darkMode ?? false;
this.PlannersAndPersonas = plannersAndPersonas ?? false;
this.Planners = planners ?? false;
this.Personas = personas ?? false;
this.SimplifiedChatExperience = simplifiedChatExperience ?? false;
this.AzureContentSafety = azureContentSafety ?? false;
this.AzureAISearch = azureAISearch ?? false;
this.ExportChatSessions = exportChatSessions ?? false;
this.LiveChatSessionSharing = liveChatSessionSharing ?? false;
this.FeedbackFromUser = feedbackFromUser ?? false;
this.DeploymentGPT35 = deploymentGPT35 ?? false;
this.DeploymentGPT4 = deploymentGPT4 ?? false;
}
}
7 changes: 6 additions & 1 deletion webapi/Options/AzureSpeechOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,9 @@ public sealed class AzureSpeechOptions
/// Key to access the Azure speech service.
/// </summary>
public string? Key { get; set; } = string.Empty;
}
/// <summary>
/// Endpoint of the Azure speech service to use in case of Gov Clouds
/// </summary>
public string? Endpoint { get; set; } = string.Empty;

}
9 changes: 5 additions & 4 deletions webapi/Services/SemanticKernelProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ public sealed class SemanticKernelProvider
{
private readonly IKernelBuilder _builderChat;

public SemanticKernelProvider(IServiceProvider serviceProvider, IConfiguration configuration, IHttpClientFactory httpClientFactory)
public SemanticKernelProvider(IServiceProvider serviceProvider, IConfiguration configuration, IHttpClientFactory httpClientFactory, string? deploymentName)
{
this._builderChat = InitializeCompletionKernel(serviceProvider, configuration, httpClientFactory);
this._builderChat = InitializeCompletionKernel(serviceProvider, configuration, httpClientFactory, deploymentName);
}

/// <summary>
Expand All @@ -30,7 +30,8 @@ public SemanticKernelProvider(IServiceProvider serviceProvider, IConfiguration c
private static IKernelBuilder InitializeCompletionKernel(
IServiceProvider serviceProvider,
IConfiguration configuration,
IHttpClientFactory httpClientFactory)
IHttpClientFactory httpClientFactory,
string? deploymentName)
{
var builder = Kernel.CreateBuilder();

Expand All @@ -45,7 +46,7 @@ private static IKernelBuilder InitializeCompletionKernel(
var azureAIOptions = memoryOptions.GetServiceConfig<AzureOpenAIConfig>(configuration, "AzureOpenAIText");
#pragma warning disable CA2000 // No need to dispose of HttpClient instances from IHttpClientFactory
builder.AddAzureOpenAIChatCompletion(
azureAIOptions.Deployment,
(deploymentName != null) ? deploymentName : azureAIOptions.Deployment, // User can switch AI deployment name
azureAIOptions.Endpoint,
azureAIOptions.APIKey,
httpClient: httpClientFactory.CreateClient());
Expand Down
10 changes: 8 additions & 2 deletions webapp/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,16 @@ const App = () => {
if (us !== undefined) {
dispatch(setUserSettings(us));
if (us.darkMode) dispatch(toggleFeatureFlag(FeatureKeys.DarkMode)); // Turn on
if (us.plannersAndPersonas) dispatch(toggleFeatureFlag(FeatureKeys.PluginsPlannersAndPersonas)); // Turn on
if (us.planners) dispatch(toggleFeatureFlag(FeatureKeys.Planners)); // Turn on
if (us.personas) dispatch(toggleFeatureFlag(FeatureKeys.Personas)); // Turn on
if (us.simplifiedChatExperience) dispatch(toggleFeatureFlag(FeatureKeys.SimplifiedExperience)); // Turn on
if (us.azureContentSafety) dispatch(toggleFeatureFlag(FeatureKeys.AzureContentSafety)); // Turn on
if (us.azureAISearch) dispatch(toggleFeatureFlag(FeatureKeys.AzureAISearch)); // Turn on
if (us.exportChatSessions) dispatch(toggleFeatureFlag(FeatureKeys.ExportChatSessions)); // Turn on
if (us.liveChatSessionSharing) dispatch(toggleFeatureFlag(FeatureKeys.LiveChatSessionSharing)); // Turn on
if (us.feedbackFromUser) dispatch(toggleFeatureFlag(FeatureKeys.RLHF)); // Turn on
if (us.deploymentGPT35) dispatch(toggleFeatureFlag(FeatureKeys.DeploymentGPT35)); // Turn on
if (us.deploymentGPT4) dispatch(toggleFeatureFlag(FeatureKeys.DeploymentGPT4)); // Turn on
}
});

Expand Down Expand Up @@ -163,13 +166,16 @@ const App = () => {
if (us !== undefined) {
dispatch(setUserSettings(us));
if (us.darkMode) dispatch(toggleFeatureFlag(FeatureKeys.DarkMode)); // Turn on
if (us.plannersAndPersonas) dispatch(toggleFeatureFlag(FeatureKeys.PluginsPlannersAndPersonas)); // Turn on
if (us.planners) dispatch(toggleFeatureFlag(FeatureKeys.Planners)); // Turn on
if (us.personas) dispatch(toggleFeatureFlag(FeatureKeys.Personas)); // Turn on
if (us.simplifiedChatExperience) dispatch(toggleFeatureFlag(FeatureKeys.SimplifiedExperience)); // Turn on
if (us.azureContentSafety) dispatch(toggleFeatureFlag(FeatureKeys.AzureContentSafety)); // Turn on
if (us.azureAISearch) dispatch(toggleFeatureFlag(FeatureKeys.AzureAISearch)); // Turn on
if (us.exportChatSessions) dispatch(toggleFeatureFlag(FeatureKeys.ExportChatSessions)); // Turn on
if (us.liveChatSessionSharing) dispatch(toggleFeatureFlag(FeatureKeys.LiveChatSessionSharing)); // Turn on
if (us.feedbackFromUser) dispatch(toggleFeatureFlag(FeatureKeys.RLHF)); // Turn on
if (us.deploymentGPT35) dispatch(toggleFeatureFlag(FeatureKeys.DeploymentGPT35)); // Turn on
if (us.deploymentGPT4) dispatch(toggleFeatureFlag(FeatureKeys.DeploymentGPT4)); // Turn on
}
});
}
Expand Down
Loading

0 comments on commit 04ce7f5

Please sign in to comment.