Skip to contents

Overview

This guide explains how to enrich your slides with AI in two complementary ways:

  • Speaker notes with get_ai_notes() — attaches an AI-written analysis to each slide as PowerPoint speaker notes (hidden from the audience, visible to the presenter).
  • Story slides with add_ai_story() — a post-processing step that reads a generated deck, asks an LLM to tell the story of the data, and inserts real content slides (a summary section at the front and a conclusions section at the end) that show in presentation mode.

Both features talk to an LLM through the ellmer package, so they work against a local model (Ollama) or a hosted provider (Anthropic/Claude, OpenAI, DeepSeek).

Note — two different AI roles, don’t conflate them. autoslider.core ships an MCP server (inst/mcp/autoslider_mcp_server.R). When you drive it from an MCP client — Claude Desktop / Claude Code, or CodeBuddy — that client is helping with the coding and programming part: it orchestrates the pipeline tools (list_programs, load_spec, run_pipeline, generate_slides, add_ai_notes, add_ai_story) conversationally so you don’t have to write the R by hand.

The insight generation part — actually reading the tables and writing the narrative — is not done by the MCP client. It is performed by whatever LLM you configure through ellmer, and that call requires an API key (for a hosted provider) or a running local endpoint (for Ollama). In short: the MCP client writes and runs the code; ellmer (with your key) produces the analytical content. These can even be different models — e.g. Claude Code orchestrating a run whose notes are generated by DeepSeek.

Prerequisite

Before you begin, ensure you have the following ready:

  • A Prompt File (prompt.yml) containing the instructions for the AI model (needed for get_ai_notes(); add_ai_story() builds its own prompt from the tables and needs no prompt file).

  • Access to an LLM: either a local instance (Ollama) or an API key for a hosted provider. API keys are read from the usual environment variables (ANTHROPIC_API_KEY, OPENAI_API_KEY, DEEPSEEK_API_KEY) or passed directly.

Please see autoslideR.Rmd for some readily available spec and filter examples and detailed instructions on how to use them. If you do not have an LLM model installed yet, see appendix on how to deploy your own local LLM.

Speaker notes workflow

The process involves three main steps: generating the initial slide data, adding the AI footnotes, and then creating the final PowerPoint file.

Step 1: Initial Slide Generation

First, generate the core slide outputs from your specification file. This process reads your spec, filters it for the desired programs, and generates the basic table and plot objects.

spec <- read_spec("path/to/your/spec.yml")
filters::load_filters("path/to/your/filter.yml")
prompt_list <- get_prompt_list("path/to/your/prompt.yml")

# Generate the initial outputs
outputs <- spec %>%
  filter_spec(program %in% c("t_dm_slide")) %>%
  generate_outputs(datasets = my_datasets) %>%
  decorate_outputs()

Step 2: Adding AI Footnotes

Next, pass the outputs object to the get_ai_notes() function. This function iterates through your outputs, and for each one that has a corresponding prompt, it communicates with the specified LLM model to generate a response in the form of a speaker note.

You can configure the function to point to different AI platforms.

Example: Using a Local LLM

This is ideal for local development. It assumes you have Ollama on your local machine and is developing in a Docker container.

outputs_ai <- get_ai_notes(
  outputs = outputs,
  prompt_list = prompt_list,
  platform = "ollama",
  base_url = "http://host.docker.internal:11434", # URL for Ollama if R in a Docker container
  model = "deepseek-r1:1.5b" # The LLM model name
)

The parameters you pass in might depend on your specific situation. In general:

  • platform: Set to ollama.

  • base_url: Points to where your Ollama instance is running.

  • model: The name of a model you have pulled in Ollama.

Step 3: Create the Final PowerPoint File

Finally, take the modified outputs_ai object and pass it to generate_slides() to create the presentation. The footnotes will be automatically included on the relevant slides.

outputs_ai %>%
  generate_slides(outfile = "My_AI_Presentation.pptx")

This will produce a PowerPoint file with your tables and plots, and enhanced with AI generated analysis.

Story slides workflow

Speaker notes are easy to miss — they never appear in presentation mode. When you want the narrative on the slides themselves, use add_ai_story(). It is a post-processing step: you first generate a normal deck, then hand the .pptx back to add_ai_story(), which reads the underlying tables, asks an LLM to tell the story, and inserts real content slides:

  • a summary section at the front of the deck (the key takeaways, before the detailed TLGs), and
  • a conclusions section at the end (the main conclusions and caveats).

Each inserted slide is a title plus concise bullets, on an AI-chosen layout drawn from a safe text-only subset (Section Header, Title and Content, Title Only) intersected with the layouts your template actually ships — so the narrative always renders.

Step 1: Generate the content deck

Build and write a deck as usual.

outputs <- spec %>%
  filter_spec(program %in% c("t_dm_slide", "t_ae_slide")) %>%
  generate_outputs(datasets = my_datasets) %>%
  decorate_outputs()

generate_slides(outputs, outfile = "deck.pptx")

Step 2: Add the AI story

Pass the same outputs (the data the story is told from) and the deck you just wrote. The result is a new deck with the summary and conclusions sections inserted.

# Using Anthropic / Claude (reads ANTHROPIC_API_KEY from the environment)
add_ai_story(
  outputs,
  infile   = "deck.pptx",
  outfile  = "deck_story.pptx",
  platform = "anthropic",
  model    = "claude-haiku-4-5",
  max_slides = 3        # cap on slides per section
)

The same call works against other providers — for example DeepSeek:

add_ai_story(
  outputs,
  infile   = "deck.pptx",
  outfile  = "deck_story.pptx",
  platform = "deepseek",
  base_url = "https://api.deepseek.com",
  model    = "deepseek-chat"
)

add_ai_story() prefers the provider’s native structured output; for providers that do not support it (e.g. DeepSeek) it automatically falls back to a plain-text JSON mode and parses the response, so all supported providers work.

Reminder: as with speaker notes, the storytelling is produced by ellmer and therefore needs an API key (hosted providers) or a local Ollama endpoint — even when you are orchestrating the run through an MCP client such as Claude Code or CodeBuddy. The MCP client handles the how (running the pipeline); the LLM you point ellmer at handles the what (the analysis).

Under the hood

add_ai_story() is a thin wrapper around two pieces you can also call directly:

  • get_ai_story(outputs, allowed_layouts, platform, ...) — the LLM call. Returns a structured list(summary = ..., conclusions = ...) of slides.
  • add_story_slides(ppt, story) — pure officer slide insertion (no network), so it is easy to test or to feed a hand-written story.

From the MCP server

The same capability is exposed as the add_ai_story MCP tool. A typical conversational flow from an MCP client (Claude Desktop/Code, CodeBuddy) is: load_specrun_pipelinegenerate_slidesadd_ai_story. Remember that the tool still calls out to ellmer for the narrative, so the provider key must be available to the R session running the MCP server.

Appendix

Running Your Local LLM

First of all, we need to download the Ollama tool at https://ollama.com/download. Once Ollama is installed, you can run any model from its library with a single command. For this example, we’ll use deepseek-r1:1.5b.

Open your command-line tool (e.g., Terminal, Windows PowerShell).

Type the following command and press Enter. Ollama will automatically download the model, which may take a few minutes.

$ ollama run deepseek-r1:1.5b

After the process completes, you will see a success message and a new prompt, like this:

$ >>> Send a message (/? for help)

This means you have successfully installed and are now running a local LLM. Feel free to start a conversation and play around with some prompts!