Academia Deltamontero · Documentación
Desarrollolocal_deltamodules

Asistente de IA

Cómo se integra el chat de IA (local_ai_manager y block_ai_chat) con el código propio - perfil del usuario, agente de acciones, niveles de cuota, autor de preguntas y Configuración IA.

El chat de IA de la Academia combina dos plugins de terceros con código propio:

PiezaOrigenPapel
local_ai_manager (v1.1)TerceroProxy hacia el proveedor (instancias, propósitos, cuotas por nivel, aceptación de términos por usuario en local_ai_manager_userinfo).
block_ai_chat (v1.0)TerceroInterfaz del chat (botón flotante ✦ y ventana).
ai_role_injectorlocal_deltamodulesAgrega al mensaje de sistema el perfil real del usuario.
ai_agentlocal_deltamodulesAgente de acciones con llamadas a funciones para quien gestiona.
ai_tierslocal_deltamodulesNivel de cuota según el perfil.
ai_authorlocal_deltamodulesPropone objetivos y preguntas al crear un módulo desde un documento (Importador).
policieslocal_deltamodulesCondiciones de uso del Asistente (Políticas y aceptaciones).

Proveedor

configure-ai-groq.php configura una instancia del conector chatgpt de local_ai_manager apuntando a la API compatible con OpenAI de Groq, con el modelo openai/gpt-oss-20b y la clave tomada de la variable GROQ_API_KEY. Es idempotente (actualiza la instancia existente en vez de duplicarla). moodle-config.sh lo ejecuta en cada despliegue como paso critico cuando GROQ_API_KEY está definida, antes de las cuotas de IA: cambiar la clave en Coolify y hacer Redeploy basta. Sin la variable, el paso no corre y se conservan la instancia y la clave guardadas en la base de datos; si se ejecuta a mano sin la variable, también conserva la clave ya guardada. configure-ai-manager.php es el script anterior para Gemini (clave GEMINI_API_KEY). Las clases propias localizan la instancia buscando el conector chatgpt con un endpoint que contenga groq, o la instancia llamada "Chat IA - Academia Deltamontero".

Perfil del usuario en el chat: ai_role_injector

El parche patch-ai-role-injection.php inserta en local_ai_manager/classes/external/submit_query.php, justo después de decodificar $options, una llamada a ai_role_injector::inject($options).

inject() busca el perfil delta_* del usuario (primero en contexto de sistema, luego en cualquier curso; el más reciente) y agrega al mensaje con sender = 'system' de options['conversationcontext'] un bloque de contexto con la descripción del perfil (ROLE_LABELS) e instrucciones: responder si su perfil le permite o no una acción, sin remitirlo a otro rol y sin conceder accesos. Si no hay mensaje de sistema, lo crea. No actúa con invitados ni sin perfil.

Agente de acciones: ai_agent

El parche patch-ai-agent.php agrega, después del bloque anterior, un cortocircuito: si ai_agent::maybe_handle($prompt, $options, $contextid) devuelve texto, submit_query responde ese texto; si devuelve null, sigue el chat informativo normal.

Regla de diseño del código: la IA propone, Moodle dispone. Cada herramienta se ejecuta como el usuario conectado, vuelve a validar sus capacidades en el servidor y nunca hace más de lo que esa persona podría hacer a mano.

ConstanteValor
GATE_CAPmoodle/user:create (sin ella, el agente no actúa y responde el chat normal)
AGENT_MODELopenai/gpt-oss-120b (el comentario explica que el modelo de 20b fallaba la validación del esquema al crear)
AGENT_TEMPERATURE0.1
MAX_ITERATIONS5 vueltas del ciclo de herramientas

Herramientas

HerramientaTipoCapacidad exigida
buscar_usuarioLecturaGATE_CAP
avance_de_usuarioLecturaGATE_CAP
pendientes_de_cursoLecturaGATE_CAP
generar_reporte (usuarios, avance de un curso, certificados; filtros y agrupación de una lista blanca)LecturaGATE_CAP
reporte_formacion (los reportes de la página Reportes, con descarga)Lecturalocal/deltamodules:viewreports
menu_reportesLecturalocal/deltamodules:viewreports
guia_crear_usuarioGuíamoodle/user:create
crear_colaboradorEscrituramoodle/user:create (usa staff_manager::create)
asignar_cargoEscrituramoodle/user:create
asignar_cedulaEscrituramoodle/user:update
matricular_en_cohorteEscrituramoodle/cohort:assign
resetear_contrasenaEscrituramoodle/user:update

Salvaguardas

  • Confirmación determinista: una escritura nunca se ejecuta porque lo pida el modelo. Se muestra un resumen y la acción queda en $SESSION->deltaagent_pending; solo si el siguiente mensaje del usuario es afirmativo (is_affirmative) el código la ejecuta directamente.
  • Cuentas protegidas (target_denied): la propia cuenta, los super administradores y, si quien pide no es super administrador, las cuentas de gestión no se modifican desde el chat.
  • Credenciales: la contraseña temporal la muestra el código (credentials_box), no el texto del modelo. Si el correo está configurado, al crear un colaborador no se muestra contraseña: se envía el correo de activación.
  • Postulantes: reciben siempre "El asistente de IA no está disponible durante el proceso de selección" (además el botón del chat está oculto para ellos).
  • Atajos sin modelo: pedir crear un usuario sin datos muestra la guía de campos y cargos; pedir "un reporte" sin precisar muestra el menú de reportes; responder solo un formato ("en PDF") devuelve el archivo del último reporte ($SESSION->deltaagent_report_last).
  • Datos personales ocultos al proveedor: ver la sección siguiente.

Cédulas, RUC y correos fuera del proveedor (pii_hide y pii_restore)

Antes de enviar nada a Groq, el agente reemplaza en el texto los datos identificativos por marcadores:

DatoDetecciónMarcador
CédulaNúmero de 10 dígitosCEDULA_1, CEDULA_2…
RUCNúmero de 13 dígitosRUC_1, RUC_2…
CorreoDirección de correo electrónicocorreo1@dato.oculto, correo2@dato.oculto…
  • pii_hide() se aplica al mensaje actual, a cada mensaje del historial (build_messages) y al resultado de cada herramienta antes de devolverlo al modelo. El mismo dato recibe siempre el mismo marcador.
  • La tabla marcador → dato real vive solo en la sesión de la plataforma ($SESSION->deltaagent_pii); no se guarda en la base de datos ni se envía al proveedor.
  • pii_restore() devuelve el dato real en dos puntos: en los argumentos de cada herramienta al inicio de run_tool (para que la búsqueda, la creación o la asignación de cédula usen el dato verdadero) y en la respuesta final que ve la persona. Reemplaza primero los marcadores más largos (CEDULA_10 antes que CEDULA_1).
  • El mensaje de sistema del agente y las descripciones de las herramientas crear_colaborador y asignar_cedula le indican al modelo que los marcadores son datos válidos y que debe pasarlos tal cual.
  • Los nombres sí viajan al proveedor: hacen falta para buscar a las personas y para responder.

El reemplazo lo hace el agente de acciones. Si el agente no usa ninguna herramienta en su primera vuelta (consulta informativa) o la persona no tiene moodle/user:create, responde el chat normal de local_ai_manager, que envía el mensaje tal como se escribió. Por eso las condiciones de uso siguen pidiendo no escribir datos personales de terceros en el chat.

Niveles de cuota: ai_tiers

NivelConstantePerfilesCuota del propósito chat
Sin límiteUNLIMITED = 3delta_socios, delta_jefaturas, delta_a1_operacionesSin tope
AmpliadoEXTENDED = 2delta_gerentes, delta_jefatura_tecnica, delta_a3, delta_a2_rrhh60 mensajes por día
BásicoBASIC = 1delta_operativo, delta_operativo_tecnico, delta_operativo_backof, delta_auxiliares, delta_pasante15 mensajes por día

Las cuotas (chat_max_requests_basic, chat_max_requests_extended, periodo de 86.400 s) las fija configure-ai-quotas-and-persona.php en cada despliegue, que además crea la "persona" plantilla del chat con el mensaje de sistema de la Academia y llama a ai_tiers::apply_all().

ai_tiers::apply_user($userid) toma el nivel más alto de los perfiles de la persona. Si no tiene fila en local_ai_manager_userinfo, la crea con ese nivel sin aceptar los términos por ella. Si el nivel actual lo puso este código (registro en la configuración aitier_applied), lo actualiza; si lo cambió una persona en Configuración IA, lo respeta. Nunca desbloquea a alguien bloqueado a mano. Se llama también desde staff_manager::assign_cargo().

Otros ajustes del chat

AjusteDónde
Chat visible en todas las páginas para todosParche patch-ai-chat-everywhere.php (alcance por defecto SCOPE_EVERYWHERE) y configure-ai-chat-global.php (showonpagetypes = * del bloque)
Sin chat sin sesión o como invitadohook_callbacks::before_head agrega CSS que oculta el botón y la ventana
Sin chat durante un examen ni sobre el reproductor de videoCSS en additionalhtmlhead
Copiar respuesta también por HTTPParche patch-ai-chat-copy.php
Nombre, ids y límite diario disponibles para el JavaScript propio; contexto de 50 mensajesParche patch-ai-chat-ui.php
Historial que se envía al modelo: mínimo 50 mensajesPaso de moodle-config.sh que actualiza block_ai_chat_options.historycontextmax
Ventana flotante a la derecha, saludo, títulos, borrado por conversación, chat nuevo por sesiónJavaScript y CSS inline en additionalhtmlhead (ver Interfaz global)
Activación automática cuando no se exige aceptar las condicioneshook_callbacks::before_http_headers marca como confirmado (una vez por sesión, $SESSION->deltaaiauto) a quien no es postulante
La página de términos de local_ai_managerRedirige a aiterms.php

Configuración IA: aiconfig.php

Administración del sitio → Configuración IA (categoría propia creada en settings.php si existe local/ai_manager/tenant_config.php), capacidad local/ai_manager:manage. Pestañas:

PestañaContenido
resumenActivar o desactivar el Asistente para todos (tenantenabled de local_ai_manager), pedir o no la aceptación de las condiciones, estado de condiciones y aceptaciones.
condicionesEditar el resumen y el acuerdo completo; publicar una versión nueva.
aceptacionesQuién aceptó y quién falta, con descarga en Excel.
tecnicoAccesos a las páginas de local_ai_manager (proveedor y modelo, propósitos, límites, estadísticas).

El agente MCP de administración (servicio delta_ai_mcp_ro con el usuario mcpservice) es un canal distinto del chat de usuarios: se describe en Servicios web.

En esta página