//+------------------------------------------------------------------+ //| TlgReciber.mqh | //| Copyright 2025, Niquel Mendoza. | //| https://www.mql5.com/es/users/nique_372 | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, Niquel Mendoza." #property link "https://www.mql5.com/es/users/nique_372" #property strict #ifndef AIFULLTAB_SRC_TLG_TLGRECIBER_MQH #define AIFULLTAB_SRC_TLG_TLGRECIBER_MQH //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ #include "Def.mqh" #include "..\\..\\..\\TelegramByLeo\\Telegram.mqh" #include #include //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ namespace TSN { //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CEasyTokCounter : public ILLmTokensCounter { public: CEasyTokCounter(void) {} ~CEasyTokCounter(void) {} int Count(const string& text) override final { return StringLen(text) >> 2; }// 4 aprox }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CChatTelegramBase : public CTlgFullBot { protected: //--- bool m_init; long m_chart_id_padre; double m_key; const long m_chart_id; //--- CAgentBase* m_agent; CLLmToolsManager* m_tools; CEasyTokCounter m_tok; //--- bool m_in_execution; bool m_first; //--- virtual bool OnBeforeSetTools() = 0; public: CChatTelegramBase(); ~CChatTelegramBase(void); //--- bool Init(const long chart_id_padre, double key, const string& system_promt, const string& prompt_to_resume, const string& db_folder, bool comon); //--- void ProcessMessages() override final; //--- void OnTimerEvent(); //--- void ChartEvent(const int32_t id, const long& lparam, const double& dparam, const string& sparam); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CChatTelegramBase::CChatTelegramBase() : m_chart_id_padre(-1), m_in_execution(false), m_init(false), m_key(-1.0), m_first(false), m_chart_id(ChartID()), m_agent(NULL), m_tools(NULL) { } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CChatTelegramBase::~CChatTelegramBase(void) { //--- if(CheckPointer(m_agent) == POINTER_DYNAMIC) { delete m_agent; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CChatTelegramBase::Init(const long chart_id_padre, double key, const string& system_promt, const string& prompt_to_resume, const string& db_folder, bool comon) { //--- if(m_init) return true; //-- Consutrccion inicial m_agent = LlmAgentsByLeo_CreateGroqAgent(); m_tools = LlmAgentsByLeo_CreateGroqToolManager(); //--- m_agent.SetSystemPromt(system_promt); m_agent.SetPromtResume(prompt_to_resume); //--- m_agent.SetTools(m_tools); m_agent.ToolsDeleteInDestructor(true); m_agent.SetTokCounter(&m_tok); m_agent.TokCounterDelInConstructor(false); m_agent.GetParametersModel().Set("reasoning_format", "hidden", 0); //--- if(!m_agent.OpenSqlDbModels(db_folder, comon)) { return false; } //--- parametros por defecto... /* La idea e sque al inicar solo hagmaos lo basico luego el user antes de conectar telegram debera de configurar todo m_agent.GetParametersModel().Set("model", "qwen/qwen3-32b", 0); m_agent.GetParametersModel().Set("max_completion_tokens", long(1024)); */ //--- m_chart_id_padre = chart_id_padre; m_key = key; m_tools.InitializeToolBuild(); //--- Cargar todas las tools con esquema y todo.. if(!OnBeforeSetTools()) return false; //--- if(!m_tools.FinishToolBuild()) { LogError("Fallo al finalizar build de json tools", FUNCION_ACTUAL); return false; } //--- m_init = true; //--- return true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CChatTelegramBase::ChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { //--- //dparam = key //soaram = valor //lparam = parametro if(id == CHARTEVENT_CUSTOM + CHATELGRAM_E_ON_CHANGE_PARAM && fabs(dparam - m_key) < 0.10) { switch(uint8_t(lparam)) { case TLGM_RECIBER_PARAM_TOKEN: { if(Token(sparam) != 0) { FastLog(FUNCION_ACTUAL, FATAL_ERROR_TEXT, "No se pudo cambiar el Token del bot"); } break; } case TLGM_RECIBER_PARAM_CHATID: { PermitedChats().Clear(); PermitedChats().Add(long(sparam)); break; } case TLGM_RECIBER_PARAM_APIKEY: { m_agent.ApiKey(sparam); break; } case TLGM_RECIBER_PARAM_MODELNAME: { m_agent.GetParametersModel().Set("model", sparam, 0); //--- if(!m_agent.GetInfoModel()) { LogError("Fallo al traer data del modelo modelo", FUNCION_ACTUAL); LogWarning("Ingrese su api key y vuelva a modifcar quizas quitar agregar un espacio para que se recuaalr la ventana de contexto", FUNCION_ACTUAL); } if((m_agent.Flags()&LLMDEF_FLAG_REASONING) != 0) { // Si tiene lo ocultamos m_agent.GetParametersModel().Set("reasoning_format", "hidden", 0); } else { // Lo quitamos en caso no lo soporte.. m_agent.GetParametersModel().Remove("reasoning_format"); } m_agent.SetCompactMarginExtra(10.0); // 10 break; } case TLGM_RECIBER_PARAM_MAXTOKENS: { m_agent.GetParametersModel().Set("max_completion_tokens", long(sparam)); break; } case TLGM_RECIBER_PARAM_CONFIG: { //--- string arr[2]; if(StringSplit(sparam, '|', arr) != 2) { FastLog(FUNCION_ACTUAL, FATAL_ERROR_TEXT, "Fallo al hacer split de config"); return; } //--- CJsonParser* parser = m_agent.GetJson(); //--- const string fn = arr[TLGM_RECIBIR_PARAM_CONFIG_IDX_FILENAME]; const int ext = parser.AssingFile(fn, (int(arr[TLGM_RECIBIR_PARAM_CONFIG_IDX_FILEFLAGS])&FILE_COMMON) != 0); //--- if(!parser.AutoParseByFileExt(ext)) { FastLog(FUNCION_ACTUAL, FATAL_ERROR_TEXT, StringFormat("Fallo al parsear json =%s, error=%s", fn, ::EnumToString(parser.LastErr()))); return; } //--- CJsonNode root = parser.GetRoot(); //--- Acutlizamos la ui // Edits bot token Token(root["bot_token"].ToString()); PermitedChats().Clear(); PermitedChats().Add(root["chat_id"].ToInt(0)); //--- const string apikey = root["api_key"].ToString(); m_agent.ApiKey(apikey); m_agent.GetParametersModel().Set("max_completion_tokens", root["max_completion_tokens"].ToInt(0)); //--- m_agent.GetParametersModel().Set("model", root["model_name"].ToString(), 0); //--- if(!m_agent.GetInfoModel()) { LogError("Fallo al traer info del modelo", FUNCION_ACTUAL); } //--- if((m_agent.Flags()&LLMDEF_FLAG_REASONING) != 0) { // Si tiene lo ocultamos m_agent.GetParametersModel().Set("reasoning_format", "hidden", 0); } else { // Lo quitamos en caso no lo soporte.. m_agent.GetParametersModel().Remove("reasoning_format"); } //--- m_agent.SetCompactMarginExtra(10.0); // 10 break; } case TLGM_RECIBER_PARAM_STATE: { m_in_execution = bool(int(sparam)); m_first = true; FastLog(FUNCION_ACTUAL, INFO_TEXT, StringFormat("Telegram esta: %s", (m_in_execution ? "ejecutandose" : "detenido"))); break; } case TLGM_RECIBER_PARAM_SAVE_MEMORY: { //--- string arr[2]; if(StringSplit(sparam, '|', arr) != 2) { FastLog(FUNCION_ACTUAL, FATAL_ERROR_TEXT, "Fallo al hacer split de memory save"); return; } //--- const string fn = arr[TLGM_RECIBIR_PARAM_CONFIG_IDX_FILENAME]; //--- m_agent.SaveChatHistory(fn, (int(arr[TLGM_RECIBIR_PARAM_CONFIG_IDX_FILEFLAGS]))); break; } case TLGM_RECIBER_PARAM_LOAD_MEMORY: { //--- string arr[2]; if(StringSplit(sparam, '|', arr) != 2) { FastLog(FUNCION_ACTUAL, FATAL_ERROR_TEXT, "Fallo al hacer split de memory load"); return; } //--- const string fn = arr[TLGM_RECIBIR_PARAM_CONFIG_IDX_FILENAME]; //--- m_agent.LoadChatHistory(fn, (int(arr[TLGM_RECIBIR_PARAM_CONFIG_IDX_FILEFLAGS]))); break; } default: FastLog(FUNCION_ACTUAL, WARNING_TEXT, StringFormat("Tipo de evento desconocido = %I64d", lparam)); break; } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CChatTelegramBase::ProcessMessages(void) { //Print("first"); for(int i = 0; i < m_chats.Total(); i++) { //--- CCustomChat *chat = m_chats.GetNodeAtIndex(i); m_chat_id = chat.m_id; //--- //Print("si"); if(!chat.m_new_one.done) { chat.m_new_one.done = true; //--- // Print("con"); static string out; if(m_agent.Consultar(chat.m_new_one.message_text, out)) { // Print("wsi"); SendMessage(out, NULL, TELEGRAM_PARSE_MODE_HTML); } } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CChatTelegramBase::OnTimerEvent(void) { //--- if(!m_first) return; // Solo si ya alemons se dio por primera vez //--- reading messages GetUpdates(); //--- if(m_in_execution) { ProcessMessages(); } else { for(int i = 0; i < m_chats.Total(); i++) { //--- CCustomChat *chat = m_chats.GetNodeAtIndex(i); chat.m_new_one.done = true; } } } } #endif // AIFULLTAB_SRC_TLG_TLGRECIBER_MQH //+------------------------------------------------------------------+