RObservations #32: Creating an Instant Answer Oracle with httr and Shiny

Introduction

Knowing how to write API requests and handle their responses is a valuable skill that a developer, data
engineer or data analyst/scientist needs to know. In this short blog I share how its possible leverage DuckDuckGo’s instant answer API to create a oracle which can answer (some) of your questions using the httr package and Shiny.

Asking the instant answer API

The basic functionality is pretty straight forward. The code takes a individual query and returns an answer.

library(httr)
library(tidyverse)

getAnswer<-function(query) {
 raw_data<- paste0("https://api.duckduckgo.com/?q=",
             query,
             "&format=json") %>%
      GET() %>%
      content(type = "application/json")

 if(raw_data[["Abstract"]]==""){
   return("Sorry, I don't have an answer")
 } else{
   return(raw_data[["Abstract"]])
 }
 }

For some questions, the received answer is quite sophisticated (and quoted verbatim from Wikipedia).

getAnswer("What is R Programming?")

## [1] "R is a programming language for statistical computing and graphics supported by the R Core Team and the R Foundation for Statistical Computing. Created by statisticians Ross Ihaka and Robert Gentleman, R is used among data miners, bioinformaticians and statisticians for data analysis and developing statistical software. Users have created packages to augment the functions of the R language. According to user surveys and studies of scholarly literature databases, R is one of the most commonly used programming languages used in data mining. As of March 2022, R ranks 11th in the TIOBE index, a measure of programming language popularity, in which the language peaked in 8th place in August 2020. The official R software environment is an open-source free software environment within the GNU package, available under the GNU General Public License. It is written primarily in C, Fortran, and R itself. Precompiled executables are provided for various operating systems."

And for others, not so much.

getAnswer("What is 2+2?")

## [1] "Sorry, I don't have an answer"

Building a Shiny Application.

Whats nice about the API is that the request takes care of all the back-end we need for the front end to work. The code I used to create a simple user interface is:

library(shiny)
library(httr)
library(tidyverse)
# UI
ui <- fluidPage(
  # Application title
  titlePanel("Instant Answer Oracle"),
  HTML(
    '<h3>Made with the <img src="https://cdn.freebiesupply.com/logos/thumbs/2x/duckduckgo-2-logo.png" width="20%"</img>API</h3>'
  ),
  # Sidebar layout
  sidebarLayout(
    sidebarPanel(
      textInput("query",
                label = "",
                placeholder = "What is your question?"),
      actionButton("search",
                   "Find Answer")
    ),

    # Output
    mainPanel(
      htmlOutput("heading"),
      br(),
      htmlOutput("logo"),
      br(),
      htmlOutput('answer'),
      br(),
      htmlOutput('source')
    )
  )
)

# Define server logic required 
server <- function(input, output) {
  observeEvent(input$search, {
    raw <-
      paste0("https://api.duckduckgo.com/?q=",
             input$query,
             "&format=json") %>%
      GET() %>%
      content(type = "application/json")

    if (raw[["Abstract"]] == "") {
      output$heading <- renderText("")
      output$logo <- renderText("")
      output$answer <- renderText({
        "Sorry, I don't have an Answer"
      })
      output$source <- renderText("")

    } else{
      output$heading <- renderText(h2(raw[["Heading"]]) %>% as.character())
      output$logo <- renderText(img(
          src = paste0("https://duckduckgo.com", raw[["Image"]]),
          width = "50%"
        ) %>% as.character)
      output$answer <-renderText(p(raw[["Abstract"]]) %>% as.character())
      output$source <- renderText(paste0('<p>Source: <a href="',raw[["AbstractURL"]],'"\\>',raw[["AbstractURL"]],"</a></p>") %>% as.character())
    }

  })
}
# Run the application
shinyApp(ui = ui, server = server)

If you don’t want to run this code on your own machine to check it out, you can check it out on shinyapps.io. Unfortunately the current version of WordPress doesn’t permit iframe embedding for it to be run here, but I can share a screenshot instead.

Conclusion

This endeavor was my personal exploration with the package. When working, I often find myself switching to python to use the requests module as I find that httr converts json data into nested list form which is not the easiest to work with syntax-wise. With this little project, I got more used to using the synatx and also got to share how its possible to leverage the power of APIs for building applications.

Thank you for reading!

Want to see more of my content?

Be sure to subscribe and never miss an update!

4 Comments

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s