训练聊天机器人时TensorFlow模型报错:'list'对象无'dtype'属性
从SQLite3训练聊天机器人时的TensorFlow错误修复
问题概述
使用TensorFlow v2从SQLite3数据库训练聊天机器人时,训练函数抛出错误:'list' object has no attribute 'dtype',报错代码行:inputs = tf.keras.layers.Embedding(1000, 64, input_length=10)(inputs)。
环境配置
▶ Python 3.10.9 ▶ openai == 0.25.0 ▶ tensorflow == 3.9.0 ▶ pyttsx3 == 2.90 ▶ speech_recognition == 3.9.0 ▶ requests == 2.28.1 ▶ numpy == 1.24.0 ▶ nltk == 3.8
错误原因
- 输入处理逻辑颠倒:代码中
if inputs is not None and inputs != []:的判断逻辑写反,导致有效输入时未执行文本序列化、填充操作,inputs仍为原始字符串列表,无法被Embedding层处理。 - 模型构建方式错误:直接用Embedding层调用
inputs变量,而非将其加入Sequential模型,不符合Keras模型构建规范。 - 输出数据未处理:
outputs是原始文本字符串,未做编码转换,无法适配二元交叉熵损失的训练要求。 - 函数参数传递错误:调用
train_conversation_model('chatbot.db')时传递了冗余参数,函数定义无需数据库路径。
修复步骤
- 修正输入处理判断:将判断改为
if not inputs:,空输入时提示,否则执行文本预处理。 - 规范模型构建流程:将Embedding层添加到Sequential模型中,而非直接作用于输入变量。
- 处理输出数据:对回答文本执行与输入一致的序列化、填充操作,调整模型结构适配文本生成/匹配任务。
- 修正函数调用:调用
train_conversation_model()时不传递多余参数。 - 调整模型损失函数:改用
sparse_categorical_crossentropy更适配文本序列任务,同时调整输出层维度对应词汇表大小。
修正后的完整代码
import sqlite3 import numpy as np import openai import requests import speech_recognition as sr import pyttsx3 import tensorflow as tf import pickle DATABASE = "chatbot.db" # 连接数据库并创建conversations表(question/answer两列) conn = sqlite3.connect(DATABASE) cursor = conn.cursor() cursor.execute("CREATE TABLE IF NOT EXISTS conversations (question text, answer text)") conn.commit() # 语音识别函数 def recognize_voice(): r = sr.Recognizer() with sr.Microphone() as source: print("\n▶ ") audio = r.listen(source) try: text = r.recognize_google(audio, language='pt-BR') except sr.UnknownValueError: print("我没听懂你说的内容") text = None if text and text.strip() == "": print("未能识别到有效文本") text = None return text # 语音合成函数 def synthesize_voice(text): engine = pyttsx3.init() voices = engine.getProperty('voices') engine.setProperty('voice', voices[-2].id) engine.say(text) engine.runAndWait() # 维基百科搜索函数 def search_wikipedia(keyword): url = f"https://pt.wikipedia.org/w/api.php?action=opensearch&format=json&search={keyword}" response = requests.get(url) data = response.json() if len(data[1]) > 0: page_url = data[3][0] page_response = requests.get(page_url) page_html = page_response.text start = page_html.index("<p>") end = page_html.index("</p>") paragraph = page_html[start:end+4] return paragraph else: return "未找到关于该主题的信息。" # 训练神经网络函数 def train_conversation_model(vocabulary_size=10000, maximum_sequence_length=100, embedding_dimension=32): conn = sqlite3.connect(DATABASE) cursor = conn.cursor() cursor.execute("SELECT question, answer FROM conversations") data = cursor.fetchall() inputs = [] outputs = [] for datum in data: inputs.append(datum[0]) outputs.append(datum[1]) # 处理输入和输出文本 if not inputs: print("警告:没有可用的训练数据!") return # 初始化Tokenizer并拟合文本 tokenizer = tf.keras.preprocessing.text.Tokenizer(num_words=vocabulary_size, lower=True) tokenizer.fit_on_texts(inputs + outputs) # 同时拟合输入和输出文本 # 转换为序列并填充 inputs_seq = tf.keras.preprocessing.sequence.pad_sequences( tokenizer.texts_to_sequences(inputs), maxlen=maximum_sequence_length ) outputs_seq = tf.keras.preprocessing.sequence.pad_sequences( tokenizer.texts_to_sequences(outputs), maxlen=maximum_sequence_length ) # 取每个序列最后一个词作为训练目标(简单文本生成示例) outputs_target = np.expand_dims(outputs_seq[:, -1], axis=1) # 构建模型 model = tf.keras.Sequential([ tf.keras.layers.Embedding(vocabulary_size, embedding_dimension, input_length=maximum_sequence_length), tf.keras.layers.LSTM(units=64, return_sequences=True), tf.keras.layers.LSTM(units=32), tf.keras.layers.Dense(units=vocabulary_size, activation='softmax') ]) # 编译模型 model.compile( loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'] ) # 训练模型 model.fit(inputs_seq, outputs_target, epochs=10, batch_size=64) # 保存模型和tokenizer model.save('chatbot_model.h5') with open('tokenizer.pickle', 'wb') as handle: pickle.dump(tokenizer, handle, protocol=pickle.HIGHEST_PROTOCOL) # 使用OpenAI生成回复 def generate_response(question): openai.api_key = "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" model_engine = "text-davinci-003" prompt = f"请回答以下问题:\n{question}" completions = openai.Completion.create( engine=model_engine, prompt=prompt, max_tokens=2048, n=1, stop=None, temperature=0.8, top_p=1, frequency_penalty=1, presence_penalty=1, ) message = completions.choices[0].text return message.strip() # 聊天机器人主函数 def chatbot(): while True: print("\n选择交互方式:") print("1. 语音") print("2. 文字聊天") print("3. 训练神经网络") print("4. 退出") option = input("输入选项: ") if option == "1": question = recognize_voice() if question is None: continue response = generate_response(question) synthesize_voice(response) elif option == "2": question = input("\n你: ") response = generate_response(question) print(f"\n聊天机器人: {response}") elif option == "3": train_conversation_model() elif option == "4": break # 启动聊天机器人 chatbot()
内容的提问来源于stack exchange,提问作者PeakyBlinder
相关产品推荐
相关产品推荐

