LIA: historial de conversación y prompt que no fuerza brevedad
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 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
b1a8b1abf8
commit
25a099c6ef
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
/**
|
||||
* modules/turnero/api/ai_chat.php
|
||||
* POST { pregunta: string }
|
||||
* POST { pregunta: string, historial?: [{rol:'user'|'model', texto:string}, ...] }
|
||||
* Llama a Gemini Flash con contexto completo del turnero del día.
|
||||
*/
|
||||
require_once __DIR__ . '/_helpers.php';
|
||||
@@ -14,6 +14,17 @@ $pregunta = trim($body['pregunta'] ?? '');
|
||||
if ($pregunta === '') jsonError('Pregunta vacía', 400);
|
||||
if (mb_strlen($pregunta) > 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 = <<<PROMPT
|
||||
Eres el asistente inteligente del sistema de turnero del Laboratorio Clínico.
|
||||
Responde de forma concisa y útil en español. Puedes analizar: tiempos de espera y servicio por paciente, recepcionista o bacteriólogo; facturación del día; exámenes solicitados; franjas horarias con mayor demanda; buscar pacientes por nombre o cédula.
|
||||
Eres LIA, la asistente inteligente del sistema de turnero del Laboratorio Clínico.
|
||||
Responde en español, con el detalle que la pregunta requiera: si te piden un dato puntual sé breve, pero si te piden un listado, un análisis o una comparación, desarróllalo completo. Usa tablas o viñetas cuando ayuden a leer los datos.
|
||||
Puedes analizar: tiempos de espera y servicio por paciente, recepcionista o bacteriólogo; facturación del día; exámenes solicitados; franjas horarias con mayor demanda; buscar pacientes por nombre o cédula.
|
||||
Solo usa la información del contexto proporcionado. Si no tienes el dato, dilo claramente.
|
||||
Tienes el historial de esta conversación: si el usuario pregunta algo que se refiere a tu respuesta anterior, respóndelo sin pedir que repita el contexto.
|
||||
|
||||
CONTEXTO DEL DÍA:
|
||||
{$ctx}
|
||||
@@ -184,9 +197,9 @@ PROMPT;
|
||||
// ── Llamada a Gemini Flash ────────────────────────────────────
|
||||
$payload = json_encode([
|
||||
'system_instruction' => ['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,
|
||||
|
||||
@@ -393,6 +393,7 @@ const API = '<?= BASE_URL ?>modules/turnero/api/';
|
||||
const BASE_WA = '<?= BASE_URL ?>';
|
||||
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';
|
||||
|
||||
Reference in New Issue
Block a user