You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

训练聊天机器人时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

错误原因

  1. 输入处理逻辑颠倒:代码中if inputs is not None and inputs != []:的判断逻辑写反,导致有效输入时未执行文本序列化、填充操作,inputs仍为原始字符串列表,无法被Embedding层处理。
  2. 模型构建方式错误:直接用Embedding层调用inputs变量,而非将其加入Sequential模型,不符合Keras模型构建规范。
  3. 输出数据未处理:outputs是原始文本字符串,未做编码转换,无法适配二元交叉熵损失的训练要求。
  4. 函数参数传递错误:调用train_conversation_model('chatbot.db')时传递了冗余参数,函数定义无需数据库路径。

修复步骤

  1. 修正输入处理判断:将判断改为if not inputs:,空输入时提示,否则执行文本预处理。
  2. 规范模型构建流程:将Embedding层添加到Sequential模型中,而非直接作用于输入变量。
  3. 处理输出数据:对回答文本执行与输入一致的序列化、填充操作,调整模型结构适配文本生成/匹配任务。
  4. 修正函数调用:调用train_conversation_model()时不传递多余参数。
  5. 调整模型损失函数:改用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 05:01:39