Crea un chatbot de inteligencia artificial con R
1/6/2026
Con R y los paquetes apropiados, en pocos minutos podrás crear un chat interactivo de inteligencia artificial dentro de una aplicación Shiny, para poder chatear con un modelo de lenguaje (LLM) de tu elección.
El objetivo es poder crear un chat interactivo e ir mejorándolo con la capacidad de consultar datos, realizar cálculos y otras capacidades propias de R, y además aumentar su conocimiento y la precisión de sus respuestas al permitirle consultar documentos y textos para responder.
¿Por qué crear un chatbot con R?
- Te entrega el control para elegir el proveedor de inteligencia artificial, o el cerebro que usará el chatbot, así como cambiarlo cuando sea necesario
- Aplicaciones: Puedes incluir el chatbot en cualquier parte de una aplicación Shiny, lo que te da libertad para crear interfaces adaptadas a tus necesidades
- Datos: Permite complementar al chatbot con herramientas, funciones de R que hacen posible que el chatbot realice tareas especializadas, como consultar bases de datos
- Conocimientos: Hace posible aumentar y afinar los conocimientos de la IA por medio de sistemas de generación aumentada por recuperación o RAG, donde recopilas documentos y textos para guiar las respuestas de la IA
Preparación
Crear un chatbot requiere de tres piezas principales: una aplicación donde introducir el chatbot, la funcionalidad de chat o conversación, y el modelo de lenguaje que será el motor de la conversación.
Estas tres piezas corresponden a los tres paquetes de R que usaremos: {shiny} para la aplicación, {shinychat} para la conversación, y {ellmer} para el modelo de lenguaje.
Si aún no tienes configurado un modelo de lenguaje en R, revisa este tutorial, donde explico cómo conectarte con el modelo de IA desde R.
Contenidos mínimos
Empezamos instalando los paquetes necesarios:
install.packages("ellmer")
install.packages("shiny")
install.packages("bslib")
install.packages("shinychat")
Ahora veremos paso a paso cómo empezar desde cero y llegar a un chatbot capaz de consultar datos y bases de conocimiento.
Crear un chatbot con Shiny
Hagamos un ayudamemorias de una aplicación Shiny mínima, sin ningún chat todavía:
library(shiny)
library(bslib)
ui <- page_fluid(
h1("Mi chatbot")
)
server <- function(input, output, session) {
}
shinyApp(ui, server)
Tenemos la sección UI, con la interfaz de la aplicación, y una sección server, donde se hacen los cálculos de la aplicación.
Esto nos entregará una app mínima, que puedes probar con el botón Run que aparecerá en RStudio o en tu IDE.
En principio esta puede ser una app que ya hayas hecho, o puede ser el lienzo para que complementes tu chatbot con otros elementos de una aplicación normal.
Instrucciones detalladas
Ahora vamos a transformar la aplicación en un chatbot en tres pasos: agregar la interfaz del chat, configurar el modelo de lenguaje, y conectar ambas partes en la sección server de la app.
Interfaz del chat
El paquete {shinychat} nos entrega una interfaz de conversación tipo chat, con burbujitas de mensaje y todo, que simplemente se agrega a tu app con la función chat_ui().
Se recomienda usar page_fillable() en la app para que ocupe toda la pantalla, y dentro ponemos chat_ui().
Por ahora la app iría quedando así:
library(shiny)
library(bslib)
library(ellmer)
library(shinychat)
ui <- page_fillable(
chat_ui(
id = "chat",
messages = "**¡Hola!** ¿En qué te puedo ayudar hoy?"
),
fillable_mobile = TRUE
)
server <- function(input, output, session) {
}
shinyApp(ui, server)
Con esto creamos la parte visible del chat, pero falta el funcionamiento y el cerebro.
Modelo de lenguaje para el chatbot
En la sección server, donde se realizan los cálculos de una app Shiny, creamos el chat que hará funcionar al chatbot.
Como vimos en el
tutorial de chats de IA en R, creamos el chat con la función chat_anthropic(), chat_ollama(), o el proveedor que te corresponda a ti. Este objeto representa la conversación completa con el modelo de lenguaje: guarda el historial de mensajes y se encarga de comunicarse con la API.
library(shiny)
library(bslib)
library(ellmer)
library(shinychat)
ui <- page_fillable(
chat_ui(
id = "chat",
messages = "**¡Hola!** ¿En qué te puedo ayudar hoy?"
),
fillable_mobile = TRUE
)
server <- function(input, output, session) {
chat <- chat_anthropic(
system_prompt = "Eres un chatbot respetuoso, útil y conciso."
)
}
shinyApp(ui, server)
El argumento system_prompt son las instrucciones que le damos al modelo para guiar su comportamiento: el rol que debe cumplir, el tono que debe usar, explicaciones sobre su función principal, las formas apropiadas de responder, y sus restricciones.
Conectar la interfaz con el modelo
Ahora falta el último paso: conectar el modelo de lenguaje creado con chat_anthropic() con el chat_ui() que pusimos en la interfaz de la app.
library(shiny)
library(bslib)
library(ellmer)
library(shinychat)
ui <- page_fillable(
chat_ui(
id = "chat",
messages = "**¡Hola!** ¿En qué te puedo ayudar hoy?"
),
fillable_mobile = TRUE
)
server <- function(input, output, session) {
chat <- chat_openai(
system_prompt = "Eres un chatbot respetuoso, útil y conciso."
)
observeEvent(input$chat_user_input, {
stream <- chat$stream_async(input$chat_user_input)
chat_append("chat", stream)
})
}
shinyApp(ui, server)
Siguiendo
lo que aprendimos en el tutorial de Shiny, el bloque observeEvent() se activará cada vez que se envíe un mensaje en la interfaz de chat_ui(). Dentro de él ocurren dos cosas:
- La primera línea,
chat$stream_async(input$chat_user_input), manda el mensaje del usuario/a al modelo de lenguaje (el objetochat), y obtiene la respuesta que emita la IA. - La segunda línea,
chat_append("chat", stream), va añadiendo las burbujas de mensajitos a la interfaz del chat a medida que llega el texto. La app lo va recibiendo en tiempo real en vez de esperar la respuesta completa.
Código completo de la app con chatbot
library(shiny)
library(bslib)
library(ellmer)
library(shinychat)
ui <- page_fillable(
chat_ui(
id = "chat",
messages = "**¡Hola!** ¿En qué te puedo ayudar hoy?"
),
fillable_mobile = TRUE
)
server <- function(input, output, session) {
chat <- chat_anthropic(
system_prompt = "Eres un chatbot respetuoso, útil y conciso."
)
observeEvent(input$chat_user_input, {
stream <- chat$stream_async(input$chat_user_input)
chat_append("chat", stream)
})
}
shinyApp(ui, server)
Probemos el chatbot!
Si configuraste bien tu proveedor de IA, vas a poder conversar con tu modelo mediante la aplicación Shiny.
Ahora pasamos a la gracia de todo esto: potenciar el chatbot con herramientas para que pueda acceder a datos, y darle una base de conocimientos con documentos específicos.
Entregar herramientas al chatbot
Para ilustrar el desarrollo de un chatbot enfocado en datos con R, hagamos que queremos desarrollar un chatbot que pueda decirnos cifras de la situación de pobreza en Chile.
Primero pongamos a prueba el chatbot que ya creamos, que no tiene ningún conocimiento específico (solamente el conocimiento propio del entrenamiento de la IA), y preguntémosle por un dato:
El modelo de lenguaje no supo responder! 🫤
Cuando la IA no sabe responder, usualmente rellena con cualquier cosa, o se atreve a una estimación. En la mayoría de lso casos, esto debería ser inaceptable.
Ver código completo del chatbot hasta ahora
Especificamos algunas cosas en el código: elejimos un modelo económico, Claude Haiku, definiendo model = "claude-haiku-4-5" dentro de chat_anthropic(), y además especifiquemos el system prompt: "Eres un chatbot respetuoso, útil y conciso. Responde muy brevemente solamente lo que se te pregunta." para que nos entregue menos cháchara.
library(shiny)
library(bslib)
library(ellmer)
library(shinychat)
ui <- page_fillable(
chat_ui(
id = "chat",
messages = "**¡Hola!** ¿En qué te puedo ayudar hoy?"
),
fillable_mobile = TRUE
)
server <- function(input, output, session) {
chat <- chat_anthropic(
model = "claude-haiku-4-5",
system_prompt = "Eres un chatbot respetuoso, útil y conciso. Responde muy
brevemente solamente lo que se te pregunta, sin rodeos."
)
observeEvent(input$chat_user_input, {
stream <- chat$stream_async(input$chat_user_input)
chat_append("chat", stream)
})
}
shinyApp(ui, server)
Descargar datos
Bajemos un conjunto de datos que nos pueden servir: las estimaciones de pobreza comunal 2024 calculadas por el Ministerio de Desarrollo Social de Chile.
pobreza <- read_xlsx("sae_ingresos_2024.xlsx")
Cargamos y limpiamos los datos hasta que obtenemos una tabla ordenada:
Ver código de la limpieza de datos
library(readxl)
library(dplyr)
library(janitor)
pobreza <- read_xlsx("sae_ingresos_2024.xlsx")
# limpiar columnas
pobreza <- pobreza |>
row_to_names(2) |>
clean_names() |>
rename(poblacion = numero_de_personas_segun_proyecciones_de_poblacion,
pobreza_personas = numero_de_personas_en_situacion_de_pobreza_de_ingresos,
pobreza_porcentaje = porcentaje_de_personas_en_situacion_de_pobreza_de_ingresos_2024,
pobreza_porcentaje_inf = limite_inferior,
pobreza_porcentaje_sup = limite_superior)
# convertir a numéricos
pobreza <- pobreza |>
mutate(
across(
c(poblacion, starts_with("pobreza")),
as.numeric)
)
| nombre_comuna | poblacion | pobreza_personas | pobreza_porcentaje |
|---|---|---|---|
| Iquique | 232455 | 37598 | 0.161 |
| Alto Hospicio | 144554 | 38759 | 0.268 |
| Pozo Almonte | 18811 | 3968 | 0.210 |
| Camiña | 1376 | 600 | 0.436 |
| Colchane | 1553 | 791 | 0.509 |
| Huara | 3111 | 1240 | 0.398 |
| Pica | 6313 | 1980 | 0.313 |
| Antofagasta | 445152 | 69705 | 0.156 |
| Mejillones | 15950 | 2239 | 0.140 |
| Sierra Gorda | 1807 | 256 | 0.141 |
Función de consulta de datos
Ahora que tenemos los datos, hagamos una función muy breve que nos permita filtrar la tabla de datos, siguiendo las instrucciones de este tutorial.
El objetivo es crear una función sencilla que opere como una API para consultar datos, una especie de herramienta que resuelve una necesidad de información.
# crear la función de consulta de datos
consultar_pobreza <- function(comuna) {
message("comuna elegida: ", comuna)
pobreza |>
filter(nombre_comuna == comuna) |>
select(region, pobreza_personas, pobreza_porcentaje,
pobreza_porcentaje_inf, pobreza_porcentaje_sup)
}
La función tiene un sólo argumento, con el cual se filtra la columna nombre_comuna para obtener cifras exactas de pobreza.
Probemos la función de consulta de datos:
consultar_pobreza("Maipú")
$ nombre_comuna <chr> "Maipú"
$ region <chr> "Metropolitana"
$ pobreza_personas <dbl> 70661.29
$ pobreza_porcentaje <dbl> 0.1203846
$ pobreza_porcentaje_inf <dbl> 0.09052756
$ pobreza_porcentaje_sup <dbl> 0.1502416
Estupendo! La función nos sirve para que con un sólo argumento podamos filtrar los datos.
Instrucciones detalladas
Registrar la herramienta
Cualquier función de R que tengamos o que creemos podemos pasársela al modelo de lenguaje. Para que el modelo la entienda, tenemos que explicarle la herramienta. De esta manera, el modelo podrá usar funciones de R cuando sean relevantes para responder las preguntas que le hagamos.
Para enseñarle al modelo cómo se usa la función, usamos tool() de {ellmer}, donde entregamos la función, agregamos una descripción general, y describimos también sus argumentos:
herramienta <- tool(
consultar_pobreza,
description = "Función que entrega datos de la estimación de pobreza por ingresos
a nivel de cantidad de personas estimada y porcentaje de la población,
basándose en datos de la Encuesta de Caracterización Socioeconómica
Nacional (Casen) 2024 del Ministerio de Desarrollo Social y Familia.",
arguments = list(
comuna = type_string(
description = "Comuna de Chile que se desea consultar"
)
)
)
Esto es como hacer una especie de documentación de la función, pero enfocada en que los modelos de lenguaje sepan cómo y cuándo usar la función.
Publicaciones relacionadas
Para agregar herramientas al chatbot, basta con registrarlas en el objeto chat de esta manera:
chat$register_tool(herramienta)
Esta línea se agrega dentro de server, luego de crear el chat. Así, cuando se pregunte algo que active la herramienta, el modelo la usará automáticamente.
Ver código del chatbot con herramienta de consulta de datos
library(shiny)
library(bslib)
library(ellmer)
library(shinychat)
# código de limpieza de datos
source("datos_pobreza.R")
# código de la función de consulta de datos
source("funcion_pobreza.R")
ui <- page_fillable(
chat_ui(
id = "chat",
messages = "**¡Hola!** ¿En qué te puedo ayudar hoy?"
),
fillable_mobile = TRUE
)
server <- function(input, output, session) {
# definir herramienta
herramienta <- tool(
consultar_pobreza,
description = "Función que entrega datos de la estimación de pobreza por ingresos
a nivel de cantidad de personas estimada y porcentaje de la población,
basándose en datos de la Encuesta de Caracterización Socioeconómica
Nacional (Casen) 2024 del Ministerio de Desarrollo Social y Familia.",
arguments = list(
comuna = type_string(
description = "Comuna de Chile que se desea consultar"
)
)
)
# crear chat
chat <- chat_anthropic(
model = "claude-haiku-4-5",
system_prompt = "Eres un chatbot respetuoso, útil y conciso. Responde muy
brevemente solamente lo que se te pregunta, sin rodeos."
)
# entregar la herramienta al modelo
chat$register_tool(herramienta)
observeEvent(input$chat_user_input, {
stream <- chat$stream_async(input$chat_user_input)
chat_append("chat", stream)
})
}
shinyApp(ui, server)
Ahora volvamos a probar el chatbot preguntándole lo mismo:
Ahora responde correctamente! 🥳
Si nos fijamos en la consola, vemos que el chatbot consultó correctamente la herramienta, y se basó en ella para responder:
Instrucciones detalladas
Darle conocimientos especializados al chatbot
Por ahora el modelo responde correctamente desde los datos, pero si le preguntamos otras cosas, deja de responder bien:
Si bien la cifra es correcta, al preguntarle algo sobre la metodología de los datos, responde algo genérico para omitir que no sabe realmente de dónde viene la información.
Para hacer que el chatbot maneje conocimientos complejos o especializados, y que además responda preguntas limitándose a documentos específicos, podemos entregarle una herramienta para generación aumentada por recuperación o RAG. Esto significa que el modelo accederá a informes, manuales, papers, o cualquier material relevante para tu caso de uso.
Entonces descarguemos la metodología correspondiente a los datos que estamos trabajando:
Con el paquete {ragnar} podemos crear una base de conocimientos a partir de nuestros documentos y conectarla al chatbot,
como se detalla en este tutorial.
Primero tenemos que crear una base de conocimientos:
library(ragnar)
store <- ragnar_store_create(
location = "documentos.ragnar.duckdb",
embed = NULL
)
Ahora cargamos los documentos y los procesamos:
metodologia <- read_as_markdown("content/blog/shinychat/estimaciones-sae-2024.pdf")
metodologia <- markdown_chunk(metodologia)
Finalmente los insertamos en la base y creamos el índice para que funcione:
ragnar_store_insert(store, informe_secciones)
ragnar_store_build_index(store)
Instrucciones detalladas
Ahora, en el código de nuestro chatbot, agregamos la conexión a la base de conocimientos y luego, después de la creación del chat, ponemos el registro de la herramienta de RAG:
# conectarse a la base de conocimientos
store <- ragnar_store_connect("documentos.ragnar.duckdb", read_only = TRUE)
# registrar la herramienta de búsqueda en el modelo
ragnar_register_tool_retrieve(
chat,
store,
store_description = "Base de conocimientos sobre metodología
de cálculo de estimaciones de pobreza a
partir de la encuesta Casen 2024"
)
Ver código completo del chatbot con RAG
library(shiny)
library(bslib)
library(ellmer)
library(shinychat)
library(ragnar)
# código de limpieza de datos
source("datos_pobreza.R")
# código de la función de consulta de datos
source("funcion_pobreza.R")
ui <- page_fillable(
chat_ui(
id = "chat",
messages = "**¡Hola!** ¿En qué te puedo ayudar hoy?"
),
fillable_mobile = TRUE
)
server <- function(input, output, session) {
# definir herramienta
herramienta <- tool(
consultar_pobreza,
description = "Función que entrega datos de la estimación de pobreza por ingresos
a nivel de cantidad de personas estimada y porcentaje de la población,
basándose en datos de la Encuesta de Caracterización Socioeconómica
Nacional (Casen) 2024 del Ministerio de Desarrollo Social y Familia.",
arguments = list(
comuna = type_string(
description = "Comuna de Chile que se desea consultar"
)
)
)
# crear chat
chat <- chat_anthropic(
model = "claude-haiku-4-5",
system_prompt = "Eres un chatbot respetuoso, útil y conciso. Responde muy
brevemente solamente lo que se te pregunta, sin rodeos."
)
# entregar la herramienta al modelo
chat$register_tool(herramienta)
# conectarse a la base de conocimientos
store <- ragnar_store_connect("documentos.ragnar.duckdb", read_only = TRUE)
# registrar la herramienta de búsqueda en el modelo
ragnar_register_tool_retrieve(
chat,
store,
store_description = "Base de conocimientos sobre metodología
de cálculo de estimaciones de pobreza Casen 2024"
)
observeEvent(input$chat_user_input, {
stream <- chat$stream_async(input$chat_user_input)
chat_append("chat", stream)
})
}
shinyApp(ui, server)
Igual que con las herramientas, esto va en el server junto al objeto chat. Una vez registrada, la IA decidirá cuándo necesita consultar los documentos para responder mejor, y lo hará automáticamente.
Ahora volvemos a probar el chatbot con una pregunta compleja:
Ahora sí, en vez de chamullar una respuesta, el chatbot se basa en el documento entregado para dar una respuesta precisa informada por el texto!
Con estos tres elementos (el chatbot base, las herramientas de consulta de datos y la consulta de documentos con RAG), y sumándole un buen system prompt, puedes construir en nada de tiempo asistentes de IA útiles y confiables, adaptados completamente a tus datos y necesidades, sin depender de ninguna plataforma de chat externa.
Estos asistentes puedes ponerlos en tus aplicaciones Shiny y luego publicar tus apps a internet, o insertarlos/embeberlos en otros sitios web.
Personalmente he desarrollado varios chatbots que consultan datos complejos de estudios, y su funcionamiento es excelente, incluso con los modelos de inteligencia artificial más pequeños, porque la gracia es que R apoya a la IA con datos e información para responder correctamente, en vez de depender de modelos de IA gigantes que aspiran a saberlo todo (cosa que es imposible).
Publicaciones sobre inteligencia artificial
- Fecha de publicación:
- June 1, 2026
- Extensión:
- 15 minute read, 3016 words
- Categorías:
- Tutoriales
- Tags:
- shiny inteligencia artificial