2025-10-22 11:45:15 +02:00
|
|
|
|
using BeWo.ServerUtils.ApiFacade;
|
|
|
|
|
|
using BS.Shared.DataContracts;
|
2025-07-03 13:55:46 +02:00
|
|
|
|
using BS.Shared.DataContracts.Feature.AI;
|
|
|
|
|
|
using BS.Shared.Extensions;
|
|
|
|
|
|
using BS.Shared.Interface;
|
|
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.IO;
|
|
|
|
|
|
using System.Linq;
|
2025-08-05 11:55:48 +02:00
|
|
|
|
using System.Text.Json;
|
2025-07-03 13:55:46 +02:00
|
|
|
|
|
2025-08-05 11:55:48 +02:00
|
|
|
|
namespace AICore.Facade.LLM
|
2025-07-03 13:55:46 +02:00
|
|
|
|
{
|
2025-08-05 11:55:48 +02:00
|
|
|
|
public class OpenWebApiClient : BaseLLMApiClient
|
2025-07-03 13:55:46 +02:00
|
|
|
|
{
|
2025-08-05 11:55:48 +02:00
|
|
|
|
private protected readonly HttpClientFacade _GetClientFacade;
|
|
|
|
|
|
private protected readonly JsonHttpClientFacade _PostClientFacade;
|
|
|
|
|
|
private protected readonly IApiErrorExtractor _ErrorExtractor;
|
2025-07-03 13:55:46 +02:00
|
|
|
|
|
|
|
|
|
|
public OpenWebApiClient(string base_url, string api_key)
|
|
|
|
|
|
{
|
2025-08-05 14:45:25 +02:00
|
|
|
|
_GetClientFacade = new HttpClientFacade(base_url, api_key);
|
|
|
|
|
|
_PostClientFacade = new JsonHttpClientFacade(base_url, api_key)
|
|
|
|
|
|
{
|
2025-08-11 13:05:45 +02:00
|
|
|
|
Timeout = TimeSpan.FromMinutes(10)
|
2025-08-05 14:45:25 +02:00
|
|
|
|
};
|
2025-07-03 13:55:46 +02:00
|
|
|
|
_ErrorExtractor = new DefaultErrorExtractor();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-05 15:57:30 +02:00
|
|
|
|
public override ApiResponse<IEnumerable<AiModelDC>> GetAiModelle()
|
2025-07-03 13:55:46 +02:00
|
|
|
|
{
|
|
|
|
|
|
var models = new List<AiModelDC>();
|
|
|
|
|
|
|
|
|
|
|
|
var response_format = new
|
|
|
|
|
|
{
|
2025-08-05 11:55:48 +02:00
|
|
|
|
data = new[]
|
|
|
|
|
|
{
|
|
|
|
|
|
new
|
|
|
|
|
|
{
|
|
|
|
|
|
id = "",
|
2025-08-05 15:57:30 +02:00
|
|
|
|
name = "",
|
|
|
|
|
|
details = new
|
|
|
|
|
|
{
|
|
|
|
|
|
max_context_size = 0
|
|
|
|
|
|
}
|
2025-08-05 11:55:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2025-07-03 13:55:46 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
var response = _GetClientFacade.GetAnonymousTypeAsync("api/models", response_format, _ErrorExtractor).GetAwaiter().GetResult();
|
|
|
|
|
|
|
|
|
|
|
|
if (!response.Success)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-07 16:40:07 +02:00
|
|
|
|
var data = response.Data.data.Select(x => new AiModelDC(BS.Shared.AiModelSource.openwebui, x.name, x.details?.max_context_size ?? -2));
|
2025-07-03 13:55:46 +02:00
|
|
|
|
|
2025-08-05 15:57:30 +02:00
|
|
|
|
return ApiResponse<IEnumerable<AiModelDC>>.SuccessResponse(data);
|
2025-07-03 13:55:46 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-05 11:55:48 +02:00
|
|
|
|
public override ApiResponse<string> SendAiMessageRequest(dynamic payload, out string message, out string model, out int? duration)
|
2025-07-03 13:55:46 +02:00
|
|
|
|
{
|
|
|
|
|
|
message = null;
|
|
|
|
|
|
duration = null;
|
|
|
|
|
|
model = null;
|
|
|
|
|
|
|
2025-08-05 11:55:48 +02:00
|
|
|
|
_PostClientFacade.JsonObject = payload;
|
2025-07-03 13:55:46 +02:00
|
|
|
|
|
|
|
|
|
|
var response_format = new
|
|
|
|
|
|
{
|
|
|
|
|
|
id = string.Empty,
|
|
|
|
|
|
model = string.Empty,
|
|
|
|
|
|
choices = new[]
|
|
|
|
|
|
{
|
|
|
|
|
|
new
|
|
|
|
|
|
{
|
|
|
|
|
|
index = 0,
|
|
|
|
|
|
message = new
|
|
|
|
|
|
{
|
|
|
|
|
|
content = string.Empty,
|
|
|
|
|
|
role = string.Empty
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
usage = new
|
|
|
|
|
|
{
|
|
|
|
|
|
total_duration = 0L,
|
|
|
|
|
|
total_tokens = 68L
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-08-05 11:55:48 +02:00
|
|
|
|
var response = _PostClientFacade.GetAnonymousTypeAsync("api/chat/completions", response_format, _ErrorExtractor).GetAwaiter().GetResult();
|
2025-07-04 14:27:08 +02:00
|
|
|
|
|
|
|
|
|
|
if (!response.Success)
|
|
|
|
|
|
return response.Copy<string>();
|
|
|
|
|
|
|
2025-07-03 14:17:31 +02:00
|
|
|
|
var json = response.GetResponseData();
|
2025-07-03 13:55:46 +02:00
|
|
|
|
|
2025-07-03 14:17:31 +02:00
|
|
|
|
foreach (var choice in json.choices)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (choice?.message is object && !string.IsNullOrEmpty(choice.message.content))
|
|
|
|
|
|
{
|
|
|
|
|
|
var total_ns = json.usage.total_duration;
|
|
|
|
|
|
var total_ms = total_ns / 1000000;
|
2025-08-05 11:55:48 +02:00
|
|
|
|
|
2025-07-03 14:17:31 +02:00
|
|
|
|
duration = (int)total_ms;
|
|
|
|
|
|
model = json.model;
|
2025-07-03 13:55:46 +02:00
|
|
|
|
|
2025-07-03 14:17:31 +02:00
|
|
|
|
var assi_msg = BS.Shared.Core.Utils.ConvertToISO88591(choice.message.content);
|
2025-07-03 13:55:46 +02:00
|
|
|
|
|
2025-07-03 14:17:31 +02:00
|
|
|
|
message = assi_msg;
|
2025-07-03 13:55:46 +02:00
|
|
|
|
|
2025-07-03 14:17:31 +02:00
|
|
|
|
return ApiResponse<string>.SuccessResponse(assi_msg);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-07-03 13:55:46 +02:00
|
|
|
|
|
|
|
|
|
|
return ApiResponse<string>.FailureResponse("Keine Antwort");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|