|
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // MistralClientTests.cs
-
- using System.Text.Json;
- using System.Text.Json.Serialization;
- using AutoGen.Core;
- using AutoGen.Mistral.Extension;
- using AutoGen.Tests;
- using FluentAssertions;
- using Xunit;
-
- namespace AutoGen.Mistral.Tests;
-
- [Trait("Category", "UnitV1")]
- public partial class MistralClientTests
- {
- [Function]
- public async Task<string> GetWeather(string city)
- {
- return $"The weather in {city} is sunny.";
- }
-
- [ApiKeyFact("MISTRAL_API_KEY")]
- public async Task MistralClientChatCompletionTestAsync()
- {
- var apiKey = Environment.GetEnvironmentVariable("MISTRAL_API_KEY") ?? throw new InvalidOperationException("MISTRAL_API_KEY is not set.");
- var client = new MistralClient(apiKey: apiKey);
-
- var systemMessage = new ChatMessage(ChatMessage.RoleEnum.System, "You are a helpful assistant.");
- var userMessage = new ChatMessage(ChatMessage.RoleEnum.User, "What is the weather like today?");
-
- var request = new ChatCompletionRequest(
- model: "open-mistral-7b",
- messages: new List<ChatMessage> { systemMessage, userMessage },
- temperature: 0);
-
- var response = await client.CreateChatCompletionsAsync(request);
-
- response.Choices!.Count().Should().Be(1);
- response.Choices!.First().Message!.Content.Should().NotBeNullOrEmpty();
- response.Choices!.First().Message!.Role.Should().Be(ChatMessage.RoleEnum.Assistant);
- response.Usage!.TotalTokens.Should().BeGreaterThan(0);
- }
-
- [ApiKeyFact("MISTRAL_API_KEY")]
- public async Task MistralClientStreamingChatCompletionTestAsync()
- {
- var apiKey = Environment.GetEnvironmentVariable("MISTRAL_API_KEY") ?? throw new InvalidOperationException("MISTRAL_API_KEY is not set.");
- var client = new MistralClient(apiKey: apiKey);
-
- var systemMessage = new ChatMessage(ChatMessage.RoleEnum.System, "You are a helpful assistant.");
- var userMessage = new ChatMessage(ChatMessage.RoleEnum.User, "What is the weather like today?");
-
- var request = new ChatCompletionRequest(
- model: "open-mistral-7b",
- messages: new List<ChatMessage> { systemMessage, userMessage },
- temperature: 0);
-
- var response = client.StreamingChatCompletionsAsync(request);
- var results = new List<ChatCompletionResponse>();
-
- await foreach (var item in response)
- {
- results.Add(item);
- item.VarObject.Should().Be("chat.completion.chunk");
- }
-
- results.Count.Should().BeGreaterThan(0);
-
- // merge result
- var finalResult = results.First();
- foreach (var result in results)
- {
- if (finalResult.Choices!.First().Message is null)
- {
- finalResult.Choices!.First().Message = result.Choices!.First().Delta;
- }
- else
- {
- finalResult.Choices!.First().Message!.Content += result.Choices!.First().Delta!.Content;
- }
-
- // the usage information will be included in the last result
- if (result.Usage != null)
- {
- finalResult.Usage = result.Usage;
- }
- }
- finalResult.Choices!.First().Message!.Content.Should().NotBeNullOrEmpty();
- finalResult.Choices!.First().Message!.Role.Should().Be(ChatMessage.RoleEnum.Assistant);
- finalResult.Usage!.TotalTokens.Should().BeGreaterThan(0);
- }
-
- [ApiKeyFact("MISTRAL_API_KEY")]
- public async Task MistralClientStreamingChatJsonModeCompletionTestAsync()
- {
- var apiKey = Environment.GetEnvironmentVariable("MISTRAL_API_KEY") ?? throw new InvalidOperationException("MISTRAL_API_KEY is not set.");
- var client = new MistralClient(apiKey: apiKey);
-
- var systemMessage = new ChatMessage(ChatMessage.RoleEnum.System, "You are a helpful assistant that convert input to json object");
- var userMessage = new ChatMessage(ChatMessage.RoleEnum.User, "name: John, age: 41, email: g123456@gmail.com");
-
- var request = new ChatCompletionRequest(
- model: "open-mistral-7b",
- messages: new List<ChatMessage> { systemMessage, userMessage },
- temperature: 0)
- {
- ResponseFormat = new ResponseFormat { ResponseFormatType = "json_object" },
- };
-
- var response = client.StreamingChatCompletionsAsync(request);
- var results = new List<ChatCompletionResponse>();
-
- await foreach (var item in response)
- {
- results.Add(item);
- item.VarObject.Should().Be("chat.completion.chunk");
- }
-
- results.Count.Should().BeGreaterThan(0);
-
- // merge result
- var finalResult = results.First();
- foreach (var result in results)
- {
- if (finalResult.Choices!.First().Message is null)
- {
- finalResult.Choices!.First().Message = result.Choices!.First().Delta;
- }
- else
- {
- finalResult.Choices!.First().Message!.Content += result.Choices!.First().Delta!.Content;
- }
-
- // the usage information will be included in the last result
- if (result.Usage != null)
- {
- finalResult.Usage = result.Usage;
- }
- }
-
- finalResult.Choices!.First().Message!.Content.Should().NotBeNullOrEmpty();
- finalResult.Choices!.First().Message!.Role.Should().Be(ChatMessage.RoleEnum.Assistant);
- finalResult.Usage!.TotalTokens.Should().BeGreaterThan(0);
- var responseContent = finalResult.Choices!.First().Message!.Content ?? throw new InvalidOperationException("Response content is null.");
- var person = JsonSerializer.Deserialize<Person>(responseContent);
- person.Should().NotBeNull();
-
- person!.Name.Should().Be("John");
- person!.Age.Should().Be(41);
- person!.Email.Should().Be("g123456@gmail.com");
- }
-
- [ApiKeyFact("MISTRAL_API_KEY")]
- public async Task MistralClientJsonModeTestAsync()
- {
- var apiKey = Environment.GetEnvironmentVariable("MISTRAL_API_KEY") ?? throw new InvalidOperationException("MISTRAL_API_KEY is not set.");
- var client = new MistralClient(apiKey: apiKey);
-
- var systemMessage = new ChatMessage(ChatMessage.RoleEnum.System, "You are a helpful assistant that convert input to json object");
- var userMessage = new ChatMessage(ChatMessage.RoleEnum.User, "name: John, age: 41, email: g123456@gmail.com");
-
- var request = new ChatCompletionRequest(
- model: "open-mistral-7b",
- messages: new List<ChatMessage> { systemMessage, userMessage },
- temperature: 0)
- {
- ResponseFormat = new ResponseFormat { ResponseFormatType = "json_object" },
- };
-
- var response = await client.CreateChatCompletionsAsync(request);
-
- response.Choices!.Count().Should().Be(1);
- response.Choices!.First().Message!.Content.Should().NotBeNullOrEmpty();
- response.Choices!.First().Message!.Role.Should().Be(ChatMessage.RoleEnum.Assistant);
- response.Usage!.TotalTokens.Should().BeGreaterThan(0);
-
- // check if the response is a valid json object
- var responseContent = response.Choices!.First().Message!.Content ?? throw new InvalidOperationException("Response content is null.");
- var person = JsonSerializer.Deserialize<Person>(responseContent);
- person.Should().NotBeNull();
-
- person!.Name.Should().Be("John");
- person!.Age.Should().Be(41);
- person!.Email.Should().Be("g123456@gmail.com");
- }
-
- [ApiKeyFact("MISTRAL_API_KEY")]
- public async Task MistralClientFunctionCallTestAsync()
- {
- var apiKey = Environment.GetEnvironmentVariable("MISTRAL_API_KEY") ?? throw new InvalidOperationException("MISTRAL_API_KEY is not set.");
- using var client = new MistralClient(apiKey: apiKey);
-
- var getWeatherFunctionContract = this.GetWeatherFunctionContract;
- var functionDefinition = getWeatherFunctionContract.ToMistralFunctionDefinition();
-
- var systemMessage = new ChatMessage(ChatMessage.RoleEnum.System, "You are a helpful assistant.");
- var userMessage = new ChatMessage(ChatMessage.RoleEnum.User, "What is the weather in Seattle?");
-
- var request = new ChatCompletionRequest(
- model: "mistral-small-latest", // only large or small latest models support function calls
- messages: new List<ChatMessage> { systemMessage, userMessage },
- temperature: 0)
- {
- Tools = [new FunctionTool(functionDefinition)],
- ToolChoice = ToolChoiceEnum.Any,
- };
-
- var response = await client.CreateChatCompletionsAsync(request);
-
- response.Choices!.Count().Should().Be(1);
- response.Choices!.First().Message!.Content.Should().BeNullOrEmpty();
- response.Choices!.First().FinishReason.Should().Be(Choice.FinishReasonEnum.ToolCalls);
- response.Choices!.First().Message!.ToolCalls!.Count.Should().Be(1);
- response.Choices!.First().Message!.ToolCalls!.First().Function.Name.Should().Be("GetWeather");
- }
-
- [ApiKeyFact("MISTRAL_API_KEY")]
- public async Task MistralClientStreamingFunctionCallTestAsync()
- {
- var apiKey = Environment.GetEnvironmentVariable("MISTRAL_API_KEY") ?? throw new InvalidOperationException("MISTRAL_API_KEY is not set.");
- using var client = new MistralClient(apiKey: apiKey);
-
- var getWeatherFunctionContract = this.GetWeatherFunctionContract;
- var functionDefinition = getWeatherFunctionContract.ToMistralFunctionDefinition();
-
- var systemMessage = new ChatMessage(ChatMessage.RoleEnum.System, "You are a helpful assistant.");
- var userMessage = new ChatMessage(ChatMessage.RoleEnum.User, "What is the weather in Seattle?");
-
- var request = new ChatCompletionRequest(
- model: "mistral-small-latest",
- messages: new List<ChatMessage> { systemMessage, userMessage },
- temperature: 0)
- {
- Tools = [new FunctionTool(functionDefinition)],
- ToolChoice = ToolChoiceEnum.Any,
- };
-
- var response = client.StreamingChatCompletionsAsync(request);
-
- var results = new List<ChatCompletionResponse>();
- await foreach (var item in response)
- {
- results.Add(item);
- item.VarObject.Should().Be("chat.completion.chunk");
- }
-
- // merge result
- var finalResult = results.First();
- var lastResult = results.Last();
- lastResult.Choices!.First().FinishReason.Should().Be(Choice.FinishReasonEnum.ToolCalls);
-
- foreach (var result in results)
- {
- if (finalResult.Choices!.First().Message is null)
- {
- finalResult.Choices!.First().Message = result.Choices!.First().Delta;
- finalResult.Choices!.First().Message!.ToolCalls = [];
- }
- else
- {
- finalResult.Choices!.First().Message!.ToolCalls = finalResult.Choices!.First().Message!.ToolCalls!.Concat(result.Choices!.First().Delta!.ToolCalls!).ToList();
- }
-
- // the usage information will be included in the last result
- if (result.Usage != null)
- {
- finalResult.Usage = result.Usage;
- }
- }
-
- finalResult.Choices!.First().Message!.Content.Should().BeNullOrEmpty();
- finalResult.Choices!.First().Message!.ToolCalls!.Count.Should().BeGreaterThan(0);
- finalResult.Usage!.TotalTokens.Should().BeGreaterThan(0);
- finalResult.Choices!.First().Message!.ToolCalls!.First().Function.Name.Should().Be("GetWeather");
- }
- }
- public 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;
- }
|