using BeWo.Core; using BeWo.Core.Commands; using BeWo.ServiceProxy; using BS.Shared; using BS.Shared.Core; using BS.Shared.DataContracts; using BS.Shared.DataContracts.Feature.AI; using BS.Shared.Extensions; using ChatController.Utilities.Extensions; using DevExpress.Mvvm; using DevExpress.Xpf.Editors; using DevExpress.XtraPrinting.Native; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; using System.Runtime.Remoting.Contexts; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Data; using System.Windows.Input; using System.Windows.Markup; using System.Windows.Threading; namespace BeWo.ViewModel.ListViewModel { public class AiConversationListVM : AbstractDCListMapperVM { private bool _IsSettingsOpen; private bool _IsCloneOpen; private bool _IsSending; private string _MessageInput; private string _ContextInput; private AiModelDC _SelectedModel; private AiConfigVM _Config; public AiConversationListVM() : this(null) { if (BeWoApp.IsInDesignMode) { InitDesigner(); } } public AiConversationListVM(List pDCs) : base(pDCs) { Models = new BS.Shared.Core.ObservableSortCollection(); bool sendCanExecute() => SelectedVM is object && !string.IsNullOrWhiteSpace(MessageInput) && !IsSending; SendNewMessageCommand = new DelegateCommand(SendNewMessage, sendCanExecute); OpenNewConversationCommand = new DelegateCommand(OpenNewConversation, () => BeWoApp.HasLoggedOnUserRight(UserRightType.AiModuleChatAdd)); bool startconvCanExecute() => !string.IsNullOrWhiteSpace(MessageInput) && !IsSending; StartConversationWithMessageCommand = new DelegateCommand(StartConversationWithMessage, startconvCanExecute); ReloadConfigCommand = new DelegateCommand(ReloadConfig); ReloadConversationsCommand = new DelegateCommand(ReloadConversations); ReloadModelsCommand = new DelegateCommand(ReloadModels); bool openCanExecute() => (BeWoApp.AppSettings?.ModuleAiSettingsEnabled ?? true) && BeWoApp.HasLoggedOnUserRight(UserRightType.AiModuleViewSetting); OpenSettingCommand = new DelegateCommand(OpenSetting, openCanExecute, false); OpenCloneCommand = new DelegateCommand(OpenClone, () => BeWoApp.HasLoggedOnUserRight(UserRightType.AiModuleChatClone) && SelectedVM is object); CloneCommand = new DelegateCommand(Clone); AskDeleteCommand = new DelegateCommand(AskDelete, () => BeWoApp.HasLoggedOnUserRight(UserRightType.AiModuleChatDelete) && SelectedVM is object); SelectedVMChanged += (s, e) => FirePropertyChanged(nameof(IsNewConversationVisible)); } public event EventHandler SendNewMessageSuccess; public DelegateCommand SendNewMessageCommand { get; set; } public DelegateCommand OpenNewConversationCommand { get; set; } public DelegateCommand StartConversationWithMessageCommand { get; set; } //public DelegateCommand RequestNewConversationCommand { get; set; } //public DelegateCommand TestCommand { get; set; } public DelegateCommand AskDeleteCommand { get; set; } public DelegateCommand ReloadConfigCommand { get; set; } public DelegateCommand ReloadConversationsCommand { get; set; } public DelegateCommand ReloadModelsCommand { get; set; } public DelegateCommand OpenSettingCommand { get; set; } public DelegateCommand OpenCloneCommand { get; set; } public DelegateCommand CloneCommand { get; set; } public ObservableCollection Models { get; set; } public AiModelDC SelectedModel { get { return _SelectedModel; } set { if (_SelectedModel == value) return; _SelectedModel = value; FirePropertyChanged(nameof(SelectedModel)); } } public AiConfigVM Config { get { return _Config; } set { if (Config == value) return; _Config = value; FirePropertyChanged(nameof(Config)); } } public string MessageInput { get { return _MessageInput; } set { if (MessageInput == value) return; _MessageInput = value; FirePropertyChanged(nameof(MessageInput)); } } public string ContextInput { get { return _ContextInput; } set { if (ContextInput == value) return; _ContextInput = value; FirePropertyChanged(nameof(ContextInput)); } } public bool IsSettingsOpen { get => _IsSettingsOpen; set { _IsSettingsOpen = value; FirePropertyChanged(nameof(IsSettingsOpen)); } } public bool IsCloneOpen { get => _IsCloneOpen; set { _IsCloneOpen = value; FirePropertyChanged(nameof(IsCloneOpen)); } } public bool IsSending { get => _IsSending; set { _IsSending = value; FirePropertyChanged(nameof(IsSending)); } } public bool IsNewConversationVisible => SelectedVM is null; public int UIContext { get; set; } public long? ReferenceObjectOid { get; set; } public Dictionary ContextBeWoObjects { get; set; } private void StartConversationWithMessage() { StartSending(); try { var message = MessageInput; var conv = new AiConversationDC(); conv.Created = DateTime.Now; conv.Updated = DateTime.Now; conv.UIContext = UIContext; conv.ContextBeWoObjects = ContextBeWoObjects; conv.Messages = new List() { new AiConversationMessageDC() { Message = message, Role = AiConversationMessageRole.User } }; var vm = InsertConverstion(conv); ServiceFacade.DoAiEnhancedServiceAsnyc( x => x.CreateAiConversationWithMessage(conv, Config.SelectedModel.Oid.Value, message), dc => UpdateConverstion(vm, dc), e => EndSending()); } catch(Exception ex) { EndSending(); } } private void OpenNewConversation() { SelectedVM = null; } private void SendNewMessage() { StartSending(); try { var conv = SelectedVM; var msg_dc = new AiConversationMessageDC(); msg_dc.Message = MessageInput; msg_dc.Role = AiConversationMessageRole.User; msg_dc.Created = DateTime.Now; var msg_vm = new AiConversationMessageVM(msg_dc); conv.Messages.VMList.Add(msg_vm); ServiceFacade.DoAiEnhancedServiceAsnyc( x => x.SendNewMessage(conv.DataContract.Oid.Value, MessageInput), (messages) => { if (messages.Count != 2) throw new InvalidOperationException("message count: " + messages.Count); msg_vm.DataContract = messages[0]; conv.Messages.VMList.Add(new AiConversationMessageVM(messages[1])); MessageInput = string.Empty; EndSending(); SendNewMessageSuccess?.Invoke(this, EventArgs.Empty); }, (exception) => { conv.Messages.VMList.Remove(msg_vm); EndSending(); } ); } catch (Exception ex) { EndSending(); } } private void StartSending() { if (IsSending) throw new InvalidOperationException("Sendet bereits"); IsSending = true; } private void EndSending() { if (!IsSending) throw new InvalidOperationException("Sendet nicht"); IsSending = false; } private void Test() { throw new NotImplementedException(); //var limit = 5; //var models = ServiceFacade.DoOperationsEnhancedServiceSnyc(x => x.GetAiModels()); //Models.MakeEqualTo(models); //VMList.Clear(); //foreach (var vm in Models) //{ // var dc = new AiConversationDC(); // dc.Created = DateTime.Now; // dc.Displayname = "Example"; // dc.Modell = vm.ToString(); // var pvm = new AiConversationVM(dc); // VMList.Add(pvm); //} //var msg = "Wie alt ist Frau Müller?"; //var context = "Frau Müller wurde am 1.1.1950 geboren. Aktuelle haben wir folgende Universalzeit: " + DateTime.Now.ToUniversalTime(); //for (var i = 0; i < limit; i++) //{ // foreach (var vm in VMList) // { // ServiceFacade.DoOperationsEnhancedServiceAsnyc(x => x.SendNewMessage(vm.CommitToDataContract(), context, msg), (message) => // { // vm.Messages.VMList.Add(new AiConversationMessageVM(message)); // }); // } //} } private AiConversationVM InsertConverstion(AiConversationDC dc) { var vm = new AiConversationVM(dc); VMList.Insert(0, vm); SelectedVM = vm; return vm; } private void UpdateConverstion(AiConversationVM vm, AiConversationDC dc) { vm.UpdateByDataContract(dc); MessageInput = string.Empty; EndSending(); SendNewMessageSuccess?.Invoke(this, EventArgs.Empty); } private void ReloadConfig() { ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.GetAiConfig(), (x) => { if (Config is null) Config = new AiConfigVM(x); else Config.Update(x); }); } public void UpdateConfig() { if (!Config.IsDirty) return; ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.UpdateAiConfig(Config.CommitToDataContract()), (x) => { Config.Update(x); }); } private void ReloadModels() { ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.GetAiModels(), (x) => { Models.MakeEqualTo(x); if (Config.SelectedModel is null && Models.Any()) Config.SelectedModel = Models.First(); }); } private void ReloadConversations() { var ui_context = UIContext; var reference = ReferenceObjectOid; ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.GetAiConversations(ui_context, reference), (x) => { x.Reverse(); var vms = new AiConversationListVM(x); VMList.MakeEqualTo(vms.VMList); }); } private void OpenSetting() { ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.GetAiModels(), (x) => { Models.MakeEqualTo(x); IsSettingsOpen = true; }); } private void OpenClone() { foreach (var message in SelectedVM.Messages.VMList) { message.IsChecked = true; } IsCloneOpen = true; } private void Clone() { var conv = SelectedVM; AiConversationMessageVM last = null; foreach (var msg in conv.Messages.VMList) { if (!msg.IsChecked) break; last = msg; } var conv_oid = conv.DataContract.Oid.Value; var msg_oid = last?.DataContract.Oid; ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.CloneAiConversation(conv_oid, msg_oid), dc => { InsertConverstion(dc); CloseClone(); }); } private void CloseClone() { IsCloneOpen = false; } public void AskDelete() { var selected = SelectedVM; var oid = selected.DataContract.Oid.Value; var msg = $"Wollen Sie die ausgewählte Konversation ({oid}) löschen?"; if (MessageBox.Show(msg, "Konversation löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes) { ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.DeleteAiConversation(oid), () => { VMList.Remove(selected); CommandManager.InvalidateRequerySuggested(); //SelectedVM = VMList.FirstOrDefault(); }); } } #region Designer private void InitDesigner() { var model = new AiModelDC() { ModelName = "N llama3.2" }; var message_dc = new AiConversationMessageDC() { Created = DateTime.Now, Message = "Nu bist eine intelligente Einheit mit ganz ganz vielen Eingaben: value1, value2, value3, value4\r\nTest", Role = BS.Shared.AiConversationMessageRole.System }; var message_dc2 = new AiConversationMessageDC() { Created = DateTime.Now, Message = "N. Dies ist eine Design Frage: Du sollst ganz viele Sachen machen. Dabei sollst du auf ganz viele Sachen achten: Zum Beispiel:\r\nSache 1\r\nSchritt 2", Role = BS.Shared.AiConversationMessageRole.User }; var message_dc3 = new AiConversationMessageDC() { Created = DateTime.Now, Message = "N. Deine Antwort. Dies ist eine Design Antwort. Du hast ganz viele Sachen angefragt. Dabei soll ich auf ganz viele Sachen achten. Wie Test, test, tEst und tesT.\r\nTest\r\nTest\r\nTest", Role = BS.Shared.AiConversationMessageRole.Assistent, ModelName = model.ModelName, Duration = 10, }; var messages_dc = new List() { message_dc, message_dc2, message_dc3, message_dc2, message_dc3, message_dc2, message_dc3, message_dc2, message_dc3, }; var conversation_dc = new AiConversationDC() { Created = DateTime.Now, Displayname = "Displayname Megamegalange Deluxe Op 3000", Messages = messages_dc, Modell = model, UIContext = 19, Updated = DateTime.Now, }; var conversation_vm = new AiConversationVM(conversation_dc); VMList.Add(conversation_vm); InitDummyConversations(10); //SelectedVM = conversation_vm; } private void InitDummyConversations(int count) { var model = new AiModelDC() { ModelName = "llama3.2" }; for (int i = 0; i < count; i++) { var conversation_dc2 = new AiConversationDC() { Created = DateTime.Now, Displayname = "Dummy Num " + i.ToString(), Modell = model, UIContext = 19, Updated = DateTime.Now, }; var conversation_vm2 = new AiConversationVM(conversation_dc2); VMList.Add(conversation_vm2); } } #endregion } }