rchat / app.R
Geoeasy's picture
Update app.R
e5b68d3 verified
# 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)