Skip to content

Commit 8378af8

Browse files
committed
Merge branch 'master' of https://github.com/SciSharp/BotSharp
2 parents c212559 + 8e6b5de commit 8378af8

12 files changed

+543
-0
lines changed

BotSharp.sln

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Plugin.MongoStorag
6363
EndProject
6464
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Plugin.GoogleAI", "src\Plugins\BotSharp.Plugin.GoogleAI\BotSharp.Plugin.GoogleAI.csproj", "{8BC29F8A-78D6-422C-B522-10687ADC38ED}"
6565
EndProject
66+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Plugin.SemanticKernel", "src\Plugins\BotSharp.Plugin.SemanticKernel\BotSharp.Plugin.SemanticKernel.csproj", "{73EE2CD0-3B27-4F02-A67B-762CBDD740D0}"
67+
EndProject
68+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Plugin.SemanticKernel.UnitTests", "tests\BotSharp.Plugin.SemanticKernel.UnitTests\BotSharp.Plugin.SemanticKernel.UnitTests.csproj", "{BC57D428-A1A4-4D38-A2D0-AC6CA943F247}"
69+
EndProject
6670
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Plugin.Twilio", "src\Plugins\BotSharp.Plugin.Twilio\BotSharp.Plugin.Twilio.csproj", "{E627F1E3-BE03-443A-83A2-86A855A278EB}"
6771
EndProject
6872
Global
@@ -225,6 +229,22 @@ Global
225229
{8BC29F8A-78D6-422C-B522-10687ADC38ED}.Release|Any CPU.Build.0 = Release|Any CPU
226230
{8BC29F8A-78D6-422C-B522-10687ADC38ED}.Release|x64.ActiveCfg = Release|Any CPU
227231
{8BC29F8A-78D6-422C-B522-10687ADC38ED}.Release|x64.Build.0 = Release|Any CPU
232+
{73EE2CD0-3B27-4F02-A67B-762CBDD740D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
233+
{73EE2CD0-3B27-4F02-A67B-762CBDD740D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
234+
{73EE2CD0-3B27-4F02-A67B-762CBDD740D0}.Debug|x64.ActiveCfg = Debug|Any CPU
235+
{73EE2CD0-3B27-4F02-A67B-762CBDD740D0}.Debug|x64.Build.0 = Debug|Any CPU
236+
{73EE2CD0-3B27-4F02-A67B-762CBDD740D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
237+
{73EE2CD0-3B27-4F02-A67B-762CBDD740D0}.Release|Any CPU.Build.0 = Release|Any CPU
238+
{73EE2CD0-3B27-4F02-A67B-762CBDD740D0}.Release|x64.ActiveCfg = Release|Any CPU
239+
{73EE2CD0-3B27-4F02-A67B-762CBDD740D0}.Release|x64.Build.0 = Release|Any CPU
240+
{BC57D428-A1A4-4D38-A2D0-AC6CA943F247}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
241+
{BC57D428-A1A4-4D38-A2D0-AC6CA943F247}.Debug|Any CPU.Build.0 = Debug|Any CPU
242+
{BC57D428-A1A4-4D38-A2D0-AC6CA943F247}.Debug|x64.ActiveCfg = Debug|Any CPU
243+
{BC57D428-A1A4-4D38-A2D0-AC6CA943F247}.Debug|x64.Build.0 = Debug|Any CPU
244+
{BC57D428-A1A4-4D38-A2D0-AC6CA943F247}.Release|Any CPU.ActiveCfg = Release|Any CPU
245+
{BC57D428-A1A4-4D38-A2D0-AC6CA943F247}.Release|Any CPU.Build.0 = Release|Any CPU
246+
{BC57D428-A1A4-4D38-A2D0-AC6CA943F247}.Release|x64.ActiveCfg = Release|Any CPU
247+
{BC57D428-A1A4-4D38-A2D0-AC6CA943F247}.Release|x64.Build.0 = Release|Any CPU
228248
{E627F1E3-BE03-443A-83A2-86A855A278EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
229249
{E627F1E3-BE03-443A-83A2-86A855A278EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
230250
{E627F1E3-BE03-443A-83A2-86A855A278EB}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -264,6 +284,8 @@ Global
264284
{5CD330E1-9E5A-4112-8346-6E31CA98EF78} = {2635EC9B-2E5F-4313-AC21-0B847F31F36C}
265285
{DB3DE37B-1208-4ED3-9615-A52AD0AAD69C} = {5CD330E1-9E5A-4112-8346-6E31CA98EF78}
266286
{8BC29F8A-78D6-422C-B522-10687ADC38ED} = {D5293208-2BEF-42FC-A64C-5954F61720BA}
287+
{73EE2CD0-3B27-4F02-A67B-762CBDD740D0} = {D5293208-2BEF-42FC-A64C-5954F61720BA}
288+
{BC57D428-A1A4-4D38-A2D0-AC6CA943F247} = {32FAFFFE-A4CB-4FEE-BF7C-84518BBC6DCC}
267289
{E627F1E3-BE03-443A-83A2-86A855A278EB} = {64264688-0F5C-4AB0-8F2B-B59B717CCE00}
268290
EndGlobalSection
269291
GlobalSection(ExtensibilityGlobals) = postSolution
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netstandard2.1</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<LangVersion>$(LangVersion)</LangVersion>
7+
<VersionPrefix>$(BotSharpVersion)</VersionPrefix>
8+
<GeneratePackageOnBuild>$(GeneratePackageOnBuild)</GeneratePackageOnBuild>
9+
<GenerateDocumentationFile>True</GenerateDocumentationFile>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="Microsoft.SemanticKernel.Abstractions" Version="1.0.0-beta6" />
14+
<PackageReference Include="Microsoft.VisualStudio.Validation" Version="17.6.11" />
15+
</ItemGroup>
16+
17+
<ItemGroup>
18+
<ProjectReference Include="..\..\Infrastructure\BotSharp.Abstraction\BotSharp.Abstraction.csproj" />
19+
</ItemGroup>
20+
21+
<ItemGroup>
22+
<InternalsVisibleTo Include="BotSharp.Plugin.SemanticKernel.UnitTests" />
23+
</ItemGroup>
24+
25+
</Project>
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
using BotSharp.Abstraction.Agents;
2+
using BotSharp.Abstraction.Agents.Enums;
3+
using BotSharp.Abstraction.Agents.Models;
4+
using BotSharp.Abstraction.Conversations;
5+
using BotSharp.Abstraction.Conversations.Models;
6+
using BotSharp.Abstraction.MLTasks;
7+
using Microsoft.Extensions.DependencyInjection;
8+
using Microsoft.SemanticKernel;
9+
using System;
10+
using System.Collections.Generic;
11+
using System.Linq;
12+
using System.Threading.Tasks;
13+
14+
namespace BotSharp.Plugin.SemanticKernel
15+
{
16+
/// <summary>
17+
/// Use Semantic Kernel as chat completion provider
18+
/// </summary>
19+
public class SemanticKernelChatCompletionProvider : IChatCompletion
20+
{
21+
private IKernel _kernel;
22+
private IServiceProvider _services;
23+
private ITokenStatistics _tokenStatistics;
24+
private string? _model = null;
25+
26+
/// <inheritdoc/>
27+
public string Provider => "semantic-kernel";
28+
29+
/// <summary>
30+
/// Create a new instance of <see cref="SemanticKernelChatCompletionProvider"/>
31+
/// </summary>
32+
/// <param name="kernel"></param>
33+
/// <param name="services"></param>
34+
/// <param name="tokenStatistics"></param>
35+
public SemanticKernelChatCompletionProvider(IKernel kernel,
36+
IServiceProvider services,
37+
ITokenStatistics tokenStatistics)
38+
{
39+
this._kernel = kernel;
40+
this._services = services;
41+
this._tokenStatistics = tokenStatistics;
42+
}
43+
/// <inheritdoc/>
44+
public RoleDialogModel GetChatCompletions(Agent agent, List<RoleDialogModel> conversations)
45+
{
46+
var hooks = _services.GetServices<IContentGeneratingHook>().ToList();
47+
48+
// Before chat completion hook
49+
Task.WaitAll(hooks.Select(hook =>
50+
hook.BeforeGenerating(agent, conversations)).ToArray());
51+
52+
var completion = _kernel.GetService<Microsoft.SemanticKernel.AI.ChatCompletion.IChatCompletion>(_model);
53+
54+
var agentService = _services.GetRequiredService<IAgentService>();
55+
var instruction = agentService.RenderedInstruction(agent);
56+
57+
var chatHistory = completion.CreateNewChat(instruction);
58+
59+
foreach (var message in conversations)
60+
{
61+
if (message.Role == AgentRole.User)
62+
{
63+
chatHistory.AddUserMessage(message.Content);
64+
}
65+
else
66+
{
67+
chatHistory.AddAssistantMessage(message.Content);
68+
}
69+
}
70+
71+
var response = completion.GetChatCompletionsAsync(chatHistory)
72+
.ContinueWith(async t =>
73+
{
74+
var result = await t;
75+
var message = await result.First().GetChatMessageAsync();
76+
return message.Content;
77+
}).ConfigureAwait(false).GetAwaiter().GetResult()
78+
.ConfigureAwait(false).GetAwaiter().GetResult();
79+
80+
var msg = new RoleDialogModel(AgentRole.Assistant, response)
81+
{
82+
CurrentAgentId = agent.Id
83+
};
84+
85+
// After chat completion hook
86+
Task.WaitAll(hooks.Select(hook =>
87+
hook.AfterGenerated(msg, new TokenStatsModel
88+
{
89+
Model = _model ?? "default"
90+
})).ToArray());
91+
92+
return msg;
93+
}
94+
/// <inheritdoc/>
95+
public Task<bool> GetChatCompletionsAsync(Agent agent, List<RoleDialogModel> conversations, Func<RoleDialogModel, Task> onMessageReceived, Func<RoleDialogModel, Task> onFunctionExecuting)
96+
{
97+
throw new NotImplementedException();
98+
}
99+
/// <inheritdoc/>
100+
public Task<bool> GetChatCompletionsStreamingAsync(Agent agent, List<RoleDialogModel> conversations, Func<RoleDialogModel, Task> onMessageReceived)
101+
{
102+
throw new NotImplementedException();
103+
}
104+
105+
/// <inheritdoc/>
106+
public void SetModelName(string model)
107+
{
108+
if (!string.IsNullOrWhiteSpace(model))
109+
this._model = model;
110+
}
111+
}
112+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using BotSharp.Abstraction.MLTasks;
2+
using BotSharp.Abstraction.Plugins;
3+
using Microsoft.Extensions.Configuration;
4+
using Microsoft.Extensions.DependencyInjection;
5+
6+
namespace BotSharp.Plugin.SemanticKernel
7+
{
8+
public class SemanticKernelPlugin : IBotSharpPlugin
9+
{
10+
public string Name => "Semantic Kernel";
11+
public string Description => "Semantic Kernel Service";
12+
13+
public void RegisterDI(IServiceCollection services, IConfiguration config)
14+
{
15+
services.AddScoped<ITextCompletion, SemanticKernelTextCompletionProvider>();
16+
services.AddScoped<IChatCompletion, SemanticKernelChatCompletionProvider>();
17+
}
18+
}
19+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
using BotSharp.Abstraction.Agents.Enums;
2+
using BotSharp.Abstraction.Agents.Models;
3+
using BotSharp.Abstraction.Conversations;
4+
using BotSharp.Abstraction.Conversations.Models;
5+
using BotSharp.Abstraction.MLTasks;
6+
using Microsoft;
7+
using Microsoft.Extensions.DependencyInjection;
8+
using Microsoft.SemanticKernel;
9+
using Microsoft.SemanticKernel.AI.TextCompletion;
10+
using System;
11+
using System.Collections.Generic;
12+
using System.Linq;
13+
using System.Threading.Tasks;
14+
15+
namespace BotSharp.Plugin.SemanticKernel
16+
{
17+
/// <summary>
18+
/// User Semantic Kernel as text completion provider
19+
/// </summary>
20+
public class SemanticKernelTextCompletionProvider : Abstraction.MLTasks.ITextCompletion
21+
{
22+
private readonly IKernel _kernel;
23+
private readonly IServiceProvider _services;
24+
private readonly ITokenStatistics _tokenStatistics;
25+
private string? _model = null;
26+
27+
/// <inheritdoc/>
28+
public string Provider => "semantic-kernel";
29+
30+
/// <summary>
31+
/// Create a new instance of <see cref="SemanticKernelTextCompletionProvider"/>
32+
/// </summary>
33+
/// <param name="kernel"></param>
34+
/// <param name="services"></param>
35+
/// <param name="tokenStatistics"></param>
36+
public SemanticKernelTextCompletionProvider(IKernel kernel,
37+
IServiceProvider services,
38+
ITokenStatistics tokenStatistics)
39+
{
40+
Requires.NotNull(kernel, nameof(IKernel));
41+
42+
this._kernel = kernel;
43+
this._services = services;
44+
this._tokenStatistics = tokenStatistics;
45+
}
46+
47+
/// <inheritdoc/>
48+
public async Task<string> GetCompletion(string text, string agentId, string messageId)
49+
{
50+
var hooks = _services.GetServices<IContentGeneratingHook>().ToList();
51+
52+
// Before chat completion hook
53+
var agent = new Agent()
54+
{
55+
Id = agentId
56+
};
57+
var userMessage = new RoleDialogModel(AgentRole.User, text)
58+
{
59+
MessageId = messageId
60+
};
61+
Task.WaitAll(hooks.Select(hook =>
62+
hook.BeforeGenerating(agent, new List<RoleDialogModel> { userMessage })).ToArray());
63+
64+
var completion = _kernel.GetService<Microsoft.SemanticKernel.AI.TextCompletion.ITextCompletion>(_model);
65+
_tokenStatistics.StartTimer();
66+
var result = await completion.CompleteAsync(text);
67+
_tokenStatistics.StopTimer();
68+
69+
// After chat completion hook
70+
Task.WaitAll(hooks.Select(hook =>
71+
hook.AfterGenerated(new RoleDialogModel(AgentRole.Assistant, result), new TokenStatsModel
72+
{
73+
Model = _model ?? "default"
74+
})).ToArray());
75+
76+
return result;
77+
}
78+
79+
/// <inheritdoc/>
80+
public void SetModelName(string model)
81+
{
82+
if (!string.IsNullOrWhiteSpace(model))
83+
this._model = model;
84+
}
85+
}
86+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net6.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
8+
<IsPackable>false</IsPackable>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
13+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
14+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
15+
<PackageReference Include="Microsoft.SemanticKernel" Version="1.0.0-beta6" />
16+
<PackageReference Include="Moq" Version="4.20.69" />
17+
<PackageReference Include="xunit" Version="2.4.1" />
18+
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
19+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
20+
<PrivateAssets>all</PrivateAssets>
21+
</PackageReference>
22+
<PackageReference Include="coverlet.collector" Version="3.1.2">
23+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
24+
<PrivateAssets>all</PrivateAssets>
25+
</PackageReference>
26+
</ItemGroup>
27+
28+
<ItemGroup>
29+
<ProjectReference Include="..\..\src\Plugins\BotSharp.Plugin.SemanticKernel\BotSharp.Plugin.SemanticKernel.csproj" />
30+
</ItemGroup>
31+
32+
</Project>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using Microsoft.SemanticKernel.AI.ChatCompletion;
2+
using Microsoft.SemanticKernel.AI.TextCompletion;
3+
using Microsoft.SemanticKernel.Orchestration;
4+
5+
namespace BotSharp.Plugin.SemanticKernel.UnitTests.Helpers
6+
{
7+
public class ResultHelper : IChatResult, ITextResult
8+
{
9+
public ModelResult ModelResult { get; set; }
10+
private string _response;
11+
12+
public ResultHelper(string response)
13+
{
14+
ModelResult = new ModelResult(response);
15+
_response = response;
16+
}
17+
18+
public async Task<ChatMessageBase> GetChatMessageAsync(CancellationToken cancellationToken = default)
19+
{
20+
return await Task.FromResult(new MockModelResult(_response));
21+
}
22+
23+
public Task<string> GetCompletionAsync(CancellationToken cancellationToken = default)
24+
{
25+
return Task.FromResult(_response);
26+
}
27+
28+
public class MockModelResult : ChatMessageBase
29+
{
30+
public MockModelResult(string content) : base(AuthorRole.Assistant, content, null)
31+
{
32+
}
33+
}
34+
}
35+
}

0 commit comments

Comments
 (0)