使用 Python 实现一个简单的人工智能对话系统,能够根据用户的输入进行简单的自然语言对话
时间: 2023-06-12 12:07:05 浏览: 66
好的,我们可以使用 Python 中的自然语言处理库 NLTK 和 PyTorch 实现一个简单的人工智能对话系统。我们可以使用 Seq2Seq 模型,其中 Encoder 将输入语句编码成一个向量,Decoder 将这个向量解码成输出语句。
以下是一个简单的示例代码:
```python
import nltk
from nltk.stem import WordNetLemmatizer
import numpy as np
import torch
import torch.nn as nn
from torch.utils.data import Dataset, DataLoader
# 定义一个简单的对话数据集
dataset = {
"hello": "Hi there!",
"what's your name?": "My name is AI.",
"how are you?": "I'm doing well, thank you.",
"bye": "Goodbye!"
}
# 定义一个词形还原器
lemmatizer = WordNetLemmatizer()
# 分词和词形还原
def tokenize(sentence):
tokens = nltk.word_tokenize(sentence)
return [lemmatizer.lemmatize(token.lower()) for token in tokens]
# 定义一个编码器
class Encoder(nn.Module):
def __init__(self, vocab_size, embedding_size, hidden_size):
super().__init__()
self.embedding = nn.Embedding(vocab_size, embedding_size)
self.gru = nn.GRU(embedding_size, hidden_size)
def forward(self, input):
embedded = self.embedding(input)
output, hidden = self.gru(embedded)
return hidden
# 定义一个解码器
class Decoder(nn.Module):
def __init__(self, vocab_size, embedding_size, hidden_size):
super().__init__()
self.embedding = nn.Embedding(vocab_size, embedding_size)
self.gru = nn.GRU(embedding_size, hidden_size)
self.fc = nn.Linear(hidden_size, vocab_size)
def forward(self, input, hidden):
embedded = self.embedding(input)
output, hidden = self.gru(embedded, hidden)
output = self.fc(output)
return output, hidden
# 定义一个对话数据集类
class ChatDataset(Dataset):
def __init__(self, dataset):
self.questions = []
self.answers = []
for question, answer in dataset.items():
self.questions.append(tokenize(question))
self.answers.append(tokenize(answer))
self.vocab = set([word for sentence in self.questions + self.answers for word in sentence])
self.word2idx = {word: idx for idx, word in enumerate(self.vocab)}
self.idx2word = {idx: word for word, idx in self.word2idx.items()}
def __len__(self):
return len(self.questions)
def __getitem__(self, index):
question = self.questions[index]
answer = self.answers[index]
question = [self.word2idx[word] for word in question]
answer = [self.word2idx[word] for word in answer]
question = np.array(question)
answer = np.array(answer)
return question, answer
# 定义一个对话数据集加载器
def collate_fn(batch):
questions = [item[0] for item in batch]
answers = [item[1] for item in batch]
questions = torch.from_numpy(np.array(questions))
answers = torch.from_numpy(np.array(answers))
return questions, answers
# 定义超参数
vocab_size = len(ChatDataset(dataset).vocab)
embedding_size = 128
hidden_size = 256
learning_rate = 0.001
batch_size = 2
num_epochs = 100
# 初始化模型
encoder = Encoder(vocab_size, embedding_size, hidden_size)
decoder = Decoder(vocab_size, embedding_size, hidden_size)
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(list(encoder.parameters()) + list(decoder.parameters()), lr=learning_rate)
# 加载数据集
dataset = ChatDataset(dataset)
dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True, collate_fn=collate_fn)
# 训练模型
for epoch in range(num_epochs):
for questions, answers in dataloader:
# 前向传播
encoder_hidden = encoder(questions)
decoder_input = answers[:, :-1]
decoder_hidden = encoder_hidden.unsqueeze(0)
decoder_output, _ = decoder(decoder_input, decoder_hidden)
decoder_output = decoder_output.reshape(-1, vocab_size)
answers = answers[:, 1:].reshape(-1)
loss = criterion(decoder_output, answers)
# 反向传播和优化
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 打印训练信息
print(f"Epoch {epoch+1}/{num_epochs}, Loss: {loss.item():.4f}")
# 使用模型进行对话
while True:
question = input("You: ")
if question == "quit":
break
question = tokenize(question)
question = [dataset.word2idx.get(word, len(dataset.vocab)) for word in question]
question = np.array(question)
question = torch.from_numpy(question).unsqueeze(0)
encoder_hidden = encoder(question)
decoder_input = torch.tensor([[dataset.word2idx["<start>"]]])
decoder_hidden = encoder_hidden.unsqueeze(0)
answer = ""
while True:
decoder_output, decoder_hidden = decoder(decoder_input, decoder_hidden)
decoder_output = decoder_output.squeeze(0)
token = torch.argmax(decoder_output).item()
if dataset.idx2word[token] == "<end>":
break
answer += dataset.idx2word[token] + " "
decoder_input = torch.tensor([[token]])
print(f"AI: {answer}")
```
在以上代码中,我们首先定义了一个简单的对话数据集,其中包含了一些常见的对话。然后我们使用 NLTK 库的分词和词形还原器将这些对话进行了预处理。
接下来我们定义了一个 Seq2Seq 模型,其中 Encoder 和 Decoder 都是单层的 GRU 网络。我们还定义了一个对话数据集类和一个对话数据集加载器,用于加载和处理对话数据集。
在训练模型时,我们使用了交叉熵损失函数和 Adam 优化器。在使用模型进行对话时,我们首先将用户的输入进行预处理,然后使用 Encoder 将其编码成一个向量。然后我们使用 Decoder 不断生成回答,直到生成了结束符号。
最后,我们可以使用以上代码实现一个简单的人工智能对话系统。