2024-06-27 23:26:53 -05:00
|
|
|
namespace AnthropicClient.Tests.Unit.Models;
|
|
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
public class MessageRequestTests : SerializationTest
|
2024-06-27 23:26:53 -05:00
|
|
|
{
|
|
|
|
|
private readonly string _testJson = @"{
|
|
|
|
|
""model"": ""claude-3-sonnet-20240229"",
|
2024-08-16 09:21:43 -05:00
|
|
|
""system"": [{
|
|
|
|
|
""type"": ""text"",
|
|
|
|
|
""text"": ""test-system""
|
|
|
|
|
}],
|
2024-06-27 23:26:53 -05:00
|
|
|
""messages"": [
|
|
|
|
|
{ ""role"": ""user"", ""content"": [{ ""text"": ""Hello!"", ""type"": ""text"" }] }
|
|
|
|
|
],
|
|
|
|
|
""max_tokens"": 512,
|
|
|
|
|
""metadata"": { ""test"":""test"" },
|
|
|
|
|
""stop_sequences"": [],
|
|
|
|
|
""temperature"": 0.5,
|
|
|
|
|
""topK"": 10,
|
|
|
|
|
""topP"": 0.5,
|
|
|
|
|
""tool_choice"": { ""type"":""auto"" },
|
2024-06-30 12:04:02 -05:00
|
|
|
""tools"": [],
|
2024-06-27 23:26:53 -05:00
|
|
|
""stream"": false
|
|
|
|
|
}";
|
|
|
|
|
|
|
|
|
|
private readonly string _testJsonWithAnyToolChoice = @"{
|
|
|
|
|
""model"": ""claude-3-sonnet-20240229"",
|
2024-08-16 09:21:43 -05:00
|
|
|
""system"": [{
|
|
|
|
|
""type"": ""text"",
|
|
|
|
|
""text"": ""test-system""
|
|
|
|
|
}],
|
2024-06-27 23:26:53 -05:00
|
|
|
""messages"":[
|
|
|
|
|
{ ""role"": ""user"", ""content"": [{ ""text"": ""Hello!"", ""type"":""text"" }] }
|
|
|
|
|
],
|
|
|
|
|
""max_tokens"": 512,
|
|
|
|
|
""metadata"": {""test"":""test""},
|
|
|
|
|
""stop_sequences"": [],
|
|
|
|
|
""temperature"": 0.5,
|
|
|
|
|
""topK"": 10,
|
|
|
|
|
""topP"": 0.5,
|
|
|
|
|
""tool_choice"": {""type"":""any""},
|
2024-06-30 12:04:02 -05:00
|
|
|
""tools"": [],
|
2024-06-27 23:26:53 -05:00
|
|
|
""stream"":false
|
|
|
|
|
}";
|
2024-07-01 22:46:02 -05:00
|
|
|
|
2024-06-27 23:26:53 -05:00
|
|
|
private readonly string _testJsonWithSpecificToolChoice = @"{
|
|
|
|
|
""model"": ""claude-3-sonnet-20240229"",
|
2024-08-16 09:21:43 -05:00
|
|
|
""system"": [{
|
|
|
|
|
""type"": ""text"",
|
|
|
|
|
""text"": ""test-system""
|
|
|
|
|
}],
|
2024-06-27 23:26:53 -05:00
|
|
|
""messages"": [
|
|
|
|
|
{ ""role"": ""user"", ""content"": [{ ""text"": ""Hello!"", ""type"": ""text"" }] }
|
|
|
|
|
],
|
|
|
|
|
""max_tokens"": 512,
|
|
|
|
|
""metadata"": { ""test"": ""test"" },
|
|
|
|
|
""stop_sequences"": [],
|
|
|
|
|
""temperature"": 0.5,
|
|
|
|
|
""topK"": 10,
|
|
|
|
|
""topP"": 0.5,
|
|
|
|
|
""tool_choice"": { ""type"": ""tool"", ""name"": ""test-tool"" },
|
2024-06-30 12:04:02 -05:00
|
|
|
""tools"": [],
|
2024-06-27 23:26:53 -05:00
|
|
|
""stream"": false
|
|
|
|
|
}";
|
2024-07-01 22:46:02 -05:00
|
|
|
|
2024-06-27 23:26:53 -05:00
|
|
|
private readonly string _testJsonWithImageContent = @"{
|
|
|
|
|
""model"": ""claude-3-sonnet-20240229"",
|
2024-08-16 09:21:43 -05:00
|
|
|
""system"": [{
|
|
|
|
|
""type"": ""text"",
|
|
|
|
|
""text"": ""test-system""
|
|
|
|
|
}],
|
2024-06-27 23:26:53 -05:00
|
|
|
""messages"":[
|
|
|
|
|
{
|
|
|
|
|
""role"": ""user"",
|
|
|
|
|
""content"": [
|
|
|
|
|
{
|
|
|
|
|
""type"": ""image"",
|
|
|
|
|
""source"": { ""media_type"": ""image/jpeg"", ""data"": ""data"" }
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
""max_tokens"": 512,
|
|
|
|
|
""metadata"": { ""test"": ""test"" },
|
|
|
|
|
""stop_sequences"": [],
|
|
|
|
|
""temperature"": 0.5,
|
|
|
|
|
""topK"": 10,
|
|
|
|
|
""topP"": 0.5,
|
|
|
|
|
""tool_choice"": { ""type"": ""auto"" },
|
2024-06-30 12:04:02 -05:00
|
|
|
""tools"":[],
|
2024-06-27 23:26:53 -05:00
|
|
|
""stream"": false
|
|
|
|
|
}";
|
2024-07-01 22:46:02 -05:00
|
|
|
|
2024-06-27 23:26:53 -05:00
|
|
|
private readonly string _testJsonWithUnknownContent = @"{
|
|
|
|
|
""model"": ""claude-3-sonnet-20240229"",
|
2024-08-16 09:21:43 -05:00
|
|
|
""system"": [{
|
|
|
|
|
""type"": ""text"",
|
|
|
|
|
""text"": ""test-system""
|
|
|
|
|
}],
|
2024-06-27 23:26:53 -05:00
|
|
|
""messages"": [{ ""role"": ""user"", ""content"": [{ ""type"": ""unknown"", ""text"": ""text"" }] }],
|
|
|
|
|
""max_tokens"": 512,
|
|
|
|
|
""metadata"": { ""test"": ""test"" },
|
|
|
|
|
""stop_sequences"": [],
|
|
|
|
|
""temperature"": 0.5,
|
|
|
|
|
""topK"": 10,
|
|
|
|
|
""topP"": 0.5,
|
|
|
|
|
""tool_choice"": { ""type"":""auto"" },
|
2024-06-30 12:04:02 -05:00
|
|
|
""tools"": [],
|
2024-06-27 23:26:53 -05:00
|
|
|
""stream"": false
|
|
|
|
|
}";
|
2024-07-01 22:46:02 -05:00
|
|
|
|
2024-06-27 23:26:53 -05:00
|
|
|
private readonly string _testJsonWithToolUseContent = @"{
|
|
|
|
|
""model"": ""claude-3-sonnet-20240229"",
|
2024-08-16 09:21:43 -05:00
|
|
|
""system"": [{
|
|
|
|
|
""type"": ""text"",
|
|
|
|
|
""text"": ""test-system""
|
|
|
|
|
}],
|
2024-06-27 23:26:53 -05:00
|
|
|
""messages"": [
|
|
|
|
|
{
|
|
|
|
|
""role"": ""assistant"",
|
|
|
|
|
""content"": [
|
|
|
|
|
{
|
|
|
|
|
""type"": ""tool_use"",
|
|
|
|
|
""name"": ""test-tool"",
|
|
|
|
|
""id"": ""test-tool-id"",
|
|
|
|
|
""input"": {
|
|
|
|
|
""test-property"": ""test-value""
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
""max_tokens"": 512,
|
|
|
|
|
""metadata"": { ""test"": ""test"" },
|
|
|
|
|
""stop_sequences"": [],
|
|
|
|
|
""temperature"": 0.5,
|
|
|
|
|
""topK"": 10,
|
|
|
|
|
""topP"": 0.5,
|
|
|
|
|
""tool_choice"": { ""type"": ""auto"" },
|
2024-06-30 12:04:02 -05:00
|
|
|
""tools"": [],
|
2024-06-27 23:26:53 -05:00
|
|
|
""stream"": false
|
|
|
|
|
}";
|
2024-07-01 22:46:02 -05:00
|
|
|
|
2024-06-27 23:26:53 -05:00
|
|
|
private readonly string _testJsonWithToolResultContent = @"{
|
|
|
|
|
""model"": ""claude-3-sonnet-20240229"",
|
2024-08-16 09:21:43 -05:00
|
|
|
""system"": [{
|
|
|
|
|
""type"": ""text"",
|
|
|
|
|
""text"": ""test-system""
|
|
|
|
|
}],
|
2024-06-27 23:26:53 -05:00
|
|
|
""messages"": [
|
|
|
|
|
{
|
|
|
|
|
""role"": ""assistant"",
|
|
|
|
|
""content"": [
|
|
|
|
|
{
|
|
|
|
|
""type"": ""tool_result"",
|
|
|
|
|
""tool_use_id"": ""test-tool"",
|
|
|
|
|
""content"": ""test-value""
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
""max_tokens"": 512,
|
|
|
|
|
""metadata"": { ""test"": ""test"" },
|
|
|
|
|
""stop_sequences"": [],
|
|
|
|
|
""temperature"": 0.5,
|
|
|
|
|
""topK"": 10,
|
|
|
|
|
""topP"": 0.5,
|
|
|
|
|
""tool_choice"": { ""type"": ""auto"" },
|
2024-06-30 12:04:02 -05:00
|
|
|
""tools"": [],
|
2024-06-27 23:26:53 -05:00
|
|
|
""stream"":false
|
|
|
|
|
}";
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Constructor_WhenCalled_ItShouldInitializeProperties()
|
|
|
|
|
{
|
|
|
|
|
var model = AnthropicModels.Claude3Sonnet;
|
2024-07-03 16:57:27 -05:00
|
|
|
var messages = new List<Message> { new() };
|
2024-06-27 23:26:53 -05:00
|
|
|
var maxTokens = 512;
|
|
|
|
|
var system = "test-system";
|
|
|
|
|
var metadata = new Dictionary<string, object> { ["test"] = "test" };
|
|
|
|
|
var temperature = 0.5m;
|
|
|
|
|
var topK = 10;
|
|
|
|
|
var topP = 0.5m;
|
|
|
|
|
var toolChoice = new AutoToolChoice();
|
2024-06-30 12:04:02 -05:00
|
|
|
var tools = new List<Tool>();
|
2024-06-27 23:26:53 -05:00
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
var messageRequest = new MessageRequest(
|
2024-06-27 23:26:53 -05:00
|
|
|
model: model,
|
|
|
|
|
messages: messages,
|
|
|
|
|
maxTokens: maxTokens,
|
|
|
|
|
system: system,
|
|
|
|
|
metadata: metadata,
|
|
|
|
|
temperature: temperature,
|
|
|
|
|
topK: topK,
|
|
|
|
|
topP: topP,
|
|
|
|
|
toolChoice: toolChoice,
|
|
|
|
|
tools: tools
|
|
|
|
|
);
|
|
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
messageRequest.Model.Should().Be(model);
|
|
|
|
|
messageRequest.Messages.Should().BeSameAs(messages);
|
|
|
|
|
messageRequest.MaxTokens.Should().Be(maxTokens);
|
|
|
|
|
messageRequest.System.Should().Be(system);
|
|
|
|
|
messageRequest.Metadata.Should().BeSameAs(metadata);
|
|
|
|
|
messageRequest.Temperature.Should().Be(temperature);
|
|
|
|
|
messageRequest.TopK.Should().Be(topK);
|
|
|
|
|
messageRequest.TopP.Should().Be(topP);
|
|
|
|
|
messageRequest.ToolChoice.Should().Be(toolChoice);
|
|
|
|
|
messageRequest.Tools.Should().BeSameAs(tools);
|
|
|
|
|
messageRequest.Stream.Should().BeFalse();
|
2024-06-27 23:26:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Constructor_WhenCalledAndModelIsNull_ItShouldThrowArgumentNullException()
|
|
|
|
|
{
|
2024-07-03 16:57:27 -05:00
|
|
|
var action = () => new MessageRequest(
|
2024-06-27 23:26:53 -05:00
|
|
|
model: null!,
|
|
|
|
|
messages: [new()]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
action.Should().Throw<ArgumentNullException>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Constructor_WhenCalledAndMessagesIsNull_ItShouldThrowArgumentNullException()
|
|
|
|
|
{
|
2024-07-03 16:57:27 -05:00
|
|
|
var action = () => new MessageRequest(
|
2024-06-27 23:26:53 -05:00
|
|
|
model: AnthropicModels.Claude3Sonnet,
|
|
|
|
|
messages: null!
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
action.Should().Throw<ArgumentNullException>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Constructor_WhenCalledAndModelIsInvalid_ItShouldThrowArgumentException()
|
|
|
|
|
{
|
2024-07-03 16:57:27 -05:00
|
|
|
var action = () => new MessageRequest(
|
2024-06-27 23:26:53 -05:00
|
|
|
model: "invalid-model",
|
|
|
|
|
messages: [new()]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
action.Should().Throw<ArgumentException>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Constructor_WhenCalledAndMessagesIsEmpty_ItShouldThrowArgumentException()
|
|
|
|
|
{
|
2024-07-03 16:57:27 -05:00
|
|
|
var action = () => new MessageRequest(
|
2024-06-27 23:26:53 -05:00
|
|
|
model: AnthropicModels.Claude3Sonnet,
|
|
|
|
|
messages: []
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
action.Should().Throw<ArgumentException>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Constructor_WhenCalledAndMaxTokensIsInvalid_ItShouldThrowArgumentException()
|
|
|
|
|
{
|
2024-07-03 16:57:27 -05:00
|
|
|
var action = () => new MessageRequest(
|
2024-06-27 23:26:53 -05:00
|
|
|
model: AnthropicModels.Claude3Sonnet,
|
|
|
|
|
messages: [new()],
|
|
|
|
|
maxTokens: 0
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
action.Should().Throw<ArgumentException>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Theory]
|
|
|
|
|
[InlineData(-1)]
|
|
|
|
|
[InlineData(2)]
|
|
|
|
|
public void Constructor_WhenCalledAndTemperatureIsInvalid_ItShouldThrowArgumentException(decimal temperature)
|
|
|
|
|
{
|
2024-07-03 16:57:27 -05:00
|
|
|
var action = () => new MessageRequest(
|
2024-06-27 23:26:53 -05:00
|
|
|
model: AnthropicModels.Claude3Sonnet,
|
|
|
|
|
messages: [new()],
|
|
|
|
|
temperature: temperature
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
action.Should().Throw<ArgumentException>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void JsonSerialization_WhenSerialized_ItShouldHaveExpectedShape()
|
|
|
|
|
{
|
2024-07-03 16:57:27 -05:00
|
|
|
var messages = new List<Message>()
|
2024-06-27 23:26:53 -05:00
|
|
|
{
|
|
|
|
|
new()
|
|
|
|
|
{
|
|
|
|
|
Role = MessageRole.User,
|
|
|
|
|
Content = [new TextContent("Hello!")]
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var model = AnthropicModels.Claude3Sonnet;
|
|
|
|
|
var maxTokens = 512;
|
|
|
|
|
var system = "test-system";
|
|
|
|
|
var metadata = new Dictionary<string, object>
|
|
|
|
|
{
|
|
|
|
|
["test"] = "test"
|
|
|
|
|
};
|
|
|
|
|
var temperature = 0.5m;
|
|
|
|
|
var topK = 10;
|
|
|
|
|
var topP = 0.5m;
|
|
|
|
|
var toolChoice = new AutoToolChoice();
|
2024-06-30 12:04:02 -05:00
|
|
|
var tools = new List<Tool>();
|
2024-06-27 23:26:53 -05:00
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
var messageRequest = new MessageRequest(
|
2024-06-27 23:26:53 -05:00
|
|
|
model: model,
|
|
|
|
|
messages: messages,
|
|
|
|
|
maxTokens: maxTokens,
|
|
|
|
|
system: system,
|
|
|
|
|
metadata: metadata,
|
|
|
|
|
temperature: temperature,
|
|
|
|
|
topK: topK,
|
|
|
|
|
topP: topP,
|
|
|
|
|
toolChoice: toolChoice,
|
|
|
|
|
tools: tools
|
|
|
|
|
);
|
|
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
var actual = Serialize(messageRequest);
|
2024-06-27 23:26:53 -05:00
|
|
|
|
|
|
|
|
JsonAssert.Equal(_testJson, actual);
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-18 11:37:19 -05:00
|
|
|
[Fact]
|
|
|
|
|
public void JsonSerialization_WhenSerializedAndSystemMessagesAndSystemAreNull_ItShouldNotHaveSystemProperty()
|
|
|
|
|
{
|
|
|
|
|
var messageRequest = new MessageRequest(
|
|
|
|
|
model: AnthropicModels.Claude3Haiku,
|
|
|
|
|
messages: [
|
|
|
|
|
new()
|
|
|
|
|
{
|
|
|
|
|
Role = MessageRole.User,
|
|
|
|
|
Content = [new TextContent("Hello!")]
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
var expected = @"{
|
|
|
|
|
""model"": ""claude-3-haiku-20240307"",
|
|
|
|
|
""messages"": [
|
|
|
|
|
{
|
|
|
|
|
""role"": ""user"",
|
|
|
|
|
""content"": [
|
|
|
|
|
{
|
|
|
|
|
""text"": ""Hello!"",
|
|
|
|
|
""type"": ""text""
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
""max_tokens"": 1024,
|
|
|
|
|
""stop_sequences"": [],
|
|
|
|
|
""temperature"": 0.0,
|
|
|
|
|
""stream"": false
|
|
|
|
|
}";
|
|
|
|
|
|
|
|
|
|
var actual = Serialize(messageRequest);
|
|
|
|
|
|
|
|
|
|
JsonAssert.Equal(expected, actual);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void JsonSerialization_WhenSerializedAndSystemMessagesAreProvided_ItShouldUseSystemMessagesForHaveSystemProperty()
|
|
|
|
|
{
|
|
|
|
|
var messageRequest = new MessageRequest(
|
|
|
|
|
model: AnthropicModels.Claude3Haiku,
|
|
|
|
|
messages: [
|
|
|
|
|
new()
|
|
|
|
|
{
|
|
|
|
|
Role = MessageRole.User,
|
|
|
|
|
Content = [new TextContent("Hello!")]
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
systemMessages: [
|
|
|
|
|
new TextContent("You are a helpful assistant.")
|
|
|
|
|
],
|
|
|
|
|
system: "test-system"
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
var expected = @"{
|
|
|
|
|
""model"": ""claude-3-haiku-20240307"",
|
|
|
|
|
""system"": [
|
|
|
|
|
{
|
|
|
|
|
""text"": ""You are a helpful assistant."",
|
|
|
|
|
""type"": ""text""
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
""messages"": [
|
|
|
|
|
{
|
|
|
|
|
""role"": ""user"",
|
|
|
|
|
""content"": [
|
|
|
|
|
{
|
|
|
|
|
""text"": ""Hello!"",
|
|
|
|
|
""type"": ""text""
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
""max_tokens"": 1024,
|
|
|
|
|
""stop_sequences"": [],
|
|
|
|
|
""temperature"": 0.0,
|
|
|
|
|
""stream"": false
|
|
|
|
|
}";
|
|
|
|
|
|
|
|
|
|
var actual = Serialize(messageRequest);
|
|
|
|
|
|
|
|
|
|
JsonAssert.Equal(expected, actual);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void JsonSerialization_WhenSerializedAndSystemMessageIsProvided_ItShouldUseSystemMessageForHaveSystemProperty()
|
|
|
|
|
{
|
|
|
|
|
var messageRequest = new MessageRequest(
|
|
|
|
|
model: AnthropicModels.Claude3Haiku,
|
|
|
|
|
messages: [
|
|
|
|
|
new()
|
|
|
|
|
{
|
|
|
|
|
Role = MessageRole.User,
|
|
|
|
|
Content = [new TextContent("Hello!")]
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
system: "test-system"
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
var expected = @"{
|
|
|
|
|
""model"": ""claude-3-haiku-20240307"",
|
|
|
|
|
""system"": [
|
|
|
|
|
{
|
|
|
|
|
""text"": ""test-system"",
|
|
|
|
|
""type"": ""text""
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
""messages"": [
|
|
|
|
|
{
|
|
|
|
|
""role"": ""user"",
|
|
|
|
|
""content"": [
|
|
|
|
|
{
|
|
|
|
|
""text"": ""Hello!"",
|
|
|
|
|
""type"": ""text""
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
""max_tokens"": 1024,
|
|
|
|
|
""stop_sequences"": [],
|
|
|
|
|
""temperature"": 0.0,
|
|
|
|
|
""stream"": false
|
|
|
|
|
}";
|
|
|
|
|
|
|
|
|
|
var actual = Serialize(messageRequest);
|
|
|
|
|
|
|
|
|
|
JsonAssert.Equal(expected, actual);
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-27 23:26:53 -05:00
|
|
|
[Fact]
|
|
|
|
|
public void JsonDeserialization_WhenDeserialized_ItShouldHaveExpectedShape()
|
|
|
|
|
{
|
2024-07-03 16:57:27 -05:00
|
|
|
var messageRequest = Deserialize<MessageRequest>(_testJson);
|
2024-06-27 23:26:53 -05:00
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
messageRequest!.Model.Should().Be(AnthropicModels.Claude3Sonnet);
|
2024-08-16 09:21:43 -05:00
|
|
|
messageRequest.System.Should().BeNull();
|
2024-07-03 16:57:27 -05:00
|
|
|
messageRequest.Messages.Should().HaveCount(1);
|
|
|
|
|
messageRequest.MaxTokens.Should().Be(512);
|
|
|
|
|
messageRequest.Metadata.Should().HaveCount(1);
|
2024-06-27 23:26:53 -05:00
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
var testValue = messageRequest.Metadata!.GetValueOrDefault("test")!.ToString();
|
2024-06-27 23:26:53 -05:00
|
|
|
testValue.Should().Be("test");
|
|
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
messageRequest.Temperature.Should().Be(0.5m);
|
|
|
|
|
messageRequest.TopK.Should().Be(10);
|
|
|
|
|
messageRequest.TopP.Should().Be(0.5m);
|
|
|
|
|
messageRequest.ToolChoice.Should().BeOfType<AutoToolChoice>();
|
|
|
|
|
messageRequest.ToolChoice!.Type.Should().Be("auto");
|
|
|
|
|
messageRequest.Tools.Should().HaveCount(0);
|
|
|
|
|
messageRequest.Stream.Should().BeFalse();
|
2024-06-27 23:26:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void JsonDeserialization_WhenDeserializedWithAnyToolChoice_ItShouldHaveExpectedShape()
|
|
|
|
|
{
|
2024-07-03 16:57:27 -05:00
|
|
|
var messageRequest = Deserialize<MessageRequest>(_testJsonWithAnyToolChoice);
|
2024-06-27 23:26:53 -05:00
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
messageRequest!.Model.Should().Be(AnthropicModels.Claude3Sonnet);
|
2024-08-16 09:21:43 -05:00
|
|
|
messageRequest.System.Should().BeNull();
|
2024-07-03 16:57:27 -05:00
|
|
|
messageRequest.Messages.Should().HaveCount(1);
|
|
|
|
|
messageRequest.MaxTokens.Should().Be(512);
|
|
|
|
|
messageRequest.Metadata.Should().HaveCount(1);
|
2024-06-27 23:26:53 -05:00
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
var testValue = messageRequest.Metadata!.GetValueOrDefault("test")!.ToString();
|
2024-06-27 23:26:53 -05:00
|
|
|
testValue.Should().Be("test");
|
|
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
messageRequest.Temperature.Should().Be(0.5m);
|
|
|
|
|
messageRequest.TopK.Should().Be(10);
|
|
|
|
|
messageRequest.TopP.Should().Be(0.5m);
|
|
|
|
|
messageRequest.ToolChoice.Should().BeOfType<AnyToolChoice>();
|
|
|
|
|
messageRequest.ToolChoice!.Type.Should().Be("any");
|
|
|
|
|
messageRequest.Tools.Should().HaveCount(0);
|
2024-06-27 23:26:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void JsonDeserialization_WhenDeserializedWithSpecificToolChoice_ItShouldHaveExpectedShape()
|
|
|
|
|
{
|
2024-07-03 16:57:27 -05:00
|
|
|
var messageRequest = Deserialize<MessageRequest>(_testJsonWithSpecificToolChoice);
|
2024-06-27 23:26:53 -05:00
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
messageRequest!.Model.Should().Be(AnthropicModels.Claude3Sonnet);
|
2024-08-16 09:21:43 -05:00
|
|
|
messageRequest.System.Should().BeNull();
|
2024-07-03 16:57:27 -05:00
|
|
|
messageRequest.Messages.Should().HaveCount(1);
|
|
|
|
|
messageRequest.MaxTokens.Should().Be(512);
|
|
|
|
|
messageRequest.Metadata.Should().HaveCount(1);
|
2024-06-27 23:26:53 -05:00
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
var testValue = messageRequest.Metadata!.GetValueOrDefault("test")!.ToString();
|
2024-06-27 23:26:53 -05:00
|
|
|
testValue.Should().Be("test");
|
|
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
messageRequest.Temperature.Should().Be(0.5m);
|
|
|
|
|
messageRequest.TopK.Should().Be(10);
|
|
|
|
|
messageRequest.TopP.Should().Be(0.5m);
|
|
|
|
|
messageRequest.ToolChoice.Should().BeOfType<SpecificToolChoice>();
|
2024-06-27 23:26:53 -05:00
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
var specificToolChoice = messageRequest.ToolChoice as SpecificToolChoice;
|
2024-06-27 23:26:53 -05:00
|
|
|
specificToolChoice!.Type.Should().Be("tool");
|
|
|
|
|
specificToolChoice.Name.Should().Be("test-tool");
|
2024-07-03 16:57:27 -05:00
|
|
|
messageRequest.Tools.Should().HaveCount(0);
|
2024-07-01 22:46:02 -05:00
|
|
|
}
|
2024-06-27 23:26:53 -05:00
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void JsonDeserialization_WhenDeserializedWithUnknownToolChoice_ItShouldThrowJsonException()
|
|
|
|
|
{
|
|
|
|
|
var json = @"{""model"":""claude-3-sonnet-20240229"",""system"":""test-system"",""messages"":[{""role"":""user"",""content"":[{""text"":""Hello!"",""type"":""text""}]}],""max_tokens"":512,""metadata"":{""test"":""test""},""stop_sequences"":[],""temperature"":0.5,""topK"":10,""topP"":0.5,""tool_choice"":{""type"":""unknown""},""tools"":[{""name"":""test-tool"",""description"":""test-description"",""input_schema"":{""type"":""object"",""properties"":{""test-property"":{""type"":""string"",""description"":""test-description""}},""required"":[""test-property""]}}],""stream"":false}";
|
|
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
var action = () => Deserialize<MessageRequest>(json);
|
2024-06-27 23:26:53 -05:00
|
|
|
|
|
|
|
|
action.Should().Throw<JsonException>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void JsonDeserialization_WhenDeserializedWithImageContent_ItShouldHaveExpectedShape()
|
|
|
|
|
{
|
2024-07-03 16:57:27 -05:00
|
|
|
var messageRequest = Deserialize<MessageRequest>(_testJsonWithImageContent);
|
2024-06-27 23:26:53 -05:00
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
messageRequest!.Model.Should().Be(AnthropicModels.Claude3Sonnet);
|
2024-08-16 09:21:43 -05:00
|
|
|
messageRequest.System.Should().BeNull();
|
2024-07-03 16:57:27 -05:00
|
|
|
messageRequest.Messages.Should().HaveCount(1);
|
|
|
|
|
messageRequest.MaxTokens.Should().Be(512);
|
|
|
|
|
messageRequest.Metadata.Should().HaveCount(1);
|
2024-06-27 23:26:53 -05:00
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
var testValue = messageRequest.Metadata!.GetValueOrDefault("test")!.ToString();
|
2024-06-27 23:26:53 -05:00
|
|
|
testValue.Should().Be("test");
|
|
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
messageRequest.Temperature.Should().Be(0.5m);
|
|
|
|
|
messageRequest.TopK.Should().Be(10);
|
|
|
|
|
messageRequest.TopP.Should().Be(0.5m);
|
|
|
|
|
messageRequest.ToolChoice.Should().BeOfType<AutoToolChoice>();
|
|
|
|
|
messageRequest.ToolChoice!.Type.Should().Be("auto");
|
|
|
|
|
messageRequest.Tools.Should().HaveCount(0);
|
|
|
|
|
messageRequest.Messages[0].Content.Should().HaveCount(1);
|
|
|
|
|
messageRequest.Messages[0].Content[0].Should().BeOfType<ImageContent>();
|
2024-06-27 23:26:53 -05:00
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
var imageContent = messageRequest.Messages[0].Content[0] as ImageContent;
|
2024-06-27 23:26:53 -05:00
|
|
|
imageContent!.Type.Should().Be("image");
|
|
|
|
|
imageContent.Source.MediaType.Should().Be("image/jpeg");
|
|
|
|
|
imageContent.Source.Data.Should().Be("data");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void JsonDeserialization_WhenDeserializedWithToolUseContent_ItShouldHaveExpectedShape()
|
|
|
|
|
{
|
2024-07-03 16:57:27 -05:00
|
|
|
var messageRequest = Deserialize<MessageRequest>(_testJsonWithToolUseContent);
|
2024-06-27 23:26:53 -05:00
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
messageRequest!.Model.Should().Be(AnthropicModels.Claude3Sonnet);
|
2024-08-16 09:21:43 -05:00
|
|
|
messageRequest.System.Should().BeNull();
|
2024-07-03 16:57:27 -05:00
|
|
|
messageRequest.Messages.Should().HaveCount(1);
|
|
|
|
|
messageRequest.MaxTokens.Should().Be(512);
|
|
|
|
|
messageRequest.Metadata.Should().HaveCount(1);
|
2024-06-27 23:26:53 -05:00
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
var testValue = messageRequest.Metadata!.GetValueOrDefault("test")!.ToString();
|
2024-06-27 23:26:53 -05:00
|
|
|
testValue.Should().Be("test");
|
|
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
messageRequest.Temperature.Should().Be(0.5m);
|
|
|
|
|
messageRequest.TopK.Should().Be(10);
|
|
|
|
|
messageRequest.TopP.Should().Be(0.5m);
|
|
|
|
|
messageRequest.ToolChoice.Should().BeOfType<AutoToolChoice>();
|
|
|
|
|
messageRequest.ToolChoice!.Type.Should().Be("auto");
|
|
|
|
|
messageRequest.Tools.Should().HaveCount(0);
|
|
|
|
|
messageRequest.Messages[0].Content.Should().HaveCount(1);
|
|
|
|
|
messageRequest.Messages[0].Content[0].Should().BeOfType<ToolUseContent>();
|
2024-06-27 23:26:53 -05:00
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
var toolUseContent = messageRequest.Messages[0].Content[0] as ToolUseContent;
|
2024-06-27 23:26:53 -05:00
|
|
|
toolUseContent!.Type.Should().Be("tool_use");
|
|
|
|
|
toolUseContent.Name.Should().Be("test-tool");
|
|
|
|
|
toolUseContent.Id.Should().Be("test-tool-id");
|
|
|
|
|
toolUseContent.Input.Should().HaveCount(1);
|
|
|
|
|
toolUseContent.Input["test-property"]!.ToString().Should().Be("test-value");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void JsonDeserialization_WhenDeserializedWithToolResultContent_ItShouldHaveExpectedShape()
|
|
|
|
|
{
|
2024-07-03 16:57:27 -05:00
|
|
|
var messageRequest = Deserialize<MessageRequest>(_testJsonWithToolResultContent);
|
2024-06-27 23:26:53 -05:00
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
messageRequest!.Model.Should().Be(AnthropicModels.Claude3Sonnet);
|
2024-08-16 09:21:43 -05:00
|
|
|
messageRequest.System.Should().BeNull();
|
2024-07-03 16:57:27 -05:00
|
|
|
messageRequest.Messages.Should().HaveCount(1);
|
|
|
|
|
messageRequest.MaxTokens.Should().Be(512);
|
|
|
|
|
messageRequest.Metadata.Should().HaveCount(1);
|
2024-06-27 23:26:53 -05:00
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
var testValue = messageRequest.Metadata!.GetValueOrDefault("test")!.ToString();
|
2024-06-27 23:26:53 -05:00
|
|
|
testValue.Should().Be("test");
|
|
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
messageRequest.Temperature.Should().Be(0.5m);
|
|
|
|
|
messageRequest.TopK.Should().Be(10);
|
|
|
|
|
messageRequest.TopP.Should().Be(0.5m);
|
|
|
|
|
messageRequest.ToolChoice.Should().BeOfType<AutoToolChoice>();
|
|
|
|
|
messageRequest.ToolChoice!.Type.Should().Be("auto");
|
|
|
|
|
messageRequest.Tools.Should().HaveCount(0);
|
|
|
|
|
messageRequest.Messages[0].Content.Should().HaveCount(1);
|
|
|
|
|
messageRequest.Messages[0].Content[0].Should().BeOfType<ToolResultContent>();
|
2024-06-27 23:26:53 -05:00
|
|
|
|
2024-07-03 16:57:27 -05:00
|
|
|
var toolResultContent = messageRequest.Messages[0].Content[0] as ToolResultContent;
|
2024-06-27 23:26:53 -05:00
|
|
|
toolResultContent!.Type.Should().Be("tool_result");
|
|
|
|
|
toolResultContent.ToolUseId.Should().Be("test-tool");
|
|
|
|
|
toolResultContent.Content.Should().Be("test-value");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void JsonDeserialization_WhenDeserializedWithUnknownContent_ItShouldThrowJsonException()
|
|
|
|
|
{
|
2024-07-03 16:57:27 -05:00
|
|
|
var action = () => Deserialize<MessageRequest>(_testJsonWithUnknownContent);
|
2024-06-27 23:26:53 -05:00
|
|
|
|
|
|
|
|
action.Should().Throw<JsonException>();
|
|
|
|
|
}
|
|
|
|
|
}
|