From 25a099c6ef2dfa2b187ea758e5be0bd152730d21 Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Mon, 3 Aug 2026 15:03:43 -0500 Subject: [PATCH] =?UTF-8?q?LIA:=20historial=20de=20conversaci=C3=B3n=20y?= =?UTF-8?q?=20prompt=20que=20no=20fuerza=20brevedad?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cada pregunta se enviaba sola, sin los intercambios previos, así que un seguimiento del tipo "¿y de esos cuántos en la mañana?" no tenía contexto. Ahora el dashboard acumula los últimos 4 intercambios y los envía; el backend los valida y antepone a la pregunta actual (recortados para no inflar el consumo). El prompt pedía "responde de forma concisa" en todos los casos, lo que sumado al tope de tokens producía respuestas cortadas. Ahora ajusta el detalle a lo que pide la pregunta y sabe que tiene historial disponible. Co-Authored-By: Claude Opus 5 --- modules/turnero/api/ai_chat.php | 23 ++++++++++++++++++----- modules/turnero/views/dashboard.php | 7 ++++++- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/modules/turnero/api/ai_chat.php b/modules/turnero/api/ai_chat.php index ba1035b..e63ccf2 100644 --- a/modules/turnero/api/ai_chat.php +++ b/modules/turnero/api/ai_chat.php @@ -1,7 +1,7 @@ 800) jsonError('Pregunta demasiado larga', 400); +// Historial de la conversación, para que LIA entienda preguntas de seguimiento +// ("¿y de esos cuántos fueron en la mañana?"). Se limita a los últimos turnos +// para no inflar el consumo de tokens en cada llamada. +$historial = []; +foreach (array_slice(is_array($body['historial'] ?? null) ? $body['historial'] : [], -8) as $h) { + $rol = ($h['rol'] ?? '') === 'model' ? 'model' : 'user'; + $texto = trim((string)($h['texto'] ?? '')); + if ($texto === '') continue; + $historial[] = ['role' => $rol, 'parts' => [['text' => mb_substr($texto, 0, 2000)]]]; +} + define('LIA_TOKENS_MAX', 1_000_000); $pdo = db(); @@ -173,9 +184,11 @@ if (!$ses) { // ── Prompt ──────────────────────────────────────────────────── $systemPrompt = << ['parts' => [['text' => $systemPrompt]]], - 'contents' => [ + 'contents' => array_merge($historial, [ ['role' => 'user', 'parts' => [['text' => $pregunta]]] - ], + ]), 'generationConfig' => [ 'temperature' => 0.3, // 600 cortaba a media frase las respuestas largas (listados de turnos, diff --git a/modules/turnero/views/dashboard.php b/modules/turnero/views/dashboard.php index e4afd7f..5a87e6e 100644 --- a/modules/turnero/views/dashboard.php +++ b/modules/turnero/views/dashboard.php @@ -393,6 +393,7 @@ const API = 'modules/turnero/api/'; const BASE_WA = ''; let _turnos = []; // cache para búsqueda local let _autoReloadId = null; +let _liaHistorial = []; // últimos intercambios con LIA (contexto de seguimiento) // ── Entrada ────────────────────────────────────────────────── document.addEventListener('DOMContentLoaded', () => { @@ -874,13 +875,17 @@ async function enviarIA() { const res = await fetch(`${API}ai_chat.php`, { method: 'POST', headers: {'Content-Type':'application/json'}, - body: JSON.stringify({ pregunta }), + body: JSON.stringify({ pregunta, historial: _liaHistorial }), }); const d = await res.json(); typing.className = 'ai-msg bot'; if (d.ok) { typing.innerHTML = mdToHtml(d.respuesta); hablarIA(d.respuesta); + // Guardar el intercambio para que las preguntas de seguimiento tengan contexto + _liaHistorial.push({ rol: 'user', texto: pregunta }); + _liaHistorial.push({ rol: 'model', texto: d.respuesta }); + if (_liaHistorial.length > 8) _liaHistorial = _liaHistorial.slice(-8); if (d.tokens_max) _actualizarTokens(d.tokens_usados, d.tokens_max); } else { typing.textContent = d.error || 'Error al conectar con la IA';