¿Te resulta más fácil leer con fondo crema, un tono de color, más contraste o un texto más grande? Elige tus colores y tu texto una sola vez, para todas las páginas.

Lección gratuita

Cómo hacer que un chatbot cite sus fuentes

Después de esta lección: Puedo mostrar qué fuente usó una respuesta.

Lección de 60 min7 comandosLaboratorio de agente de programación con IA: usa opencode para explicar y corregir código, y comprueba su trabajo

Mostrar de dónde viene una respuesta

Una cita es una marca en una respuesta que señala la fuente de la que salió. Importa porque la gente se fía más de una respuesta que puede comprobar, y tu programa puede comprobar las marcas.

El chatbot de una biblioteca dice que un libro devuelto tarde cuesta diez céntimos al día [2]. El lector mira la fuente 2 y ve la misma regla.

Al final de esta lección

Nota

Puedo mostrar qué fuente usó una respuesta.

Palabras clave

PalabraQué significaEjemplo
Fuenteun pasaje de texto que la respuesta puede usar
Citaun enlace de la respuesta a su fuente
Marcael número entre corchetes que hace la cita[2]
Fundadabasada en las fuentes que diste
Fuente sin usaruna fuente que ninguna marca señala

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Numera las fuentes y pide marcas

Escribe cada fuente en el mensaje con un número: [1], [2], [3]. Luego pide al modelo que use solo esas fuentes y que escriba el número después de cada dato.

Las fuentes de aquí son pasajes que escribiste en el script. Buscar fuentes reales entre muchos documentos es otro tema: aquí las escribes tú. La respuesta es fundada cuando se queda en lo que le diste.

Ejemplo resuelto: fuentes y una respuesta

ParteTexto
Fuente [1]Los socios pueden llevarse hasta seis libros durante tres semanas.
Fuente [2]Un libro devuelto tarde cuesta diez céntimos al día.
Pregunta¿Cuántos libros puedo llevarme y cuánto es la multa por retraso?
RespuestaPuedes llevarte seis libros [1]. Un libro devuelto tarde cuesta diez céntimos al día [2].

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Comprueba que cada marca tiene fuente

Un modelo puede escribir [4] cuando solo hay tres fuentes. Tu programa puede detectarlo. Busca cada marca y compara cada número con la lista de ids de fuente.

Busca también las fuentes sin usar y las frases sin marca. Muestran lo que la respuesta dejó fuera.

Un error frecuente

Advertencia

Mucha gente cree que una marca prueba que la respuesta es cierta. Solo prueba que la fuente existe. El modelo puede citar la fuente equivocada para un dato. La comprobación es un primer filtro, y una persona sigue leyendo la fuente en lo que importa.

Escribir la ayuda del modelo, parte 1

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' 'async function ask(messages, sample, max) {' '  try {' '    const res = await fetch(base + \"/v1/chat/completions\", {' '      method: \"POST\",' '      headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' '      body: JSON.stringify({ model: \"lab\", messages: messages, max_tokens: max || 200 }),' '      signal: AbortSignal.timeout(30000),' '    });' '    if (res.ok === false) throw new Error(\"estado \" + res.status);' '    return (await res.json()).choices[0].message.content;' > model.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribir la ayuda del modelo, parte 2

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' '  } catch (error) {' '    console.log(\"Muestra grabada: ningún modelo respondió (\" + error.message + \").\");' '    const list = [].concat(sample);' '    const turn = messages.filter(function (m) { return m.role === \"assistant\"; }).length;' '    return list[Math.min(turn, list.length - 1)];' '  }' '}' 'module.exports = { ask };' >> model.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribir la comprobación de citas, parte 1

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' 'const SOURCES = [' '  { id: 1, text: \"Los socios pueden llevarse hasta seis libros durante tres semanas.\" },' '  { id: 2, text: \"Un libro devuelto tarde cuesta diez céntimos al día.\" },' '  { id: 3, text: \"La biblioteca abre a las nueve y cierra a las cinco de la tarde en días laborables.\" },' '];' > cite5.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribir la comprobación de citas, parte 2

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function sourceText() {' '  return SOURCES.map(function (s) { return \"[\" + s.id + \"] \" + s.text; }).join(\"\n\");' '}' 'function markersIn(reply) {' '  const found = [];' '  const re = /\[(\d+)\]/g;' '  let match = re.exec(reply);' '  while (match) { found.push(Number(match[1])); match = re.exec(reply); }' '  return found;' '}' >> cite5.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribir la comprobación de citas, parte 3

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function check(reply) {' '  const ids = SOURCES.map(function (s) { return s.id; });' '  const markers = markersIn(reply);' '  const missing = markers.filter(function (n) { return ids.includes(n) === false; });' '  return { markers: markers, missing: missing, ok: markers.length > 0 && missing.length === 0 };' '}' 'function show(label, result) {' '  console.log(label + \" marcas \" + JSON.stringify(result.markers) + \", sin fuente \" + JSON.stringify(result.missing) + \", ok: \" + result.ok);' '}' >> cite5.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribir la comprobación de citas, parte 4

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' '  const rule = \"Responde usando solo estas fuentes numeradas. Después de cada dato escribe el número de su fuente entre corchetes, como [1]. Si las fuentes no lo dicen, responde: No lo sé.\n\" + sourceText();' '  const question = \"¿Cuántos libros puedo llevarme y cuánto es la multa por retraso?\";' '  // Muestra grabada, usada solo si ningún modelo responde.' '  const sample = \"Puedes llevarte seis libros [1]. Un libro devuelto tarde cuesta diez céntimos al día [2].\";' '  const reply = await ask([{ role: \"system\", content: rule }, { role: \"user\", content: question }], sample, 80);' '  console.log(\"Respuesta:\", reply);' '  show(\"Comprobación:\", check(reply));' '  show(\"Respuesta inventada:\", check(\"Los préstamos duran tres semanas [4].\"));' '}' 'main();' >> cite5.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Preguntar y comprobar las marcas

Comando
docker exec -w /home/node/project agent node cite5.js

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Una salida posible

LíneaLo que puede mostrar
RespuestaDos frases cortas, cada una acabada en una marca como [1]
Comprobación:marcas [1,2], sin fuente [], ok: true, si la respuesta se quedó en las fuentes
Respuesta inventada:marcas [4], sin fuente [4], ok: false, siempre

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Sobre este laboratorio y su código: Laboratorio de agente de programación con IA: usa opencode para explicar y corregir código, y comprueba su trabajo

¿Enseñas a una clase? Asigna este módulo a tus alumnos con guía del profesor, tareas con corrección automática y un laboratorio para cada alumno.