Files
anthropic-client/tests/AnthropicClient.Tests/EndToEnd/AnthropicApiClientTests.cs
T

384 lines
12 KiB
C#
Raw Normal View History

using AnthropicClient.Tests.Files;
2024-06-27 23:26:53 -05:00
namespace AnthropicClient.Tests.EndToEnd;
2024-07-19 22:31:36 -05:00
public class ClientTests(ConfigurationFixture configFixture) : EndToEndTest(configFixture)
2024-06-27 23:26:53 -05:00
{
[Fact]
2024-07-03 16:57:27 -05:00
public async Task CreateMessageAsync_WhenCalled_ItShouldReturnResponse()
2024-06-27 23:26:53 -05:00
{
2024-07-03 16:57:27 -05:00
var request = new MessageRequest(
2024-06-27 23:26:53 -05:00
model: AnthropicModels.Claude3Haiku,
messages: [new(MessageRole.User, [new TextContent("Hello!")])]
);
2024-07-03 16:57:27 -05:00
var result = await _client.CreateMessageAsync(request);
2024-06-27 23:26:53 -05:00
result.IsSuccess.Should().BeTrue();
2024-07-03 16:57:27 -05:00
result.Value.Should().BeOfType<MessageResponse>();
result.Value.Content.Should().NotBeNullOrEmpty();
2024-06-27 23:26:53 -05:00
}
2024-06-28 10:54:00 -05:00
[Fact]
2024-07-03 16:57:27 -05:00
public async Task CreateMessageAsync_WhenCalledWithStreamRequest_ItShouldReturnEvents()
2024-06-28 10:54:00 -05:00
{
2024-07-03 16:57:27 -05:00
var request = new StreamMessageRequest(
2024-06-28 10:54:00 -05:00
model: AnthropicModels.Claude3Haiku,
messages: [new(MessageRole.User, [new TextContent("Hello!")])]
);
2024-07-03 16:57:27 -05:00
var response = _client.CreateMessageAsync(request);
2024-07-01 22:46:02 -05:00
2024-06-28 10:54:00 -05:00
var events = new List<AnthropicEvent>();
await foreach (var e in response)
{
events.Add(e);
}
events.Should().NotBeEmpty();
}
[Fact]
2024-07-03 16:57:27 -05:00
public async Task CreateMessageAsync_WhenCalledWithStreamRequest_ItShouldYieldAMessageCompleteEvent()
{
2024-07-03 16:57:27 -05:00
var request = new StreamMessageRequest(
model: AnthropicModels.Claude3Haiku,
messages: [new(MessageRole.User, [new TextContent("Hello!")])]
);
2024-07-03 16:57:27 -05:00
var response = _client.CreateMessageAsync(request);
2024-07-01 22:46:02 -05:00
await foreach (var e in response)
{
if (e.Data is MessageCompleteEventData messageCompleteData)
{
messageCompleteData.Message.Should().NotBeNull();
break;
}
}
}
2024-07-19 21:31:49 -05:00
[Fact]
public async Task CreateMessageAsync_WhenImageIsSent_ItShouldReturnResponse()
{
var imagePath = TestFileHelper.GetTestFilePath("elephant.jpg");
2024-07-19 21:31:49 -05:00
var mediaType = "image/jpeg";
2024-07-19 22:47:47 -05:00
var bytes = await File.ReadAllBytesAsync(imagePath);
var base64Data = Convert.ToBase64String(bytes);
2024-07-19 21:31:49 -05:00
var request = new MessageRequest(
model: AnthropicModels.Claude3Haiku,
messages: [
new(MessageRole.User, [
2024-07-19 22:38:47 -05:00
new ImageContent(mediaType, base64Data),
2024-07-19 21:31:49 -05:00
new TextContent("What is in this image?")
]),
]
);
var result = await _client.CreateMessageAsync(request);
result.IsSuccess.Should().BeTrue();
result.Value.Should().BeOfType<MessageResponse>();
result.Value.Content.Should().NotBeNullOrEmpty();
2024-07-19 21:38:52 -05:00
var text = result.Value.Content.Aggregate("", (acc, content) =>
2024-07-19 21:31:49 -05:00
{
if (content is TextContent textContent)
{
acc += textContent.Text;
}
return acc;
});
text.Should().Contain("elephant");
}
[Fact]
public async Task CreateMessageAsync_WhenSystemMessagesContainCacheControl_ItShouldUseCache()
{
var client = CreateClient(new HttpClient());
var storyPath = TestFileHelper.GetTestFilePath("story.txt");
var storyText = await File.ReadAllTextAsync(storyPath);
var request = new MessageRequest(
model: AnthropicModels.Claude3Haiku,
systemMessages: [
new("You are a helpful assistant who can answer questions about the following text:"),
new(storyText, new EphemeralCacheControl())
],
messages: [
new(MessageRole.User, [
new TextContent("Give me a one sentence summary of this story.")
]),
]
);
var resultOne = await _client.CreateMessageAsync(request);
resultOne.IsSuccess.Should().BeTrue();
resultOne.Value.Should().BeOfType<MessageResponse>();
resultOne.Value.Content.Should().NotBeNullOrEmpty();
resultOne.Value.Usage.Should().Match<Usage>(u => u.CacheCreationInputTokens > 0 || u.CacheReadInputTokens > 0);
request.Messages.Add(new(MessageRole.Assistant, resultOne.Value.Content));
request.Messages.Add(new(MessageRole.User, [new TextContent("What is the main theme of this story?")]));
var resultTwo = await client.CreateMessageAsync(request);
resultTwo.IsSuccess.Should().BeTrue();
resultTwo.Value.Should().BeOfType<MessageResponse>();
resultTwo.Value.Content.Should().NotBeNullOrEmpty();
resultTwo.Value.Usage.CacheReadInputTokens.Should().BeGreaterThan(0);
}
[Fact]
public async Task CreateMessageAsync_WhenMessagesContainCacheControl_ItShouldUseCache()
{
var client = CreateClient(new HttpClient());
var storyPath = TestFileHelper.GetTestFilePath("story.txt");
var storyText = await File.ReadAllTextAsync(storyPath);
var request = new MessageRequest(
model: AnthropicModels.Claude3Haiku,
messages: [
new(MessageRole.User, [
new TextContent("Give me a one sentence summary of this story."),
new TextContent(storyText, new EphemeralCacheControl())
]),
]
);
var resultOne = await client.CreateMessageAsync(request);
resultOne.IsSuccess.Should().BeTrue();
resultOne.Value.Should().BeOfType<MessageResponse>();
resultOne.Value.Content.Should().NotBeNullOrEmpty();
resultOne.Value.Usage.Should().Match<Usage>(u => u.CacheCreationInputTokens > 0 || u.CacheReadInputTokens > 0);
request.Messages.Add(new(MessageRole.Assistant, resultOne.Value.Content));
request.Messages.Add(new(MessageRole.User, [new TextContent("What is the main theme of this story?")]));
var resultTwo = await client.CreateMessageAsync(request);
resultTwo.IsSuccess.Should().BeTrue();
resultTwo.Value.Should().BeOfType<MessageResponse>();
resultTwo.Value.Content.Should().NotBeNullOrEmpty();
resultTwo.Value.Usage.CacheReadInputTokens.Should().BeGreaterThan(0);
}
[Fact]
public async Task CreateMessageAsync_WhenToolsContainCacheControl_ItShouldUseCache()
{
var client = CreateClient(new HttpClient());
var func = (string ticker) => ticker;
var tools = Enumerable
.Range(0, 50)
.Select(i => Tool.CreateFromFunction($"tool-{i}", $"Tool {i}", func))
.ToList();
tools.Last().CacheControl = new EphemeralCacheControl();
var request = new MessageRequest(
model: AnthropicModels.Claude3Haiku,
messages: [
new(MessageRole.User, [
new TextContent("Hi could you tell me your name?"),
]),
],
tools: tools
);
var resultOne = await client.CreateMessageAsync(request);
resultOne.IsSuccess.Should().BeTrue();
resultOne.Value.Should().BeOfType<MessageResponse>();
resultOne.Value.Content.Should().NotBeNullOrEmpty();
resultOne.Value.Usage.Should().Match<Usage>(u => u.CacheCreationInputTokens > 0 || u.CacheReadInputTokens > 0);
request.Messages.Add(new(MessageRole.Assistant, resultOne.Value.Content));
request.Messages.Add(new(MessageRole.User, [new TextContent("Could you tell me the stock price for AAPL?")]));
var resultTwo = await client.CreateMessageAsync(request);
resultTwo.IsSuccess.Should().BeTrue();
resultTwo.Value.Should().BeOfType<MessageResponse>();
resultTwo.Value.Content.Should().NotBeNullOrEmpty();
resultTwo.Value.Usage.CacheReadInputTokens.Should().BeGreaterThan(0);
}
[Fact]
public async Task CreateMessageAsync_WhenProvidedWithPDF_ItShouldReturnResponse()
{
var pdfPath = TestFileHelper.GetTestFilePath("addendum.pdf");
var bytes = await File.ReadAllBytesAsync(pdfPath);
var base64Data = Convert.ToBase64String(bytes);
var request = new MessageRequest(
model: AnthropicModels.Claude35Sonnet,
messages: [
new(MessageRole.User, [new TextContent("What is the title of this paper?")]),
new(MessageRole.User, [new DocumentContent("application/pdf", base64Data)])
]
);
var client = CreateClient(new HttpClient());
var result = await client.CreateMessageAsync(request);
result.IsSuccess.Should().BeTrue();
result.Value.Should().BeOfType<MessageResponse>();
result.Value.Content.Should().NotBeNullOrEmpty();
var text = result.Value.Content.Aggregate("", (acc, content) =>
{
if (content is TextContent textContent)
{
acc += textContent.Text;
}
return acc;
});
text.Should().Contain("Model Card Addendum: Claude 3.5 Haiku and Upgraded Claude 3.5 Sonnet");
}
[Fact]
public async Task CreateMessageAsync_WhenProvidedWithPDFWithCacheControl_ItShouldUseCache()
{
var pdfPath = TestFileHelper.GetTestFilePath("addendum.pdf");
var bytes = await File.ReadAllBytesAsync(pdfPath);
var base64Data = Convert.ToBase64String(bytes);
var client = CreateClient(new HttpClient());
var request = new MessageRequest(
model: AnthropicModels.Claude35Sonnet,
messages: [
new(MessageRole.User, [
new DocumentContent("application/pdf", base64Data, new EphemeralCacheControl()),
new TextContent("What is the title of this paper?")
]),
]
);
var resultOne = await client.CreateMessageAsync(request);
resultOne.IsSuccess.Should().BeTrue();
resultOne.Value.Should().BeOfType<MessageResponse>();
resultOne.Value.Content.Should().NotBeNullOrEmpty();
resultOne.Value.Usage.Should().Match<Usage>(u => u.CacheCreationInputTokens > 0 || u.CacheReadInputTokens > 0);
request.Messages.Add(new(MessageRole.Assistant, resultOne.Value.Content));
request.Messages.Add(new(MessageRole.User, [new TextContent("What is the main theme of this paper?")]));
var resultTwo = await client.CreateMessageAsync(request);
resultTwo.IsSuccess.Should().BeTrue();
resultTwo.Value.Should().BeOfType<MessageResponse>();
resultTwo.Value.Content.Should().NotBeNullOrEmpty();
resultTwo.Value.Usage.CacheReadInputTokens.Should().BeGreaterThan(0);
}
2025-01-01 20:13:01 -06:00
[Fact]
public async Task CountMessageTokensAsync_WhenCalled_ItShouldReturnResponse()
{
var request = new CountMessageTokensRequest(
model: AnthropicModels.Claude3Haiku,
messages: [
new(MessageRole.User, [new TextContent("Hello!")])
]
);
var result = await _client.CountMessageTokensAsync(request);
result.IsSuccess.Should().BeTrue();
result.Value.Should().BeOfType<TokenCountResponse>();
result.Value.InputTokens.Should().BeGreaterThan(0);
}
[Fact]
public async Task ListModelsAsync_WhenCalled_ItShouldReturnResponse()
{
var result = await _client.ListModelsAsync();
result.IsSuccess.Should().BeTrue();
result.Value.Should().BeOfType<Page<AnthropicModel>>();
result.Value.Data.Should().HaveCountGreaterThan(0);
}
[Fact]
public async Task ListModelsAsync_WhenCalledWithPagination_ItShouldReturnResponse()
{
var result = await _client.ListModelsAsync(new PagingRequest(limit: 1));
result.IsSuccess.Should().BeTrue();
result.Value.Should().BeOfType<Page<AnthropicModel>>();
result.Value.Data.Should().HaveCount(1);
}
[Fact]
public async Task ListAllModelsAsync_WhenCalled_ItShouldReturnResponse()
{
var responses = await _client.ListAllModelsAsync(limit: 1).ToListAsync();
responses.Should().HaveCountGreaterThan(0);
}
2025-01-05 21:36:34 -06:00
[Fact]
public async Task GetModelAsync_WhenCalled_ItShouldReturnResponse()
{
var result = await _client.GetModelAsync(AnthropicModels.Claude3Haiku);
result.IsSuccess.Should().BeTrue();
result.Value.Should().BeOfType<AnthropicModel>();
result.Value.Id.Should().Be(AnthropicModels.Claude3Haiku);
}
[Fact]
public async Task CreateMessageBatchAsync_WhenCalled_ItShouldReturnResponse()
{
var request = new MessageBatchRequest([
new(
Guid.NewGuid().ToString(),
new(
model: AnthropicModels.Claude3Haiku,
messages: [new(MessageRole.User, [new TextContent("Hello!")])]
)
),
]);
var result = await _client.CreateMessageBatchAsync(request);
result.IsSuccess.Should().BeTrue();
result.Value.Should().BeOfType<MessageBatchResponse>();
result.Value.Id.Should().NotBeNullOrEmpty();
}
2025-01-08 23:15:24 -06:00
[Fact]
public async Task GetMessageBatchAsync_WhenCalled_ItShouldReturnResponse()
{
var request = new MessageBatchRequest([
new(
Guid.NewGuid().ToString(),
new(
model: AnthropicModels.Claude3Haiku,
messages: [new(MessageRole.User, [new TextContent("Hello!")])]
)
),
]);
2025-01-08 23:15:24 -06:00
var createResult = await _client.CreateMessageBatchAsync(request);
var getResult = await _client.GetMessageBatchAsync(createResult.Value.Id);
getResult.IsSuccess.Should().BeTrue();
getResult.Value.Should().BeOfType<MessageBatchResponse>();
getResult.Value.Id.Should().Be(createResult.Value.Id);
}
2024-06-27 23:26:53 -05:00
}