исправь ошибки
const tf = require('@tensorflow/tfjs-node');
const natural = require('natural');
const { Tokenizer } = natural;
const stopword = require('stopword');

// 1. Подготовка исходных данных
const questions = [
    "Как тебя зовут?", "Сколько тебе лет?", "Откуда ты?", "Чем ты занимаешься?",
    "Какой сегодня день?", "Какая сейчас погода?", "Что ты умеешь?", "Кто твой создатель?",
    "Как мне добраться до ближайшего магазина?", "Можешь рассказать анекдот?",
    "Какое сегодня число?", "Какие у тебя хобби?"
];

const answers = [
    "Меня зовут Алекс.", "Мне 25 лет.", "Я из Москвы.", 
    "Я изучаю машинное обучение.", "Сегодня среда.", 
    "Сегодня солнечно с небольшой облачностью.", 
    "Я могу вести беседу и отвечать на вопросы.", 
    "Меня создала команда разработчиков.",
    "Чтобы добраться до магазина, вам нужно идти прямо по улице и повернуть направо на втором светофоре.",
    "Конечно! Почему программисты любят природу? Потому что там много багов.",
    "Сегодня 18 ноября 2024 года.", 
    "Я люблю читать и программировать."
];

// 2. Функция препроцессинга текста
function preprocessText(texts) {
    return texts.map(text => {
        // Приведение к нижнему регистру и удаление пунктуации
        const lowerText = text.toLowerCase().replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "");
        const tokens = lowerText.split(" ");
        const filteredTokens = stopword.removeStopwords(tokens); // Удаление стоп-слов
        return filteredTokens.join(" ");
    });
}

const cleanQuestions = preprocessText(questions);
const cleanAnswers = preprocessText(answers);

// 3. Создание токенизаторов
const questionTokenizer = new Tokenizer();
questionTokenizer.setVocabulary(cleanQuestions);
const answerTokenizer = new Tokenizer();
answerTokenizer.setVocabulary(cleanAnswers);

// Преобразование текстов в последовательности чисел
const questionSequences = cleanQuestions.map(q => questionTokenizer.tokenize(q));
const answerSequences = cleanAnswers.map(a => answerTokenizer.tokenize(a));

// Определение максимальной длины последовательности
const maxQuestionLength = Math.max(...questionSequences.map(seq => seq.length));
const maxAnswerLength = Math.max(...answerSequences.map(seq => seq.length));

// Дополнение последовательностей до максимальной длины
function padSequences(sequences, maxLength) {
    return sequences.map(seq => {
        const paddedSeq = new Array(maxLength).fill(0);
        for (let i = 0; i < seq.length; i++) {
            paddedSeq[i] = seq[i];
        }
        return paddedSeq;
    });
}

const encoderInputData = padSequences(questionSequences, maxQuestionLength);
const decoderInputData = padSequences(answerSequences.map(seq => seq.slice(0, -1)), maxAnswerLength - 1);
const decoderTargetData = padSequences(answerSequences.map(seq => seq.slice(1)), maxAnswerLength - 1);

// 4. Определение модели Seq2Seq с механизмом внимания
function createModel() {
    const encoderInputs = tf.input({ shape: [maxQuestionLength] });
    const encoderEmbedding = tf.layers.embedding({ inputDim: questionTokenizer.vocabulary.length + 1, outputDim: 128 }).apply(encoderInputs);
    const encoderLSTM = tf.layers.lstm({ units: 256, returnState: true }).apply(encoderEmbedding);
    
    const [encoderOutputs, stateH, stateC] = encoderLSTM;

    const decoderInputs = tf.input({ shape: [maxAnswerLength - 1] });
    const decoderEmbedding = tf.layers.embedding({ inputDim: answerTokenizer.vocabulary.length + 1, outputDim: 128 }).apply(decoderInputs);
    
    const decoderLSTM = tf.layers.lstm({ units: 256, returnSequences: true }).apply(decoderEmbedding, { initialState: [stateH, stateC] });
    
    // Attention Mechanism
    const attentionWeights = tf.layers.dot({ axes: [2, 2] }).apply([decoderLSTM, encoderOutputs]);
    
    const contextVector = tf.layers.dot({ axes: [1, 2] }).apply([attentionWeights, encoderOutputs]);
    
    const decoderCombinedContext = tf.layers.concatenate().apply([decoderLSTM, contextVector]);
    
    const decoderOutputsFinal = tf.layers.dense({ units: answerTokenizer.vocabulary.length + 1, activation: 'softmax' }).apply(decoderCombinedContext);

    return tf.model({ inputs: [encoderInputs, decoderInputs], outputs: decoderOutputsFinal });
}

const model = createModel();
model.compile({ optimizer: 'adam', loss: 'sparse_categorical_crossentropy', metrics: ['accuracy'] });
model.summary();

// 5. Обучение модели
async function trainModel() {
    await model.fit([tf.tensor2d(encoderInputData), tf.tensor2d(decoderInputData)], tf.tensor3d(decoderTargetData), {
        batchSize: 64,
        epochs: 100,
        verbose: 2,
        callbacks: {
            onEpochEnd: (epoch, logs) => console.log(`Epoch ${epoch}: loss=${logs.loss}`)
        }
    });
}

trainModel().then(() => console.log('Обучение завершено.'));

// Функция для генерации ответов (инференс)
function decodeSequence(inputSeq) {
    let targetSeq = Array(maxAnswerLength).fill(0);
    targetSeq[0] = answerTokenizer.wordIndex['<START>'];

    let decodedSentence = '';
    
    for (let i = 0; i < maxAnswerLength; i++) {
        const outputTokens = model.predict([tf.tensor2d(inputSeq), tf.tensor2d(targetSeq)]);
        
        const sampledTokenIndex = outputTokens.argMax(-1).dataSync()[0];
        const sampledWord = answerTokenizer.indexWord[sampledTokenIndex];

        if (sampledWord !== '<END>') {
            decodedSentence += ' ' + sampledWord;
        }

        if (sampledWord === '<END>' || decodedSentence.split(' ').length > maxAnswerLength) {
            break;
        }

        targetSeq[i + 1] = sampledTokenIndex; // Обновляем целевую последовательность
    }

    return decodedSentence.trim();
}

// Функция для получения ответа на пользовательский вопрос
function getResponse(question) 
{
    const cleanQuestionTokensRemovedPunctuationAndStopwords(question);
    const seqPaddedSeqCleanedQuestionTransformedToSequence();
    return decodeSequence(paddedSeq);
}
// Пример использования модели
const userQuestion1Response2() 
console.log(getResponse("Чем ты занимаешься?"));