# 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)