--- title: "Language models" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Language models} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- gptr logo Use `peter()` with a prompt to run a language model agent and receive a session. The agent can inspect objects already loaded in your R environment, compute on them, and reuse named results on later turns. Choosing an API, CLI or Ollama model changes the model route; its gptr R tool still works in the selected live workspace. The model receives bounded descriptions and tool results, which may include data values or plots, rather than an automatic serialization of the full dataset. [Execution model](execution-model.html) explains copies, separate workers and file-backed objects. The same call works in a function, a loop or a script. This guide executes only scripted fake providers; examples that connect to real services are shown without running them. ## Choose and connect a model `gptr_providers()` lists configured routes and credential sources without making a request. `gptr_models()` searches the catalog already available on disk. Neither listing proves that an account can make a model request. `check = TRUE` probes provider reachability and CLI versions; `refresh = TRUE` updates a catalog or asks a local server which models it has installed. `gptr_providers(check_login = TRUE)` adds CLI-reported `signed in`, `not signed in` or `unknown` states by running supported local status commands. It does not make a model request or verify credentials online. This optional probe is separate from `check = TRUE`; both default to `FALSE`, so the default listing starts no processes. A Codex API-key login can count as signed in, so login status does not establish subscription billing. ``` r gptr_providers() gptr_models("sonnet") gptr_models(provider = "openai") gptr_providers(check = TRUE) gptr_providers(check_login = TRUE) ``` Select a canonical `"provider/model"` reference to make the route explicit. Catalog aliases such as `sonnet` also work. For a default, use `gptr_config(model = ..., .scope = "user")`; pass `model = ...` to override it for one call. [Configuration](configuration.html) explains scope and precedence. ### API providers Obtain a key from the provider, then put it in the environment of your R process or an existing private `.env` file. `gptr_env()` loads that file, registers values for redaction and reports names and fingerprints. It leaves an existing environment variable alone unless `override = TRUE`. Keep the file out of version control. | Route | Credential variable | Example reference | |---|---|---| | Anthropic | `ANTHROPIC_API_KEY` | `"anthropic/claude-sonnet-5-5"` | | OpenAI | `OPENAI_API_KEY` | `"openai/gpt-6-sol"` | | Google Gemini | `GEMINI_API_KEY` or `GOOGLE_API_KEY` | `"google/gemini-3.8-flash"` | | OpenRouter | `OPENROUTER_API_KEY` | Choose a reference from `gptr_models(provider = "openrouter")` | | Hosted System 1 | `TYPESAFE_API_KEY` (`jev-key` is a `.env` alias) | `"typesafe/jev-latest"` | ``` r library(gptr) gptr_env("~/keys/models.env") gptr_config(model = "openai/gpt-6-sol", .scope = "user") session = peter("Explain the relationship between mpg and wt.", mtcars) session$text ``` At first interactive use of a remote route, gptr asks you to acknowledge the data sent to it. For unattended jobs, acknowledge the specific provider beforehand at user scope: ``` r gptr_config(egress = utils::modifyList(gptr_config()$egress, list(openai = "ack")), .scope = "user") ``` This covers automatic context; it does not pre-approve tool actions. Read `?gptr_egress` for the request contents and `?gptr_security` before using sensitive data. `gptr_login("openrouter")` offers an interactive login; `gptr_login("anthropic", method = "key")` offers masked key entry. These credentials are separate from a command-line tool's sign-in. An OpenAI-compatible service can use the existing completions adapter. Register its endpoint, credential variable and the model metadata supplied by your service: ``` r off = gptr_register(gptr_provider( "work", api = "openai-completions", base_url = "https://llm.example.org/v1", auth = "WORK_API_KEY", models = list(list(id = "work-model", context = 32000, max_output = 4000, tool_call = TRUE)) )) peter("Summarize these data.", mtcars, model = "work/work-model") off() # remove this process-lifetime provider registration ``` Declare features only when your service supports them. Endpoint compatibility alone does not establish tool, image or reasoning support. More built-in compatible routes appear in `gptr_providers()`; `?gptr_provider` documents registration and compatibility fields. ### Azure OpenAI and Amazon Bedrock The built-in Azure route reads `AZURE_OPENAI_API_KEY` and `AZURE_OPENAI_ENDPOINT`. Give the resource endpoint, such as `https://your-resource.openai.azure.com`; gptr adds `/openai/v1` and sends the key in the `api-key` header. The model sent to Azure is your deployment name. Declare that deployment and its real capacities in provider settings: ``` r gptr_env("~/keys/azure.env") # AZURE_OPENAI_API_KEY and AZURE_OPENAI_ENDPOINT azure_model = list(id = "analysis-chat", context = 32000, max_output = 4000, tool_call = TRUE) gptr_config( providers = list(azure = list(models = list(azure_model))), .scope = "session" ) session = peter("Summarize these data.", mtcars, model = "azure/analysis-chat") ``` Replace `analysis-chat` and the limits with your deployment's metadata; declare `tool_call` only when supported. Alternatively, `AZURE_OPENAI_DEPLOYMENT_NAME_MAP` maps a declared model id to its deployment using `model-id=deployment-name` pairs separated by commas. The built-in Bedrock route uses `AWS_BEARER_TOKEN_BEDROCK` with the runtime's OpenAI-compatible API. `AWS_REGION`, then `AWS_DEFAULT_REGION`, selects the region; the default is `us-east-1`. Its endpoint is `https://bedrock-runtime..amazonaws.com/openai/v1`. Choose a model your account can use through that API and declare its id and capacities: ``` r gptr_env("~/keys/bedrock.env") # AWS_BEARER_TOKEN_BEDROCK and AWS_REGION bedrock_model = list(id = "your-bedrock-model-id", context = 32000, max_output = 4000, tool_call = TRUE) gptr_config( providers = list(bedrock = list(models = list(bedrock_model))), .scope = "session" ) session = peter("Summarize these data.", mtcars, model = "bedrock/your-bedrock-model-id") ``` Replace the illustrative metadata with your service's values. This built-in route does not implement AWS SigV4 signing, AWS profile credentials or the general Bedrock Converse API. An AWS credentials file alone therefore does not authenticate it, and the route does not imply support for every Bedrock model. These remote providers need the egress acknowledgment described above, using provider ids `azure` and `bedrock`. ### Subscription command-line tools Install and sign in to the `claude` or `codex` tool outside gptr, following that tool's own setup. The executable must be on `PATH`, or you can give its path with the `gptr.cli_path` option. Then choose `model = "claude-cli"` (alias `claude_code`) or `model = "codex"`. ``` r options(gptr.cli_path = list(claude = "/path/to/claude", codex = "/path/to/codex")) gptr_providers(check = TRUE) session = peter("Inspect the columns of mtcars.", mtcars, model = "codex") ``` These calls run a child process. The built-in `claude-cli` route uses the Claude Code CLI's signed-in plan/OAuth authentication and refuses API-key billing. For API-key use, explicitly choose the direct `anthropic` provider. The Codex route uses the CLI's active authentication and billing. Live R access goes through gptr's MCP permission gate; the Codex route needs the suggested packages `httpuv`, `later` and `openssl`. First use asks for an acknowledgment. gptr checks required CLI flags and rejects incompatible versions. The Claude plan route is experimental and opt-in; review `?gptr_security` and the provider's terms before choosing it. ### Local Ollama models Run Ollama separately and install the model you intend to use. Discover the installed models, then copy a returned reference into the call: ``` r local_models = gptr_models(provider = "ollama", refresh = TRUE) local_models session = peter("Inspect mtcars and suggest a plot.", mtcars, model = "ollama/qwen3:1.7b") ``` The default server is `http://127.0.0.1:11434/v1`. For another local endpoint, configure its `base_url` explicitly with `gptr_config(providers = list(ollama = list(base_url = ...)), .scope = "user")`. gptr verifies installed-model capabilities and inference locality. Its default `local_only = TRUE` rejects cloud selectors, remote markers and ambiguous locality; it does not install, start or update Ollama, pull models or fall back to a cloud route. Conversational models return sessions. Clef and Clef Flash are native decision models, require Ollama 0.35.1 or later, and return logical, choice or score vectors. Their calls do not run an agent conversation. See [System 1 decisions](system-one.html). A local model does not keep a later cloud call or network tool local. ## Work with a session Ask for the analysis, then steer the same session: ``` r session = peter("Fit mpg from wt in mtcars. Save the model as fit.", mtcars) session |> peter("Explain how weight relates to fuel economy.") session$text ``` `gptr_fork(session)` explicitly branches the conversation into a new session with an overlay workspace. A model switch continues the existing history; a separate `peter()` call starts a new session: ``` r library(gptr) fake = gptr_fake_provider(list("Weight is associated with lower fuel economy.")) other = gptr_fake_provider(list("An association does not establish causation."), name = "other") session = peter("Describe how mpg relates to wt.", mtcars, model = fake) session |> peter("Add a caveat.", model = other) #> An association does not establish causation. #> idle . other/other-1 . 2 turns . 3.3k tokens . $0.0000 . s86baf8f136 ``` ## Put calls in functions and scripts Inside a function, `peter()` works in the function's own frame, so new objects stay local. Return the value Peter selected with ordinary R: ``` r numeric_means = function(data) { session = peter("Compute and return each numeric-column mean.", data) session$value } ```
Offline function example ``` r numeric_means = function(data) { fake = gptr_fake_provider(list( list(tool = "r", input = list(code = paste( "numeric = vapply(data, is.numeric, logical(1))", "means = colMeans(data[numeric])", "gptr_return(means)", sep = "\n" ))), "The numeric-column means are ready." )) session = peter("Compute and return each numeric-column mean.", data, model = fake, mode = auto) session$value } numeric_means(mtcars[c("mpg", "wt")]) #> mpg wt #> 20.09062 3.21725 ```
In a real script, replace the fake provider with an explicit model reference. Use `manual` when a person can answer permissions; for an unattended job, choose appropriate permission rules or an explicit mode before running it. `auto` still retains critical and secret guards. A permission question with nobody present raises `gptr_error_permission` and carries the blocked session as `e$session`. ``` r session = tryCatch( peter("Fit mpg on wt and return the coefficients.", mtcars, model = "openai/gpt-6-sol", mode = auto, budget = list(cost = 1, turns = 10)), gptr_error_permission = function(e) { message(conditionMessage(e)) e$session } ) session$status ``` `gptr_usage(session)` reports tokens and costs. `gptr_prompt(session)` inspects the frozen prompt, declared tools, first message and token estimates; it does not report the current request's budgets. Catalog prices and estimates are planning aids, and missing usage remains unknown. See [Token efficiency](token-efficiency.html) for limits and [Script as history](script-as-history.html) for recording and replay that removes repeated model calls.