File size: 6,353 Bytes
002cfd7 3a638e2 d2fa5f2 3a638e2 d2fa5f2 5e99ac2 d2fa5f2 3a638e2 002cfd7 3a638e2 002cfd7 3a638e2 002cfd7 3a638e2 002cfd7 3a638e2 002cfd7 3a638e2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
library(shiny)
library(bslib)
library(bs4Dash)
library(ellmer)
library(querychat)
library(gapminder)
library(highcharter)
library(reactable)
library(shinychat)
# get Gemini api key
api_key = Sys.getenv("GOOGLE_API_KEY")
# create data of the first 500 rows in gapminder
gdp_data <- gapminder
# initialize querychat with mtcars dataset and Gemini chat function
querychat_config <- querychat_init(gdp_data,
create_chat_func = purrr::partial(ellmer::chat_google_gemini, model = "gemini-2.0-flash"),
greeting = "")
# define the UI of the dashboard
ui <- tabsetPanel(
id = "tabs",
type = "pills",
tabPanel(
id = "query-tab",
title = strong("Data Query"),
icon = icon("chart-line",lib = "font-awesome",),
page_sidebar(
# hover bounce effect of value boxes
tags$head(
tags$style(HTML("
.bounce-hover:hover {
animation: bounce 0.6s infinite alternate;
}
.bounce-hover {
box-shadow: 0 7px 7px grey;
}
@keyframes bounce {
from {
transform: translateY(0);
}
to {
transform: translateY(-10px);
}
}
"))
),
sidebar = querychat_sidebar("chat",width = "25%"),
# to change div background color on hover: onmouseover = "this.style.backgroundColor='mediumseagreen';", onmouseout="this.style.backgroundColor='DodgerBlue';". In style = "cursor: pointer;
fluidRow(column(4,tags$div(class = "bounce-hover",valueBoxOutput("GDP"), style = "text-align:center; font-size: 20px; font-weight: bold;color:black;")),
column(4,tags$div(class = "bounce-hover",valueBoxOutput("Population"), style = "text-align:center; font-size: 20px; font-weight: bold;")),
column(4,tags$div(class = "bounce-hover",valueBoxOutput("LifeExp"),style = "text-align:center; font-size: 20px; font-weight: bold;"))),
fluidRow(column(6,highchartOutput("line",width = "98%")),
column(6,highchartOutput("column",width = "98%"))),
fluidRow(reactable::reactableOutput("table",width = "100%"))
)
),
tabPanel(
id = "chat-tab",
title = strong("EconoBot"),
icon = icon("robot",lib = "font-awesome"),
h3(strong("🤖 EconoBot"),style="text-align:center;color:DodgerBlue;"),
h5(strong("Answers your economic and financial questions"),style="text-align:center;color:#37474f;"),
chat_ui("gemini_chat",placeholder = "Type your message here...")
)
)
# define the server logic required to interact with the data
server <- function(input, output) {
# create a querychat object using the config from step 1.
query_chat <- querychat_server("chat", querychat_config)
output$table <- reactable::renderReactable({
reactable::reactable(query_chat$df(),
bordered = T,
compact = T,
highlight = T,
striped = T,
searchable = T,
filterable = T,
defaultColDef = colDef(align = "center"),
theme = reactable::reactableTheme(
stripedColor = "#0091ea",
borderColor = "#0091ea",
borderWidth = 3
))
})
output$line <- renderHighchart({
req(query_chat$df())
my_colors <- c("Africa" = "#1f77b4", "Asia" = "#ff7f0e", "Europe" = "#2ca02c",
"Americas" = "#d62728", "Oceania" = "#9467bd")
hchart(query_chat$df(),
type = "line",
hcaes(x = year, y = pop, group = continent)) |>
hc_colors(unname(my_colors)) |>
hc_title(text = "Population Per Continent or Country")
})
output$column <- renderHighchart({
req(query_chat$df())
my_colors <- c("Africa" = "#1f77b4", "Asia" = "#ff7f0e", "Europe" = "#2ca02c",
"Americas" = "#d62728", "Oceania" = "#9467bd")
hchart(query_chat$df(),
type = "column",
hcaes(x = year, y = gdpPercap, group = continent)) |>
hc_colors(unname(my_colors)) |>
hc_title(text = "GDP Per Capita Per Continent or Country")
})
output$GDP <- renderValueBox({
req(query_chat$df())
valueBox(
value = round(mean(query_chat$df()$gdpPercap, na.rm = TRUE), 2),
color = "success",
icon = icon("dollar"),
elevation = 4,
width = 4,
subtitle = " ",
footer = "Average GDP Per Capita"
)
})
output$Population <- renderValueBox({
req(query_chat$df())
valueBox(
value = round(mean(query_chat$df()$pop, na.rm = TRUE), 0),
color = "primary",
icon = icon("people-group"),
elevation = 4,
width = 4,
subtitle = " ",
footer = "Average Population"
)
})
output$LifeExp <- renderValueBox({
req(query_chat$df())
valueBox(
value = round(mean(query_chat$df()$lifeExp, na.rm = TRUE), 2),
color = "warning",
icon = icon("person-walking"),
elevation = 4,
width = 4,
subtitle = " ",
footer = "Average Life Expectancy"
)
})
# write logic for Gemini chat
gemini <- chat_google_gemini(
system_prompt = "You are a friendly and helpful economic and financial expert who only answers questions around country economy and finance. If a user asks a question that is not related to economics or finance, give the following polite response: 'I'm sorry, I can only provide economic and financial information'.
Also, if a user asks for specific or personal financial advice, give the following polite response: 'I'm sorry, I cannot provide specific financial advice. Please consult a financial advisor for personalized guidance.'",
model = "gemini-2.0-flash",
api_key = api_key,
echo = T
)
observeEvent(input$gemini_chat_user_input, {
# input$gemini_chat_user_input is from the chat id in the UI
gemini$chat_async(input$gemini_chat_user_input)$then(function(response) {
chat_append("gemini_chat", response)
})$catch(function(error) {
warning("An error occurred during chat_async: ", error$message)
})
})
}
# Run the application
shinyApp(ui = ui, server = server)
|