mirror of
https://github.com/microsoft/semantic-kernel.git
synced 2026-10-12 11:19:56 +00:00
"KernelSyntaxExamples" is the only outstanding project under /samples that still uses project references to access the kernel libraries. This change consolidates all the building, linked dotnet SDK code in SK-dotnet.sln into a single top-level folder. This will simplify build jobs, automatic code owner assignment, and other dev ops tasks. Coming next: other projects in samples will get removed from the dotnet/SK-dotnet.sln solution, and a new solution with dedicated builds created for the /samples folder. TBD: - Language-specific code "samples" will move into a similar subfolder for each language. - The current "/samples" folder (at the root) will likely become something like "apps", with the demo apps promoted to the top-level folder for better discoverability. - notebooks may also move to this folder in the future. Co-authored-by: name <email>
199 lines
6.3 KiB
C#
199 lines
6.3 KiB
C#
// Copyright (c) Microsoft. All rights reserved.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.SemanticKernel.AI.ChatCompletion;
|
|
|
|
/**
|
|
* The following example shows how to plug use a custom chat model.
|
|
*
|
|
* This might be useful in a few scenarios, for example:
|
|
* - You are not using OpenAI or Azure OpenAI models
|
|
* - You are using OpenAI/Azure OpenAI models but the models are behind a web service with a different API schema
|
|
* - You want to use a local model
|
|
*/
|
|
public sealed class MyChatCompletionService : IChatCompletion
|
|
{
|
|
public ChatHistory CreateNewChat(string? instructions = null)
|
|
{
|
|
var chatHistory = new MyChatHistory();
|
|
|
|
if (!string.IsNullOrWhiteSpace(instructions))
|
|
{
|
|
chatHistory.Add(new MyChatMessage(MyRoles.SuperUser, instructions));
|
|
}
|
|
|
|
return chatHistory;
|
|
}
|
|
|
|
public Task<IReadOnlyList<IChatResult>> GetChatCompletionsAsync(ChatHistory chat, ChatRequestSettings? requestSettings = null, CancellationToken cancellationToken = default)
|
|
{
|
|
return Task.FromResult<IReadOnlyList<IChatResult>>(new List<IChatResult>
|
|
{
|
|
new MyChatStreamingResult(MyRoles.Bot, "Hi I'm your SK Custom Assistant and I'm here to help you to create custom chats like this. :)")
|
|
});
|
|
}
|
|
|
|
public IAsyncEnumerable<IChatStreamingResult> GetStreamingChatCompletionsAsync(ChatHistory chat, ChatRequestSettings? requestSettings = null, CancellationToken cancellationToken = default)
|
|
{
|
|
return (new List<IChatStreamingResult>
|
|
{
|
|
new MyChatStreamingResult(MyRoles.Bot, "Hi I'm your SK Custom Assistant and I'm here to help you to create custom chats like this. :)")
|
|
}).ToAsyncEnumerable();
|
|
}
|
|
}
|
|
|
|
public class MyChatStreamingResult : IChatStreamingResult
|
|
{
|
|
private readonly ChatMessageBase _message;
|
|
private readonly MyRoles _role;
|
|
|
|
public MyChatStreamingResult(MyRoles role, string content)
|
|
{
|
|
this._role = role;
|
|
this._message = new MyChatMessage(role, content);
|
|
}
|
|
|
|
public Task<ChatMessageBase> GetChatMessageAsync(CancellationToken cancellationToken = default)
|
|
{
|
|
return Task.FromResult(this._message);
|
|
}
|
|
|
|
public async IAsyncEnumerable<ChatMessageBase> GetStreamingChatMessageAsync([EnumeratorCancellation] CancellationToken cancellationToken = default)
|
|
{
|
|
var streamedOutput = this._message.Content.Split(' ');
|
|
foreach (string word in streamedOutput)
|
|
{
|
|
await Task.Delay(100, cancellationToken);
|
|
yield return new MyChatMessage(this._role, $"{word} ");
|
|
}
|
|
}
|
|
}
|
|
|
|
public class MyChatMessage : ChatMessageBase
|
|
{
|
|
public MyChatMessage(MyRoles role, string content) : base(new AuthorRole(role.ToString()), content)
|
|
{
|
|
}
|
|
}
|
|
|
|
public class MyChatHistory : ChatHistory
|
|
{
|
|
public void AddMessage(MyRoles role, string message)
|
|
{
|
|
this.Add(new MyChatMessage(role, message));
|
|
}
|
|
}
|
|
|
|
public enum MyRoles
|
|
{
|
|
SuperUser,
|
|
User,
|
|
Bot
|
|
}
|
|
|
|
// ReSharper disable once InconsistentNaming
|
|
public static class Example34_CustomChatModel
|
|
{
|
|
public static async Task RunAsync()
|
|
{
|
|
await CustomChatStreamSampleAsync();
|
|
await CustomChatSampleAsync();
|
|
|
|
/* Output:
|
|
|
|
Chat content:
|
|
------------------------
|
|
System: You are a my SK Custom Assistant
|
|
------------------------
|
|
User: Hi, who are you?
|
|
------------------------
|
|
Assistant: Hi I'm your SK Custom Assistant and I'm here to help you to create custom chats like this. :)
|
|
------------------------
|
|
*/
|
|
}
|
|
|
|
private static async Task CustomChatSampleAsync()
|
|
{
|
|
Console.WriteLine("======== Custom LLM - Chat Completion ========");
|
|
|
|
IChatCompletion customChat = new MyChatCompletionService();
|
|
|
|
await StartChatAsync(customChat);
|
|
}
|
|
|
|
private static async Task StartChatAsync(IChatCompletion customChat)
|
|
{
|
|
Console.WriteLine("Chat content:");
|
|
Console.WriteLine("------------------------");
|
|
|
|
var chatHistory = (MyChatHistory)customChat.CreateNewChat("You are a my SK Custom Assistant");
|
|
|
|
// First user message
|
|
chatHistory.AddMessage(MyRoles.User, "Hi, who are you?");
|
|
await MessageOutputAsync(chatHistory);
|
|
|
|
// First bot assistant message
|
|
string reply = await customChat.GenerateMessageAsync(chatHistory);
|
|
chatHistory.AddMessage(MyRoles.Bot, reply);
|
|
await MessageOutputAsync(chatHistory);
|
|
}
|
|
|
|
private static async Task CustomChatStreamSampleAsync()
|
|
{
|
|
Console.WriteLine("======== Custom LLM - Chat Completion Streaming ========");
|
|
|
|
IChatCompletion customChat = new MyChatCompletionService();
|
|
|
|
await StartStreamingChatAsync(customChat);
|
|
}
|
|
|
|
private static async Task StartStreamingChatAsync(IChatCompletion customChat)
|
|
{
|
|
Console.WriteLine("Chat content:");
|
|
Console.WriteLine("------------------------");
|
|
|
|
var chatHistory = (MyChatHistory)customChat.CreateNewChat("You are a my SK Custom Assistant");
|
|
await MessageOutputAsync(chatHistory);
|
|
|
|
// First user message
|
|
chatHistory.AddMessage(MyRoles.User, "Hi, who are you?");
|
|
await MessageOutputAsync(chatHistory);
|
|
|
|
// Bot assistant message
|
|
await StreamMessageOutputAsync(customChat, chatHistory);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Outputs the last message of the chat history
|
|
/// </summary>
|
|
private static Task MessageOutputAsync(MyChatHistory chatHistory)
|
|
{
|
|
var message = chatHistory.Messages.Last();
|
|
|
|
Console.WriteLine($"{message.Role}: {message.Content}");
|
|
Console.WriteLine("------------------------");
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private static async Task StreamMessageOutputAsync(IChatCompletion customChat, MyChatHistory chatHistory, MyRoles myModelRole = MyRoles.Bot)
|
|
{
|
|
Console.Write($"{myModelRole}: ");
|
|
string fullMessage = string.Empty;
|
|
|
|
await foreach (string message in customChat.GenerateMessageStreamAsync(chatHistory))
|
|
{
|
|
fullMessage += message;
|
|
Console.Write(message);
|
|
}
|
|
|
|
Console.WriteLine("\n------------------------");
|
|
chatHistory.AddMessage(myModelRole, fullMessage);
|
|
}
|
|
}
|