Format ellmer content for shinychat
Arguments
- content
An
ellmer::Contentobject.
Value
Returns text, HTML, or web component tags formatted for use in
chat_ui().
Extending contents_shinychat()
You can extend contents_shinychat() to handle custom content types in your
application. contents_shinychat() is an S7 generic. If
you haven't worked with S7 before, you can learn more about S7 classes,
generics and methods in the S7 documentation.
For most tool-result customization, use tool_result_display() in the
result's extra = list(display = ...). It keeps shinychat's compact activity
row and drill-down card while letting you set a title, label, result preview,
and rich card content. The Tool Calling UI article
describes that recommended path.
We'll work through a short example creating a custom display for the results of a tool that gets local weather forecasts. We first need to create a custom class that extends ellmer::ContentToolResult.
library(ellmer)
WeatherToolResult <- S7::new_class(
"WeatherToolResult",
parent = ContentToolResult,
properties = list(
location_name = S7::class_character
)
)Next, we'll create a simple ellmer::tool() that gets the weather forecast
for a location and returns our custom WeatherToolResult class. The custom
class works just like a regular ContentToolResult, but it has an additional
location_name property.
get_weather_forecast <- tool(
function(lat, lon, location_name) {
WeatherToolResult(
weathR::point_tomorrow(lat, lon, short = FALSE),
location_name = location_name
)
},
name = "get_weather_forecast",
description = "Get the weather forecast for a location.",
arguments = list(
lat = type_number("Latitude"),
lon = type_number("Longitude"),
location_name = type_string("Name of the location for display to the user")
)
)Finally, define the external generic and implement a method for your custom class:
contents_shinychat <- S7::new_external_generic(
package = "shinychat",
name = "contents_shinychat",
dispatch_args = "contents"
)
S7::method(contents_shinychat, WeatherToolResult) <- function(content) {
# Your custom rendering logic here
}Use S7::super() when you want to extend shinychat's default card. The
resulting output still participates in the normal compact activity row and
drill-down card:
S7::method(contents_shinychat, WeatherToolResult) <- function(content) {
# Call the super method for ContentToolResult to get shinychat's defaults
res <- contents_shinychat(S7::super(content, ContentToolResult))
# Then update the result object with more specific content
# In this case, we render the tool result dataframe as a {gt} table...
res$value <- gt::as_raw_html(gt::gt(content@value))
res$value_type <- "html"
# ...and update the tool result title to include the location name
res$title <- paste("Got weather forecast for", content@location_name)
res$label <- content@location_name
res$value_preview <- paste(nrow(content@value), "hourly readings")
res
}Alternatively, return arbitrary HTML or Shiny UI directly from the method to replace the default card completely. While the tool runs, shinychat still shows its activity row. When the custom result settles, shinychat renders that UI as standalone output and removes the call from the activity row.
This extension point is for fully custom standalone output. To customize the
default card, use tool_result_display() instead of constructing a generic
display list yourself.