Logger
This commit is contained in:
@@ -66,6 +66,10 @@
|
||||
<Project>{69D70CA9-0DF9-419E-BFAF-F4539F129BD9}</Project>
|
||||
<Name>AICore</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Service\Service.csproj">
|
||||
<Project>{094331C3-ECEE-4C89-BBFD-4C9DED89F0EF}</Project>
|
||||
<Name>Service</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Shared\Shared.csproj">
|
||||
<Project>{2F50B83D-A3F0-4EC4-979A-3F9B7E3D8ED4}</Project>
|
||||
<Name>Shared</Name>
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
using AICore.Facade.LLM;
|
||||
using BeWo.Service.Core;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting.Logging;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace AiCoreUnitTest
|
||||
{
|
||||
@@ -48,7 +51,8 @@ namespace AiCoreUnitTest
|
||||
}
|
||||
};
|
||||
|
||||
var response = client.SendAiMessageRequest(payload, out string message, out string model, out int? duration);
|
||||
var logger = ServiceLogger.GetRequestLogger();
|
||||
var response = client.SendAiMessageRequest(payload, out string message, out string model, out int? duration, logger);
|
||||
|
||||
Assert.IsTrue(response?.Success);
|
||||
}
|
||||
|
||||
@@ -13,19 +13,19 @@
|
||||
<basicHttpBinding>
|
||||
<binding name="BeWoBasicEndpoint" closeTimeout="00:05:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true" messageEncoding="Text">
|
||||
<readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
|
||||
<security mode="Transport" />
|
||||
<security mode="None" />
|
||||
<!--security mode="Transport"/-->
|
||||
<!-- mode="Transport" für https und "None" sonst-->
|
||||
</binding>
|
||||
<binding name="BeWoStreamingEndpoint" receiveTimeout="10:10:00" sendTimeout="10:01:00" maxBufferSize="65536" maxReceivedMessageSize="67108864" transferMode="StreamedRequest" useDefaultWebProxy="true" messageEncoding="Text">
|
||||
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
|
||||
<security mode="Transport" />
|
||||
<security mode="None" />
|
||||
<!--security mode="Transport"/-->
|
||||
<!-- mode="Transport" für https und "None" sonst-->
|
||||
</binding>
|
||||
<binding name="QueryServiceEndpoint" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true" messageEncoding="Text">
|
||||
<readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
|
||||
<security mode="Transport">
|
||||
<security mode="None">
|
||||
<transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
|
||||
<message clientCredentialType="UserName" algorithmSuite="Default"/>
|
||||
</security>
|
||||
|
||||
@@ -7,12 +7,29 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Text.Json;
|
||||
using BS.Shared.Interface;
|
||||
using BeWo.ServerUtils.ApiFacade;
|
||||
using BS.Shared.Logger;
|
||||
|
||||
namespace AICore.Facade.LLM
|
||||
{
|
||||
public abstract class BaseLLMApiClient
|
||||
{
|
||||
private protected readonly HttpClientFacade _GetClientFacade;
|
||||
private protected readonly JsonHttpClientFacade _PostClientFacade;
|
||||
private protected readonly IApiErrorExtractor _ErrorExtractor;
|
||||
|
||||
protected BaseLLMApiClient(string base_url, string api_key)
|
||||
{
|
||||
_GetClientFacade = new HttpClientFacade(base_url, api_key, false);
|
||||
_PostClientFacade = new JsonHttpClientFacade(base_url, api_key, false)
|
||||
{
|
||||
Timeout = TimeSpan.FromMinutes(10)
|
||||
};
|
||||
_ErrorExtractor = new DefaultErrorExtractor();
|
||||
}
|
||||
|
||||
public abstract ApiResponse<IEnumerable<AiModelDC>> GetAiModelle();
|
||||
public abstract ApiResponse<string> SendAiMessageRequest(dynamic payload, out string message, out string model, out int? duration);
|
||||
public abstract ApiResponse<string> SendAiMessageRequest(dynamic payload, out string message, out string model, out int? duration, FileLogger logger = null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,23 +8,16 @@ using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.Net;
|
||||
using BeWo.ServerUtils.ApiFacade;
|
||||
using BS.Shared;
|
||||
using BS.Shared.Logger;
|
||||
|
||||
namespace AICore.Facade.LLM
|
||||
{
|
||||
public class OllamaApiClient : BaseLLMApiClient
|
||||
{
|
||||
private protected readonly HttpClientFacade _GetClientFacade;
|
||||
private protected readonly JsonHttpClientFacade _PostClientFacade;
|
||||
private protected readonly IApiErrorExtractor _ErrorExtractor;
|
||||
|
||||
public OllamaApiClient(string base_url, string api_key)
|
||||
public OllamaApiClient(string base_url, string api_key) : base(base_url, api_key)
|
||||
{
|
||||
_GetClientFacade = new HttpClientFacade(base_url, api_key, false);
|
||||
_PostClientFacade = new JsonHttpClientFacade(base_url, api_key, false)
|
||||
{
|
||||
Timeout = TimeSpan.FromMinutes(10)
|
||||
};
|
||||
_ErrorExtractor = new DefaultErrorExtractor();
|
||||
|
||||
}
|
||||
|
||||
public override ApiResponse<IEnumerable<AiModelDC>> GetAiModelle()
|
||||
@@ -60,7 +53,7 @@ namespace AICore.Facade.LLM
|
||||
return ApiResponse<IEnumerable<AiModelDC>>.SuccessResponse(data);
|
||||
}
|
||||
|
||||
public override ApiResponse<string> SendAiMessageRequest(dynamic payload, out string message, out string model, out int? duration)
|
||||
public override ApiResponse<string> SendAiMessageRequest(dynamic payload, out string message, out string model, out int? duration, FileLogger logger = null)
|
||||
{
|
||||
message = null;
|
||||
duration = null;
|
||||
@@ -68,6 +61,12 @@ namespace AICore.Facade.LLM
|
||||
|
||||
_PostClientFacade.JsonObject = payload;
|
||||
|
||||
if(logger is object)
|
||||
{
|
||||
logger.Log(LogLevel.Info, "Request:");
|
||||
logger.LogJson(LogLevel.Info, _PostClientFacade.JsonObject);
|
||||
}
|
||||
|
||||
var response_format = new
|
||||
{
|
||||
id = string.Empty,
|
||||
@@ -89,6 +88,12 @@ namespace AICore.Facade.LLM
|
||||
|
||||
var response = _PostClientFacade.GetAnonymousTypeAsync("api/ollama/chat/completions", response_format, _ErrorExtractor).GetAwaiter().GetResult();
|
||||
|
||||
if(logger is object)
|
||||
{
|
||||
logger.Log(LogLevel.Info, "Response:");
|
||||
logger.LogJson(LogLevel.Info, response);
|
||||
}
|
||||
|
||||
if (!response.Success)
|
||||
return response.Copy<string>();
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using BeWo.ServerUtils.ApiFacade;
|
||||
using BS.Shared;
|
||||
using BS.Shared.DataContracts;
|
||||
using BS.Shared.DataContracts.Feature.AI;
|
||||
using BS.Shared.Extensions;
|
||||
using BS.Shared.Interface;
|
||||
using BS.Shared.Logger;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
@@ -13,18 +15,9 @@ namespace AICore.Facade.LLM
|
||||
{
|
||||
public class OpenWebApiClient : BaseLLMApiClient
|
||||
{
|
||||
private protected readonly HttpClientFacade _GetClientFacade;
|
||||
private protected readonly JsonHttpClientFacade _PostClientFacade;
|
||||
private protected readonly IApiErrorExtractor _ErrorExtractor;
|
||||
|
||||
public OpenWebApiClient(string base_url, string api_key)
|
||||
public OpenWebApiClient(string base_url, string api_key) : base(base_url, api_key)
|
||||
{
|
||||
_GetClientFacade = new HttpClientFacade(base_url, api_key);
|
||||
_PostClientFacade = new JsonHttpClientFacade(base_url, api_key)
|
||||
{
|
||||
Timeout = TimeSpan.FromMinutes(10)
|
||||
};
|
||||
_ErrorExtractor = new DefaultErrorExtractor();
|
||||
|
||||
}
|
||||
|
||||
public override ApiResponse<IEnumerable<AiModelDC>> GetAiModelle()
|
||||
@@ -60,7 +53,7 @@ namespace AICore.Facade.LLM
|
||||
return ApiResponse<IEnumerable<AiModelDC>>.SuccessResponse(data);
|
||||
}
|
||||
|
||||
public override ApiResponse<string> SendAiMessageRequest(dynamic payload, out string message, out string model, out int? duration)
|
||||
public override ApiResponse<string> SendAiMessageRequest(dynamic payload, out string message, out string model, out int? duration, FileLogger logger = null)
|
||||
{
|
||||
message = null;
|
||||
duration = null;
|
||||
@@ -68,6 +61,12 @@ namespace AICore.Facade.LLM
|
||||
|
||||
_PostClientFacade.JsonObject = payload;
|
||||
|
||||
if (logger is object)
|
||||
{
|
||||
logger.Log(LogLevel.Info, "Request:");
|
||||
logger.LogJson(LogLevel.Info, _PostClientFacade.JsonObject);
|
||||
}
|
||||
|
||||
var response_format = new
|
||||
{
|
||||
id = string.Empty,
|
||||
@@ -93,6 +92,12 @@ namespace AICore.Facade.LLM
|
||||
|
||||
var response = _PostClientFacade.GetAnonymousTypeAsync("api/chat/completions", response_format, _ErrorExtractor).GetAwaiter().GetResult();
|
||||
|
||||
if (logger is object)
|
||||
{
|
||||
logger.Log(LogLevel.Info, "Response:");
|
||||
logger.LogJson(LogLevel.Info, response);
|
||||
}
|
||||
|
||||
if (!response.Success)
|
||||
return response.Copy<string>();
|
||||
|
||||
|
||||
@@ -9,14 +9,62 @@ namespace BeWo.Service.Core
|
||||
{
|
||||
public static class PathHelper
|
||||
{
|
||||
#region AI
|
||||
private static string GetAiPath()
|
||||
=> Path.Combine(getRoot(), "AI");
|
||||
public static string GetAiSystemPromptPath()
|
||||
=> Path.Combine(GetAiPath(), "systemPrompts");
|
||||
#endregion
|
||||
/// <summary>
|
||||
/// Holt den Ordner, wo sich die systemInstructions befinden
|
||||
/// </summary>
|
||||
public static string GetAiSystemInstructionPath()
|
||||
=> Path.Combine(getRoot(), "AI", "systemInstructions");
|
||||
|
||||
|
||||
public static string GetOrCreateUniqueRequestLogFile()
|
||||
{
|
||||
var folder_path = Path.Combine(getExecutionRoot(), "logs", "ai", "requests");
|
||||
Directory.CreateDirectory(folder_path);
|
||||
|
||||
var file_name = getUniqueFileName(folder_path, $"{DateTime.Now:yyyy.MM.dd HH_mm_ss}", 20);
|
||||
|
||||
if (file_name == null)
|
||||
return null;
|
||||
|
||||
return Path.Combine(folder_path, file_name + ".log");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Holt den Server Root Path
|
||||
/// Normalerweise: C:/BeWoPlaner
|
||||
/// </summary>
|
||||
private static string getRoot()
|
||||
=> MergedConfig.GetSetting(WebConfigSetting.BeWoPlanerServiceRoot);
|
||||
|
||||
/// <summary>
|
||||
/// Holt den Service Root Path
|
||||
/// Normalerweise: C:/BeWoPlaner/service/Host
|
||||
/// </summary>
|
||||
private static string getExecutionRoot()
|
||||
=> AppDomain.CurrentDomain.BaseDirectory;
|
||||
|
||||
|
||||
private static string getUniqueFileName(string folderPath, string fileName, int retries)
|
||||
{
|
||||
var path = Path.Combine(folderPath, fileName);
|
||||
|
||||
if (!File.Exists(path))
|
||||
return fileName;
|
||||
|
||||
var name = 2;
|
||||
while(retries-- > 0)
|
||||
{
|
||||
var new_fileName = fileName + $" ({name})";
|
||||
var new_path = Path.Combine(folderPath, new_fileName);
|
||||
|
||||
if (!File.Exists(new_path))
|
||||
return new_fileName;
|
||||
|
||||
name++;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,16 +8,13 @@ using System.Threading.Tasks;
|
||||
using System.ServiceModel.Dispatcher;
|
||||
using BeWo.Service.ServiceUtils;
|
||||
using BS.Shared.Extensions;
|
||||
using BS.Shared.Logger;
|
||||
using BeWo.ServerUtils;
|
||||
|
||||
namespace BeWo.Service.Core
|
||||
{
|
||||
public static class ServiceHelper
|
||||
{
|
||||
public static FileLogger CoreLogger { get; } = new FileLogger(MergedConfig.GetSetting(WebConfigSetting.ServiceLogFilePath));
|
||||
public static FileLogger WCFErrorLogger { get; } = new FileLogger(MergedConfig.GetSetting(WebConfigSetting.WCFErrorLogFilePath));
|
||||
public static FileLogger JsonErrorLogger { get; } = new FileLogger(MergedConfig.GetSetting(WebConfigSetting.JsonErrorLogFilePath));
|
||||
|
||||
public static Tuple<string, string> GetInterfaceAndMethodWCF(Message request, IClientChannel channel)
|
||||
{
|
||||
var lTemp = request.Headers.Action.Split("/");
|
||||
|
||||
27
Service/Core/ServiceLogger.cs
Normal file
27
Service/Core/ServiceLogger.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using BS.Shared.Logger;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BeWo.Service.Core
|
||||
{
|
||||
public static class ServiceLogger
|
||||
{
|
||||
public static FileLogger CoreLogger { get; } = new FileLogger(MergedConfig.GetSetting(WebConfigSetting.ServiceLogFilePath));
|
||||
public static FileLogger WCFErrorLogger { get; } = new FileLogger(MergedConfig.GetSetting(WebConfigSetting.WCFErrorLogFilePath));
|
||||
public static FileLogger JsonErrorLogger { get; } = new FileLogger(MergedConfig.GetSetting(WebConfigSetting.JsonErrorLogFilePath));
|
||||
|
||||
public static FileLogger GetRequestLogger()
|
||||
{
|
||||
var filePath = PathHelper.GetOrCreateUniqueRequestLogFile();
|
||||
|
||||
if (filePath == null)
|
||||
throw new NotImplementedException("err98462");
|
||||
|
||||
return new FileLogger(filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ namespace BeWo.Service.Plugins
|
||||
// Anfrage zusammensetzen
|
||||
var context = AiFunctionContextLoader.LoadServiceRecordDocumentationContext(request);
|
||||
|
||||
var systemInstructionsFolderPath = PathHelper.GetAiSystemPromptPath();
|
||||
var systemInstructionsFolderPath = PathHelper.GetAiSystemInstructionPath();
|
||||
var factory = new AiFunctionSystemInstructionBuilder(systemInstructionsFolderPath);
|
||||
var system_prompt = factory.CreateServiceRecordDocumentationSystemInstructions(context);
|
||||
|
||||
@@ -76,7 +76,8 @@ namespace BeWo.Service.Plugins
|
||||
}
|
||||
};
|
||||
|
||||
var response = ServiceFacade.OllamaApiClient.SendAiMessageRequest(payload, out string message, out string model, out int? duration);
|
||||
var logger = ServiceLogger.GetRequestLogger();
|
||||
var response = ServiceFacade.OllamaApiClient.SendAiMessageRequest(payload, out string message, out string model, out int? duration, logger);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
@@ -270,7 +270,7 @@ namespace BeWo.Service.Plugins
|
||||
{
|
||||
var current_user = UserRightHelper.GetLoggedInUserWithOid();
|
||||
|
||||
var systemInstructionsFolderPath = PathHelper.GetAiSystemPromptPath();
|
||||
var systemInstructionsFolderPath = PathHelper.GetAiSystemInstructionPath();
|
||||
var factory = new AiConversationSystemInstructionBuilder(systemInstructionsFolderPath);
|
||||
|
||||
var context_loaded = AiContextLoader.LoadContext(uicontext, context_reference);
|
||||
@@ -343,13 +343,15 @@ namespace BeWo.Service.Plugins
|
||||
// Send Request, wait for Response
|
||||
var dt_before_request = DateTime.Now;
|
||||
|
||||
var logger = ServiceLogger.GetRequestLogger();
|
||||
|
||||
ApiResponse<string> response;
|
||||
string message2, model;
|
||||
int? duration;
|
||||
if (config.SelectedModel.ModelSource == AiModelSource.openwebui)
|
||||
response = ServiceFacade.OpenWebApiClient.SendAiMessageRequest(payload, out message2, out model, out duration);
|
||||
response = ServiceFacade.OpenWebApiClient.SendAiMessageRequest(payload, out message2, out model, out duration, logger);
|
||||
else if (config.SelectedModel.ModelSource == AiModelSource.ollama)
|
||||
response = ServiceFacade.OllamaApiClient.SendAiMessageRequest(payload, out message2, out model, out duration);
|
||||
response = ServiceFacade.OllamaApiClient.SendAiMessageRequest(payload, out message2, out model, out duration, logger);
|
||||
else
|
||||
throw new NotImplementedException();
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ using BS.Shared;
|
||||
using BS.Shared.Core;
|
||||
using BS.Shared.DataContracts;
|
||||
using BS.Shared.Interface;
|
||||
using BS.Shared.Logger;
|
||||
using DevExpress.Export;
|
||||
using DevExpress.Utils.Filtering.Internal;
|
||||
using Newtonsoft.Json;
|
||||
@@ -35,7 +36,7 @@ namespace BeWo.Service.Plugins
|
||||
_storage = DAOFactory.GetLocalTenantFileStorage(lStoragePath);
|
||||
|
||||
_genericDAO = DAOFactory.GenericDAO;
|
||||
_logger = ServiceHelper.CoreLogger;
|
||||
_logger = ServiceLogger.CoreLogger;
|
||||
}
|
||||
|
||||
public ApiResponse<Tuple<StoredFileDC, byte[]>> GetXRechnung(long invoice_base_oid, int report_type, string report_url)
|
||||
|
||||
@@ -228,9 +228,9 @@
|
||||
<Compile Include="Core\DiamantExporter.cs" />
|
||||
<Compile Include="Core\ExcelDownload.cs" />
|
||||
<Compile Include="Core\FileAttachmentUtils.cs" />
|
||||
<Compile Include="Core\FileLogger.cs" />
|
||||
<Compile Include="Core\MergedConfig.cs" />
|
||||
<Compile Include="Core\PathHelper.cs" />
|
||||
<Compile Include="Core\ServiceLogger.cs" />
|
||||
<Compile Include="Core\ServiceLogic.cs" />
|
||||
<Compile Include="Core\SettingsLogic.cs" />
|
||||
<Compile Include="Core\Utils.cs" />
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace BeWo.Service.ServiceBehavior.JsonError
|
||||
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
|
||||
{
|
||||
// Logge in File
|
||||
ServiceHelper.JsonErrorLogger.LogError(error);
|
||||
ServiceLogger.JsonErrorLogger.LogError(error);
|
||||
|
||||
// Erstelle eine JSON-Fehlermeldung
|
||||
var jsonError = new JsonError
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace BeWo.Service.ServiceBehavior.WCFError
|
||||
public void ProvideFault(Exception error, MessageVersion version, ref Message message)
|
||||
{
|
||||
// Logge in File
|
||||
ServiceHelper.WCFErrorLogger.LogError(error);
|
||||
ServiceLogger.WCFErrorLogger.LogError(error);
|
||||
|
||||
var wcfError = Utils.CreateBeWoFaultException(error);
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ using BS.Shared.Core;
|
||||
using BS.Shared.Exceptions;
|
||||
using BS.Shared.Interface;
|
||||
using Newtonsoft.Json;
|
||||
using RestSharp.Validation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
@@ -11,7 +10,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BeWo.Service.Core
|
||||
namespace BS.Shared.Logger
|
||||
{
|
||||
public class FileLogger
|
||||
{
|
||||
@@ -429,6 +429,7 @@
|
||||
<Compile Include="Interface\IInvoiceItem.cs" />
|
||||
<Compile Include="Interface\ISupportConcept.cs" />
|
||||
<Compile Include="Interface\IStoredFile.cs" />
|
||||
<Compile Include="Logger\FileLogger.cs" />
|
||||
<Compile Include="Models\AddressInformation.cs" />
|
||||
<Compile Include="Packet.cs" />
|
||||
<Compile Include="ReportRequests\AbstractReportRequest.cs" />
|
||||
|
||||
Reference in New Issue
Block a user