diff --git a/BeWo/View/Master/AdministrationView.xaml b/BeWo/View/Master/AdministrationView.xaml index ccb00b66b..5146dc6b0 100644 --- a/BeWo/View/Master/AdministrationView.xaml +++ b/BeWo/View/Master/AdministrationView.xaml @@ -319,33 +319,40 @@ Selected="Tabitem_Selected" /> - + IsEnabled="False" + Selected="Tabitem_Selected" />--> + Header="{markup:Translate Prompt}"> + + Name="TabitemAiPromptbausteineComplexTree1" + Foreground="Black" + Header="{markup:Translate Chat}" + Selected="Tabitem_Selected" /> + Name="TabitemAiPromptbausteineComplexTree2" + Foreground="Black" + Header="{markup:Translate Dokumentation}" + Selected="Tabitem_Selected" /> + - + AddView(TabitemSozioTherapie, new SoziotherapieSettingsView(this))); return; - case nameof(TabitemAiPromptbausteine): - VMFactory.CreateAiPromptbausteinListVMAsync( - r => this.Dispatch(() => AddView(TabitemAiPromptbausteine, new AiPromptbausteinView(r)))); - return; - case nameof(TabitemAiPromptbausteineTree): - AddView(TabitemAiPromptbausteineTree, new AiPromptbausteinTreeView()); - return; + //case nameof(TabitemAiPromptbausteine): + // VMFactory.CreateAiPromptbausteinListVMAsync( + // r => this.Dispatch(() => AddView(TabitemAiPromptbausteine, new AiPromptbausteinView(r)))); + // return; + //case nameof(TabitemAiPr omptbausteineTree): + // AddView(TabitemAiPromptbausteineTree, new AiPromptbausteinTreeView()); + // return; case nameof(TabitemAiPromptbausteineComplexTree1): var vm11 = new AiPromptbausteinComplexTreeViewModel(BeWoApp.MainControl.WindowService, AiActionType.ServiceRecordConversation); AddView(TabitemAiPromptbausteineComplexTree1, new AiPromptbausteinComplexTreeView(vm11)); diff --git a/BeWo/ViewModel/AiPromptbausteinFolderVM.cs b/BeWo/ViewModel/AiPromptbausteinFolderVM.cs index 1d35e3295..6fd53d3e3 100644 --- a/BeWo/ViewModel/AiPromptbausteinFolderVM.cs +++ b/BeWo/ViewModel/AiPromptbausteinFolderVM.cs @@ -126,7 +126,7 @@ namespace BeWo.ViewModel public AiPromptbausteinFolderVM Parent { get; set; } - public FontWeight FontWeight => !IsNew && ParentFolderOid is null ? FontWeights.SemiBold : FontWeights.Medium; + public FontWeight FontWeight => !IsNew && Parent is null ? FontWeights.SemiBold : FontWeights.Medium; public bool HasSubFolders => SubFolders is object && SubFolders.Count > 0; public string Displayname { diff --git a/BeWo/ViewModel/ListViewModel/AiPromptbausteinFolderListVM.cs b/BeWo/ViewModel/ListViewModel/AiPromptbausteinFolderListVM.cs index 50ce106b5..1e41125c0 100644 --- a/BeWo/ViewModel/ListViewModel/AiPromptbausteinFolderListVM.cs +++ b/BeWo/ViewModel/ListViewModel/AiPromptbausteinFolderListVM.cs @@ -15,7 +15,11 @@ namespace BeWo.ViewModel.ListViewModel foreach (var vm in VMList) { vm.Parent = parent; - vm.ParentFolderOid = parent?.DataContract?.Oid; + + if(vm.DataContract.ParentFolderOid != null) + { + vm.ParentFolderOid = parent?.DataContract?.Oid; + } } } @@ -26,6 +30,9 @@ namespace BeWo.ViewModel.ListViewModel foreach (var vm in VMList) { + if (vm.DataContract.Oid < -1) + return false; + if (vm.SubFolders is object && vm.SubFolders.ContainsDirtyObject()) return true; diff --git a/BeWo/ViewModel/View/Administration/AiPromptbausteinComplexTreeViewModel.cs b/BeWo/ViewModel/View/Administration/AiPromptbausteinComplexTreeViewModel.cs index 69601339e..56f1b52bc 100644 --- a/BeWo/ViewModel/View/Administration/AiPromptbausteinComplexTreeViewModel.cs +++ b/BeWo/ViewModel/View/Administration/AiPromptbausteinComplexTreeViewModel.cs @@ -183,6 +183,9 @@ namespace BeWo.ViewModel.View.Administration { foreach (var node in folders.VMList) { + if (node.DataContract.Oid is long oid && oid < -1) + continue; + if (node.IsNew) { toadd_Folder.Add(node); @@ -203,11 +206,13 @@ namespace BeWo.ViewModel.View.Administration } } } - void DFS_Search_Delete(AiPromptbausteinFolderListVM folders, ref List todelete_Folder, ref List todelete_Prompt) { foreach (var node_dc in folders.DCBackup) { + if (node_dc.Oid is long oid && oid < -1) + continue; + if (folders.VMList.FirstOrDefault(vm => vm.DataContract == node_dc) is AiPromptbausteinFolderVM node_vm) { if (node_vm.SubFolders.DCBackup is object && node_vm.SubFolders.DCBackup.Count > 0) diff --git a/Data/Entities/AiPromptbausteinPrompt.cs b/Data/Entities/AiPromptbausteinPrompt.cs index c27708181..f9821dfb4 100644 --- a/Data/Entities/AiPromptbausteinPrompt.cs +++ b/Data/Entities/AiPromptbausteinPrompt.cs @@ -3,10 +3,11 @@ using System.Collections.Generic; using BS.Shared; using BS.Shared.Core; +using BS.Shared.Interface; namespace BeWo.Data.Entities { - public class AiPromptbausteinPrompt : BeWoEntityBase + public class AiPromptbausteinPrompt : BeWoEntityBase, IAiPromptbausteinPrompt { public AiPromptbausteinPrompt() { diff --git a/Server/Components/AICore/Context/SummaryParser/CsvContextSummaryParser.cs b/Server/Components/AICore/Context/SummaryParser/CsvContextSummaryParser.cs index 40b6436f8..ed28a4b97 100644 --- a/Server/Components/AICore/Context/SummaryParser/CsvContextSummaryParser.cs +++ b/Server/Components/AICore/Context/SummaryParser/CsvContextSummaryParser.cs @@ -71,7 +71,7 @@ namespace AICore.Context.SummaryParser sb.AppendLine("#### **Zeiterfassungseinträge**"); sb.AppendLine(ToCsvString(fcs.ServiceRecords)); sb.AppendLine(); - sb.AppendLine("#### **Dokumentationfelder**"); + sb.AppendLine("#### **Dokumentations(text)**"); sb.AppendLine(fcs.Dokutext); sb.AppendLine(); return sb.ToString(); diff --git a/Server/Components/AICore/Prompt/Core/AiUtils.cs b/Server/Components/AICore/Prompt/Core/AiUtils.cs index f20ec8beb..7e6a01bfa 100644 --- a/Server/Components/AICore/Prompt/Core/AiUtils.cs +++ b/Server/Components/AICore/Prompt/Core/AiUtils.cs @@ -1,12 +1,18 @@ using BS.Shared.Exceptions; using BS.Shared.Interface.Feature.AICore; using System.Collections.Generic; +using System.Linq; namespace AICore.Prompt.Core { public static class AiUtils { public static void CheckTokenSize(IEnumerable messages, string modelName, int max_context_size) + { + CheckTokenSize(messages.Select(x => x.Message), modelName, max_context_size); + } + + public static void CheckTokenSize(IEnumerable messages, string modelName, int max_context_size) { var buffer = 500; @@ -19,7 +25,7 @@ namespace AICore.Prompt.Core var calc_tokens = prev_tokens + buffer; - var percentage = calc_tokens * 100 / max_tokens; + var percentage = (double)calc_tokens * 100 / max_tokens; if (calc_tokens > max_tokens) { @@ -28,17 +34,18 @@ namespace AICore.Prompt.Core } } - private static int CalculateTokensByModel(IEnumerable messages, string modelName) + private static int CalculateTokensByModel(IEnumerable messages, string modelName) { var count = 0; foreach (var message in messages) { count += 4; - count += message.Message.Length / 2; + count += message.Length / 2; } return count; } + } } diff --git a/Service/Core/PathHelper.cs b/Service/Core/BeWoServerPathHelper.cs similarity index 94% rename from Service/Core/PathHelper.cs rename to Service/Core/BeWoServerPathHelper.cs index e6291f988..abc256ef1 100644 --- a/Service/Core/PathHelper.cs +++ b/Service/Core/BeWoServerPathHelper.cs @@ -8,13 +8,15 @@ using System.Threading.Tasks; namespace BeWo.Service.Core { - public static class PathHelper + public static class BeWoServerPathHelper { /// /// Holt den Ordner, wo sich die systemPrompts befinden /// public static string GetAiSystemPromptPath() => Path.Combine(getRoot(), "AI", "systemPrompts"); + public static string GetAiOwnsoftPromptPath() + => Path.Combine(getRoot(), "AI", "ownsoftPrompts"); public static string GetUniqueRequestLogFile() diff --git a/Service/Core/ServiceLogger.cs b/Service/Core/ServiceLogger.cs index a708a813c..b365b3c69 100644 --- a/Service/Core/ServiceLogger.cs +++ b/Service/Core/ServiceLogger.cs @@ -10,13 +10,13 @@ namespace BeWo.Service.Core { public static class ServiceLogger { - public static FileLogger CoreLogger { get; } = new FileLogger(PathHelper.GetServiceLogFile()); - public static FileLogger WCFErrorLogger { get; } = new FileLogger(PathHelper.GetWCFErrorLogFile()); - public static FileLogger JsonErrorLogger { get; } = new FileLogger(PathHelper.GetJsonErrorLogFile()); + public static FileLogger CoreLogger { get; } = new FileLogger(BeWoServerPathHelper.GetServiceLogFile()); + public static FileLogger WCFErrorLogger { get; } = new FileLogger(BeWoServerPathHelper.GetWCFErrorLogFile()); + public static FileLogger JsonErrorLogger { get; } = new FileLogger(BeWoServerPathHelper.GetJsonErrorLogFile()); public static FileLogger GetRequestLogger() { - var filePath = PathHelper.GetUniqueRequestLogFile(); + var filePath = BeWoServerPathHelper.GetUniqueRequestLogFile(); if (filePath == null) throw new NotImplementedException("err98462"); diff --git a/Service/Plugins/AiFunctionService.cs b/Service/Plugins/AiFunctionService.cs index 0c39cdf7e..357ab890a 100644 --- a/Service/Plugins/AiFunctionService.cs +++ b/Service/Plugins/AiFunctionService.cs @@ -7,7 +7,6 @@ using BS.Shared.DataContracts; using BS.Shared.DataContracts.Feature.AI; using BS.Shared.DataContracts.Feature.AI.Functions.ServiceRecords; using DevExpress.DataAccess.Native.Web; -using Newtonsoft.Json; using RestSharp.Validation; using System; using System.Collections.Generic; @@ -17,6 +16,11 @@ using System.Threading.Tasks; using AICore.Prompt.SystemPrompts; using BeWo.Service.Core; using BS.Shared.Extensions.CustomInterfaces; +using AICore.Prompt.Core; +using DevExpress.XtraCharts.Native; +using System.IO; +using BS.Shared.Interface; +using System.Text.Json; namespace BeWo.Service.Plugins { @@ -33,7 +37,7 @@ namespace BeWo.Service.Plugins // Anfrage zusammensetzen var context = AiFunctionContextLoader.LoadServiceRecordDocumentationContext(request); - var systemPromptFolderPath = PathHelper.GetAiSystemPromptPath(); + var systemPromptFolderPath = BeWoServerPathHelper.GetAiSystemPromptPath(); var factory = new AiFunctionSystemPromptBuilder(systemPromptFolderPath); var system_prompt = factory.CreateServiceRecordDocumentationSystemPrompt(context); @@ -41,17 +45,16 @@ namespace BeWo.Service.Plugins var prompt_baustein_ref_oid = prompt_baustein_ref.Oid; var prompt_baustein_ref_ver = prompt_baustein_ref.Version; - var prompt_baustein = DAOFactory.GenericDAO.LoadByID(prompt_baustein_ref_oid); - ServiceLogic.ConcurrencyCheck(prompt_baustein_ref_ver, prompt_baustein); - - //if (prompt_baustein.IsOrdner()) - // throw new Exception("prompt is folder"); - - //if (prompt_baustein.IsKette()) - // throw new NotImplementedException(); - - if (prompt_baustein.Oid < 0) - throw new NotImplementedException(); + IAiPromptbausteinPrompt prompt_baustein = null; + if(prompt_baustein_ref_oid > 0) + { + prompt_baustein = DAOFactory.GenericDAO.LoadByID(prompt_baustein_ref_oid); + ServiceLogic.ConcurrencyCheck(prompt_baustein_ref_ver, (AiPromptbausteinPrompt)prompt_baustein); + } + else + { + prompt_baustein = findOwnsoftPrompt(AiActionType.ServiceRecordDocumentation, prompt_baustein_ref.Oid); + } // Anfrage abschicken var result = getResult(system_prompt, prompt_baustein.Prompt); @@ -65,8 +68,26 @@ namespace BeWo.Service.Plugins return response; } + private string getResult(string system, string user_prompt) { + var models = ServiceFacade.Ollama2ApiClient.GetAiModelle(); + + var model = models.Data.FirstOrDefault(x => x.ModelName == "gemma3_12b_max_context:latest"); + + if (model == null) + throw new NotImplementedException(); + + var messages = new List() + { + system, user_prompt + }; + + if(model.Value > -1) + { + AiUtils.CheckTokenSize(messages, model.ModelName, model.Value); + } + var payload = new { model = "gemma3_12b_max_context:latest", @@ -86,7 +107,7 @@ namespace BeWo.Service.Plugins }; var logger = ServiceLogger.GetRequestLogger(); - var response = ServiceFacade.Ollama2ApiClient.SendAiMessageRequest(payload, out string message, out string model, out int? duration, logger); + var response = ServiceFacade.Ollama2ApiClient.SendAiMessageRequest(payload, out string message, out string model2, out int? duration, logger); return message; } @@ -95,5 +116,48 @@ namespace BeWo.Service.Plugins { //throw new NotImplementedException(); } + + + private AiPromptbausteinPromptDC findOwnsoftPrompt(AiActionType aiAction, long prompt_oid) + { + var root = getOwnsoftFolder(aiAction); + + return findOwnsoftPrompt_rec(root, prompt_oid); + } + + private AiPromptbausteinPromptDC findOwnsoftPrompt_rec(AiPromptbausteinFolderDC dc, long prompt_oid) + { + foreach (var subprompts in dc.SubPrompts) + { + if (subprompts.Oid == prompt_oid) + return subprompts; + } + + foreach (var subfolder in dc.SubFolders) + { + var search = findOwnsoftPrompt_rec(subfolder, prompt_oid); + + if (search != null) + return search; + } + + return null; + } + + private AiPromptbausteinFolderDC getOwnsoftFolder(AiActionType aiActionType) + { + var folder_path = BeWoServerPathHelper.GetAiOwnsoftPromptPath(); + var file_name = $"{aiActionType.ToString().ToLower()}.json"; + var file_path = Path.Combine(folder_path, file_name); + + if (!File.Exists(file_path)) + return null; + + var json = File.ReadAllText(file_path, Encoding.UTF8); + + var ownsoft_folder = JsonSerializer.Deserialize(json); + + return ownsoft_folder; + } } } diff --git a/Service/Plugins/AiPromptbausteineService.cs b/Service/Plugins/AiPromptbausteineService.cs index 3c21b54fb..b00692863 100644 --- a/Service/Plugins/AiPromptbausteineService.cs +++ b/Service/Plugins/AiPromptbausteineService.cs @@ -9,8 +9,12 @@ using BS.Shared.DataContracts.Feature.AI; using BS.Shared.Extensions; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Linq.Expressions; +using System.Text; +using System.Text.Json; +using System.Xml; namespace BeWo.Service.Plugins { @@ -144,13 +148,12 @@ namespace BeWo.Service.Plugins aiPromptbausteinListe.Add(aiPromptbaustein); } - - public IEnumerable GetAiPromptbausteinFolder(AiActionType aiActionType) { var own_bib = PredefinedAiPromptbausteinFolders.CreateOwnBibNode(aiActionType); var shared_bib = PredefinedAiPromptbausteinFolders.CreateSharedBibNode(aiActionType); var public_bib = PredefinedAiPromptbausteinFolders.CreatePublicBibNode(aiActionType); + var ownsoft_bib = GetOwnsoftFolder(aiActionType); var own = DAOFactory.SearchDAO.GetOwnActiveRootAiPromptbausteineFolders(aiActionType); var own_dcs = MapperFactory.AiPromptbausteinFolder.MapToNewDCs(own); @@ -163,9 +166,14 @@ namespace BeWo.Service.Plugins own_bib.SubFolders.AddRange(own_dcs); - return new List() { + var result = new List() { own_bib, shared_bib, public_bib }; + + if(ownsoft_bib is object) + result.Add(ownsoft_bib); + + return result; } private void initOwnFolder(AiPromptbausteinFolderDC folder) { @@ -249,5 +257,21 @@ namespace BeWo.Service.Plugins DAOFactory.GenericDAO.SetActivationType(originale, BS.Shared.ActivationTypeId.Deleted); } + + private AiPromptbausteinFolderDC GetOwnsoftFolder(AiActionType aiActionType) + { + var folder_path = BeWoServerPathHelper.GetAiOwnsoftPromptPath(); + var file_name = $"{aiActionType.ToString().ToLower()}.json"; + var file_path = Path.Combine(folder_path, file_name); + + if (!File.Exists(file_path)) + return null; + + var json = File.ReadAllText(file_path, Encoding.UTF8); + + var ownsoft_folder = JsonSerializer.Deserialize(json); + + return ownsoft_folder; + } } } diff --git a/Service/Plugins/AiService2.cs b/Service/Plugins/AiService2.cs index 57b215b7e..3668e5541 100644 --- a/Service/Plugins/AiService2.cs +++ b/Service/Plugins/AiService2.cs @@ -272,7 +272,7 @@ namespace BeWo.Service.Plugins { var current_user = UserRightHelper.GetLoggedInUserWithOid(); - var systemPromptFolderPath = PathHelper.GetAiSystemPromptPath(); + var systemPromptFolderPath = BeWoServerPathHelper.GetAiSystemPromptPath(); var factory = new AiConversationSystemPromptBuilder(systemPromptFolderPath); var context_loaded = AiContextLoader.LoadContext(uicontext, context_reference); diff --git a/Service/Service.csproj b/Service/Service.csproj index 741db7bf6..c5f097321 100644 --- a/Service/Service.csproj +++ b/Service/Service.csproj @@ -230,7 +230,7 @@ - + diff --git a/Service/ServiceImplementations/ApiServiceImp.cs b/Service/ServiceImplementations/ApiServiceImp.cs index 50d9afed3..fb329f004 100644 --- a/Service/ServiceImplementations/ApiServiceImp.cs +++ b/Service/ServiceImplementations/ApiServiceImp.cs @@ -77,7 +77,7 @@ namespace BeWo.Service.ServiceImplementations }; var str = JsonConvert.SerializeObject(log, Formatting.Indented); - File.WriteAllText(PathHelper.GetApiServiceTestFile(), str, Encoding.UTF8); + File.WriteAllText(BeWoServerPathHelper.GetApiServiceTestFile(), str, Encoding.UTF8); return ApiResponse.SuccessResponse("Hello World!"); } diff --git a/Shared/DataContracts/AiPromptbausteinFolderDC.cs b/Shared/DataContracts/AiPromptbausteinFolderDC.cs index 7efd05809..4b0b9eaad 100644 --- a/Shared/DataContracts/AiPromptbausteinFolderDC.cs +++ b/Shared/DataContracts/AiPromptbausteinFolderDC.cs @@ -99,13 +99,30 @@ namespace BS.Shared.DataContracts }; } - private static AiPromptbausteinFolderDC CreateExampleNode(AiActionType aiActionType) + public static AiPromptbausteinFolderDC CreateOwnsoftBibNode(AiActionType aiActionType) + { + return new AiPromptbausteinFolderDC() + { + ActionType = aiActionType, + Description = AiPromptbausteineTexts.OwnsoftBibNodeDescription, + Oid = -4, + ParentFolderOid = null, + SubFolders = new List(), + SubPrompts = new List(), + Title = AiPromptbausteineTexts.OwnsoftBibNodeDescription, + Version = 1, + IsExpanded = true, + IsNewFeature = false + }; + } + + public static AiPromptbausteinFolderDC CreateExampleNode(AiActionType aiActionType) { return new AiPromptbausteinFolderDC() { ActionType = aiActionType, Description = "Beispielbeschreibung", - Oid = -4, + Oid = -100, ParentFolderOid = null, SubFolders = new List(), SubPrompts = new List(), @@ -117,11 +134,11 @@ namespace BS.Shared.DataContracts }; } - private static AiPromptbausteinPromptDC CreateExamplePrompt(AiActionType aiActionType) + public static AiPromptbausteinPromptDC CreateExamplePrompt(AiActionType aiActionType) { return new AiPromptbausteinPromptDC() { - Oid = -5, + Oid = -101, Description = "Beispielbeschreibung", Title = "Beispieltitel", Prompt = "Beispielprompt", diff --git a/Shared/DataContracts/AiPromptbausteinPromptDC.cs b/Shared/DataContracts/AiPromptbausteinPromptDC.cs index 947576f26..e95c534c4 100644 --- a/Shared/DataContracts/AiPromptbausteinPromptDC.cs +++ b/Shared/DataContracts/AiPromptbausteinPromptDC.cs @@ -1,11 +1,12 @@ using BS.Shared.DataContracts.Compact; +using BS.Shared.Interface; using System; using System.Runtime.Serialization; namespace BS.Shared.DataContracts { [DataContract] - public class AiPromptbausteinPromptDC : BeWoDataContract + public class AiPromptbausteinPromptDC : BeWoDataContract, IAiPromptbausteinPrompt { [DataMember] public string Title { get; set; } [DataMember] public string Description { get; set; } diff --git a/Shared/Interface/IAiPromptbausteinPrompt.cs b/Shared/Interface/IAiPromptbausteinPrompt.cs new file mode 100644 index 000000000..6de829fb6 --- /dev/null +++ b/Shared/Interface/IAiPromptbausteinPrompt.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BS.Shared.Interface +{ + public interface IAiPromptbausteinPrompt + { + string Prompt { get; set; } + } +} diff --git a/Shared/Shared.csproj b/Shared/Shared.csproj index 066c7cd64..57581d621 100644 --- a/Shared/Shared.csproj +++ b/Shared/Shared.csproj @@ -422,6 +422,7 @@ + diff --git a/Shared/Text/AiPromptbausteineTexts.cs b/Shared/Text/AiPromptbausteineTexts.cs index a25afb5b7..cabc4e5eb 100644 --- a/Shared/Text/AiPromptbausteineTexts.cs +++ b/Shared/Text/AiPromptbausteineTexts.cs @@ -14,5 +14,7 @@ namespace BS.Shared.Text public static string SharedBibNodeDescription => "Hier sehen Sie Prompts, welche von Ihren Kollegin"; public static string PublicBibNodeTitle => "Öffentlich"; public static string PublicBibNodeDescription => "Hier sehen Sie öffentliche Prompts"; + public static string OwnsoftBibNodeTitle => "Ownsoft"; + public static string OwnsoftBibNodeDescription => "Hier können Sie vordefinierte Prompts sehen"; } }