|
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // AnthropicClientTest.cs
-
- using System.Text;
- using System.Text.Json;
- using System.Text.Json.Nodes;
- using System.Text.Json.Serialization;
- using AutoGen.Anthropic.DTO;
- using AutoGen.Anthropic.Utils;
- using AutoGen.Tests;
- using FluentAssertions;
- using Xunit;
-
- namespace AutoGen.Anthropic.Tests;
-
- [Trait("Category", "UnitV1")]
- public class AnthropicClientTests
- {
- [ApiKeyFact("ANTHROPIC_API_KEY")]
- public async Task AnthropicClientChatCompletionTestAsync()
- {
- var anthropicClient = new AnthropicClient(new HttpClient(), AnthropicConstants.Endpoint, AnthropicTestUtils.ApiKey);
-
- var request = new ChatCompletionRequest();
- request.Model = AnthropicConstants.Claude3Haiku;
- request.Stream = false;
- request.MaxTokens = 100;
- request.Messages = new List<ChatMessage>() { new ChatMessage("user", "Hello world") };
- ChatCompletionResponse response = await anthropicClient.CreateChatCompletionsAsync(request, CancellationToken.None);
-
- Assert.NotNull(response);
- Assert.NotNull(response.Content);
- Assert.NotEmpty(response.Content);
- response.Content.Count.Should().Be(1);
- response.Content.First().Should().BeOfType<TextContent>();
- var textContent = (TextContent)response.Content.First();
- Assert.Equal("text", textContent.Type);
- Assert.NotNull(response.Usage);
- response.Usage.OutputTokens.Should().BeGreaterThan(0);
- }
-
- [ApiKeyFact("ANTHROPIC_API_KEY")]
- public async Task AnthropicClientStreamingChatCompletionTestAsync()
- {
- var anthropicClient = new AnthropicClient(new HttpClient(), AnthropicConstants.Endpoint, AnthropicTestUtils.ApiKey);
-
- var request = new ChatCompletionRequest();
- request.Model = AnthropicConstants.Claude3Haiku;
- request.Stream = true;
- request.MaxTokens = 500;
- request.SystemMessage =
- [
- SystemMessage.CreateSystemMessage(
- "You are a helpful assistant that convert input to json object, use JSON format.")
- ];
-
- request.Messages = new List<ChatMessage>()
- {
- new("user", "name: John, age: 41, email: g123456@gmail.com")
- };
-
- var response = anthropicClient.StreamingChatCompletionsAsync(request, CancellationToken.None);
- var results = await response.ToListAsync();
- results.Count.Should().BeGreaterThan(0);
-
- // Merge the chunks.
- StringBuilder sb = new();
- foreach (ChatCompletionResponse result in results)
- {
- if (result.Delta is not null && !string.IsNullOrEmpty(result.Delta.Text))
- {
- sb.Append(result.Delta.Text);
- }
- }
-
- string resultContent = sb.ToString();
- Assert.NotNull(resultContent);
-
- var person = JsonSerializer.Deserialize<Person>(resultContent);
- Assert.NotNull(person);
- person.Name.Should().Be("John");
- person.Age.Should().Be(41);
- person.Email.Should().Be("g123456@gmail.com");
- Assert.NotNull(results.First().StreamingMessage);
- results.First().StreamingMessage!.Role.Should().Be("assistant");
- }
-
- [ApiKeyFact("ANTHROPIC_API_KEY")]
- public async Task AnthropicClientImageChatCompletionTestAsync()
- {
- var anthropicClient = new AnthropicClient(new HttpClient(), AnthropicConstants.Endpoint, AnthropicTestUtils.ApiKey);
-
- var request = new ChatCompletionRequest();
- request.Model = AnthropicConstants.Claude3Haiku;
- request.Stream = false;
- request.MaxTokens = 100;
- request.SystemMessage =
- [
- SystemMessage.CreateSystemMessage(
- "You are a LLM that is suppose to describe the content of the image. Give me a description of the provided image."),
- ];
-
- var base64Image = await AnthropicTestUtils.Base64FromImageAsync("square.png");
- var messages = new List<ChatMessage>
- {
- new("user",
- [
- new ImageContent { Source = new ImageSource {MediaType = "image/png", Data = base64Image} }
- ])
- };
-
- request.Messages = messages;
-
- var response = await anthropicClient.CreateChatCompletionsAsync(request, CancellationToken.None);
-
- Assert.NotNull(response);
- Assert.NotNull(response.Content);
- Assert.NotEmpty(response.Content);
- response.Content.Count.Should().Be(1);
- response.Content.First().Should().BeOfType<TextContent>();
- var textContent = (TextContent)response.Content.First();
- Assert.Equal("text", textContent.Type);
- Assert.NotNull(response.Usage);
- response.Usage.OutputTokens.Should().BeGreaterThan(0);
- }
-
- [ApiKeyFact("ANTHROPIC_API_KEY")]
- public async Task AnthropicClientTestToolsAsync()
- {
- var anthropicClient = new AnthropicClient(new HttpClient(), AnthropicConstants.Endpoint, AnthropicTestUtils.ApiKey);
-
- var request = new ChatCompletionRequest();
- request.Model = AnthropicConstants.Claude3Haiku;
- request.Stream = false;
- request.MaxTokens = 100;
- request.Messages = new List<ChatMessage>() { new("user", "Use the stock price tool to look for MSFT. Your response should only be the tool.") };
- request.Tools = new List<Tool>() { AnthropicTestUtils.StockTool };
-
- ChatCompletionResponse response =
- await anthropicClient.CreateChatCompletionsAsync(request, CancellationToken.None);
-
- Assert.NotNull(response.Content);
- Assert.True(response.Content.First() is ToolUseContent);
- ToolUseContent toolUseContent = ((ToolUseContent)response.Content.First());
- Assert.Equal("get_stock_price", toolUseContent.Name);
- Assert.NotNull(toolUseContent.Input);
- Assert.True(toolUseContent.Input is JsonNode);
- JsonNode jsonNode = toolUseContent.Input;
- Assert.Equal("{\"ticker\":\"MSFT\"}", jsonNode.ToJsonString());
- }
-
- [ApiKeyFact("ANTHROPIC_API_KEY")]
- public async Task AnthropicClientTestToolChoiceAsync()
- {
- var anthropicClient = new AnthropicClient(new HttpClient(), AnthropicConstants.Endpoint, AnthropicTestUtils.ApiKey);
-
- var request = new ChatCompletionRequest();
- request.Model = AnthropicConstants.Claude3Haiku;
- request.Stream = false;
- request.MaxTokens = 100;
- request.Messages = new List<ChatMessage>() { new("user", "What is the weather today? Your response should only be the tool.") };
- request.Tools = new List<Tool>() { AnthropicTestUtils.StockTool, AnthropicTestUtils.WeatherTool };
-
- // Force to use get_stock_price even though the prompt is about weather
- request.ToolChoice = ToolChoice.ToolUse("get_stock_price");
-
- ChatCompletionResponse response =
- await anthropicClient.CreateChatCompletionsAsync(request, CancellationToken.None);
-
- Assert.NotNull(response.Content);
- Assert.True(response.Content.First() is ToolUseContent);
- ToolUseContent toolUseContent = ((ToolUseContent)response.Content.First());
- Assert.Equal("get_stock_price", toolUseContent.Name);
- Assert.NotNull(toolUseContent.Input);
- Assert.True(toolUseContent.Input is JsonNode);
- }
-
- [ApiKeyFact("ANTHROPIC_API_KEY")]
- public async Task AnthropicClientChatCompletionCacheControlTestAsync()
- {
- var anthropicClient = new AnthropicClient(new HttpClient(), AnthropicConstants.Endpoint, AnthropicTestUtils.ApiKey);
-
- var request = new ChatCompletionRequest();
- request.Model = AnthropicConstants.Claude35Sonnet;
- request.Stream = false;
- request.MaxTokens = 100;
-
- request.SystemMessage =
- [
- SystemMessage.CreateSystemMessageWithCacheControl(
- $"You are an LLM that is great at remembering stories {AnthropicTestUtils.LongStory}"),
- ];
-
- request.Messages =
- [
- new ChatMessage("user", "What should i know about Bob?")
- ];
-
- var response = await anthropicClient.CreateChatCompletionsAsync(request, CancellationToken.None);
- response.Usage.Should().NotBeNull();
-
- // There's no way to clear the cache. Running the assert frequently may cause this to fail because the cache is already been created
- // response.Usage!.CreationInputTokens.Should().BeGreaterThan(0);
- // The cache reduces the input tokens. We expect the input tokens to be less the large system prompt and only the user message
- response.Usage!.InputTokens.Should().BeLessThan(20);
-
- request.Messages =
- [
- new ChatMessage("user", "Summarize the story of bob")
- ];
-
- response = await anthropicClient.CreateChatCompletionsAsync(request, CancellationToken.None);
- response.Usage.Should().NotBeNull();
- response.Usage!.CacheReadInputTokens.Should().BeGreaterThan(0);
- response.Usage!.InputTokens.Should().BeLessThan(20);
-
- // Should not use the cache
- request.SystemMessage =
- [
- SystemMessage.CreateSystemMessage("You are a helpful assistant.")
- ];
-
- request.Messages =
- [
- new ChatMessage("user", "What are some text editors I could use to write C#?")
- ];
-
- response = await anthropicClient.CreateChatCompletionsAsync(request, CancellationToken.None);
- response.Usage!.CacheReadInputTokens.Should().Be(0);
- }
-
- private sealed class Person
- {
- [JsonPropertyName("name")]
- public string Name { get; set; } = string.Empty;
-
- [JsonPropertyName("age")]
- public int Age { get; set; }
-
- [JsonPropertyName("email")]
- public string Email { get; set; } = string.Empty;
- }
- }
|