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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use library in the context of semantic kernel ? #38

Open
giannik opened this issue Jun 29, 2024 · 2 comments
Open

Use library in the context of semantic kernel ? #38

giannik opened this issue Jun 29, 2024 · 2 comments

Comments

@giannik
Copy link

giannik commented Jun 29, 2024

Semantic kernel by Microsoft provides out of the box connectors for open ai and Google but not anthropic. Would it be possible to integrate this library within the context of semantic kernel as a text or chat completion engine?

@tghamm
Copy link
Owner

tghamm commented Jun 29, 2024

Within the context of a text or chat completion engine, absolutely. Within the context of something that supports Semantic Kernel's native function calling, I think that'd take some doing because this library won't pick up on the annotations of a KernelFunction or inherently know what to do with them out of the box. Here's a really rough implementation of how you'd implement the ChatCompletionService:

public class ClaudeChatCompletionService: IChatCompletionService
{
    public IReadOnlyDictionary<string, object?> Attributes { get; }

    public async Task<IReadOnlyList<ChatMessageContent>> GetChatMessageContentsAsync(ChatHistory chatHistory, PromptExecutionSettings? executionSettings = null,
        Kernel? kernel = null, CancellationToken cancellationToken = new CancellationToken())
    {
        throw new NotImplementedException();
    }

    public async IAsyncEnumerable<StreamingChatMessageContent> GetStreamingChatMessageContentsAsync(ChatHistory chatHistory,
        PromptExecutionSettings? executionSettings = null, Kernel? kernel = null,
        CancellationToken cancellationToken = new CancellationToken())
    {

        var client = new AnthropicClient();
        var messages = chatHistory.Where(p => p.Role != AuthorRole.System).Select(p =>
            new Message(p.Role == AuthorRole.Assistant ? RoleType.Assistant : RoleType.User, p.Content)).ToList();

        var parameters = new MessageParameters()
        {
            Messages = messages,
            MaxTokens = 512,
            Model = AnthropicModels.Claude35Sonnet,
            Stream = true,
            Temperature = 1.0m,
            SystemMessage = chatHistory.FirstOrDefault(m => m.Role == AuthorRole.System)?.Content
        };
        var first = true;
        await foreach (var res in client.Messages.StreamClaudeMessageAsync(parameters))
        {
            if (res.Delta != null)
            {
                yield return new StreamingChatMessageContent(first? AuthorRole.Assistant : null, res.Delta.Text);
                first = false;
            }

            
        }

    }
}

You'd just register and use like so:

var builder = Kernel.CreateBuilder();
   
builder.Services.AddSingleton<IChatCompletionService>(provider => new ClaudeChatCompletionService());

Kernel kernel = builder.Build();


IChatCompletionService chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();

// Create the chat history
ChatHistory chatMessages = new ChatHistory("""
                                           You are a friendly assistant who likes to follow the rules. 
                                           You will complete required steps
                                           and request approval before taking any consequential actions. If the user doesn't provide
                                           enough information for you to complete a task, you will keep asking questions until you have
                                           enough information to complete the task.
                                           """);

// Start the conversation
while (true)
{
    // Get user input
    System.Console.Write("User > ");
    chatMessages.AddUserMessage(Console.ReadLine()!);

    // Get the chat completions
    OpenAIPromptExecutionSettings openAIPromptExecutionSettings = new()
    {
        
    };
    var result = chatCompletionService.GetStreamingChatMessageContentsAsync(
        chatMessages,
        executionSettings: openAIPromptExecutionSettings,
        kernel: kernel);

    // Stream the results
    string fullMessage = "";
    await foreach (var content in result)
    {
        if (content.Role.HasValue)
        {
            System.Console.Write("Assistant > ");
        }
        System.Console.Write(content.Content);
        fullMessage += content.Content;
    }
    System.Console.WriteLine();

    // Add the message from the agent to the chat history
    chatMessages.AddAssistantMessage(fullMessage);
}

@giannik
Copy link
Author

giannik commented Jun 29, 2024

thank you for thorough reponse .

i would add it as extension method also:

IKernelBuilder kernelBuilder = Kernel.CreateBuilder();
kernelBuilder.AddAnthropicClaudeChatCompletion(
    modelId: "xxxx",
    apiKey: "YOUR_API_KEY",
    orgId: "YOUR_ORG_ID", // Optional
    serviceId: "YOUR_SERVICE_ID", // Optional; for targeting specific services within Semantic Kernel
    httpClient: new HttpClient() // Optional; if not provided, the HttpClient from the kernel will be used
);
Kernel kernel = kernelBuilder.Build();

Will dig around the other neccesities for full coverage for semantic kernel,as you mention.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants