步骤 1:审题与分解 描述:首先,我需要理解您的需求。您希望在PyCharm上运行一个简单的前端代码,用于完成作业。该前端应能连接本地的seq2seq框架模型,实现南京旅游问答系统的功能。未来可能还需要集成一个大语言模型。您已经提供了分词表(vocab.json)和训练好的模型文件(seq2seq_best.pth),并指定使用Python语言在Windows环境下开发。 决定:接下来,我将设计前端的基本结构,并确定如何与本地的seq2seq模型进行交互。 --- 步骤 2:设计前端界面 描述:为了实现南京旅游问答系统,前端需要有一个用户界面,允许用户输入问题并显示模型的回答。可以使用Python的`Flask`框架来搭建一个简单的Web应用,结合`HTML`、`CSS`和`JavaScript`来创建用户界面。需要确保前端能够与本地的seq2seq模型进行通信,这可以通过调用后端的API来实现。 决定:下一步是编写Flask应用的基本结构,并设置路由以处理用户的输入和模型的响应。 --- 步骤 3:集成Seq2Seq模型 描述:在Flask应用中,需要加载本地的seq2seq模型(seq2seq_best.pth)和分词表(vocab.json)。当用户提交问题时,前端将问题发送到后端,后端使用加载的模型生成回答,并将结果返回给前端显示。为了简化集成过程,可以使用`torch`库加载模型,并编写相应的推理代码。 决定:接下来,我将提供完整的Flask应用代码,包括必要的依赖导入、模型加载和路由处理。 --- 最终答案 ```python # 导入必要的依赖项 from flask import Flask, request, jsonify, render_template import torch import torch.nn as nn import json import os app = Flask(__name__) # 加载分词表 with open('vocab.json', 'r', encoding='utf-8') as f: vocab = json.load(f) word2idx = vocab['word2idx'] idx2word = vocab['idx2word'] # 定义Seq2Seq模型结构 class Encoder(nn.Module): def __init__(self, input_size, embed_size, hidden_size): super(Encoder, self).__init__() self.embedding = nn.Embedding(input_size, embed_size) self.rnn = nn.GRU(embed_size, hidden_size) def forward(self, src): embedded = self.embedding(src) outputs, hidden = self.rnn(embedded) return hidden class Decoder(nn.Module): def __init__(self, output_size, embed_size, hidden_size): super(Decoder, self).__init__() self.embedding = nn.Embedding(output_size, embed_size) self.rnn = nn.GRU(embed_size, hidden_size) self.fc = nn.Linear(hidden_size, output_size) def forward(self, trg, hidden): embedded = self.embedding(trg) output, hidden = self.rnn(embedded, hidden) output = self.fc(output) return output, hidden class Seq2Seq(nn.Module): def __init__(self, encoder, decoder, device): super(Seq2Seq, self).__init__() self.encoder = encoder self.decoder = decoder self.device = device def forward(self, src, trg, teacher_forcing_ratio=0.5): batch_size = src.size(0) trg_len = trg.size(0) trg_vocab_size = self.decoder.embedding.num_embeddings outputs = torch.zeros(trg_len, batch_size, trg_vocab_size).to(self.device) hidden = self.encoder(src) input = trg[0] for t in range(1, trg_len): output, hidden = self.decoder(input, hidden) outputs[t] = output top1 = output.argmax(1) input = trg[t] if torch.rand(1).item() < teacher_forcing_ratio else top1 return outputs # 初始化设备 device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') # 模型参数 INPUT_SIZE = len(word2idx) OUTPUT_SIZE = len(word2idx) EMBED_SIZE = 256 HIDDEN_SIZE = 512 # 初始化Encoder和Decoder encoder = Encoder(INPUT_SIZE, EMBED_SIZE, HIDDEN_SIZE).to(device) decoder = Decoder(OUTPUT_SIZE, EMBED_SIZE, HIDDEN_SIZE).to(device) model = Seq2Seq(encoder, decoder, device).to(device) # 加载训练好的模型参数 model.load_state_dict(torch.load('seq2seq_best.pth', map_location=device)) model.eval() # 定义文本预处理函数 def sentence_to_index(sentence): return [word2idx.get(word, word2idx['<unk>']) for word in sentence] def index_to_sentence(indices): return ' '.join([idx2word.get(idx, '<unk>') for idx in indices]) # 定义翻译函数 def translate(src): src_indices = sentence_to_index(src) src_tensor = torch.LongTensor(src_indices).unsqueeze(0).to(device) with torch.no_grad(): hidden = model.encoder(src_tensor) trg_indices = [word2idx['<sos>']] for i in range(50): # 限制最大长度 trg_tensor = torch.LongTensor(trg_indices).unsqueeze(0).to(device) output, hidden = model.decoder(trg_tensor, hidden) pred_token = output.argmax(2).item() trg_indices.append(pred_token) if pred_token == word2idx['<eos>']: break trg_sentence = index_to_sentence(trg_indices) return trg_sentence # 定义路由处理用户输入 @app.route('/') def home(): return render_template('index.html') @app.route('/ask', methods=['POST']) def ask(): data = request.get_json() user_question = data.get('question', '') answer = translate(user_question) return jsonify({'answer': answer}) # 运行Flask应用 if __name__ == '__main__': app.run(debug=True) ``` 说明: 1. 依赖导入:导入了Flask用于搭建Web应用,torch用于加载和运行seq2seq模型,json用于处理分词表。 2. 分词表加载:从`vocab.json`中加载词汇表,构建`word2idx`和`idx2word`字典。 3. 模型定义:定义了Encoder、Decoder和Seq2Seq类,确保与训练时的模型结构一致。 4. 模型加载:使用`torch.load`加载训练好的模型参数,并将模型设置为评估模式。 5. 文本处理函数:`sentence_to_index`将输入的句子转换为索引,`index_to_sentence`将输出的索引转换回句子。 6. 翻译函数:`translate`函数接收用户输入,经过模型生成回答。 7. 路由设置: - `/`路由渲染前端页面。 - `/ask`路由处理POST请求,接收用户问题,调用`translate`函数生成回答,并返回JSON响应。 8. 运行应用:在本地启动Flask服务器,开启调试模式以便在PyCharm中运行和调试。 三条额外需要注意的逻辑点: 1. 模型兼容性:确保`seq2seq_best.pth`文件中的模型架构与代码中定义的Encoder、Decoder和Seq2Seq类完全一致,否则会导致加载失败或运行时错误。 2. 输入输出处理:当前`translate`函数限制了生成回答的最大长度为50个词 [2025-05-25 22:54:47 | AI写代码神器 | 2056点数解答]