-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
.Net: Add Amazon's AWS Bedrock Connector (#7627)
# Add Amazon's AWS Bedrock Connector - Resolves #4335 Adding support for Amazon AWS Connector to the Semantic Kernel. --------- Co-authored-by: Charlize Yeh <[email protected]> Co-authored-by: Charlize Yeh <[email protected]> Co-authored-by: Roger Barreto <[email protected]>
- Loading branch information
1 parent
5e632fd
commit 0edba1b
Showing
67 changed files
with
8,059 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 20 additions & 0 deletions
20
dotnet/samples/Demos/AmazonBedrockModels/AmazonBedrockAIModels.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<Nullable>enable</Nullable> | ||
<RootNamespace>AmazonBedrockAIModels</RootNamespace> | ||
</PropertyGroup> | ||
<PropertyGroup> | ||
<NoWarn>$(NoWarn);SKEXP0001;SKEXP0070</NoWarn> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="AWSSDK.BedrockRuntime" /> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<ProjectReference Include="..\..\..\src\Connectors\Connectors.Amazon\Connectors.Amazon.csproj"/> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,272 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using Microsoft.SemanticKernel; | ||
using Microsoft.SemanticKernel.ChatCompletion; | ||
using Microsoft.SemanticKernel.TextGeneration; | ||
|
||
// List of available models | ||
Dictionary<int, ModelDefinition> bedrockModels = GetBedrockModels(); | ||
|
||
// Get user choice | ||
int choice = GetUserChoice(); | ||
|
||
switch (choice) | ||
{ | ||
case 1: | ||
await PerformChatCompletion().ConfigureAwait(false); | ||
break; | ||
case 2: | ||
await PerformTextGeneration().ConfigureAwait(false); | ||
break; | ||
case 3: | ||
await PerformStreamChatCompletion().ConfigureAwait(false); | ||
break; | ||
case 4: | ||
await PerformStreamTextGeneration().ConfigureAwait(false); | ||
break; | ||
} | ||
|
||
async Task PerformChatCompletion() | ||
{ | ||
string userInput; | ||
ChatHistory chatHistory = new(); | ||
|
||
// Get available chat completion models | ||
var availableChatModels = bedrockModels.Values | ||
.Where(m => m.Modalities.Contains(ModelDefinition.SupportedModality.ChatCompletion)) | ||
.ToDictionary(m => bedrockModels.Single(kvp => kvp.Value.Name == m.Name).Key, m => m.Name); | ||
|
||
// Show user what models are available and let them choose | ||
int chosenModel = GetModelNumber(availableChatModels, "chat completion"); | ||
|
||
var kernel = Kernel.CreateBuilder().AddBedrockChatCompletionService(availableChatModels[chosenModel]).Build(); | ||
var chatCompletionService = kernel.GetRequiredService<IChatCompletionService>(); | ||
|
||
do | ||
{ | ||
Console.Write("Enter a prompt (or leave empty to quit): "); | ||
userInput = Console.ReadLine() ?? string.Empty; | ||
|
||
if (!string.IsNullOrEmpty(userInput)) | ||
{ | ||
chatHistory.AddMessage(AuthorRole.User, userInput); | ||
var result = await chatCompletionService.GetChatMessageContentsAsync(chatHistory).ConfigureAwait(false); | ||
string output = ""; | ||
foreach (var message in result) | ||
{ | ||
output += message.Content; | ||
Console.WriteLine($"Chat Completion Answer: {message.Content}"); | ||
Console.WriteLine(); | ||
} | ||
|
||
chatHistory.AddMessage(AuthorRole.Assistant, output); | ||
} | ||
} while (!string.IsNullOrEmpty(userInput)); | ||
} | ||
|
||
async Task PerformTextGeneration() | ||
{ | ||
// Get available text generation models | ||
var availableTextGenerationModels = bedrockModels.Values | ||
.Where(m => m.Modalities.Contains(ModelDefinition.SupportedModality.TextCompletion)) | ||
.ToDictionary(m => bedrockModels.Single(kvp => kvp.Value.Name == m.Name).Key, m => m.Name); | ||
|
||
// Show user what models are available and let them choose | ||
int chosenTextGenerationModel = GetModelNumber(availableTextGenerationModels, "text generation"); | ||
|
||
Console.Write("Text Generation Prompt: "); | ||
string userTextPrompt = Console.ReadLine() ?? ""; | ||
|
||
var kernel = Kernel.CreateBuilder().AddBedrockTextGenerationService(availableTextGenerationModels[chosenTextGenerationModel]).Build(); | ||
|
||
var textGenerationService = kernel.GetRequiredService<ITextGenerationService>(); | ||
var textGeneration = await textGenerationService.GetTextContentsAsync(userTextPrompt).ConfigureAwait(false); | ||
if (textGeneration.Count > 0) | ||
{ | ||
var firstTextContent = textGeneration[0]; | ||
if (firstTextContent != null) | ||
{ | ||
Console.WriteLine("Text Generation Answer: " + firstTextContent.Text); | ||
} | ||
else | ||
{ | ||
Console.WriteLine("Text Generation Answer: (none)"); | ||
} | ||
} | ||
else | ||
{ | ||
Console.WriteLine("Text Generation Answer: (No output text)"); | ||
} | ||
} | ||
|
||
async Task PerformStreamChatCompletion() | ||
{ | ||
string userInput; | ||
ChatHistory streamChatHistory = new(); | ||
|
||
// Get available streaming chat completion models | ||
var availableStreamingChatModels = bedrockModels.Values | ||
.Where(m => m.Modalities.Contains(ModelDefinition.SupportedModality.ChatCompletion) && m.CanStream) | ||
.ToDictionary(m => bedrockModels.Single(kvp => kvp.Value.Name == m.Name).Key, m => m.Name); | ||
|
||
// Show user what models are available and let them choose | ||
int chosenStreamChatCompletionModel = GetModelNumber(availableStreamingChatModels, "stream chat completion"); | ||
|
||
var kernel = Kernel.CreateBuilder().AddBedrockChatCompletionService(availableStreamingChatModels[chosenStreamChatCompletionModel]).Build(); | ||
var chatStreamCompletionService = kernel.GetRequiredService<IChatCompletionService>(); | ||
|
||
do | ||
{ | ||
Console.Write("Enter a prompt (or leave empty to quit): "); | ||
userInput = Console.ReadLine() ?? string.Empty; | ||
|
||
if (!string.IsNullOrEmpty(userInput)) | ||
{ | ||
streamChatHistory.AddMessage(AuthorRole.User, userInput); | ||
var result = chatStreamCompletionService.GetStreamingChatMessageContentsAsync(streamChatHistory).ConfigureAwait(false); | ||
string output = ""; | ||
await foreach (var message in result) | ||
{ | ||
Console.Write($"{message.Content}"); | ||
output += message.Content; | ||
} | ||
|
||
Console.WriteLine(); | ||
streamChatHistory.AddMessage(AuthorRole.Assistant, output); | ||
} | ||
} while (!string.IsNullOrEmpty(userInput)); | ||
} | ||
|
||
async Task PerformStreamTextGeneration() | ||
{ | ||
// Get available streaming text generation models | ||
var availableStreamingTextGenerationModels = bedrockModels.Values | ||
.Where(m => m.Modalities.Contains(ModelDefinition.SupportedModality.TextCompletion) && m.CanStream) | ||
.ToDictionary(m => bedrockModels.Single(kvp => kvp.Value.Name == m.Name).Key, m => m.Name); | ||
|
||
// Show user what models are available and let them choose | ||
int chosenStreamTextGenerationModel = GetModelNumber(availableStreamingTextGenerationModels, "stream text generation"); | ||
|
||
Console.Write("Stream Text Generation Prompt: "); | ||
string userStreamTextPrompt = Console.ReadLine() ?? ""; | ||
|
||
var kernel = Kernel.CreateBuilder().AddBedrockTextGenerationService(availableStreamingTextGenerationModels[chosenStreamTextGenerationModel]).Build(); | ||
|
||
var streamTextGenerationService = kernel.GetRequiredService<ITextGenerationService>(); | ||
var streamTextGeneration = streamTextGenerationService.GetStreamingTextContentsAsync(userStreamTextPrompt).ConfigureAwait(true); | ||
await foreach (var textContent in streamTextGeneration) | ||
{ | ||
Console.Write(textContent.Text); | ||
} | ||
|
||
Console.WriteLine(); | ||
} | ||
|
||
// Get the user's model choice | ||
int GetUserChoice() | ||
{ | ||
int pick; | ||
|
||
// Display the available options | ||
Console.WriteLine("Choose an option:"); | ||
Console.WriteLine("1. Chat Completion"); | ||
Console.WriteLine("2. Text Generation"); | ||
Console.WriteLine("3. Stream Chat Completion"); | ||
Console.WriteLine("4. Stream Text Generation"); | ||
|
||
Console.Write("Enter your choice (1-4): "); | ||
while (!int.TryParse(Console.ReadLine(), out pick) || pick < 1 || pick > 4) | ||
{ | ||
Console.WriteLine("Invalid input. Please enter a valid number from the list."); | ||
Console.Write("Enter your choice (1-4): "); | ||
} | ||
|
||
return pick; | ||
} | ||
|
||
int GetModelNumber(Dictionary<int, string> availableModels, string serviceType) | ||
{ | ||
int chosenModel; | ||
|
||
// Display the model options | ||
Console.WriteLine($"Available {serviceType} models:"); | ||
foreach (var option in availableModels) | ||
{ | ||
Console.WriteLine($"{option.Key}. {option.Value}"); | ||
} | ||
|
||
Console.Write($"Enter the number of the model you want to use for {serviceType}: "); | ||
while (!int.TryParse(Console.ReadLine(), out chosenModel) || !availableModels.ContainsKey(chosenModel)) | ||
{ | ||
Console.WriteLine("Invalid input. Please enter a valid number from the list."); | ||
Console.Write($"Enter the number of the model you want to use for {serviceType}: "); | ||
} | ||
|
||
return chosenModel; | ||
} | ||
|
||
Dictionary<int, ModelDefinition> GetBedrockModels() | ||
{ | ||
return new Dictionary<int, ModelDefinition> | ||
{ | ||
{ 1, new ModelDefinition { Modalities = [ModelDefinition.SupportedModality.ChatCompletion, ModelDefinition.SupportedModality.TextCompletion], Name = "anthropic.claude-v2", CanStream = true } }, | ||
{ 2, new ModelDefinition { Modalities = [ModelDefinition.SupportedModality.ChatCompletion, ModelDefinition.SupportedModality.TextCompletion], Name = "anthropic.claude-v2:1", CanStream = true } }, | ||
{ 3, new ModelDefinition { Modalities = [ModelDefinition.SupportedModality.ChatCompletion, ModelDefinition.SupportedModality.TextCompletion], Name = "anthropic.claude-instant-v1", CanStream = false } }, | ||
{ 4, new ModelDefinition { Modalities = [ModelDefinition.SupportedModality.ChatCompletion, ModelDefinition.SupportedModality.TextCompletion], Name = "anthropic.claude-3-sonnet-20240229-v1:0", CanStream = false } }, | ||
{ 5, new ModelDefinition { Modalities = [ModelDefinition.SupportedModality.ChatCompletion, ModelDefinition.SupportedModality.TextCompletion], Name = "anthropic.claude-3-haiku-20240307-v1:0", CanStream = false } }, | ||
{ 6, new ModelDefinition { Modalities = [ModelDefinition.SupportedModality.TextCompletion], Name = "cohere.command-light-text-v14", CanStream = false } }, | ||
{ 7, new ModelDefinition { Modalities = [ModelDefinition.SupportedModality.TextCompletion], Name = "cohere.command-text-v14", CanStream = false } }, | ||
{ 8, new ModelDefinition { Modalities = [ModelDefinition.SupportedModality.ChatCompletion, ModelDefinition.SupportedModality.TextCompletion], Name = "cohere.command-r-v1:0", CanStream = true } }, | ||
{ 9, new ModelDefinition { Modalities = [ModelDefinition.SupportedModality.ChatCompletion, ModelDefinition.SupportedModality.TextCompletion], Name = "cohere.command-r-plus-v1:0", CanStream = true } }, | ||
{ 10, new ModelDefinition { Modalities = [ModelDefinition.SupportedModality.ChatCompletion, ModelDefinition.SupportedModality.TextCompletion], Name = "ai21.jamba-instruct-v1:0", CanStream = true } }, | ||
{ 11, new ModelDefinition { Modalities = [ModelDefinition.SupportedModality.TextCompletion], Name = "ai21.j2-mid-v1", CanStream = false } }, | ||
{ 12, new ModelDefinition { Modalities = [ModelDefinition.SupportedModality.TextCompletion], Name = "ai21.j2-ultra-v1", CanStream = false } }, | ||
{ 13, new ModelDefinition { Modalities = [ModelDefinition.SupportedModality.ChatCompletion, ModelDefinition.SupportedModality.TextCompletion], Name = "meta.llama3-8b-instruct-v1:0", CanStream = true } }, | ||
{ 14, new ModelDefinition { Modalities = [ModelDefinition.SupportedModality.ChatCompletion, ModelDefinition.SupportedModality.TextCompletion], Name = "meta.llama3-70b-instruct-v1:0", CanStream = true } }, | ||
{ 15, new ModelDefinition { Modalities = [ModelDefinition.SupportedModality.ChatCompletion, ModelDefinition.SupportedModality.TextCompletion], Name = "mistral.mistral-7b-instruct-v0:2", CanStream = true } }, | ||
{ 16, new ModelDefinition { Modalities = [ModelDefinition.SupportedModality.ChatCompletion, ModelDefinition.SupportedModality.TextCompletion], Name = "mistral.mixtral-8x7b-instruct-v0:1", CanStream = true } }, | ||
{ 17, new ModelDefinition { Modalities = [ModelDefinition.SupportedModality.ChatCompletion, ModelDefinition.SupportedModality.TextCompletion], Name = "mistral.mistral-large-2402-v1:0", CanStream = true } }, | ||
{ 18, new ModelDefinition { Modalities = [ModelDefinition.SupportedModality.ChatCompletion, ModelDefinition.SupportedModality.TextCompletion], Name = "mistral.mistral-small-2402-v1:0", CanStream = true } }, | ||
{ 19, new ModelDefinition { Modalities = [ModelDefinition.SupportedModality.ChatCompletion, ModelDefinition.SupportedModality.TextCompletion], Name = "amazon.titan-text-lite-v1", CanStream = true } }, | ||
{ 20, new ModelDefinition { Modalities = [ModelDefinition.SupportedModality.ChatCompletion, ModelDefinition.SupportedModality.TextCompletion], Name = "amazon.titan-text-express-v1", CanStream = true } }, | ||
{ 21, new ModelDefinition { Modalities = [ModelDefinition.SupportedModality.ChatCompletion, ModelDefinition.SupportedModality.TextCompletion], Name = "amazon.titan-text-premier-v1:0", CanStream = true } } | ||
}; | ||
} | ||
|
||
/// <summary> | ||
/// ModelDefinition. | ||
/// </summary> | ||
internal struct ModelDefinition | ||
{ | ||
/// <summary> | ||
/// List of services that the model supports. | ||
/// </summary> | ||
internal List<SupportedModality> Modalities { get; set; } | ||
/// <summary> | ||
/// Model ID. | ||
/// </summary> | ||
internal string Name { get; set; } | ||
/// <summary> | ||
/// If the model supports streaming. | ||
/// </summary> | ||
internal bool CanStream { get; set; } | ||
|
||
/// <summary> | ||
/// The services the model supports. | ||
/// </summary> | ||
internal enum SupportedModality | ||
{ | ||
/// <summary> | ||
/// Text completion service. | ||
/// </summary> | ||
TextCompletion, | ||
/// <summary> | ||
/// Chat completion service. | ||
/// </summary> | ||
ChatCompletion | ||
} | ||
} |
Oops, something went wrong.