Files
microsoft--semantic-kernel/dotnet/samples/Demos/AmazonBedrockModels/Program.cs
T
wehub-resource-sync b957a53def
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
chore: import upstream snapshot with attribution
2026-07-13 13:21:23 +08:00

280 lines
13 KiB
C#

// Copyright (c) Microsoft. All rights reserved.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Amazon.BedrockRuntime.Model;
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;
default:
throw new InvalidOperationException("Invalid choice");
}
async Task PerformChatCompletion()
{
string userInput;
ChatHistory chatHistory = [];
// 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}");
var innerContent = message.InnerContent as ConverseResponse;
Console.WriteLine($"Usage Metadata: {JsonSerializer.Serialize(innerContent?.Usage)}");
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);
Console.WriteLine($"Metadata: {JsonSerializer.Serialize(firstTextContent.InnerContent)}");
}
else
{
Console.WriteLine("Text Generation Answer: (none)");
}
}
else
{
Console.WriteLine("Text Generation Answer: (No output text)");
}
}
async Task PerformStreamChatCompletion()
{
string userInput;
ChatHistory streamChatHistory = [];
// 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
}
}