Connects 'ellmer' chats to a 'ChatGPT' subscription through 'OpenAI''s documented "Sign in with ChatGPT" flow for open-source, locally hosted apps < https://developers.openai.com/siwc/token-sharing-open-source>. Provides a stable, explicitly bounded core of the public 'ellmer' (>= 0.5.0) Chat object, including browser sign-in with dynamic client registration, package-scoped credential storage, redacted diagnostics, multi-turn text, streaming, structured-output, function-tool, asynchronous, cancellation, cloning, metadata, multimodal chat, account-specific model discovery, and reasoning-effort selection through the public 'Responses' API. Parallel and batch helper functions are explicitly unsupported because 'ChatGPT' plan usage is stream-only. This independent third-party integration is not endorsed by 'OpenAI'.

ellmercodex te permite usar una cuenta de ChatGPT desde R a través de una
interfaz de chat de ellmer: los modelos
incluidos en tu plan de ChatGPT funcionan como un proveedor más de ellmer,
sin clave de API. Así puedes incorporar modelos de lenguaje a tus flujos de
análisis en R.
El paquete es independiente de OpenAI y no requiere una clave de API ni el CLI de Codex. Usa el flujo documentado por OpenAI "Sign in with ChatGPT" para apps de código abierto que se ejecutan localmente, y la API pública de Responses. Consulta la documentación técnica para conocer los límites de soporte, la implementación y los riesgos actuales.
Los ejemplos de resultados estructurados y herramientas están inspirados en
el artículo sobre ellmercodex en el blog.
El paquete todavía no está en CRAN. Instálalo desde GitHub usando
pak:
install.packages("pak")
pak::pak("simxnherrera/ellmercodex")
Si vienes de una versión 0.1.x, vuelve a iniciar sesión con codex_login()
después de actualizar: la forma de autenticación cambió y las credenciales
anteriores no se conservan.
Comprueba la integración local, inicia sesión y crea una conversación:
library(ellmercodex)
codex_available()
auth <- codex_login()
chat <- chat_codex(model = "gpt-6-luna", effort = "low")
chat$chat("Hola desde R")
#> ¡Hola! ¿En qué puedo ayudarte con R?
codex_login() abre una ventana del navegador para autenticarte con tu
cuenta de ChatGPT. Como chat_codex() devuelve un objeto Chat de ellmer,
puedes usar buena parte de su interfaz habitual. Cada llamada a $chat()
mantiene el historial de la conversación; usa $stream() si quieres recibir
la respuesta en streaming:
chat$stream("Dame tres ideas para nombrar un paquete de R.")
Si ya iniciaste sesión y la credencial está disponible, puedes llamar a
chat_codex() directamente. Con model = NULL, el paquete selecciona un
modelo utilizable del catálogo de tu cuenta autenticada.
Como trabajamos con un objeto Chat de ellmer, podemos pedir resultados
estructurados en lugar de texto libre. Por ejemplo, podemos clasificar un
fragmento de un debate parlamentario sobre la regulación del cannabis:
# Fragmento real de un debate parlamentario sobre regulación del cannabis
fragmento <- paste(
"seguimos pensando que además de la represión y del combate al",
"narcotráfico que debe seguir con firmeza y decisión como sociedad",
"debemos apostar a dos o tres pilares fundamentales la educación",
"la prevención y la rehabilitación"
)
resultado <- chat$chat_structured(
paste(
"Clasifica el fragmento como PREVENTIVA, PUNITIVA, MIXTA o",
"SIN_ORIENTACIÓN_ATRIBUIBLE.",
"Usa MIXTA cuando se defiendan simultáneamente respuestas",
"preventivas y punitivas.",
"\n\nFragmento:",
fragmento
),
type = ellmer::type_object(
codigo = ellmer::type_enum(c(
"PREVENTIVA",
"PUNITIVA",
"MIXTA",
"SIN_ORIENTACIÓN_ATRIBUIBLE"
)),
justificacion = ellmer::type_string()
)
)
resultado
#> $codigo
#> [1] "MIXTA"
#>
#> $justificacion
#> [1] "El fragmento defiende explícitamente la represión y el combate al
#> narcotráfico, que son respuestas punitivas, y simultáneamente propone la
#> educación, la prevención y la rehabilitación, de carácter preventivo o
#> rehabilitador."
Para tareas de análisis de texto, esto permite solicitar directamente una
estructura que R pueda incorporar a un data.frame, validar o analizar.
También puedes registrar funciones como herramientas que el modelo puede decidir utilizar durante una conversación. Supongamos que tenemos intervenciones parlamentarias ya clasificadas:
intervenciones <- data.frame(
partido = c("FA", "FA", "PN", "PN", "PN"),
orientacion = c(
"PREVENTIVA",
"MIXTA",
"PUNITIVA",
"PUNITIVA",
"MIXTA"
)
)
Podemos crear una función de R que resuma las orientaciones observadas para
un partido y exponerla al modelo como una herramienta de ellmer:
resumir_partido <- function(partido_buscado) {
intervenciones |>
dplyr::filter(partido == partido_buscado) |>
dplyr::count(orientacion)
}
resumen_tool <- ellmer::tool(
resumir_partido,
name = "resumir_partido",
description = "Cuenta las orientaciones discursivas de un partido.",
arguments = list(
partido_buscado = ellmer::type_string()
)
)
chat$register_tool(resumen_tool)
chat$chat(
paste(
"Compara las orientaciones discursivas de FA y PN.",
"Usa la herramienta disponible."
)
)
#> - **FA:** 1 fragmento **MIXTO** y 1 **PREVENTIVO**.
#> - **PN:** 1 fragmento **MIXTO** y 2 **PUNITIVOS**.
#>
#> En comparación, ambos presentan orientación mixta, pero el **FA** también
#> muestra una orientación preventiva, mientras que el **PN** registra una
#> mayor presencia de respuestas punitivas.
El modelo puede decidir llamar a resumir_partido() para cada partido, recibir
los resultados producidos por R y utilizarlos para elaborar su respuesta. La
herramienta podría consultar una base de datos, buscar en un corpus, realizar
un cálculo, recuperar información de una API o ejecutar cualquier otra
operación que decidas implementar.
R sigue siendo quien ejecuta las funciones: el modelo solo puede utilizar las herramientas que registres explícitamente y decide cuándo usarlas y con qué argumentos.
La disponibilidad de modelos depende de tu cuenta y espacio de trabajo. Consulta el catálogo después de iniciar sesión:
modelos <- codex_models()
modelos[c("id", "display_name", "default_reasoning_effort",
"supported_reasoning_efforts")]
El catálogo no siempre incluye todos los modelos que acepta el servicio.
Puedes pasar explícitamente un ID aunque no aparezca en codex_models(), y
el servicio validará el modelo y el esfuerzo. Por ejemplo, gpt-6-luna
funciona aunque el catálogo no lo liste.
Puedes seleccionar un modelo y el esfuerzo de razonamiento explícitamente:
chat <- chat_codex(model = "gpt-6-luna", effort = "max")
chat <- chat_codex(
model = "gpt-6-luna",
params = ellmer::params(reasoning_effort = "max")
)
Usa ELLMERCODEX_MODEL si quieres establecer un modelo sin pasarlo cada vez:
Sys.setenv(ELLMERCODEX_MODEL = "gpt-6-luna")
chat <- chat_codex()
El objeto Chat también admite los métodos asíncronos de ellmer:
chat$chat_async("Resume la conversación.")
controller <- ellmer::stream_controller()
stream <- chat$stream_async(
"Escribe un cuento breve.",
stream = "content",
controller = controller
)
# Pasa `stream` a un consumidor asíncrono, como un componente de chat de Shiny.
# Llama a `controller$cancel()` desde la interfaz para detener la generación.
También puedes enviar imágenes y PDF usando los constructores habituales de
ellmer:
chat$chat(
ellmer::content_image_url("https://example.com/diagram.png"),
ellmer::ContentPDF("application/pdf", "<base64-data>", "report.pdf"),
"Explica estos archivos."
)
codex_login() abre el navegador para que elijas tu cuenta y espacio de
trabajo de ChatGPT y autorices el uso de tu plan. La primera vez se crea un
registro vinculado a esa cuenta; los inicios de sesión siguientes lo
reutilizan. La credencial se guarda en tools::R_user_dir("ellmercodex", "config") (o en ELLMERCODEX_HOME) con permisos solo para tu usuario.
Consulta el estado de inicio de sesión con un resumen de cuenta redactado:
codex_account()
Para una sesión que solo dure lo que dure el proceso, usa:
auth <- codex_login(persist = FALSE)
Cierra la sesión, revoca el token y elimina la credencial administrada por
este paquete con codex_logout(). Para cambiar de cuenta o de espacio de
trabajo, cierra sesión y vuelve a llamar a codex_login():
codex_logout()
El uso del plan de ChatGPT mediante "Sign in with ChatGPT" es una función en
vista previa de OpenAI: requiere un plan y un espacio de trabajo elegibles, y
sus límites y funciones admitidas pueden cambiar. Mientras dure la vista
previa no se admiten temperature, top_p, max_tokens ni otros argumentos
que OpenAI excluye; el paquete los rechaza antes de enviar la solicitud.
ellmercodex es una integración independiente y no está afiliada a OpenAI ni
cuenta con su respaldo. El foco actual está puesto en el objeto Chat de
ellmer 0.5.0 o posterior y en operaciones interactivas sobre una conversación.
El conteo de tokens del proveedor, la gestión de archivos y las funciones
parallel_chat() y batch_chat() no están soportados.
Para más detalles:
ellmer
registra los métodos Chat soportados, sus firmas, los valores devueltos y
las transiciones de estado.?chat_codex, ?codex_login, ?codex_models y
?ellmercodex-conditions para consultar la referencia de funciones.El alcance estable es el uso interactivo de una sola conversación mediante el
objeto Chat público de ellmer 0.5.0 o posterior. El conteo de tokens del
proveedor, la gestión de archivos y las funciones independientes
parallel_chat*() y batch_chat*() no están soportadas por este paquete.
ellmercodex lets you use your ChatGPT plan from R through an
ellmer chat interface: the models in your
plan work as one more ellmer provider, with no API key. The normal workflow
is to sign in, create a chat, and then use the regular ellmer Chat methods.
The package is independent of OpenAI and does not require an API key or the
Codex CLI. It uses OpenAI's documented
"Sign in with ChatGPT"
flow for open-source, locally hosted apps and the public Responses API. See the
technical documentation
for the implementation, support boundaries, and current risks. ChatGPT plan
usage is an OpenAI preview: it needs an eligible plan and workspace, and it
does not accept temperature, top_p, max_tokens, or other excluded
arguments.
The package is not on CRAN yet. Install it from GitHub with
pak:
install.packages("pak")
pak::pak("simxnherrera/ellmercodex")
If you are upgrading from 0.1.x, sign in again with codex_login(): the
authentication flow changed and earlier credentials are not kept.
Check the local integration, sign in, and create a chat:
library(ellmercodex)
codex_available()
auth <- codex_login()
chat <- chat_codex(
system_prompt = "Be concise and helpful.",
model = "gpt-6-luna"
)
chat$chat("Explain why reproducible examples matter in R packages.")
chat$chat("Now summarize that in one sentence.")
The returned object is an ellmer Chat, so each $chat() call keeps the
conversation history. Use $stream() when you want streamed output:
chat$stream("Give me three ideas for naming an R package.")
If you have already signed in and the credential is available, you can call
chat_codex() directly. With model = NULL, the package selects a usable
model from the authenticated account catalog.
Model availability depends on your account and workspace. Query the catalog after signing in:
models <- codex_models()
models[c("id", "display_name", "default_reasoning_effort",
"supported_reasoning_efforts")]
The catalog does not always include every model the service accepts. You can
pass a model ID explicitly even when it is absent from codex_models(), and
the service validates the model and reasoning effort. For example,
gpt-6-luna works although the catalog does not list it.
Select a model explicitly when needed:
chat <- chat_codex(model = "gpt-6-luna")
Reasoning effort can be supplied directly or through ellmer-style parameters:
chat <- chat_codex(model = "gpt-6-luna", effort = "max")
chat <- chat_codex(
model = "gpt-6-luna",
params = ellmer::params(reasoning_effort = "max")
)
Use ELLMERCODEX_MODEL when you want an explicit model without passing
model each time:
Sys.setenv(ELLMERCODEX_MODEL = "gpt-6-luna")
chat <- chat_codex()
Register tools with the normal ellmer API:
weather_tool <- ellmer::tool(
function(city) paste("Sunny in", city),
name = "get_weather",
description = "Get the current weather for a city.",
arguments = list(city = ellmer::type_string())
)
chat <- chat_codex(model = "gpt-6-luna")
chat$register_tool(weather_tool)
chat$chat("What is the weather in Montevideo?")
Tool requests and results remain in the conversation history as the usual
ellmer content objects.
Use ellmer's type system with $chat_structured():
chat <- chat_codex(model = "gpt-6-luna")
chat$chat_structured(
"My name is Susan and I'm 13 years old.",
type = ellmer::type_object(
name = ellmer::type_string(),
age = ellmer::type_integer()
)
)
As in ellmer, structured requests do not use registered tools. Gather any
tool-assisted context with $chat() first, then extract the result with
$chat_structured().
The returned chat also supports ellmer's asynchronous methods:
chat$chat_async("Summarize the conversation.")
controller <- ellmer::stream_controller()
stream <- chat$stream_async(
"Write a short story.",
stream = "content",
controller = controller
)
# Pass `stream` to an async consumer such as a Shiny chat component.
# Call `controller$cancel()` from the UI to stop generation.
Images and PDFs can be passed with ellmer's normal content constructors:
chat$chat(
ellmer::content_image_url("https://example.com/diagram.png"),
ellmer::ContentPDF("application/pdf", "<base64-data>", "report.pdf"),
"Explain these files."
)
codex_login() opens the browser so you can choose your ChatGPT account and
workspace and allow ChatGPT plan usage. The first sign-in creates a
registration bound to that account; later sign-ins reuse it. The credential is
stored in tools::R_user_dir("ellmercodex", "config") (or ELLMERCODEX_HOME)
with owner-only permissions.
Inspect sign-in state with a redacted account summary:
codex_account()
For a process-only session, use:
auth <- codex_login(persist = FALSE)
Sign out, revoke the token, and remove the credential owned by this package
with codex_logout(). To switch accounts or workspaces, sign out and call
codex_login() again:
codex_logout()
The README is intentionally focused on installation and user-facing workflows. For more detail:
?chat_codex, ?codex_login, ?codex_models, and
?ellmercodex-conditions for the function reference.The stable scope is interactive, single-conversation use of the public
ellmer Chat object (0.5.0 or later). Provider token counting and file
management, as well as the separate parallel_chat*() and batch_chat*()
helpers, are unsupported by this package.