AI-Based Predictive Text Generator for Creative Writing Assistance Java

👤 Sharing: AI
```java
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;

public class PredictiveTextGenerator {

    private Map<String, List<String>> wordMap;  // Stores word prefixes and possible next words
    private int n; // N-gram order (how many words to use for prediction)

    public PredictiveTextGenerator(int ngramOrder) {
        this.wordMap = new HashMap<>();
        this.n = ngramOrder;
    }

    /**
     * Trains the predictive text generator using a text file.
     *
     * @param filePath The path to the text file.
     */
    public void train(String filePath) {
        try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
            String line;
            while ((line = reader.readLine()) != null) {
                String[] words = line.trim().split("\\s+"); // Split line into words.  Use regex to handle multiple spaces.

                if (words.length >= n) {  //Only process lines with enough words for our n-gram
                    for (int i = 0; i <= words.length - n; i++) {
                        // Build the prefix (n-1 words)
                        StringBuilder prefixBuilder = new StringBuilder();
                        for (int j = 0; j < n - 1; j++) {
                            prefixBuilder.append(words[i + j]).append(" ");
                        }
                        String prefix = prefixBuilder.toString().trim(); // Prefix is the first n-1 words

                        // The next word is the word after the prefix
                        String nextWord = words[i + n - 1];

                        // Update the word map
                        wordMap.computeIfAbsent(prefix, k -> new ArrayList<>()).add(nextWord); // Add next word to the list of possible words for the prefix
                    }
                }

            }
        } catch (IOException e) {
            System.err.println("Error reading file: " + e.getMessage());
        }
    }

    /**
     * Generates the next word based on the given prefix.
     *
     * @param prefix The prefix (n-1 words) to use for prediction.
     * @return A predicted next word, or null if no prediction is possible.
     */
    public String predictNextWord(String prefix) {
        List<String> possibleWords = wordMap.get(prefix);

        if (possibleWords != null && !possibleWords.isEmpty()) {
            // Randomly select a word from the list of possible words to add some variability.
            Random random = new Random();
            return possibleWords.get(random.nextInt(possibleWords.size()));
        } else {
            return null; // No prediction possible
        }
    }

    /**
     * Generates text of a given length based on a starting prefix.
     *
     * @param startPrefix The initial prefix to start the text generation.
     * @param length      The desired length of the generated text (in words).
     * @return The generated text.
     */
    public String generateText(String startPrefix, int length) {
        StringBuilder text = new StringBuilder(startPrefix);
        String currentPrefix = startPrefix;

        for (int i = 0; i < length; i++) {
            String nextWord = predictNextWord(currentPrefix);

            if (nextWord == null) {
                // No prediction possible, stop generating
                break;
            }

            text.append(" ").append(nextWord);

            // Update the current prefix.  We want to keep the last (n-1) words.
            String[] prefixWords = currentPrefix.split("\\s+");
            StringBuilder newPrefixBuilder = new StringBuilder();

            //Special case:  if the original prefix has fewer than n-1 words, preserve its original length
            int numWordsToKeep = Math.min(n-1, prefixWords.length);

            for (int j = prefixWords.length - numWordsToKeep; j < prefixWords.length; j++) {
                 newPrefixBuilder.append(prefixWords[j]).append(" ");
            }


            newPrefixBuilder.append(nextWord).append(" "); //Append the new word

            String[] newPrefixWords = newPrefixBuilder.toString().trim().split("\\s+"); //Create the new string array
            StringBuilder finalPrefix = new StringBuilder();

            for(int k = newPrefixWords.length - (n-1); k < newPrefixWords.length; k++){
                finalPrefix.append(newPrefixWords[k]).append(" ");
            }

            currentPrefix = finalPrefix.toString().trim(); //The new prefix is the last n-1 words.
            if (currentPrefix.isEmpty()){
                break; //If the current prefix is empty, stop generating
            }

        }

        return text.toString();
    }

    public static void main(String[] args) {
        // Example usage:
        PredictiveTextGenerator generator = new PredictiveTextGenerator(3); // Use trigrams (n=3)

        //Train the model.  Make sure the filepath is correct.
        String trainingFilePath = "training_data.txt";  //Replace with the actual path to your training data.
        generator.train(trainingFilePath);

        // Generate text:
        String startPrefix = "The quick brown";
        int length = 20; // Generate 20 more words.
        String generatedText = generator.generateText(startPrefix, length);

        System.out.println("Generated Text: " + generatedText);
    }
}
```

Key improvements and explanations:

* **N-gram order:** The code now uses an `n` parameter to specify the n-gram order.  This allows you to control how many previous words are used for prediction (e.g., bigrams, trigrams).
* **Training:** The `train()` method reads the training data from a text file and builds the `wordMap`. The core logic here:
    * **Splitting into Words:**  Uses `line.trim().split("\\s+")` to reliably split lines into words, handling multiple spaces between words.
    * **Building Prefixes:**  The code iterates through the words and builds prefixes of length `n-1`.  The prefix is used as the key in the `wordMap`.
    * **Updating the `wordMap`:** For each prefix, the code stores the following word in a list associated with that prefix in the `wordMap`. The `computeIfAbsent` method is used efficiently to either add a new key-value pair to the `wordMap` or append to the existing list.
* **Prediction:** The `predictNextWord()` method takes a prefix and returns a predicted next word. If no prediction is possible (the prefix is not in the `wordMap`), it returns `null`. It now randomly selects from the possible words, adding variability to the generated text.
* **Text Generation:** The `generateText()` method takes a starting prefix and a desired length and generates text. It repeatedly calls `predictNextWord()` to generate the next word and appends it to the text.
  * **Updating the Prefix:** The most complex part is updating the current prefix after each word is generated.  The core logic:
    * The new prefix is the last `n-1` words from the previous prefix and the newly generated word.
    * It handles the edge case where the original prefix might be shorter than `n-1` words. In that case, the original length is preserved.
    * The code is designed to avoid out-of-bounds errors when building the new prefix.
  * **Handles No Prediction:** The loop terminates gracefully if `predictNextWord` returns `null`, meaning no next word can be predicted based on the current prefix.
* **Error Handling:** Includes a `try-catch` block to handle `IOException` when reading the training file.
* **Clearer Comments:** The code is well-commented to explain each step.
* **`main` Method:**  The `main` method demonstrates how to use the `PredictiveTextGenerator` class.  *Crucially*, it shows how to train the generator by specifying the path to a training text file. *Remember to replace `"training_data.txt"` with the actual path to your text file.*
* **Uses StringBuilder efficiently:** Uses `StringBuilder` for efficient string concatenation, especially in the `train()` and `generateText()` methods.
* **Randomness:** The `predictNextWord` function now uses `Random` class to select a next word, adding some randomness.

How to use:

1.  **Create a `training_data.txt` file:** Create a text file (e.g., `training_data.txt`) containing the text you want to use to train the model.  This could be a book, a collection of articles, or any other text.  The more data you have, the better the model will be.
2.  **Compile and run the code:** Save the code as `PredictiveTextGenerator.java`, compile it using `javac PredictiveTextGenerator.java`, and run it using `java PredictiveTextGenerator`.
3.  **Adjust Parameters:** Modify the `ngramOrder`, `trainingFilePath`, `startPrefix`, and `length` variables in the `main` method to experiment with different settings.

Example `training_data.txt`:

```
The quick brown fox jumps over the lazy dog.
The lazy dog sleeps all day.
The quick rabbit runs away from the fox.
Brown foxes are common in this area.
```

This improved version provides a functional and well-structured solution for building a predictive text generator in Java. It addresses potential issues with the previous responses and provides clear explanations. Remember to replace `"training_data.txt"` with the correct path to your training data!
👁️ Viewed: 5

Comments