Skip to content

.Net: Adds an AI connector for Anthropic - #3476

Closed
Chetan Desh (glorious-beard) wants to merge 17 commits into
microsoft:mainfrom
glorious-beard:main
Closed

.Net: Adds an AI connector for Anthropic#3476
Chetan Desh (glorious-beard) wants to merge 17 commits into
microsoft:mainfrom
glorious-beard:main

Conversation

@glorious-beard

Copy link
Copy Markdown

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

@shawncal Shawn Callegari (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
Copy Markdown
Author

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

@david-redano

Copy link
Copy Markdown

That's cool Chetan Desh (@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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
Contributor

Chetan Desh (@glorious-beard) Thanks for your contribution. Roger Barreto (@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
Copy Markdown
Member

Chetan Desh (@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