-
Notifications
You must be signed in to change notification settings - Fork 2
/
MistralClient.cs
147 lines (119 loc) · 5.63 KB
/
MistralClient.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
using Microsoft.Extensions.Options;
using MistralSharp.Abstractions;
using MistralSharp.Domain;
using MistralSharp.Dto;
using MistralSharp.Helpers;
using MistralSharp.Models;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace MistralSharp
{
/// <inheritdoc />
public class MistralClient : IMistralClient
{
private readonly HttpClient _httpClient = new HttpClient();
private const string BaseUrl = "https://api.mistral.ai/v1";
public MistralClient(MistralClientOptions options)
{
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", options.ApiKey);
}
public MistralClient(IOptions<MistralClientOptions> options) : this(options.Value) { }
/// <inheritdoc />
public async Task<ChatResponse> ChatAsync(ChatRequest chatRequest)
{
if (chatRequest.Stream)
{
throw new InvalidOperationException("Error: stream parameter set to true. For streaming calls," +
"use the StreamChatAsync() method instead.");
}
var jsonResponse = await PostToApiAsync(chatRequest, "/chat/completions");
var chatResponseDto = JsonSerializer.Deserialize<ChatResponseDto>(jsonResponse);
var chatResponse = DtoMapper.MapChatResponse(chatResponseDto);
return chatResponse;
}
/// <inheritdoc />
public IAsyncEnumerable<ChatResponse> ChatStreamAsync(ChatRequest chatRequest)
{
if (chatRequest.Stream == false)
{
throw new InvalidOperationException("Error: ChatRequest.Stream is set to false. For " +
"non-streaming calls, use the ChatAsync() method instead.");
}
throw new NotImplementedException("Error: This endpoint is not yet implemented but will be in " +
"a future release.");
}
/// <inheritdoc />
public async Task<AvailableModels> GetAvailableModelsAsync()
{
var jsonResponse = await GetResponseAsync("/models");
var availableModelsDto = JsonSerializer.Deserialize<AvailableModelsDto>(jsonResponse);
var availableModels = DtoMapper.MapAvailableModels(availableModelsDto);
return availableModels;
}
/// <inheritdoc />
public async Task<EmbeddingResponse> CreateEmbeddingsAsync(EmbeddingRequest embeddingRequest)
{
var jsonResponse = await PostToApiAsync(embeddingRequest, "/embeddings");
var embeddingResponseDto = JsonSerializer.Deserialize<EmbeddingResponseDto>(jsonResponse);
var embeddingResponse = DtoMapper.MapEmbeddingResponse(embeddingResponseDto);
return embeddingResponse;
}
/// <summary>
/// Retrieves the response from the specified API endpoint asynchronously.
/// </summary>
/// <param name="endpoint">The API endpoint to send the request to.</param>
/// <returns>The response content as a string.</returns>
private async Task<string> GetResponseAsync(string endpoint)
{
var response = await _httpClient.GetAsync(BaseUrl + (endpoint ?? "")).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
var jsonResponse = await response.Content.ReadAsStringAsync();
return jsonResponse;
}
if (response.StatusCode == HttpStatusCode.InternalServerError)
{
throw new HttpRequestException(
"Mistral Platform had an internal server error. Please retry your request.");
}
if (response.StatusCode == HttpStatusCode.Unauthorized)
{
throw new HttpRequestException("Authorization error: Invalid API key.");
}
throw new HttpRequestException($"Unexpected HTTP status code: {response.StatusCode}");
}
/// <summary>
/// Helper method to serialize an object to JSON and return a JSON response string.
/// </summary>
/// <param name="objectToSerialize">The object to be serialized.</param>
/// <param name="endpoint">The endpoint to send the JSON request to.</param>
/// <returns>A string representing the JSON response.</returns>
private async Task<string> PostToApiAsync(object objectToSerialize, string endpoint)
{
var jsonRequest = JsonSerializer.Serialize(objectToSerialize);
var content = new StringContent(jsonRequest, Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync(BaseUrl + endpoint, content).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
var jsonResponse = await response.Content.ReadAsStringAsync();
return jsonResponse;
}
if (response.StatusCode == HttpStatusCode.InternalServerError)
{
throw new HttpRequestException(
"Mistral Platform had an internal server error. Please retry your request.");
}
if (response.StatusCode == HttpStatusCode.Unauthorized)
{
throw new HttpRequestException("Authorization error: Invalid API key.");
}
throw new HttpRequestException($"Unexpected HTTP status code: {response.StatusCode}");
}
}
}