86 [property: JsonPropertyName(
"messages")] IReadOnlyList<ChatMessage> Messages,
104 private readonly HttpClient _httpClient;
105 private readonly JsonSerializerOptions _jsonOptions;
107 public OllamaChatService(HttpClient httpClient,
string baseUrl =
"http://localhost:11434")
109 _httpClient = httpClient ??
throw new ArgumentNullException(nameof(httpClient));
110 _httpClient.Timeout = TimeSpan.FromMinutes(60);
111 if (_httpClient.BaseAddress ==
null)
112 _httpClient.BaseAddress =
new Uri(baseUrl);
115 _jsonOptions =
new JsonSerializerOptions
117 PropertyNamingPolicy =
null,
118 DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
119 WriteIndented =
false
123 public async Task<string> GetResponseAsync(
126 CancellationToken cancellationToken =
default)
128 var request =
new ChatRequest(
132 new ChatMessage(
"system", systemPrompt),
133 new ChatMessage(
"user", userPrompt)
136 var json = JsonSerializer.Serialize(request, _jsonOptions);
137 using var content =
new StringContent(json, Encoding.UTF8,
"application/json");
139 using var timeoutCts =
new CancellationTokenSource(TimeSpan.FromMinutes(30));
140 using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(
141 cancellationToken, timeoutCts.Token);
143 HttpResponseMessage httpResponse;
146 httpResponse = await _httpClient.PostAsync(
147 "/v1/chat/completions",
150 .ConfigureAwait(
false);
152 catch (Exception e) when (!cancellationToken.IsCancellationRequested)
154 throw new Exception();
157 if (!httpResponse.IsSuccessStatusCode)
159 var rawError = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(
false);
160 throw new HttpRequestException(
161 $
"Server returned {(int)httpResponse.StatusCode} – {httpResponse.ReasonPhrase}. Body: {rawError}");
164 var chatResponse = await httpResponse.Content
165 .ReadFromJsonAsync<ChatResponse>(_jsonOptions, linkedCts.Token)
166 .ConfigureAwait(
false);
168 var firstChoice = chatResponse?.Choices?.Count > 0 ? chatResponse.Choices[0] :
null;
169 if (firstChoice?.Message?.Content ==
null)
170 throw new InvalidOperationException(
"The response does not contain a usable message.");
172 return firstChoice.Message.Content;
218 private void SendBut_ButtonPressEvent(
object o, ButtonPressEventArgs args)