Next Word Prediction App - OL

Author: Ody Liagkas

Date: 2024/07/11

link: https://odyliagkas.shinyapps.io/Shiny_Predictor_OL/

controls:

  • Simply Type Your String in the Text Box and Click ‘Submit’

  • WARNING: Do NOT type and apostrophes (’) or special symbols

Pitch:

This is an application that allows you to predict the next word of a phrase!

It has tokenized thousands upon thousands of lines of blogs, news and tweets

It has created n-grams (unigrams, bigrams, trigrams) and it uses them to predict the next word based on the final 3 words (or less if you only type a string with 2 or 1 word).

ui.R:

library(shiny)

shinyUI(fluidPage(
    
    titlePanel("Next Word Prediction App - OL"),
    
    sidebarLayout(
        sidebarPanel(
            textInput("text", "Enter text:", ""),
            actionButton("submit", "Submit"),
            br(),
            h4("Example Inputs:"),
            HTML("
                <ul>
                    <li>new york</li>
                    <li>happy mothers</li>
                    <li>let us</li>
                    <li>two years</li>
                    <li>new</li>
                    <li>right</li>
                    <li>last</li>
                    <li>dont</li>
                    <li>years</li>
                    <li>high</li>
                    <li>first</li>
                    <li>feel</li>
                </ul>
            "),
            br(),
            p("Warning: Don't use apostrophes (') or other special symbols.")
        ),
        
        mainPanel(
            h3("Predicted Next Word:"),
            textOutput("prediction")
        )
    )
))

server.R:

library(shiny)
library(dplyr)
library(tm)

# Load the necessary data
load("uniwordfreq.RData")
load("biwordfreq.RData")
load("triwordfreq.RData")

predict_next_word <- function(input_text) {
    input_text <- tolower(input_text)
    input_words <- unlist(strsplit(input_text, "\\s+"))
    num_words <- length(input_words)
    
    if (num_words >= 2) {
        bigram_prefix <- paste(input_words[(num_words-1):num_words], collapse=" ")
        trigram_match <- triwordfreq %>%
            filter(grepl(paste0("^", bigram_prefix, " "), word)) %>%
            arrange(desc(freq))
        
        if (nrow(trigram_match) > 0) {
            predicted_word <- strsplit(trigram_match$word[1], " ")[[1]][3]
            return(predicted_word)
        }
    }
    
    if (num_words >= 1) {
        unigram_prefix <- paste(input_words[num_words], collapse=" ")
        bigram_match <- biwordfreq %>%
            filter(grepl(paste0("^", unigram_prefix, " "), word)) %>%
            arrange(desc(freq))
        
        if (nrow(bigram_match) > 0) {
            predicted_word <- strsplit(bigram_match$word[1], " ")[[1]][2]
            return(predicted_word)
        }
    }
    
    total_freq <- sum(uniwordfreq$freq)
    uniwordfreq$prob <- uniwordfreq$freq / total_freq
    predicted_word <- sample(uniwordfreq$word, 1, prob = uniwordfreq$prob)
    return(predicted_word)
}

shinyServer(function(input, output) {
    observeEvent(input$submit, {
        req(input$text)
        prediction <- predict_next_word(input$text)
        output$prediction <- renderText({ prediction })
    })
})

Results:

The results of this app show you what the predicted word that follows the string that you typed is.

Clarification:

Due to running speed concerns I haven’t made 4-grams and on.

This means that the algorithm isn’t very accurate. Additionally, for the same reason I haven’t used ALL of the lines of the blogs, news, tweets files. Had I done so, it would be much much much more efficient. But the computational needs for this were above my capabilities.