--- title: "Get started with foundryR" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Get started with foundryR} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} fixture_dir <- "getting-started" recording <- nzchar(Sys.getenv("FOUNDRY_RECORD_DOCS")) have_fixtures <- dir.exists(fixture_dir) && length(list.files(fixture_dir)) > 0 run_api <- requireNamespace("httptest2", quietly = TRUE) && (recording || have_fixtures) library(foundryR) if (run_api) { httptest2::start_vignette(fixture_dir) } knitr::opts_chunk$set(collapse = TRUE, comment = "#>", eval = run_api, fig.width = 7, fig.height = 4.5, out.width = "100%") ``` Work through this article once before the task-specific ones. It sets up credentials, gets one response, extracts two fields from course comments, and compares three short texts by embedding. Calls to Azure show output recorded from a live run, and setup code is shown but not run. ## Install Install the released package from CRAN: ```{r install-cran, eval = FALSE} install.packages("foundryR") ``` The development version on GitHub has the newest fixes. ```{r install-github, eval = FALSE} # install.packages("pak") pak::pak("farach/foundryR") ``` ## Configure credentials For API-key authentication, store the resource endpoint and key once: ```{r config-key, eval = FALSE} library(foundryR) foundry_set_endpoint(Sys.getenv("AZURE_FOUNDRY_ENDPOINT"), store = TRUE) foundry_set_key("your-api-key", store = TRUE) ``` `store = TRUE` writes package settings under `tools::R_user_dir("foundryR", "config")`; the file is plain text, so use session-only credentials or a refreshable token provider when that fits your security policy. Microsoft Entra ID uses a token provider instead of a static key. ```{r config-entra, eval = FALSE} foundry_set_endpoint(Sys.getenv("AZURE_FOUNDRY_ENDPOINT"), store = TRUE) foundry_set_token_provider(foundry_token_azure_cli(), scope = "resource") foundry_set_token_provider(foundry_token_azure_cli("https://ai.azure.com"), scope = "project") ``` The resource token uses the Cognitive Services audience. The project token uses the `https://ai.azure.com` audience. A provider is a function that asks the Azure CLI for a fresh token when the cached one is about to expire, so it lasts for the R session rather than being stored; put the two provider lines in your project's `.Rprofile` if you want them every session. `foundry_check_setup()` confirms that the resource endpoint, credentials, and default deployment work. ```{r check-setup, eval = FALSE} foundry_check_setup() ``` ## Understand endpoints and routes Microsoft Foundry exposes two endpoint shapes. A resource endpoint looks like `https://.openai.azure.com`. It is the default route for Responses API calls, files, vector stores, and most evaluation workflows that use OpenAI graders on existing columns. A project endpoint looks like `https://.services.ai.azure.com/api/projects/`. You need it for conversations, server-side agents, agent-backed responses, Foundry built-in evaluators, model-target evaluations, agent evaluations, and stored-response evaluations. Set a project endpoint when your workflow needs project objects: ```{r config-project, eval = FALSE} foundry_set_project_endpoint(Sys.getenv("AZURE_FOUNDRY_PROJECT_ENDPOINT"), store = TRUE) ``` Conversations, agents, and the evaluations that need the project use it automatically. Responses, files, vector stores, and other evaluations stay on the resource endpoint unless you pass `project_endpoint =` on a call, or call `foundry_set_route("project")` to send them to the project for the rest of the R session. Project evaluations need a Microsoft Entra ID token. In live tests on the default project, responses, conversations, files, vector stores, and agents all accepted the resource API key. ## Know deployment names The `model =` argument takes a deployment name, not a base model name. For example, if you deploy base model `gpt-5-nano` with deployment name `course-coder`, call: ```{r deployment-name, eval = FALSE} foundry_response("Code this comment.", model = "course-coder") ``` `foundry_models()` lists models available to the resource. It does not list the deployments you created in the Foundry portal. ```{r list-models, eval = FALSE} models <- foundry_models() models[, c("id", "owned_by")] ``` ## Get a first response The Responses API returns a tibble. Print the answer column when you want the text a reader or analyst will see: ```{r first-response} response <- foundry_response("Answer in one sentence: what is R?") response$output_text ``` Token columns support cost checks and audit logs. ```{r first-response-tokens} response[, c( "input_tokens", "output_tokens", "reasoning_tokens", "cached_input_tokens", "total_tokens" )] ``` `gpt-5-nano` is a reasoning model. Hidden reasoning tokens are included in `output_tokens`, so they are part of the output-token cost even though they are not visible in `output_text`. ## Extract structured fields Use structured extraction when free text needs to become analysis columns. This small schema codes course comments into sentiment and one short issue label: ```{r first-extract} schema <- foundry_schema( sentiment = schema_enum(c("positive", "negative", "mixed")), issue = schema_string("A short label for what the comment is about.") ) comments <- c( "The lecture made regression much clearer.", "The homework instructions were hard to follow.", "The examples helped, but I wanted more time for practice." ) coded <- foundry_extract(comments, schema = schema) coded[, c("sentiment", "issue")] ``` The enum keeps `sentiment` to three values you can count. The free-text `issue` field comes back in whatever form the model chooses, so two runs, or two similar comments, can produce labels that do not match. When a field needs to be counted, give it an enum and a codebook, as in `vignette("annotation-workflow")`. The returned tibble also contains dot-prefixed metadata such as response IDs, status, and raw response payloads. Keep those columns when you need provenance. Check `.error` before you analyze the fields. A failed row has missing fields, and `.error_msg` says why it failed. ## Embed and compare text Embeddings turn text into numeric vectors. For a first check, inspect the dimensions and ask which pair is most similar: ```{r first-embed} texts <- c( "The lecture made regression much clearer.", "Regression finally made sense after this class.", "The homework instructions were hard to follow." ) embeddings <- foundry_embed(texts, model = "text-embedding-3-small") embeddings[, c("text", "n_dims")] foundry_similarity(embeddings, top_k = 1) ``` `text-embedding-3-small` returns 1536 dimensions. `foundry_similarity()` computes cosine similarity from the embedding list-column. ## Choose the next article | Task | Read next | | --- | --- | | Learn the main workflow | [From text to defensible estimates](annotation-workflow.html) | | Annotate many rows | [Annotate at scale with the Batch API](files-batches.html) | | Search, cluster, or compare text | [Embeddings for research](embeddings.html) | | Put embeddings in a model recipe | [Embeddings in tidymodels recipes](tidymodels.html) | | Evaluate models or agents in Foundry | [Evaluate models and agents in Microsoft Foundry](evaluations.html) | | Analyze evaluation results | [Analyze evaluation results with uncertainty](evaluation-analysis.html) | | Gate outputs for safety | [Content Safety gates in a research pipeline](content-safety.html) | | Use tools, web search, or stateful turns | [Responses API](responses-api.html) | | Check endpoint and authentication coverage | [API support matrix](api-support.html) | | Transcribe or translate audio | [Transcribe and translate audio](audio.html) | | Generate images | [Generate images](media-generation.html) | ```{r cleanup, include = FALSE} if (run_api) { httptest2::end_vignette() } ```