Download app.R from Geoeasy/rchat: direct link, hf CLI and curl.
- Browser
- Download file 3.12 kB
-
https://huggingface.co/spaces/Geoeasy/rchat/resolve/main/app.R
- Command line
-
hf download hf://spaces/Geoeasy/rchat/app.R
-
curl -L -o app.R https://huggingface.co/spaces/Geoeasy/rchat/resolve/main/app.R
3.12 kB
| # app.R | |
| library(shiny) | |
| library(httr2) | |
| #The variable OPENAI_API_KEY uses the NVIDIA API_KEY | |
| # Helper: resolve base URL (default to NVIDIA NIM OpenAI-compatible endpoint) | |
| nim_base_url <- Sys.getenv("OPENAI_BASE_URL", unset = "https://integrate.api.nvidia.com/v1") | |
| ui <- fluidPage( | |
| titlePanel("Chat com NVIDIA NIM via httr2 (Shiny)"), | |
| sidebarLayout( | |
| sidebarPanel( | |
| textInput("model", "Modelo (NIM)", value = "meta/llama-3.1-70b-instruct"), | |
| textAreaInput("system", "System prompt:", value = "You are a helpful assistant.", rows = 2), | |
| textAreaInput("pergunta", "Pergunta (user):", value = "Descreva o package leaflet no R.", rows = 4), | |
| sliderInput("temperature", "temperature:", min = 0, max = 1, value = 0.2, step = 0.1), | |
| numericInput("max_tokens", "max_tokens:", value = 400, min = 1, step = 50), | |
| actionButton("enviar", "Enviar", class = "btn-primary"), | |
| tags$hr(), | |
| helpText("Defina a variável de ambiente OPENAI_API_KEY nas configurações do Space.") | |
| ), | |
| mainPanel( | |
| h4("Resposta"), | |
| uiOutput("status"), | |
| verbatimTextOutput("resposta"), | |
| tags$hr(), | |
| #h5("Payload (debug)"), | |
| verbatimTextOutput("payload", placeholder = TRUE) | |
| ) | |
| ) | |
| ) | |
| server <- function(input, output, session) { | |
| resposta <- reactiveVal("") | |
| status <- reactiveVal("") | |
| payload <- reactiveVal(NULL) | |
| observeEvent(input$enviar, { | |
| # checagens básicas | |
| if (Sys.getenv("OPENAI_API_KEY", unset = "") == "") { | |
| resposta("Erro: a variável OPENAI_API_KEY não está definida nas variáveis do Space.") | |
| return(invisible(NULL)) | |
| } | |
| status("Enviando… aguarde") | |
| resposta("") | |
| body <- list( | |
| model = input$model, | |
| messages = list( | |
| list(role = "system", content = input$system), | |
| list(role = "user", content = input$pergunta) | |
| ), | |
| temperature = input$temperature, | |
| max_tokens = input$max_tokens | |
| ) | |
| payload(body) | |
| req <- request(paste0(nim_base_url, "/chat/completions")) |> | |
| req_headers( | |
| Authorization = paste("Bearer", Sys.getenv("OPENAI_API_KEY")), | |
| `Content-Type` = "application/json" | |
| ) |> | |
| req_body_json(body) | |
| tryCatch({ | |
| resp <- req_perform(req) | |
| if (resp_status(resp) >= 300) { | |
| status(paste("HTTP", resp_status(resp))) | |
| } else { | |
| status("OK") | |
| } | |
| out <- resp_body_json(resp) | |
| # compatível com OpenAI-style | |
| msg <- tryCatch(out$choices[[1]]$message$content, error = function(e) NULL) | |
| if (is.null(msg)) { | |
| # fallback: alguns provedores devolvem "text" direto | |
| msg <- tryCatch(out$choices[[1]]$text, error = function(e) "(sem conteúdo)") | |
| } | |
| resposta(msg) | |
| }, error = function(e) { | |
| status("Erro na requisição") | |
| resposta(paste("Erro:", e$message)) | |
| }) | |
| }) | |
| output$resposta <- renderText(resposta()) | |
| output$status <- renderUI({ | |
| s <- status() | |
| if (!nzchar(s)) return(NULL) | |
| div(style = "margin-bottom:8px;", strong("Status:"), span(s)) | |
| }) | |
| #output$payload <- renderPrint(payload()) | |
| } | |
| shinyApp(ui, server) | |