From 89154c0223d5505bc458910ad21126b5536dbc20 Mon Sep 17 00:00:00 2001 From: Rene Evertz Date: Wed, 24 Jun 2026 10:47:29 +0200 Subject: [PATCH] =?UTF-8?q?Generischer=20AiSystemPromptBuilder=20->=20Mehr?= =?UTF-8?q?=20=C3=BCber=20SystmePrompt=20File=20steuerbar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BeWo/ViewModel/View/DialogViewModel.cs | 5 - .../customFunctionPreSystemPrompt.txt | 15 +++ .../systemPrompts/customPreSystemPrompt.txt | 13 ++ Server/Components/AICore/AICore.csproj | 1 + .../AICore/Prompt/AiSystemPromptFactory.cs | 17 +-- .../AiConversationSystemPromptBuilder.cs | 115 ++++++++++-------- .../AiFunctionSystemPromptBuilder.cs | 78 ++++++------ .../AiGenericSystemPromptBuilder.cs | 57 +++++++++ .../SystemPrompts/BaseSystemPromptBuilder.cs | 46 ++++++- Service/Plugins/AiService2.cs | 2 +- .../Feature/AI/AiViewContextDC.cs | 3 + 11 files changed, 249 insertions(+), 103 deletions(-) create mode 100644 Server/Components/AICore/Prompt/SystemPrompts/AiGenericSystemPromptBuilder.cs diff --git a/BeWo/ViewModel/View/DialogViewModel.cs b/BeWo/ViewModel/View/DialogViewModel.cs index fdb33a9a2..c926c6d59 100644 --- a/BeWo/ViewModel/View/DialogViewModel.cs +++ b/BeWo/ViewModel/View/DialogViewModel.cs @@ -1,10 +1,5 @@ using DevExpress.Mvvm; using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Input; namespace BeWo.ViewModel.View { diff --git a/Host/Config/ai/systemPrompts/customFunctionPreSystemPrompt.txt b/Host/Config/ai/systemPrompts/customFunctionPreSystemPrompt.txt index 8690091be..fb8d1a772 100644 --- a/Host/Config/ai/systemPrompts/customFunctionPreSystemPrompt.txt +++ b/Host/Config/ai/systemPrompts/customFunctionPreSystemPrompt.txt @@ -9,3 +9,18 @@ Du bist ein hilfreicher Dokumentations-Assistent, der ausschließlich auf die be - Antworte nur basierend auf dem Kontext. Wenn die Antwort nicht im Kontext zu finden ist, sage 'Ich weiß es nicht'. - Antworte nur mit Fakten und Daten aus dem Kontext. Unterlasse Spekulationen, Meinungen oder persönliche Erfahrungen. - Übersetzungen sind erlaubt. + + +--- + +### **Allgemein** +- Aktuelle Zeit: {AktuelleZeit} + +### **Ansicht** +- Ich befinde mich aktuell in der "{AktuellesModule}" meiner Anwendung. +- {FilterEinstellungen} + +### **Daten** +{DatenBlock} + +abs diff --git a/Host/Config/ai/systemPrompts/customPreSystemPrompt.txt b/Host/Config/ai/systemPrompts/customPreSystemPrompt.txt index b8e9cea0b..772818b6d 100644 --- a/Host/Config/ai/systemPrompts/customPreSystemPrompt.txt +++ b/Host/Config/ai/systemPrompts/customPreSystemPrompt.txt @@ -7,3 +7,16 @@ WICHTIG: - Falls die Daten nicht die benötigte Information enthalten, gib an, dass die Daten fehlen, anstatt zu raten. - KEINE Erklärungen, KEIN Fließtext, KEINE zusätzlichen Notizen! - Deine Antwort soll eine direkte und verständliche Antwort für den Nutzer sein. + + +--- + +### **Allgemein** +- Aktuelle Zeit: {AktuelleZeit} + +### **Ansicht** +- Ich befinde mich aktuell in der "{AktuellesModule}" meiner Anwendung. +- {FilterEinstellungen} + +### **Daten** +{DatenBlock} \ No newline at end of file diff --git a/Server/Components/AICore/AICore.csproj b/Server/Components/AICore/AICore.csproj index 99585ad6b..a6d1948fa 100644 --- a/Server/Components/AICore/AICore.csproj +++ b/Server/Components/AICore/AICore.csproj @@ -125,6 +125,7 @@ + diff --git a/Server/Components/AICore/Prompt/AiSystemPromptFactory.cs b/Server/Components/AICore/Prompt/AiSystemPromptFactory.cs index afd91dde5..e56613881 100644 --- a/Server/Components/AICore/Prompt/AiSystemPromptFactory.cs +++ b/Server/Components/AICore/Prompt/AiSystemPromptFactory.cs @@ -1,6 +1,7 @@ using AICore.Context.Summary; using AICore.Prompt.SystemPrompts; using BS.Shared; +using BS.Shared.DataContracts.Feature.AI; using BS.Shared.Exceptions; using System; using System.Collections.Generic; @@ -13,25 +14,27 @@ namespace AICore.Prompt { public class AiSystemPromptFactory { - public static string BuildContext(AiActionType actionType, string prompt_path, BaseContextSummary context, AiDataContextType context_type) + public static string BuildContext(AiActionType actionType, string prompt_path, AiViewContextDC view_context, BaseContextSummary context, AiDataContextType context_type) { switch (actionType) { case AiActionType.ServiceRecord: break; case AiActionType.ServiceRecordConversation: - var factory = new AiConversationSystemPromptBuilder(prompt_path); - var prompt = factory.CreateSystemPrompt(actionType, context, context_type); - return prompt; case AiActionType.ServiceRecordDocumentation: - var factory2 = new AiFunctionSystemPromptBuilder(prompt_path); - var prompt2 = factory2.CreateServiceRecordDocumentationSystemPrompt(context); - return prompt2; + return BuildGenericContext(actionType, prompt_path, view_context, context, context_type); default: break; } throw BeWoNotImplementedException.CreateFromEnum(actionType); } + + public static string BuildGenericContext(AiActionType actionType, string prompt_path, AiViewContextDC view_context, BaseContextSummary context, AiDataContextType context_type) + { + var factory = new AiGenericSystemPromptBuilder(prompt_path); + + return factory.CreateSystemPrompt(actionType, view_context, context, context_type); + } } } diff --git a/Server/Components/AICore/Prompt/SystemPrompts/AiConversationSystemPromptBuilder.cs b/Server/Components/AICore/Prompt/SystemPrompts/AiConversationSystemPromptBuilder.cs index a21fb8682..6674a3d2a 100644 --- a/Server/Components/AICore/Prompt/SystemPrompts/AiConversationSystemPromptBuilder.cs +++ b/Server/Components/AICore/Prompt/SystemPrompts/AiConversationSystemPromptBuilder.cs @@ -2,6 +2,7 @@ using AICore.Context.SummaryParser; using BS.Shared; using BS.Shared.Core; +using BS.Shared.DataContracts.Feature.AI; using BS.Shared.Exceptions; using BS.Shared.Translation; using System; @@ -14,66 +15,74 @@ using System.Text.Json; namespace AICore.Prompt.SystemPrompts { - internal class AiConversationSystemPromptBuilder : BaseSystemPromptBuilder - { - public AiConversationSystemPromptBuilder(string prompt_path) : base(prompt_path) { + //internal class AiConversationSystemPromptBuilder : BaseSystemPromptBuilder + //{ + // public AiConversationSystemPromptBuilder(string prompt_path) : base(prompt_path) { - } + // } - public string CreateSystemPrompt(AiActionType actionType, BaseContextSummary context, AiDataContextType aiDataContextType) - { - var sb = new StringBuilder(); + // public string CreateSystemPrompt(AiActionType actionType, AiViewContextDC view_context, BaseContextSummary context, AiDataContextType aiDataContextType) + // { + // var currentDateTime = DateTime.Now; + // var moduleName = Translations[actionType]; + // var filter = view_context.Filter is string filter_str + // ? $"Es ist folgender Filter gesetzt: {filter_str}" + // : "Es ist kein Filter gesetzt."; - sb.AppendLine(getCustomSystemPrompt()); - sb.AppendLine(); - sb.AppendLine(); - sb.AppendLine("---"); - sb.AppendLine(); - sb.AppendLine("### **Allgemein**"); - sb.AppendLine($"- Aktuelle Zeit: {DateTime.Now}"); - sb.AppendLine(); - sb.AppendLine("### **Ansicht**"); - sb.AppendLine($"- Ich befinde mich aktuell in der \"{Translations[actionType]}\" meiner Anwendung."); - sb.AppendLine($"- Es ist kein Filter gesetzt."); - sb.AppendLine(); - sb.AppendLine("### **Daten**"); + // var context = - if (context?.Context is null) - { - sb.AppendLine("Dir wurden keine Daten bereitgestellt."); - } - else - { - sb.AppendLine("Du erhälst folgende Daten:"); + // var sb = new StringBuilder(); - var parser = GetParser(aiDataContextType); - var parsed = parser.Parse(actionType, context); + // sb.AppendLine(getCustomSystemPrompt()); + // sb.AppendLine(); + // sb.AppendLine(); + // sb.AppendLine("---"); + // sb.AppendLine(); + // sb.AppendLine("### **Allgemein**"); + // sb.AppendLine($"- Aktuelle Zeit: {DateTime.Now}"); + // sb.AppendLine(); + // sb.AppendLine("### **Ansicht**"); + // sb.AppendLine($"- Ich befinde mich aktuell in der \"{Translations[actionType]}\" meiner Anwendung."); + + // sb.AppendLine(); + // sb.AppendLine("### **Daten**"); - sb.AppendLine(parsed); - } + // if (context?.Context is null) + // { + // sb.AppendLine("Dir wurden keine Daten bereitgestellt."); + // } + // else + // { + // sb.AppendLine("Du erhälst folgende Daten:"); - return sb.ToString(); - } + // var parser = GetParser(aiDataContextType); + // var parsed = parser.Parse(actionType, context); - private BaseContextSummaryParser GetParser(AiDataContextType aiDataContextType) - { - switch (aiDataContextType) - { - case AiDataContextType.json: - return new JsonContextSummaryParser(); - case AiDataContextType.csv: - return new CsvContextSummaryParser(); - case AiDataContextType.tsv: - return new CsvContextSummaryParser("\t"); - case AiDataContextType.csv2: - return new CsvContextSummaryParser(";", true); - case AiDataContextType.tsv2: - return new CsvContextSummaryParser("\t", true); - default: - break; - } + // sb.AppendLine(parsed); + // } - throw BeWoNotImplementedException.CreateFromEnum(aiDataContextType); - } - } + // return sb.ToString(); + // } + + // private BaseContextSummaryParser GetParser(AiDataContextType aiDataContextType) + // { + // switch (aiDataContextType) + // { + // case AiDataContextType.json: + // return new JsonContextSummaryParser(); + // case AiDataContextType.csv: + // return new CsvContextSummaryParser(); + // case AiDataContextType.tsv: + // return new CsvContextSummaryParser("\t"); + // case AiDataContextType.csv2: + // return new CsvContextSummaryParser(";", true); + // case AiDataContextType.tsv2: + // return new CsvContextSummaryParser("\t", true); + // default: + // break; + // } + + // throw BeWoNotImplementedException.CreateFromEnum(aiDataContextType); + // } + //} } \ No newline at end of file diff --git a/Server/Components/AICore/Prompt/SystemPrompts/AiFunctionSystemPromptBuilder.cs b/Server/Components/AICore/Prompt/SystemPrompts/AiFunctionSystemPromptBuilder.cs index 6ffb6a3c9..5b1c7dbec 100644 --- a/Server/Components/AICore/Prompt/SystemPrompts/AiFunctionSystemPromptBuilder.cs +++ b/Server/Components/AICore/Prompt/SystemPrompts/AiFunctionSystemPromptBuilder.cs @@ -3,6 +3,7 @@ using AICore.Context.Summary.Function; using AICore.Context.SummaryParser; using BS.Shared; using BS.Shared.Core; +using BS.Shared.DataContracts.Feature.AI; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; @@ -13,46 +14,53 @@ using System.Threading.Tasks; namespace AICore.Prompt.SystemPrompts { - internal class AiFunctionSystemPromptBuilder : BaseSystemPromptBuilder - { - public AiFunctionSystemPromptBuilder(string prompt_path) : base(prompt_path) - { + //internal class AiFunctionSystemPromptBuilder : BaseSystemPromptBuilder + //{ + // public AiFunctionSystemPromptBuilder(string prompt_path) : base(prompt_path) + // { - } + // } - public string CreateServiceRecordDocumentationSystemPrompt(BaseContextSummary context) - { - var sb = new StringBuilder(); + // public string CreateServiceRecordDocumentationSystemPrompt(AiViewContextDC view_context, BaseContextSummary context) + // { + // var sb = new StringBuilder(); - sb.AppendLine(getCustomSystemPrompt()); - sb.AppendLine(); - sb.AppendLine(); - sb.AppendLine("---"); - sb.AppendLine(); - sb.AppendLine("### **Allgemein**"); - sb.AppendLine($"- Aktuelle Zeit: {DateTime.Now}"); - sb.AppendLine(); - sb.AppendLine("### **Ansicht**"); - sb.AppendLine($"- Ich befinde mich aktuell in der \"Zeiterfassung\" meiner Anwendung."); - sb.AppendLine($"- Es ist kein Filter gesetzt."); - sb.AppendLine(); - sb.AppendLine("### **Daten**"); + // sb.AppendLine(getCustomSystemPrompt()); + // sb.AppendLine(); + // sb.AppendLine(); + // sb.AppendLine("---"); + // sb.AppendLine(); + // sb.AppendLine("### **Allgemein**"); + // sb.AppendLine($"- Aktuelle Zeit: {DateTime.Now}"); + // sb.AppendLine(); + // sb.AppendLine("### **Ansicht**"); + // sb.AppendLine($"- Ich befinde mich aktuell in der \"Zeiterfassung\" meiner Anwendung."); + // if(view_context.Filter is string filter_str) + // { + // sb.AppendLine($"- Es ist folgender Filter gesetzt: {filter_str}"); + // } + // else + // { + // sb.AppendLine($"- Es ist kein Filter gesetzt."); + // } + // sb.AppendLine(); + // sb.AppendLine("### **Daten**"); - if (context?.Context is null) - { - sb.AppendLine("Dir wurden keine Daten bereitgestellt."); - } - else - { - sb.AppendLine("Du erhälst folgende Daten:"); + // if (context?.Context is null) + // { + // sb.AppendLine("Dir wurden keine Daten bereitgestellt."); + // } + // else + // { + // sb.AppendLine("Du erhälst folgende Daten:"); - var parser = new CsvContextSummaryParser(); - var parsed = parser.Parse(AiActionType.ServiceRecordDocumentation, context); + // var parser = new CsvContextSummaryParser(); + // var parsed = parser.Parse(AiActionType.ServiceRecordDocumentation, context); - sb.AppendLine(parsed); - } + // sb.AppendLine(parsed); + // } - return sb.ToString(); - } - } + // return sb.ToString(); + // } + //} } \ No newline at end of file diff --git a/Server/Components/AICore/Prompt/SystemPrompts/AiGenericSystemPromptBuilder.cs b/Server/Components/AICore/Prompt/SystemPrompts/AiGenericSystemPromptBuilder.cs new file mode 100644 index 000000000..33d88f498 --- /dev/null +++ b/Server/Components/AICore/Prompt/SystemPrompts/AiGenericSystemPromptBuilder.cs @@ -0,0 +1,57 @@ +using AICore.Context.Summary; +using AICore.Context.SummaryParser; +using BS.Shared.DataContracts.Feature.AI; +using BS.Shared.Exceptions; +using BS.Shared; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Runtime.Remoting.Messaging; + +namespace AICore.Prompt.SystemPrompts +{ + internal class AiGenericSystemPromptBuilder : BaseSystemPromptBuilder + { + public AiGenericSystemPromptBuilder(string prompt_path) : base(prompt_path) + { + + } + + public string CreateSystemPrompt(AiActionType actionType, AiViewContextDC view_context, BaseContextSummary context, AiDataContextType aiDataContextType) + { + var replace_dict = new Dictionary() + { + {"{AktuelleZeit}", DateTime.Now.ToString() }, + {"{AktuellesModule}", Translations[actionType]}, + {"{FilterEinstellungen}", getFilterString(view_context.Filter)}, + {"{DatenBlock}", getContextBlock(actionType, context, aiDataContextType)} + }; + + return createSystemPrompt(replace_dict); + } + + private string getFilterString(object filter) + { + if (filter is null) + return "Es ist kein Filter gesetzt."; + + return $"Es ist folgender Filter gesetzt: {filter}"; + } + + private string getContextBlock(AiActionType actionType, BaseContextSummary context, AiDataContextType aiDataContextType) + { + if (context is null) + { + return "Dir wurden keine Daten bereitgestellt."; + } + + var parser = getParser(aiDataContextType); + var parsed = parser.Parse(actionType, context); + + return $"Du erhälst folgende Daten: {Environment.NewLine}" + + parsed; + } + } +} diff --git a/Server/Components/AICore/Prompt/SystemPrompts/BaseSystemPromptBuilder.cs b/Server/Components/AICore/Prompt/SystemPrompts/BaseSystemPromptBuilder.cs index 759459afe..9768fcf70 100644 --- a/Server/Components/AICore/Prompt/SystemPrompts/BaseSystemPromptBuilder.cs +++ b/Server/Components/AICore/Prompt/SystemPrompts/BaseSystemPromptBuilder.cs @@ -1,4 +1,8 @@ -using BS.Shared; +using AICore.Context.Summary; +using AICore.Context.SummaryParser; +using BS.Shared; +using BS.Shared.DataContracts.Feature.AI; +using BS.Shared.Exceptions; using System; using System.Collections.Generic; using System.IO; @@ -24,7 +28,45 @@ namespace AICore.Prompt.SystemPrompts Path = path; } - protected string getCustomSystemPrompt() + protected string createSystemPrompt(Dictionary replace_dict) + { + var sb = new StringBuilder(); + + sb.AppendLine(getCustomSystemPrompt()); + + foreach (var kvp in replace_dict) + { + var key = kvp.Key; + var value = kvp.Value; + + sb.Replace(key, value); + } + + return sb.ToString(); + } + + protected BaseContextSummaryParser getParser(AiDataContextType aiDataContextType) + { + switch (aiDataContextType) + { + case AiDataContextType.json: + return new JsonContextSummaryParser(); + case AiDataContextType.csv: + return new CsvContextSummaryParser(); + case AiDataContextType.tsv: + return new CsvContextSummaryParser("\t"); + case AiDataContextType.csv2: + return new CsvContextSummaryParser(";", true); + case AiDataContextType.tsv2: + return new CsvContextSummaryParser("\t", true); + default: + break; + } + + throw BeWoNotImplementedException.CreateFromEnum(aiDataContextType); + } + + private string getCustomSystemPrompt() { var path = Path; return File.ReadAllText(path); diff --git a/Service/Plugins/AiService2.cs b/Service/Plugins/AiService2.cs index b79142018..316f4f77c 100644 --- a/Service/Plugins/AiService2.cs +++ b/Service/Plugins/AiService2.cs @@ -391,7 +391,7 @@ namespace BeWo.Service.Plugins var context_loaded = AiContextLoader.LoadContext(actionType, view_context, prompt?.SamplesCount); var configPath = getPromptPath(actionType); - var system_prompt = AiSystemPromptFactory.BuildContext(actionType, configPath, context_loaded, context_Type); + var system_prompt = AiSystemPromptFactory.BuildContext(actionType, configPath, view_context, context_loaded, context_Type); var msg = new AiConversationMessage(); msg.Message = system_prompt; diff --git a/Shared/DataContracts/Feature/AI/AiViewContextDC.cs b/Shared/DataContracts/Feature/AI/AiViewContextDC.cs index f5a23237e..70b5e18f3 100644 --- a/Shared/DataContracts/Feature/AI/AiViewContextDC.cs +++ b/Shared/DataContracts/Feature/AI/AiViewContextDC.cs @@ -16,6 +16,9 @@ namespace BS.Shared.DataContracts.Feature.AI [DataMember] public object Secondary { get; set; } + [DataMember] + public object Filter { get; set; } + [DataMember] public Dictionary References { get; set; } }