исправь ошибки
# Установка необходимых библиотек
# Убедитесь, что вы установили все необходимые библиотеки перед запуском кода.
# Вы можете установить их с помощью pip:
# pip install tensorflow numpy nltk

import tensorflow as tf
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, LSTM, Dense, Embedding, Concatenate, Attention
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
import numpy as np
import nltk
from nltk.corpus import stopwords
import string

# Загрузка ресурсов NLTK
nltk.download('stopwords')

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

answers = [
    "Меня зовут Алекс.",
    "Мне 25 лет.",
    "Я из Москвы.",
    "Я изучаю машинное обучение.",
    "Сегодня среда."
]

# 2. Функция препроцессинга текста
def preprocess_text(texts):
    processed_texts = []
    stop_words = set(stopwords.words('russian'))
    translator = str.maketrans('', '', string.punctuation)
    for text in texts:
        text = text.lower()  # Приведение к нижнему регистру
        text = text.translate(translator)  # Удаление пунктуации
        tokens = text.split()
        tokens = [word for word in tokens if word not in stop_words]  # Удаление стоп-слов
        processed_text = ' '.join(tokens)
        processed_texts.append(processed_text)
    return processed_texts

clean_questions = preprocess_text(questions)
clean_answers = preprocess_text(answers)

print("Препроцессинг завершен.")
print("Вопросы после препроцессинга:", clean_questions)
print("Ответы после препроцессинга:", clean_answers)

# 3. Создание токенизаторов для вопросов и ответов
# Токенизатор для вопросов
question_tokenizer = Tokenizer(filters='', oov_token='<OOV>')
question_tokenizer.fit_on_texts(clean_questions)
question_vocab_size = len(question_tokenizer.word_index) + 1

# Токенизатор для ответов
answer_tokenizer = Tokenizer(filters='', oov_token='<OOV>')
answer_tokenizer.fit_on_texts(clean_answers)
answer_vocab_size = len(answer_tokenizer.word_index) + 1

print(f"Размер словаря вопросов: {question_vocab_size}")
print(f"Размер словаря ответов: {answer_vocab_size}")

# 4. Преобразование текстов в последовательности чисел
question_sequences = question_tokenizer.texts_to_sequences(clean_questions)
answer_sequences = answer_tokenizer.texts_to_sequences(clean_answers)

# Добавление токена начала и конца последовательности для ответов
start_token = answer_vocab_size  # Токен <START>
end_token = answer_vocab_size + 1  # Токен <END>
answer_vocab_size += 2  # Обновляем размер словаря ответов

for i in range(len(answer_sequences)):
    answer_sequences[i] = [start_token] + answer_sequences[i] + [end_token]

# Определение максимальной длины последовательности
max_question_length = max(len(seq) for seq in question_sequences)
max_answer_length = max(len(seq) for seq in answer_sequences)

# Дополнение последовательностей до максимальной длины
encoder_input_data = pad_sequences(question_sequences, maxlen=max_question_length, padding='post')
decoder_input_data = pad_sequences([seq[:-1] for seq in answer_sequences], maxlen=max_answer_length - 1, padding='post')
decoder_target_data = pad_sequences([seq[1:] for seq in answer_sequences], maxlen=max_answer_length - 1, padding='post')

print("Данные подготовлены.")

# 5. Построение модели Seq2Seq с механизмом внимания
embedding_dim = 128
lstm_units = 256

# Энкодер
encoder_inputs = Input(shape=(max_question_length,), name='encoder_inputs')
encoder_embedding = Embedding(input_dim=question_vocab_size, output_dim=embedding_dim, mask_zero=True, name='encoder_embedding')(encoder_inputs)
encoder_lstm = LSTM(lstm_units, return_sequences=True, return_state=True, name='encoder_lstm')
encoder_outputs, state_h, state_c = encoder_lstm(encoder_embedding)
encoder_states = [state_h, state_c]

# Декодер
decoder_inputs = Input(shape=(max_answer_length -1,), name='decoder_inputs')
decoder_embedding = Embedding(input_dim=answer_vocab_size, output_dim=embedding_dim, mask_zero=True, name='decoder_embedding')(decoder_inputs)
decoder_lstm = LSTM(lstm_units, return_sequences=True, return_state=True, name='decoder_lstm')
decoder_outputs, _, _ = decoder_lstm(decoder_embedding, initial_state=encoder_states)

# Механизм внимания
attention_layer = Attention(name='attention_layer')
# Исправленный вызов Attention слоя с использованием именованных аргументов
attention_result = attention_layer(query=decoder_outputs, value=encoder_outputs)

# Конкатенация внимания с декодером
decoder_concat_input = Concatenate(axis=-1, name='concat_layer')([decoder_outputs, attention_result])

# Полносвязный слой для предсказания
decoder_dense = Dense(answer_vocab_size, activation='softmax', name='decoder_dense')
decoder_outputs_dense = decoder_dense(decoder_concat_input)

# Создание модели
model = Model([encoder_inputs, decoder_inputs], decoder_outputs_dense)
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.summary()

# 6. Обучение модели
# Преобразование целевых данных в формат, подходящий для loss='sparse_categorical_crossentropy'
decoder_target_data = np.expand_dims(decoder_target_data, -1)

# Параметры обучения
epochs = 1000
batch_size = 64

# Обучение модели
model.fit(
    [encoder_input_data, decoder_input_data],
    decoder_target_data,
    batch_size=batch_size,
    epochs=epochs,
    verbose=2
)

# 7. Создание моделей энкодера и декодера для инференса

# Модель энкодера
encoder_model_inf = Model(encoder_inputs, [encoder_outputs, state_h, state_c])

# Настройка входов для декодера во время инференса
decoder_state_input_h = Input(shape=(lstm_units,), name='decoder_state_input_h')
decoder_state_input_c = Input(shape=(lstm_units,), name='decoder_state_input_c')
decoder_hidden_state_input = Input(shape=(max_question_length, lstm_units), name='decoder_hidden_state_input')

# Получение эмбеддингов для декодера
decoder_embedding_inf = decoder_embedding(decoder_inputs)

# Декодирование с состояниями из предыдущего шага
decoder_outputs_inf, state_h_inf, state_c_inf = decoder_lstm(
    decoder_embedding_inf, initial_state=[decoder_state_input_h, decoder_state_input_c]
)

# Механизм внимания
attention_result_inf = attention_layer(query=decoder_outputs_inf, value=decoder_hidden_state_input)

# Конкатенация
decoder_concat_input_inf = Concatenate(axis=-1)([decoder_outputs_inf, attention_result_inf])

# Выходной слой
decoder_outputs_inf = decoder_dense(decoder_concat_input_inf)

# Создание модели декодера
decoder_model_inf = Model(
    [decoder_inputs, decoder_hidden_state_input, decoder_state_input_h, decoder_state_input_c],
    [decoder_outputs_inf, state_h_inf, state_c_inf]
)

# 8. Функция для генерации ответов
def decode_sequence(input_seq):
    # Получение состояний энкодера и его выходов
    encoder_outs, state_h, state_c = encoder_model_inf.predict(input_seq)

    # Инициализация целевой последовательности с токеном <START>
    target_seq = np.array([[start_token]])

    # Инициализация переменных
    stop_condition = False
    decoded_tokens = []
    max_dec_steps = max_answer_length - 1

    while not stop_condition and len(decoded_tokens) < max_dec_steps:
        # Предсказание следующего слова
        output_tokens, h, c = decoder_model_inf.predict([target_seq, encoder_outs, state_h, state_c])

        # Выбор слова с наибольшей вероятностью
        sampled_token_index = np.argmax(output_tokens[0, -1, :])
        sampled_word = answer_tokenizer.index_word.get(sampled_token_index, '<OOV>')

        # Проверка условия остановки
        if sampled_word == '<OOV>' or sampled_word == '<END>':
            stop_condition = True
        else:
            decoded_tokens.append(sampled_word)

        # Обновление целевой последовательности
        target_seq = np.array([[sampled_token_index]])

        # Обновление состояний
        state_h, state_c = h, c

    return ' '.join(decoded_tokens)

# 9. Функция для получения ответа на пользовательский вопрос
def get_response(question):
    # Препроцессинг вопроса
    question = question.lower()
    question = question.translate(str.maketrans('', '', string.punctuation))
    tokens = question.split()
    tokens = [word for word in tokens if word not in set(stopwords.words('russian'))]
    clean_question = ' '.join(tokens)

    # Преобразование в последовательность
    seq = question_tokenizer.texts_to_sequences([clean_question])
    padded_seq = pad_sequences(seq, maxlen=max_question_length, padding='post')

    # Генерация ответа
    answer = decode_sequence(padded_seq)
    return answer

# 10. Пример использования модели
user_question = "Чем ты занимаешься?"
response = get_response(user_question)
print("Вопрос:", user_question)
print("Ответ:", response)

# Дополнительный пример
user_question2 = "Откуда ты?"
response2 = get_response(user_question2)
print("\nВопрос:", user_question2)
print("Ответ:", response2)