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

.Net: Adds an AI connector for Anthropic #3476

Closed
wants to merge 17 commits into from

Conversation

glorious-beard
Copy link

Motivation and Context

  1. Why is this change required?
    This allows solutions utilizing Claude or Claude 2 to use the Microsoft Semantic Toolkit.
  2. What problem does it solve?
    It provides an additional AI connector that can be used for solutions where the generative AI is Anthropic, and also where multiple generative AIs may be working together.
  3. What scenario does it contribute to?
    Agnostic access to generative AI
  4. If it fixes an open issue, please link to the issue here.
    .Net: Add Anthropic Support (I can contribute a PR for this) #3462

Description

This PR introduces a new chat completion object that implements IChatCompletion and ITextCompletion follows the same design patterns as the other AI connectors already in the kernel.

Contribution Checklist

@glorious-beard glorious-beard requested a review from a team as a code owner November 13, 2023 19:46
@shawncal shawncal added docs and tests Improvements or additions to documentation .NET Issue or Pull requests regarding .NET code kernel Issues or pull requests impacting the core kernel labels Nov 13, 2023
@github-actions github-actions bot changed the title Adds an AI connector for Anthropic .Net: Adds an AI connector for Anthropic Nov 13, 2023
@glorious-beard
Copy link
Author

@microsoft-github-policy-service agree company="Advocat AI"

@RogerBarreto RogerBarreto added the PR: ready for review All feedback addressed, ready for reviews label Nov 13, 2023
@david-redano
Copy link

That's cool @glorious-beard!

Could this be extended to support functions as well? That would be an adaptation of this code from @mshumer

Thanks in advance!


private readonly ILogger? _log;
private readonly HttpClient _httpClient;
private readonly bool _disposeHttpClient;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any situation where this needs to be disposed? If it came from externally, we musn't. And if we created it from the internal factory, we don't need to.

/// <summary>
/// A chat completion connector for the Anthropic API.
/// </summary>
public class AnthropicChatCompletion : IChatCompletion, ITextCompletion, IDisposable
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sealed


private HttpRequestMessage CreateHttpRequest(AnthropicRequest request)
{
var json = JsonSerializer.Serialize(request);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be more efficient (skipping an intermediate string) to use SerializeToUTF8 and create a ByteArrayContent.

catch (HttpOperationException e) when (!string.IsNullOrWhiteSpace(e.ResponseContent))
{
this._log?.LogError(e, "Error sending request to Anthropic API: {Error}", e.ResponseContent);
var error = JsonSerializer.Deserialize<AnthropicError>(e.ResponseContent!);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if this throws an exception?

private static string ToPrompt(ChatHistory chat)
{
var promptBuilder = new StringBuilder();
foreach (var message in chat.Where(message => message.Role == AuthorRole.User || message.Role == AuthorRole.Assistant))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be more efficient to just do this as an if check at the beginning of the while loop rather than using a Where

/// </remarks>
[JsonPropertyName("temperature")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public double? Temperature
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it nullable?

/// </remarks>
[JsonPropertyName("top_p")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public double? TopP
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it nullable?


this._temperature = value;

if (this._temperature == null)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having one property set another like this is anti-pattern, as it means order of setting matters.

/// <summary>
/// A successful response from the Anthropic API.
/// </summary>
public class AnthropicResponse
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sealed

await Task.Yield();
yield return _message;
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand the complexity of this method. Shouldn't the whole thing just be:
yield return new ChatMessage(AuthorRole.Assistant, this._response.Completion);
If the concern is the warning about lack of awaits, that can be suppressed.

@markwallace-microsoft
Copy link
Member

@glorious-beard Thanks for your contribution. @RogerBarreto is working on our strategy to expand our AI Connectors. We will have an ADR available soon describing the approach we want to use and we will work with you to progress your PR.

@RogerBarreto
Copy link
Member

@glorious-beard we published our ADR regarding the process to add community connectors here

Let me know if you or any contributor from the community have intention on continuing the work in this connector and I can create a dedicated feature branch moving forward.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs and tests Improvements or additions to documentation kernel Issues or pull requests impacting the core kernel .NET Issue or Pull requests regarding .NET code PR: ready for review All feedback addressed, ready for reviews
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

6 participants