AiFullTab/Src/Tlg/TlgReciber.mqh
Nique_372 f214332240
2026-07-17 17:20:14 -05:00

407 lines
12 KiB
MQL5

//+------------------------------------------------------------------+
//| 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 <TSN\\MQLArticles\\Utils\\Basic.mqh>
#include <TSN\\LLM\\Main.mqh>
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
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
//+------------------------------------------------------------------+