Skip to content

Commit

Permalink
Merge pull request #15 from tghamm/feature/2.0.0
Browse files Browse the repository at this point in the history
Feature/2.0.0
  • Loading branch information
tghamm authored Mar 5, 2024
2 parents 3acc7ab + c39f451 commit 165f668
Show file tree
Hide file tree
Showing 16 changed files with 646 additions and 57 deletions.
10 changes: 9 additions & 1 deletion Anthropic.SDK.Tests/Anthropic.SDK.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
Expand All @@ -8,6 +8,14 @@
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<None Remove="Red_Apple.jpg" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="Red_Apple.jpg" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="7.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
Expand Down
2 changes: 1 addition & 1 deletion Anthropic.SDK.Tests/Completions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public async Task TestClaudeCompletion()
public async Task TestClaudeStreamingCompletion()
{
var client = new AnthropicClient();
var prompt = AnthropicSignals.HumanSignal + "Write me a sonnet about Joe Biden." +
var prompt = AnthropicSignals.HumanSignal + "Write me a sonnet about The Statue of Liberty." +
AnthropicSignals.AssistantSignal;

var parameters = new SamplingParameters()
Expand Down
152 changes: 152 additions & 0 deletions Anthropic.SDK.Tests/Messages.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Anthropic.SDK.Constants;
using Anthropic.SDK.Messaging;

namespace Anthropic.SDK.Tests
{
[TestClass]
public class Messages
{
[TestMethod]
public async Task TestBasicClaude3Message()
{
var client = new AnthropicClient();
var messages = new List<Message>();
messages.Add(new Message()
{
Role = RoleType.User,
Content = "Write me a sonnet about the Statue of Liberty"
});
var parameters = new MessageParameters()
{
Messages = messages,
MaxTokens = 512,
Model = AnthropicModels.Claude3Sonnet,
Stream = false,
Temperature = 1.0m,
};
var res = await client.Messages.GetClaudeMessageAsync(parameters);
}

[TestMethod]
public async Task TestBasicClaude3ImageMessage()
{
string resourceName = "Anthropic.SDK.Tests.Red_Apple.jpg";

Assembly assembly = Assembly.GetExecutingAssembly();

await using Stream stream = assembly.GetManifestResourceStream(resourceName);
byte[] imageBytes;
using (var memoryStream = new MemoryStream())
{
await stream.CopyToAsync(memoryStream);
imageBytes = memoryStream.ToArray();
}

string base64String = Convert.ToBase64String(imageBytes);

var client = new AnthropicClient();

var messages = new List<Message>();
messages.Add(new Message()
{
Role = RoleType.User,
Content = new dynamic[]
{
new ImageContent()
{
Source = new ImageSource()
{
MediaType = "image/jpeg",
Data = base64String
}
},
new TextContent()
{
Text = "What is this a picture of?"
}
}
});
var parameters = new MessageParameters()
{
Messages = messages,
MaxTokens = 512,
Model = AnthropicModels.Claude3Opus,
Stream = false,
Temperature = 1.0m,
};
var res = await client.Messages.GetClaudeMessageAsync(parameters);
}

[TestMethod]
public async Task TestStreamingClaude3ImageMessage()
{
string resourceName = "Anthropic.SDK.Tests.Red_Apple.jpg";

// Get the current assembly
Assembly assembly = Assembly.GetExecutingAssembly();

// Get a stream to the embedded resource
await using Stream stream = assembly.GetManifestResourceStream(resourceName);
// Read the stream into a byte array
byte[] imageBytes;
using (var memoryStream = new MemoryStream())
{
await stream.CopyToAsync(memoryStream);
imageBytes = memoryStream.ToArray();
}

// Convert the byte array to a base64 string
string base64String = Convert.ToBase64String(imageBytes);

var client = new AnthropicClient();
var messages = new List<Message>();
messages.Add(new Message()
{
Role = RoleType.User,
Content = new dynamic[]
{
new ImageContent()
{
Source = new ImageSource()
{
MediaType = "image/jpeg",
Data = base64String
}
},
new TextContent()
{
Text = "What is this a picture of?"
}
}
});
var parameters = new MessageParameters()
{
Messages = messages,
MaxTokens = 512,
Model = AnthropicModels.Claude3Opus,
Stream = true,
Temperature = 1.0m,
};
var outputs = new List<MessageResponse>();
await foreach (var res in client.Messages.StreamClaudeMessageAsync(parameters))
{
if (res.Delta != null)
{
Debug.Write(res.Delta.Text);
}

outputs.Add(res);
}
Debug.WriteLine(string.Empty);
Debug.WriteLine($@"Used Tokens - Input:{outputs.First().StreamStartMessage.Usage.InputTokens}.
Output: {outputs.Last().Usage.OutputTokens}");
}
}
}
Binary file added Anthropic.SDK.Tests/Red_Apple.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions Anthropic.SDK/Anthropic.SDK.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
<PackageTags>Claude, AI, ML, API, Anthropic</PackageTags>
<Title>Claude API</Title>
<PackageReleaseNotes>
Adds token counter extension method helper.
Support for Messages Endpoint and Claude 3
</PackageReleaseNotes>
<PackageId>Anthropic.SDK</PackageId>
<Version>1.3.0</Version>
<AssemblyVersion>1.3.0.0</AssemblyVersion>
<FileVersion>1.3.0.0</FileVersion>
<Version>2.0.0</Version>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
<FileVersion>2.0.0.0</FileVersion>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<PackageReadmeFile>README.md</PackageReadmeFile>
<ProduceReferenceAssembly>True</ProduceReferenceAssembly>
Expand Down
7 changes: 7 additions & 0 deletions Anthropic.SDK/AnthropicClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System;
using System.Net.Http;
using System.Reflection;
using Anthropic.SDK.Messaging;

namespace Anthropic.SDK
{
Expand Down Expand Up @@ -33,11 +34,17 @@ public AnthropicClient(APIAuthentication apiKeys = null)
{
this.Auth = apiKeys.ThisOrDefault();
Completions = new CompletionsEndpoint(this);
Messages = new MessagesEndpoint(this);
}

/// <summary>
/// Text generation is the core function of the API. You give the API a prompt, and it generates a completion. The way you “program” the API to do a task is by simply describing the task in plain english or providing a few written examples. This simple approach works for a wide range of use cases, including summarization, translation, grammar correction, question answering, chatbots, composing emails, and much more (see the prompt library for inspiration).
/// </summary>
public CompletionsEndpoint Completions { get; }

/// <summary>
/// Text generation is the core function of the API. You give the API a prompt, and it generates a completion. The way you “program” the API to do a task is by simply describing the task in plain english or providing a few written examples. This simple approach works for a wide range of use cases, including summarization, translation, grammar correction, question answering, chatbots, composing emails, and much more (see the prompt library for inspiration).
/// </summary>
public MessagesEndpoint Messages { get; }
}
}
12 changes: 8 additions & 4 deletions Anthropic.SDK/Completions/CompletionsEndpoint.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;

namespace Anthropic.SDK.Completions
Expand All @@ -19,23 +21,25 @@ internal CompletionsEndpoint(AnthropicClient client) : base(client) { }
/// Makes a non-streaming call to the Claude completion API. Be sure to set stream to false in <param name="parameters"></param>.
/// </summary>
/// <param name="parameters"></param>
public async Task<CompletionResponse> GetClaudeCompletionAsync(SamplingParameters parameters)
/// <param name="ctx"></param>
public async Task<CompletionResponse> GetClaudeCompletionAsync(SamplingParameters parameters, CancellationToken ctx = default)
{
parameters.Stream = false;
ValidateParameters(parameters);
var response = await HttpRequest(Url, HttpMethod.Post, parameters);
var response = await HttpRequest<CompletionResponse>(Url, HttpMethod.Post, parameters, ctx);
return response;
}

/// <summary>
/// Makes a streaming call to the Claude completion API using an IAsyncEnumerable. Be sure to set stream to true in <param name="parameters"></param>.
/// </summary>
/// <param name="parameters"></param>
public async IAsyncEnumerable<CompletionResponse> StreamClaudeCompletionAsync(SamplingParameters parameters)
/// <param name="ctx"></param>
public async IAsyncEnumerable<CompletionResponse> StreamClaudeCompletionAsync(SamplingParameters parameters, [EnumeratorCancellation] CancellationToken ctx = default)
{
parameters.Stream = true;
ValidateParameters(parameters);
await foreach (var result in HttpStreamingRequest(Url, HttpMethod.Post, parameters))
await foreach (var result in HttpStreamingRequest<CompletionResponse>(Url, HttpMethod.Post, parameters, ctx))
{
yield return result;
}
Expand Down
10 changes: 10 additions & 0 deletions Anthropic.SDK/Constants/AnthropicModels.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,15 @@ public static class AnthropicModels
/// Claude Instant V1.2 latest full version.
/// </summary>
public const string ClaudeInstant_v1_2 = "claude-instant-1.2";

/// <summary>
/// Claude 3 Opus
/// </summary>
public const string Claude3Opus = "claude-3-opus-20240229";

/// <summary>
/// Claude 3 Sonnet
/// </summary>
public const string Claude3Sonnet = "claude-3-sonnet-20240229";
}
}
Loading

0 comments on commit 165f668

Please sign in to comment.