Skip to content

Question: Unable to update a widget from within a tool function in Shiny app #152

@noamanemobidata

Description

@noamanemobidata

What I'm trying to achieve:
I want to create a tool that:

  • Geocodes an address using google_geocode()
  • Updates the main Google Map (rendered with renderGoogle_map()) to add a marker at the geocoded location
  • Returns the coordinates to the chat interface

Any guidance would be greatly appreciated!

library(shiny)
library(googleway)
library(bslib)
library(ellmer)
library(shinychat)
options(shinychat.tool_display = "rich")

# Google Maps API Key
GOOGLE_MAPS_API_KEY <- Sys.getenv("GOOGLE_MAPS_API_KEY")

ui <- bslib::page_sidebar(
  gap = 0,
  padding = 0,
  sidebar = sidebar(
    chat_mod_ui(
      "chat",
      messages = list(
        "Hi! Use this chat interface to chat with OpenAI's gpt-4o-mini."
      ),
      fill = TRUE,
      height = "90vh"
    ),
    width = 500
  ),
  google_mapOutput("map", height = "100%"),
  fillable = TRUE,
  fill = TRUE
)

server <- function(input, output, session) {
  
  # Render Google Map
  output$map <- renderGoogle_map({
    google_map(
      key = GOOGLE_MAPS_API_KEY,
      location = c(48.8566, 2.3522),
      zoom = 12
    )
  })
  
  # Define the tool in the server to have access to the Shiny context
  geocode_address <- tool(
    function(address) {
      library(googleway)
      
      # Geocoding the address
      result <- googleway::google_geocode(
        address, 
        key = Sys.getenv("GOOGLE_MAPS_API_KEY")
      )
      
      # Check the result
      if (result$status != "OK") {
        return(ContentToolResult(
          list(error = "Geocoding failed"),
          extra = list(display = list(
            show_request = FALSE,
            open = TRUE,
            html = paste0("<p style='color: red;'>Error: Unable to geocode address '", address, "'</p>"),
            title = "Geocoding Error"
          ))
        ))
      }
      
      # Extract coordinates
      lat <- result$results$geometry$location$lat[1]
      lng <- result$results$geometry$location$lng[1]
      
  
      google_map_update(map_id = "map") %>%
        add_markers(
          data = result$results$geometry$location,
          lat = "lat",
          lon = "lng"
        )
      
      coords <- list(lat = lat, lng = lng, address = address)
      
      # Création de la carte pour le chat
      map_widget <- google_map(
        key = Sys.getenv("GOOGLE_MAPS_API_KEY"),
        data = result$results$geometry$location,
        zoom = 15
      ) %>%
        add_markers(
          data = result$results$geometry$location,
          lat = "lat",
          lon = "lng"
        )
      
      # Conversion to HTML
      map_html <- as.character(htmltools::as.tags(map_widget))
      
      ContentToolResult(
        coords,
        extra = list(
          display = list(
            show_request = TRUE,
            open = TRUE,
            html = map_html,
            title = paste("Coordinates for", address)
          )
        )
      )
    },
    name = "geocode_address",
    description = "Get the latitude and longitude of an address using the Google Maps API.",
    arguments = list(
      address = type_string("The address to geocode.")
    ),
    annotations = tool_annotations(
      title = "Geocode Address",
      icon = bsicons::bs_icon("map")
    )
  )
  
  llm <- ellmer::chat("openai/gpt-4o-mini", echo = "all")
  llm$register_tool(geocode_address)
  chat_mod_server("chat", llm)
}

shinyApp(ui, server)```

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions