Chat Tutor Multi-Turn — bib_ask con historial conversacional
Chat Tutor Multi-Turn — bib_ask con historial conversacional
Resumen
El Chat Tutor Multi-Turn (s55) convierte el modo IT Tutor del Help Widget de CreaRack Pro en un chat conversacional real. Antes de este cambio, cada pregunta al tutor era independiente — el modelo respondía sin ningún contexto de los mensajes previos. A partir de este commit, el handler handleAsk acepta un array history de turnos anteriores y lo inyecta en el prompt del modelo para mantener coherencia conversacional entre mensajes.
Motivación
El Help Widget ofrecía dos modos:
- Help mode: recupera chunks de la wiki interna y responde solo sobre CreaRack Pro.
- IT Tutor mode: responde preguntas generales de IT/Networking/Datacenter desde el conocimiento del modelo, sin grounding por chunks.
El Tutor era útil pero stateless: si el usuario preguntaba “¿qué es un VLAN?” y luego “¿y cómo se configura en Cisco?”, la segunda pregunta llegaba al modelo sin contexto de la primera. Este cambio resuelve exactamente ese problema.
Cambios introducidos
archivo-core.ts
Nueva interfaz exportada: TutorMessage
export interface TutorMessage {
role: 'user' | 'assistant';
content: string;
}
Representa un turno del historial conversacional. Es la API pública que el frontend de CreaRack-Pro consume al enviar los últimos N turnos en cada petición.
buildTutorPrompts — parámetro history opcional
function buildTutorPrompts(
question: string,
lang: 'en' | 'es',
history?: TutorMessage[],
): { systemPrompt: string; userPrompt: string }
Si se pasa history, genera un bloque de texto conversacional ("--- CONVERSATION SO FAR ---" en EN, "--- CONVERSACIÓN HASTA AHORA ---" en ES) que se inyecta en el userPrompt antes de la nueva pregunta. Cada turno se formatea como:
User: <contenido>
Assistant: <contenido>
(o Usuario: / Asistente: en ES según el idioma detectado server-side.)
Decisión de diseño: single user content vs. multi-turn API
No se usa
contents[role: model]separados (multi-turn nativo de la API de Gemini) porqueresponseSchema+responseMimeType: "application/json"funcionan de forma más fiable con un únicousercontent. El historial se inyecta como texto plano dentro de ese content único.
synthesizeAnswer — firma ampliada
export async function synthesizeAnswer(
apiKey: string,
question: string,
chunks: ChunkMatch[],
mode: 'help' | 'tutor',
history?: TutorMessage[],
): Promise<AskResult>
Recibe history y lo pasa a buildTutorPrompts. Help mode no usa historial (cada pregunta trae sus propios chunks).
archivo.ts
handleAsk — validación y paso de history
const rawHistory = Array.isArray(args.history) ? args.history : [];
const history = rawHistory
.filter((m): m is { role: string; content: string } => {
return !!m && typeof m === 'object'
&& typeof (m as Record<string, unknown>).role === 'string'
&& typeof (m as Record<string, unknown>).content === 'string';
})
.map((m) => ({
role: (m.role === 'assistant' ? 'assistant' : 'user') as 'user' | 'assistant',
content: m.content,
}));
Se validan estrictamente los objetos malformados con typeof guards antes de pasarlos a synthesizeAnswer. El rol se normaliza: cualquier valor que no sea 'assistant' se trata como 'user' (seguro por defecto).
Contrato de la API MCP
Herramienta: bib_ask — parámetros Tutor mode
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
question | string | Sí | La nueva pregunta del usuario |
mode | 'tutor' | Sí (para activar tutor) | Activa el modo IT Tutor |
history | TutorMessage[] | No | Array de turnos previos (máx ~10 enviados por el frontend) |
Comportamiento según modo
| Modo | Grounding | Historial | Fuente de conocimiento |
|---|---|---|---|
help | Chunks de wiki | ❌ No | Wiki interna CreaRack Pro |
tutor | Sin chunks | ✅ Sí (s55) | Conocimiento del modelo (Gemini) |
Flujo de datos
Frontend CreaRack-Pro
└─ Envía últimos 10 turnos como `args.history`
└─ handleAsk (archivo.ts)
├─ Valida y tipifica history[]
└─ synthesizeAnswer(..., history)
└─ buildTutorPrompts(question, lang, history)
└─ Inyecta conversationBlock en userPrompt
└─ Gemini REST API → JSON {"answer": "..."}
Alcance y limitaciones
- Help mode sin cambios: cada pregunta Help es independiente y trae sus propios chunks. El historial no aplica a Help mode.
- El frontend (commit separado en CreaRack-Pro) es quien decide cuántos turnos enviar — actualmente los últimos 10.
- Sin multi-turn nativo de API: se usa un único
usercontent por compatibilidad conresponseSchema. - Sin persistencia de sesión en el servidor: el historial vive en el cliente. El servidor es stateless.
Véase también
- [[entity—archivo—function—tutor-message]]
- [[entity—archivo—function—synthesize-answer]]
- [[entity—archivo—function—build-tutor-prompts]]
- [[feature—archivo—help-widget-it-tutor]]
- [[concept—biblioteca—mcp-handler-archivo]]