Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update SK from 0.19.230804.2-preview to 0.21.230828.2-preview #305

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 3 additions & 2 deletions webapi/Controllers/ChatController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
using Microsoft.Graph;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.AI;
using Microsoft.SemanticKernel.Diagnostics;
using Microsoft.SemanticKernel.Orchestration;
using Microsoft.SemanticKernel.SkillDefinition;
using Microsoft.SemanticKernel.Skills.MsGraph;
Expand Down Expand Up @@ -127,9 +128,9 @@ public ChatController(ILogger<ChatController> logger, ITelemetryService telemetr
{
function = kernel.Skills.GetFunction(ChatSkillName, ChatFunctionName);
}
catch (KernelException ke)
catch (SKException ex)
{
this._logger.LogError("Failed to find {0}/{1} on server: {2}", ChatSkillName, ChatFunctionName, ke);
this._logger.LogError("Failed to find {0}/{1} on server: {2}", ChatSkillName, ChatFunctionName, ex);

return this.NotFound($"Failed to find {ChatSkillName}/{ChatFunctionName} on server");
}
Expand Down
20 changes: 10 additions & 10 deletions webapi/CopilotChatWebApi.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@
<ItemGroup>
<PackageReference Include="Azure.AI.FormRecognizer" Version="4.1.0" />
<PackageReference Include="Microsoft.Azure.Cosmos" Version="3.35.3" />
<PackageReference Include="Microsoft.SemanticKernel" Version="0.19.230804.2-preview" />
<PackageReference Include="Microsoft.SemanticKernel.Planning.StepwisePlanner" Version="0.19.230804.2-preview" />
<PackageReference Include="Microsoft.SemanticKernel.Connectors.AI.OpenAI" Version="0.19.230804.2-preview" />
<PackageReference Include="Microsoft.SemanticKernel.Connectors.Memory.AzureCognitiveSearch" Version="0.19.230804.2-preview" />
<PackageReference Include="Microsoft.SemanticKernel.Connectors.Memory.Chroma" Version="0.19.230804.2-preview" />
<PackageReference Include="Microsoft.SemanticKernel.Connectors.Memory.Qdrant" Version="0.19.230804.2-preview" />
<PackageReference Include="Microsoft.SemanticKernel.Connectors.Memory.Postgres" Version="0.19.230804.2-preview" />
<PackageReference Include="Microsoft.SemanticKernel.Skills.MsGraph" Version="0.19.230804.2-preview" />
<PackageReference Include="Microsoft.SemanticKernel.Skills.OpenAPI" Version="0.19.230804.2-preview" />
<PackageReference Include="Microsoft.SemanticKernel.Skills.Web" Version="0.19.230804.2-preview" />
<PackageReference Include="Microsoft.SemanticKernel" Version="0.21.230828.2-preview" />
<PackageReference Include="Microsoft.SemanticKernel.Planning.StepwisePlanner" Version="0.21.230828.2-preview" />
<PackageReference Include="Microsoft.SemanticKernel.Connectors.AI.OpenAI" Version="0.21.230828.2-preview" />
<PackageReference Include="Microsoft.SemanticKernel.Connectors.Memory.AzureCognitiveSearch" Version="0.21.230828.2-preview" />
<PackageReference Include="Microsoft.SemanticKernel.Connectors.Memory.Chroma" Version="0.21.230828.2-preview" />
<PackageReference Include="Microsoft.SemanticKernel.Connectors.Memory.Qdrant" Version="0.21.230828.2-preview" />
<PackageReference Include="Microsoft.SemanticKernel.Connectors.Memory.Postgres" Version="0.21.230828.2-preview" />
<PackageReference Include="Microsoft.SemanticKernel.Skills.MsGraph" Version="0.21.230828.2-preview" />
<PackageReference Include="Microsoft.SemanticKernel.Skills.OpenAPI" Version="0.21.230828.2-preview" />
<PackageReference Include="Microsoft.SemanticKernel.Skills.Web" Version="0.21.230828.2-preview" />
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.2.2" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.21.0" />
<PackageReference Include="Microsoft.Identity.Web" Version="2.13.3" />
Expand Down
30 changes: 16 additions & 14 deletions webapi/Extensions/SemanticKernelExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@
using Microsoft.SemanticKernel.Connectors.Memory.Chroma;
using Microsoft.SemanticKernel.Connectors.Memory.Postgres;
using Microsoft.SemanticKernel.Connectors.Memory.Qdrant;
using Microsoft.SemanticKernel.Diagnostics;
using Microsoft.SemanticKernel.Memory;
using Microsoft.SemanticKernel.Orchestration;
using Microsoft.SemanticKernel.Skills.Core;
using Microsoft.SemanticKernel.TemplateEngine;
using Npgsql;
using Pgvector.Npgsql;
using static CopilotChat.WebApi.Options.MemoryStoreOptions;
Expand All @@ -50,7 +50,7 @@ internal static IServiceCollection AddSemanticKernelServices(this IServiceCollec
services.AddScoped<IKernel>(sp =>
{
IKernel kernel = Kernel.Builder
.WithLogger(sp.GetRequiredService<ILogger<IKernel>>())
.WithLoggerFactory(sp.GetRequiredService<ILoggerFactory>())
.WithMemory(sp.GetRequiredService<ISemanticTextMemory>())
.WithCompletionBackend(sp.GetRequiredService<IOptions<AIServiceOptions>>().Value)
.WithEmbeddingBackend(sp.GetRequiredService<IOptions<AIServiceOptions>>().Value)
Expand Down Expand Up @@ -81,12 +81,12 @@ public static IServiceCollection AddPlannerServices(this IServiceCollection serv
services.AddScoped<CopilotChatPlanner>(sp =>
{
IKernel plannerKernel = Kernel.Builder
.WithLogger(sp.GetRequiredService<ILogger<IKernel>>())
.WithLoggerFactory(sp.GetRequiredService<ILoggerFactory>())
.WithMemory(sp.GetRequiredService<ISemanticTextMemory>())
// TODO: [sk Issue #2046] verify planner has AI service configured
.WithPlannerBackend(sp.GetRequiredService<IOptions<AIServiceOptions>>().Value)
.Build();
return new CopilotChatPlanner(plannerKernel, plannerOptions?.Value);
return new CopilotChatPlanner(plannerKernel, plannerOptions?.Value, sp.GetRequiredService<ILogger<CopilotChatPlanner>>());
});

// Register Planner skills (AI plugins) here.
Expand Down Expand Up @@ -123,7 +123,8 @@ public static void ThrowIfFailed(this SKContext context)
{
if (context.ErrorOccurred)
{
context.Logger.LogError(context.LastException, "{0}", context.LastException?.Message);
var logger = context.LoggerFactory.CreateLogger(nameof(SKContext));
logger.LogError(context.LastException, "{0}", context.LastException?.Message);
throw context.LastException!;
}
}
Expand All @@ -149,9 +150,10 @@ private static Task RegisterSkillsAsync(IServiceProvider sp, IKernel kernel)
{
kernel.ImportSemanticSkillFromDirectory(options.SemanticSkillsDirectory, Path.GetFileName(subDir)!);
}
catch (TemplateException e)
catch (SKException ex)
{
kernel.Logger.LogError("Could not load skill from {Directory}: {Message}", subDir, e.Message);
var logger = kernel.LoggerFactory.CreateLogger(nameof(Kernel));
logger.LogError("Could not load skill from {Directory}: {Message}", subDir, ex.Message);
}
}
}
Expand Down Expand Up @@ -193,7 +195,7 @@ private static void AddSemanticTextMemory(this IServiceCollection services)
httpClient: httpClient,
config.Qdrant.VectorSize,
endPointBuilder.ToString(),
logger: sp.GetRequiredService<ILogger<IQdrantVectorDbClient>>()
loggerFactory: sp.GetRequiredService<ILoggerFactory>()
);
});
break;
Expand Down Expand Up @@ -225,7 +227,7 @@ private static void AddSemanticTextMemory(this IServiceCollection services)
return new ChromaMemoryStore(
httpClient: httpClient,
endpoint: endPointBuilder.ToString(),
logger: sp.GetRequiredService<ILogger<IChromaClient>>()
loggerFactory: sp.GetRequiredService<ILoggerFactory>()
);
});
break;
Expand Down Expand Up @@ -256,7 +258,7 @@ private static void AddSemanticTextMemory(this IServiceCollection services)
services.AddScoped<ISemanticTextMemory>(sp => new SemanticTextMemory(
sp.GetRequiredService<IMemoryStore>(),
sp.GetRequiredService<IOptions<AIServiceOptions>>().Value
.ToTextEmbeddingsService(logger: sp.GetRequiredService<ILogger<AIServiceOptions>>())));
.ToTextEmbeddingsService(loggerFactory: sp.GetRequiredService<ILoggerFactory>())));
}

/// <summary>
Expand Down Expand Up @@ -323,17 +325,17 @@ private static KernelBuilder WithPlannerBackend(this KernelBuilder kernelBuilder
/// </summary>
/// <param name="options">The service configuration</param>
/// <param name="httpClient">Custom <see cref="HttpClient"/> for HTTP requests.</param>
/// <param name="logger">Application logger</param>
/// <param name="loggerFactory">Custom <see cref="ILoggerFactory"/> for logging.</param>
private static ITextEmbeddingGeneration ToTextEmbeddingsService(this AIServiceOptions options,
HttpClient? httpClient = null,
ILogger? logger = null)
ILoggerFactory? loggerFactory = null)
{
return options.Type switch
{
AIServiceOptions.AIServiceType.AzureOpenAI
=> new AzureTextEmbeddingGeneration(options.Models.Embedding, options.Endpoint, options.Key, httpClient: httpClient, logger: logger),
=> new AzureTextEmbeddingGeneration(options.Models.Embedding, options.Endpoint, options.Key, httpClient: httpClient, loggerFactory: loggerFactory),
AIServiceOptions.AIServiceType.OpenAI
=> new OpenAITextEmbeddingGeneration(options.Models.Embedding, options.Key, httpClient: httpClient, logger: logger),
=> new OpenAITextEmbeddingGeneration(options.Models.Embedding, options.Key, httpClient: httpClient, loggerFactory: loggerFactory),
_
=> throw new ArgumentException("Invalid AIService value in embeddings backend settings"),
};
Expand Down
27 changes: 13 additions & 14 deletions webapi/Options/PlannerOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,24 @@ namespace CopilotChat.WebApi.Options;
public class PlannerOptions
{
/// <summary>
/// Whether to allow missing functions in plan on creation. If allowed, proposed plan will be sanitized of no-op functions.
/// Functions are considered missing if they're not available in the planner's kernel's context.
/// Options to handle planner errors.
/// </summary>
public class MissingFunctionErrorOptions
public class ErrorOptions
{
/// <summary>
/// Flag to indicate if skips are allowed on MissingFunction error
/// If set to true, the plan will be created with missing functions as no-op steps that are filtered from the final proposed plan.
/// If this is set to false, the plan creation will fail if any functions are missing.
/// Whether to allow retries on planner errors.
/// </summary>
public bool AllowRetries { get; set; } = true;

// <summary>
// Whether to allow missing functions in the sequential plan on creation. If set to true, the
// plan will be created with missing functions as no-op steps. If set to false (default),
// the plan creation will fail if any functions are missing.
// </summary>
public bool AllowMissingFunctions { get; set; } = true;

/// <summary>
/// Max retries allowed on MissingFunctionsError.
/// Max retries allowed.
/// </summary>
[Range(1, 5)]
public int MaxRetriesAllowed { get; set; } = 3;
Expand All @@ -45,14 +49,9 @@ public class MissingFunctionErrorOptions
public double? RelevancyThreshold { get; set; } = 0;

/// <summary>
/// Options on how to handle missing functions in plan on creation.
/// </summary>
public MissingFunctionErrorOptions MissingFunctionError { get; set; } = new MissingFunctionErrorOptions();

/// <summary>
/// Whether to retry plan creation if LLM returned response that doesn't contain valid plan (e.g., invalid XML or JSON, contains missing function, etc.).
/// Options on how to handle planner errors.
/// </summary>
public bool AllowRetriesOnInvalidPlan { get; set; } = true;
public ErrorOptions ErrorHandling { get; set; } = new ErrorOptions();

/// <summary>
/// The configuration for the stepwise planner.
Expand Down
18 changes: 10 additions & 8 deletions webapi/Skills/ChatSkills/ChatSkill.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,16 @@ public class ChatSkill

this._semanticChatMemorySkill = new SemanticChatMemorySkill(
promptOptions,
chatSessionRepository, logger);
chatSessionRepository,
logger);
this._documentMemorySkill = new DocumentMemorySkill(
promptOptions,
documentImportOptions,
logger);
this._externalInformationSkill = new ExternalInformationSkill(
promptOptions,
planner);
planner,
logger);
this._contentSafety = contentSafety;
}

Expand Down Expand Up @@ -159,7 +161,7 @@ public async Task<string> ExtractUserIntentAsync(SKContext context, Cancellation
);

// Get token usage from ChatCompletion result and add to context
TokenUtilities.GetFunctionTokenUsage(result, context, "SystemIntentExtraction");
TokenUtilities.GetFunctionTokenUsage(result, context, this._logger, "SystemIntentExtraction");

result.ThrowIfFailed();

Expand Down Expand Up @@ -203,7 +205,7 @@ public async Task<string> ExtractAudienceAsync(SKContext context, CancellationTo
);

// Get token usage from ChatCompletion result and add to context
TokenUtilities.GetFunctionTokenUsage(result, context, "SystemAudienceExtraction");
TokenUtilities.GetFunctionTokenUsage(result, context, this._logger, "SystemAudienceExtraction");

result.ThrowIfFailed();

Expand Down Expand Up @@ -323,7 +325,7 @@ public async Task<string> ExtractAudienceAsync(SKContext context, CancellationTo
}
else
{
context.Logger.LogWarning("ChatSkill token usage unknown. Ensure token management has been implemented correctly.");
this._logger.LogWarning("ChatSkill token usage unknown. Ensure token management has been implemented correctly.");
}

return context;
Expand Down Expand Up @@ -443,7 +445,7 @@ private async Task<ChatMessage> GetChatResponseAsync(string chatId, string userI
var promptView = new BotResponsePrompt(renderedPrompt, this._promptOptions.SystemDescription, this._promptOptions.SystemResponse, audience, userIntent, chatMemories, documentMemories, plannerDetails, chatHistory, systemChatContinuation);

// Calculate token usage of prompt template
chatContext.Variables.Set(TokenUtilities.GetFunctionKey(chatContext.Logger, "SystemMetaPrompt")!, TokenUtilities.TokenCount(renderedPrompt).ToString(CultureInfo.InvariantCulture));
chatContext.Variables.Set(TokenUtilities.GetFunctionKey(this._logger, "SystemMetaPrompt")!, TokenUtilities.TokenCount(renderedPrompt).ToString(CultureInfo.InvariantCulture));

chatContext.ThrowIfFailed();

Expand Down Expand Up @@ -485,7 +487,7 @@ private async Task<string> GetAudienceAsync(SKContext context, CancellationToken
var audience = await this.ExtractAudienceAsync(audienceContext, cancellationToken);

// Copy token usage into original chat context
var functionKey = TokenUtilities.GetFunctionKey(context.Logger, "SystemAudienceExtraction")!;
var functionKey = TokenUtilities.GetFunctionKey(this._logger, "SystemAudienceExtraction")!;
if (audienceContext.Variables.TryGetValue(functionKey, out string? tokenUsage))
{
context.Variables.Set(functionKey, tokenUsage);
Expand All @@ -512,7 +514,7 @@ private async Task<string> GetUserIntentAsync(SKContext context, CancellationTok
userIntent = await this.ExtractUserIntentAsync(intentContext, cancellationToken);

// Copy token usage into original chat context
var functionKey = TokenUtilities.GetFunctionKey(context.Logger, "SystemIntentExtraction")!;
var functionKey = TokenUtilities.GetFunctionKey(this._logger, "SystemIntentExtraction")!;
if (intentContext.Variables.TryGetValue(functionKey!, out string? tokenUsage))
{
context.Variables.Set(functionKey!, tokenUsage);
Expand Down
17 changes: 12 additions & 5 deletions webapi/Skills/ChatSkills/CopilotChatPlanner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using CopilotChat.WebApi.Options;
using Microsoft.Extensions.Logging;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Diagnostics;
using Microsoft.SemanticKernel.Orchestration;
using Microsoft.SemanticKernel.Planning;
using Microsoft.SemanticKernel.Planning.Sequential;
Expand All @@ -23,6 +24,11 @@ namespace CopilotChat.WebApi.Skills.ChatSkills;
/// </summary>
public class CopilotChatPlanner
{
/// <summary>
/// High level logger.
/// </summary>
private readonly ILogger _logger;

/// <summary>
/// The planner's kernel.
/// </summary>
Expand Down Expand Up @@ -62,10 +68,11 @@ public class CopilotChatPlanner
/// Initializes a new instance of the <see cref="CopilotChatPlanner"/> class.
/// </summary>
/// <param name="plannerKernel">The planner's kernel.</param>
public CopilotChatPlanner(IKernel plannerKernel, PlannerOptions? plannerOptions)
public CopilotChatPlanner(IKernel plannerKernel, PlannerOptions? plannerOptions, ILogger logger)
{
this.Kernel = plannerKernel;
this._plannerOptions = plannerOptions;
this._logger = logger;
}

/// <summary>
Expand Down Expand Up @@ -97,7 +104,7 @@ public async Task<Plan> CreatePlanAsync(string goal, ILogger logger, Cancellatio
{
RelevancyThreshold = this._plannerOptions?.RelevancyThreshold,
// Allow plan to be created with missing functions
AllowMissingFunctions = this._plannerOptions?.MissingFunctionError.AllowRetries ?? false
AllowMissingFunctions = this._plannerOptions?.ErrorHandling.AllowMissingFunctions ?? false
}
).CreatePlanAsync(goal, cancellationToken);
break;
Expand All @@ -106,13 +113,13 @@ public async Task<Plan> CreatePlanAsync(string goal, ILogger logger, Cancellatio
break;
}
}
catch (PlanningException e) when (e.ErrorCode == PlanningException.ErrorCodes.CreatePlanError && e.Message.Contains("Not possible to create plan for goal with available functions", StringComparison.InvariantCulture))
catch (SKException)
{
// No relevant functions are available - return an empty plan.
return new Plan(goal);
}

return this._plannerOptions!.MissingFunctionError.AllowRetries ? this.SanitizePlan(plan, plannerFunctionsView, logger) : plan;
return this._plannerOptions!.ErrorHandling.AllowMissingFunctions ? this.SanitizePlan(plan, plannerFunctionsView, logger) : plan;
}

/// <summary>
Expand Down Expand Up @@ -147,7 +154,7 @@ public async Task<SKContext> RunStepwisePlannerAsync(string goal, SKContext cont
}
catch (Exception e)
{
context.Logger.LogError(e, "Error running stepwise planner");
this._logger.LogError(e, "Error running stepwise planner");
throw;
}
}
Expand Down
2 changes: 1 addition & 1 deletion webapi/Skills/ChatSkills/DocumentMemorySkill.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public class DocumentMemorySkill
public DocumentMemorySkill(
IOptions<PromptsOptions> promptOptions,
IOptions<DocumentMemoryOptions> documentImportOptions,
Microsoft.Extensions.Logging.ILogger logger)
ILogger logger)
{
this._logger = logger;
this._promptOptions = promptOptions.Value;
Expand Down