Spaces:
Runtime error
Runtime error
# Load required libraries | |
library(caret) | |
library(dplyr) | |
library(shiny) | |
library(jsonlite) # For JSON conversion | |
# Use the system's Python executable or configure Python path | |
python_path <- "python3" | |
model= readRDS("model.rds") | |
# Sample data table to display | |
difficulty_table <- data.frame( | |
Grade = c("Grade 3", "Grade 4", "Grade 5", "Grade 6", "Grade 7", "Grade 8"), | |
`Mean Grade-Level Difficulty` = c(0.3, 0.431, 0.533, 0.611, 0.656, 0.7) | |
) | |
# Define UI for the Shiny application | |
ui <- fluidPage( | |
titlePanel("Reading comprehension difficulty prediction using BERT embeddings"), | |
fluidRow( | |
column( | |
width = 12, | |
h4("How does this work?"), | |
p("This app predicts average difficulty for an item. Difficulty can be interpreted using the table below. As the table shows, difficulty increases with grade level. | |
For example, an item of difficulty 0.3 is of average difficulty for Grade 3, an item of difficulty 0.4 is of average difficulty for Grade 4, and so on. Note that as difficulty increases, probability of correct answer reduces."), | |
# Display the table as a rendered output | |
h5(""), | |
tableOutput("difficultyTable"), | |
# Add external link for NWEA norms | |
p("Difficulty outputs are on a linear scale. The scale is defined to have mean difficulty of 0.3 at Grade 3 and mean difficulty 0.7 at Grade 8. This scale is based on grade level growth norms reported by ", | |
a("NWEA MAP Spring 2020 Reading Student Achievement Norms", | |
href = "https://www.nwea.org/uploads/MAP-Growth-Normative-Data-Overview.pdf", target = "_blank")) | |
) | |
), | |
# App UI elements | |
sidebarLayout( | |
sidebarPanel( | |
width = 12, | |
textInput("passage", "Passage", placeholder = "Enter passage text here"), | |
textInput("question", "Question Text", placeholder = "Enter question text here"), | |
textInput("correctAnswer", "Correct Answer", placeholder = "Enter the correct answer here"), | |
# Numeric input to ask how many incorrect options (distractors) | |
numericInput("numDistractors", "Number of Incorrect Options:", value = 1, min = 1, max = 10), | |
# Dynamic UI for the distractors | |
uiOutput("distractorsInputs"), | |
actionButton("printBtn", "Estimate difficulty") | |
), | |
mainPanel( | |
h3("Estimated difficulty"), | |
verbatimTextOutput("inputsOutput") | |
) | |
) | |
) | |
# Function to call Python script and get combined input | |
call_python_script <- function(passage, question, distractors) { | |
# Prepare input data as JSON | |
input_data <- toJSON(list( | |
Passage = passage, | |
QuestionText = question, | |
Distractors = distractors | |
), auto_unbox = TRUE) | |
# Call the Python script and capture the output | |
result <- system2( | |
command = python_path, # Python executable | |
args = c("bertembedtoy.py"), # Python script name | |
input = input_data, # Pass input data as JSON | |
stdout = TRUE # Capture script output | |
) | |
# Return the result from Python | |
return(result) | |
} | |
# Read the CSV data into a dataframe | |
#embedding_df <- read.csv(text =result) | |
# Define server logic | |
server <- function(input, output, session) { | |
# Reactive value to store predictions | |
predictions <- reactiveVal(NULL) | |
#df <- reactiveVal(data.frame()) | |
# Render the difficulty table in the UI | |
output$difficultyTable <- renderTable({ | |
difficulty_table | |
}, rownames = FALSE) # Avoid showing rownames in the table | |
# Dynamically generate text inputs for distractors based on user input | |
output$distractorsInputs <- renderUI({ | |
n <- input$numDistractors # Get the number of distractors | |
if (is.null(n) || n <= 0) return(NULL) # No inputs if value is invalid | |
# Generate textInput fields dynamically | |
lapply(1:n, function(i) { | |
textInput(inputId = paste0("distractor", i), | |
label = paste("Wrong answer", i), | |
placeholder = paste("Enter wrong answer", i)) | |
}) | |
}) | |
# Event triggered when the button is clicked | |
observeEvent(input$printBtn, { | |
distractors <- c(sapply(1:input$numDistractors, function(i) {input[[paste0("distractor", i)]]})) | |
# Combine the distractors into a single string | |
for (i in 1:length(distractors)) { | |
distractors[i]= paste0("wrong answer ",i,":", distractors[i]) | |
} | |
distractors <- c(paste0("Correct answer:",input$correctAnswer), distractors) | |
distractors=paste(distractors, collapse = " \n") | |
print(distractors) | |
# Call the Python script and capture the dataframe | |
python_output <- call_python_script(input$passage, | |
input$question, | |
distractors) | |
result_vector <- as.numeric(unlist(strsplit(python_output, ","))) | |
result_vector= as.data.frame(t(result_vector) ) | |
names(result_vector) = paste0("embed.bert", 1:768) | |
model_predictions= predict(model, result_vector) | |
predictions(model_predictions) | |
}) | |
# Output predictions to the UI (or use it elsewhere) | |
output$inputsOutput <- renderPrint({ | |
predictions() | |
}) | |
} | |
# Run the Shiny App | |
shinyApp(ui = ui, server = server) | |