Add code to save the model parameters in a json file, vocab in a separate file with the appropriate extension to this code, **code**: import torch
import torch.nn as nn
from torch.utils.data import DataLoader, TensorDataset
import json

# Define pair-bit tokenizer
def tokenize(text):
    tokens = text.split()
    token_pairs = []
    for i in range(len(tokens)-1):
        token_pairs.append((tokens[i], tokens[i+1]))
    return token_pairs

# Load training data from JSON file
try:
    with open('Chatdata.json', 'r') as file:
        training_data = json.load(file)
except FileNotFoundError:
    print("Training data file not found.")
    exit()

# Tokenization using pair-bit tokenizer
vocab = set()
for item in training_data:
    token_pairs = tokenize(item['input'])
    token_pairs += tokenize(item['output'])
    vocab.update(token_pairs)
vocab_size = len(vocab) 
index_to_char = list(vocab)
char_to_index = {char: index for index, char in enumerate(index_to_char)}

# Convert input and output sequences to numerical representation and pad them
max_seq_length = max(max(len(tokenize(item['input'])), len(tokenize(item['output']))) for item in training_data)
input_sequences = torch.zeros((len(training_data), max_seq_length), dtype=torch.long)
output_sequences = torch.zeros((len(training_data), max_seq_length), dtype=torch.long)

for i, item in enumerate(training_data):
    input_seq = [char_to_index[pair] for pair in tokenize(item['input'])]
    output_seq = [char_to_index[pair] for pair in tokenize(item['output'])]
    input_sequences[i, :len(input_seq)] = torch.tensor(input_seq)
    output_sequences[i, :len(output_seq)] = torch.tensor(output_seq)

# Define LSTM model
class ChatbotLSTM(nn.Module):
    def __init__(self, vocab_size, hidden_size):
        super(ChatbotLSTM, self).__init__()
        self.hidden_size = hidden_size
        self.embedding = nn.Embedding(vocab_size, hidden_size)
        self.lstm = nn.LSTM(hidden_size, hidden_size, batch_first=True)
        self.fc = nn.Linear(hidden_size, vocab_size)

    def forward(self, input_seq):
        embedded = self.embedding(input_seq)
        lstm_out, _ = self.lstm(embedded)
        output = self.fc(lstm_out)
        return output

# Initialize the model
hidden_size = 512
model = ChatbotLSTM(vocab_size, hidden_size)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

# Create DataLoader for batch processing
batch_size = 64
dataset = TensorDataset(input_sequences, output_sequences)
dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True)

# Train the model
model.train()
for epoch in range(200):
    for input_batch, target_batch in dataloader:
        optimizer.zero_grad()
        output = model(input_batch)
        
        # Reshape the output and target for CrossEntropyLoss, needs batches to come first
        loss = criterion(output.view(-1, vocab_size), target_batch.view(-1))
        loss.backward()
        optimizer.step()

    # Print loss after each epoch
    print(f'Epoch {epoch+1}, Loss: {loss.item()}')

# Save the trained model and the mappings
torch.save({
    'model_state_dict': model.state_dict(),
    'char_to_index': char_to_index,
    'index_to_char': index_to_char
}, 'chatbot_model_5.pth')