|
|
|
|
|
library(shiny) |
|
|
library(httr2) |
|
|
|
|
|
|
|
|
|
|
|
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(), |
|
|
|
|
|
verbatimTextOutput("payload", placeholder = TRUE) |
|
|
) |
|
|
) |
|
|
) |
|
|
|
|
|
server <- function(input, output, session) { |
|
|
resposta <- reactiveVal("") |
|
|
status <- reactiveVal("") |
|
|
payload <- reactiveVal(NULL) |
|
|
|
|
|
observeEvent(input$enviar, { |
|
|
|
|
|
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) |
|
|
|
|
|
msg <- tryCatch(out$choices[[1]]$message$content, error = function(e) NULL) |
|
|
if (is.null(msg)) { |
|
|
|
|
|
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)) |
|
|
}) |
|
|
|
|
|
} |
|
|
|
|
|
shinyApp(ui, server) |
|
|
|
|
|
|