Samuel Tandoh
April 27, 2026
Smart Next-Word Prediction App
Product value: helps users type faster by suggesting likely next words.
The app uses an optimized n-gram backoff model.
predict_next_words <- function(input_text, top_n = 3) {
cleaned <- clean_input(input_text)
words <- unlist(strsplit(cleaned, " "))
words <- words[words != ""]
if (length(words) >= 2) {
context_tri <- paste(tail(words, 2), collapse = " ")
tri_match <- trigram_dt[context_tri]
if (nrow(tri_match) > 0) return(head(tri_match$next_word, top_n))
}
if (length(words) >= 1) {
context_bi <- tail(words, 1)
bi_match <- bigram_dt[context_bi]
if (nrow(bi_match) > 0) return(head(bi_match$next_word, top_n))
}
head(unigram_dt$word, top_n)
}
The model was evaluated on 5,000 held-out test cases.
| Metric | Result |
|---|---|
| Top-1 Accuracy | 8.84% |
| Top-3 Accuracy | 13.54% |
| Perplexity | 514.06 |
| Time for 1,000 predictions | 1.50 seconds |
| Approx. seconds per prediction | 0.0015 |
| Total model size | 28.41 MB |
Interpretation: the model is lightweight and fast enough for an interactive Shiny app, while still providing useful next-word suggestions.
How the user interacts with the app:
output$prediction <- renderText({
preds <- predict_next_words(input$user_text, top_n = 3)
preds[1]
})
output$top_predictions <- renderTable({
preds <- predict_next_words(input$user_text, top_n = 3)
data.frame(
Rank = seq_along(preds),
Predicted_Word = preds
)
})
Example:
Input: I am going
Prediction: to
This product demonstrates the full data science pipeline:
Future improvements: