|
|
@ -1,3 +1,4 @@
|
|
|
|
|
|
|
|
import pymysql
|
|
|
|
import time
|
|
|
|
import time
|
|
|
|
import wave
|
|
|
|
import wave
|
|
|
|
import requests
|
|
|
|
import requests
|
|
|
@ -7,20 +8,18 @@ import pyttsx3
|
|
|
|
from tkinter import *
|
|
|
|
from tkinter import *
|
|
|
|
from tkinter import messagebox
|
|
|
|
from tkinter import messagebox
|
|
|
|
import speech_recognition as sr
|
|
|
|
import speech_recognition as sr
|
|
|
|
|
|
|
|
from tkinter import Text, Scrollbar, Entry, Button
|
|
|
|
import nltk
|
|
|
|
import nltk
|
|
|
|
from nltk.tokenize import word_tokenize
|
|
|
|
from nltk.tokenize import word_tokenize
|
|
|
|
from nltk.corpus import stopwords
|
|
|
|
from nltk.corpus import stopwords
|
|
|
|
from nltk.tokenize import RegexpTokenizer
|
|
|
|
|
|
|
|
from nltk.stem import WordNetLemmatizer
|
|
|
|
from nltk.stem import WordNetLemmatizer
|
|
|
|
from nltk.probability import FreqDist
|
|
|
|
|
|
|
|
import string
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Constants for audio recording
|
|
|
|
# Constants for audio recording
|
|
|
|
framer = 16000 # Sample rate
|
|
|
|
framer = 16000 # Sample rate
|
|
|
|
num_samples = 2000 # Sample points
|
|
|
|
num_samples = 2000 # Sample points
|
|
|
|
channels = 1
|
|
|
|
channels = 1
|
|
|
|
sampwidth = 2
|
|
|
|
sampwidth = 2
|
|
|
|
FILEPATH = 'myvoices.wav' # Specify the path to save the recorded audio file
|
|
|
|
audio_file = 'myvoices.wav' # Specify the path to save the recorded audio file
|
|
|
|
APP_ID = '73927317'
|
|
|
|
APP_ID = '73927317'
|
|
|
|
API_KEY = '3jGcj5fLma64CtB3tTEuLcei'
|
|
|
|
API_KEY = '3jGcj5fLma64CtB3tTEuLcei'
|
|
|
|
SECRET_KEY = 'qm8gPCF7DSKpqatx5ZQ8e4OvNLmgdYcG' # Add your own API credentials here
|
|
|
|
SECRET_KEY = 'qm8gPCF7DSKpqatx5ZQ8e4OvNLmgdYcG' # Add your own API credentials here
|
|
|
@ -38,29 +37,26 @@ class Speak():
|
|
|
|
def my_record(self):
|
|
|
|
def my_record(self):
|
|
|
|
pa = PyAudio()
|
|
|
|
pa = PyAudio()
|
|
|
|
stream = pa.open(format=paInt16, channels=channels, rate=framer, input=True, frames_per_buffer=num_samples)
|
|
|
|
stream = pa.open(format=paInt16, channels=channels, rate=framer, input=True, frames_per_buffer=num_samples)
|
|
|
|
my_buf = [] # Store recorded data
|
|
|
|
my_buf = []
|
|
|
|
t_end = time.time() + 5 # Record for 5 seconds
|
|
|
|
t_end = time.time() + 5
|
|
|
|
print('Speak now...')
|
|
|
|
print('Speak now...')
|
|
|
|
while time.time() < t_end:
|
|
|
|
while time.time() < t_end:
|
|
|
|
string_audio_data = stream.read(num_samples)
|
|
|
|
string_audio_data = stream.read(num_samples)
|
|
|
|
my_buf.append(string_audio_data)
|
|
|
|
my_buf.append(string_audio_data)
|
|
|
|
print('Recording ended')
|
|
|
|
print('Recording ended')
|
|
|
|
self.save_wave_file(FILEPATH, my_buf) # Save the recorded audio
|
|
|
|
self.save_wave_file(audio_file, my_buf)
|
|
|
|
stream.close()
|
|
|
|
stream.close()
|
|
|
|
|
|
|
|
|
|
|
|
# Initialize the AipSpeech client
|
|
|
|
client = AipSpeech('73927317', '3jGcj5fLma64CtB3tTEuLcei', 'qm8gPCF7DSKpqatx5ZQ8e4OvNLmgdYcG')
|
|
|
|
client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Class for handling text-to-speech
|
|
|
|
|
|
|
|
class RobotSay():
|
|
|
|
class RobotSay():
|
|
|
|
def __init__(self):
|
|
|
|
def __init__(self):
|
|
|
|
self.engine = pyttsx3.init() # Initialize TTS engine
|
|
|
|
self.engine = pyttsx3.init()
|
|
|
|
|
|
|
|
|
|
|
|
def say(self, msg):
|
|
|
|
def say(self, msg):
|
|
|
|
self.engine.say(msg)
|
|
|
|
self.engine.say(msg)
|
|
|
|
self.engine.runAndWait()
|
|
|
|
self.engine.runAndWait()
|
|
|
|
|
|
|
|
|
|
|
|
# Class for handling speech recognition
|
|
|
|
|
|
|
|
class ReadWav():
|
|
|
|
class ReadWav():
|
|
|
|
def get_file_content(self, filePath):
|
|
|
|
def get_file_content(self, filePath):
|
|
|
|
with open(filePath, 'rb') as fp:
|
|
|
|
with open(filePath, 'rb') as fp:
|
|
|
@ -71,7 +67,7 @@ class ReadWav():
|
|
|
|
'dev_pid': 1537,
|
|
|
|
'dev_pid': 1537,
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
# Define the login window
|
|
|
|
# 定义登录窗口
|
|
|
|
class LoginWindow:
|
|
|
|
class LoginWindow:
|
|
|
|
def __init__(self, master):
|
|
|
|
def __init__(self, master):
|
|
|
|
self.master = master
|
|
|
|
self.master = master
|
|
|
@ -97,11 +93,9 @@ class LoginWindow:
|
|
|
|
|
|
|
|
|
|
|
|
self.button_login = Button(master, text="登录", command=self.login)
|
|
|
|
self.button_login = Button(master, text="登录", command=self.login)
|
|
|
|
self.button_login.pack()
|
|
|
|
self.button_login.pack()
|
|
|
|
|
|
|
|
|
|
|
|
def login(self):
|
|
|
|
def login(self):
|
|
|
|
username = self.entry_username.get()
|
|
|
|
username = self.entry_username.get()
|
|
|
|
password = self.entry_password.get()
|
|
|
|
password = self.entry_password.get()
|
|
|
|
# You can add actual validation logic here by checking against a database or hardcoded values
|
|
|
|
|
|
|
|
if username == "123" and password == "123":
|
|
|
|
if username == "123" and password == "123":
|
|
|
|
messagebox.showinfo("登陆成功", "恭喜你登陆成功")
|
|
|
|
messagebox.showinfo("登陆成功", "恭喜你登陆成功")
|
|
|
|
self.open_chat_window()
|
|
|
|
self.open_chat_window()
|
|
|
@ -109,16 +103,22 @@ class LoginWindow:
|
|
|
|
messagebox.showerror("登录失败", "无效的用户名或密码")
|
|
|
|
messagebox.showerror("登录失败", "无效的用户名或密码")
|
|
|
|
|
|
|
|
|
|
|
|
def open_chat_window(self):
|
|
|
|
def open_chat_window(self):
|
|
|
|
self.master.withdraw() # Hide the login window
|
|
|
|
self.master.withdraw()
|
|
|
|
chat_root = Toplevel(self.master) # Create a new window for chat
|
|
|
|
chat_root = Toplevel(self.master)
|
|
|
|
chat_window = ChatWindow(chat_root) # Open the chat window
|
|
|
|
chat_window = ChatWindow(chat_root)
|
|
|
|
chat_root.protocol("WM_DELETE_WINDOW", self.master.quit) # Close the entire application when chat window is closed
|
|
|
|
chat_root.protocol("WM_DELETE_WINDOW", self.master.quit)
|
|
|
|
class ChatWindow:
|
|
|
|
class ChatWindow:
|
|
|
|
def __init__(self, master):
|
|
|
|
def __init__(self, master):
|
|
|
|
self.master = master
|
|
|
|
self.master = master
|
|
|
|
self.master.title("开始聊天")
|
|
|
|
self.master.title("开始聊天")
|
|
|
|
self.master.geometry("700x500")
|
|
|
|
self.master.geometry("700x500")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.screen_width = self.master.winfo_screenwidth()
|
|
|
|
|
|
|
|
self.screen_height = self.master.winfo_screenheight()
|
|
|
|
|
|
|
|
self.x_pos = (self.screen_width - 300) // 2
|
|
|
|
|
|
|
|
self.y_pos = (self.screen_height - 200) // 2
|
|
|
|
|
|
|
|
self.master.geometry(f"700x500+{self.x_pos}+{self.y_pos}")
|
|
|
|
|
|
|
|
|
|
|
|
self.chat_text = Text(self.master)
|
|
|
|
self.chat_text = Text(self.master)
|
|
|
|
self.chat_text.pack()
|
|
|
|
self.chat_text.pack()
|
|
|
|
|
|
|
|
|
|
|
@ -128,15 +128,31 @@ class ChatWindow:
|
|
|
|
self.send_button = Button(self.master, text="发送", command=self.send_message)
|
|
|
|
self.send_button = Button(self.master, text="发送", command=self.send_message)
|
|
|
|
self.send_button.pack()
|
|
|
|
self.send_button.pack()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.view_button = Button(self.master, text="查看聊天记录", command=self.view_chat_history)
|
|
|
|
|
|
|
|
self.view_button.pack()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.delete_button = Button(self.master, text="删除聊天记录", command=self.delete_chat_history)
|
|
|
|
|
|
|
|
self.delete_button.pack()
|
|
|
|
|
|
|
|
|
|
|
|
self.recognizer = sr.Recognizer()
|
|
|
|
self.recognizer = sr.Recognizer()
|
|
|
|
self.engine = pyttsx3.init()
|
|
|
|
self.engine = pyttsx3.init()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.connection = pymysql.connect(host="localhost",
|
|
|
|
|
|
|
|
user="root",
|
|
|
|
|
|
|
|
password="myroot",
|
|
|
|
|
|
|
|
database="ai_chatter",
|
|
|
|
|
|
|
|
port=3306)
|
|
|
|
|
|
|
|
self.cursor = self.connection.cursor()
|
|
|
|
|
|
|
|
self.chat_history = []
|
|
|
|
|
|
|
|
nltk.download('punkt')
|
|
|
|
|
|
|
|
nltk.download('stopwords')
|
|
|
|
|
|
|
|
nltk.download('wordnet')
|
|
|
|
def send_message(self):
|
|
|
|
def send_message(self):
|
|
|
|
user_input = self.input_field.get()
|
|
|
|
user_input = self.input_field.get()
|
|
|
|
self.update_chat("你: " + user_input + "\n")
|
|
|
|
self.update_chat("你: " + user_input + "\n")
|
|
|
|
response = self.get_qingyunke_response(user_input)
|
|
|
|
response = self.get_qingyunke_response(user_input)
|
|
|
|
self.update_chat("菲菲: " + response + "\n")
|
|
|
|
self.update_chat("菲菲: " + response + "\n")
|
|
|
|
self.speak(response) # Speaking the response
|
|
|
|
self.speak(response)
|
|
|
|
|
|
|
|
|
|
|
|
def get_qingyunke_response(self, message):
|
|
|
|
def get_qingyunke_response(self, message):
|
|
|
|
api_url = "http://api.qingyunke.com/api.php?key=free&appid=0&msg=" + message
|
|
|
|
api_url = "http://api.qingyunke.com/api.php?key=free&appid=0&msg=" + message
|
|
|
@ -149,36 +165,73 @@ class ChatWindow:
|
|
|
|
return "对不起,我不能理解."
|
|
|
|
return "对不起,我不能理解."
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
return "我目前无法处理您的请求."
|
|
|
|
return "我目前无法处理您的请求."
|
|
|
|
# 下载NLTK数据
|
|
|
|
def update_chat(self, text):
|
|
|
|
nltk.download('stopwords')
|
|
|
|
self.chat_text.insert(END, text)
|
|
|
|
nltk.download('punkt')
|
|
|
|
def speak(self, text):
|
|
|
|
nltk.download('wordnet')
|
|
|
|
self.engine.say(text)
|
|
|
|
# 假设用户输入作为文本样本
|
|
|
|
self.engine.runAndWait()
|
|
|
|
user_input = "我想了解自然语言处理。你能帮助我吗?"
|
|
|
|
|
|
|
|
# 小写化
|
|
|
|
def transcribe_audio(self, audio_file):
|
|
|
|
user_input = user_input.lower()
|
|
|
|
with sr.AudioFile(audio_file) as source:
|
|
|
|
# 标点符号移除
|
|
|
|
audio_data = self.recognizer.record(source)
|
|
|
|
translator = str.maketrans('', '', string.punctuation)
|
|
|
|
text = self.recognizer.recognize_sphinx(audio_data)
|
|
|
|
user_input = user_input.translate(translator)
|
|
|
|
return text
|
|
|
|
# 分词
|
|
|
|
#使用mysql数据库来保存
|
|
|
|
|
|
|
|
def save_to_database(self, user_message, bot_response):
|
|
|
|
|
|
|
|
sql = "INSERT INTO chat_history (user_message, bot_response) VALUES (%s, %s)"
|
|
|
|
|
|
|
|
text = (user_message, bot_response)
|
|
|
|
|
|
|
|
self.connection.cursor().execute(sql, text)
|
|
|
|
|
|
|
|
self.connection.commit()
|
|
|
|
|
|
|
|
print("聊天记录保存与数据库中.")
|
|
|
|
|
|
|
|
def view_chat_history(self):
|
|
|
|
|
|
|
|
self.chat_text.delete('1.0', END)
|
|
|
|
|
|
|
|
sql = "SELECT * FROM ai_chatter.chat_history"
|
|
|
|
|
|
|
|
self.cursor.execute(sql)
|
|
|
|
|
|
|
|
records = self.cursor.fetchall()
|
|
|
|
|
|
|
|
for record in records:
|
|
|
|
|
|
|
|
self.update_chat("你: " + record[1] + "\n")
|
|
|
|
|
|
|
|
self.update_chat("菲菲: " + record[2] + "\n")
|
|
|
|
|
|
|
|
if self.chat_history:
|
|
|
|
|
|
|
|
self.update_chat("\n--- 聊天记录 ---\n")
|
|
|
|
|
|
|
|
for message in self.chat_history:
|
|
|
|
|
|
|
|
self.update_chat(message + "\n")
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
self.update_chat("没有找到聊天记录\n")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def delete_chat_history(self):
|
|
|
|
|
|
|
|
sql = "DELETE FROM chat_history"
|
|
|
|
|
|
|
|
self.cursor.execute(sql)
|
|
|
|
|
|
|
|
self.connection.commit()
|
|
|
|
|
|
|
|
self.chat_text.delete('1.0', END)
|
|
|
|
|
|
|
|
self.update_chat("聊天记录已删除。\n")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.chat_history:
|
|
|
|
|
|
|
|
self.chat_history.clear()
|
|
|
|
|
|
|
|
self.update_chat("聊天记录已删除\n")
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
self.update_chat("没有找到聊天记录\n")
|
|
|
|
|
|
|
|
def close_connection(self):
|
|
|
|
|
|
|
|
self.cursor.close()
|
|
|
|
|
|
|
|
self.connection.close()
|
|
|
|
|
|
|
|
#自然语言处理
|
|
|
|
|
|
|
|
def process_user_input(self, user_input):
|
|
|
|
|
|
|
|
# 对用户输入进行分词
|
|
|
|
tokens = word_tokenize(user_input)
|
|
|
|
tokens = word_tokenize(user_input)
|
|
|
|
# 去除停用词
|
|
|
|
# 去除停用词
|
|
|
|
stop_words = set(stopwords.words('english'))
|
|
|
|
stop_words = set(stopwords.words('english'))
|
|
|
|
filtered_tokens = [word for word in tokens if word not in stop_words]
|
|
|
|
filtered_tokens = [word for word in tokens if word.lower() not in stop_words]
|
|
|
|
# 词形还原
|
|
|
|
# 词形还原
|
|
|
|
lemmatizer = WordNetLemmatizer()
|
|
|
|
lemmatizer = WordNetLemmatizer()
|
|
|
|
lemmatized_tokens = [lemmatizer.lemmatize(word) for word in filtered_tokens]
|
|
|
|
lemmatized_tokens = [lemmatizer.lemmatize(word) for word in filtered_tokens]
|
|
|
|
# 频率分布
|
|
|
|
# 将处理后的文本重新组合为句子
|
|
|
|
fdist = FreqDist(lemmatized_tokens)
|
|
|
|
processed_input = ' '.join(lemmatized_tokens)
|
|
|
|
print(fdist.most_common(5))
|
|
|
|
# 返回处理后的文本
|
|
|
|
def update_chat(self, text):
|
|
|
|
return processed_input
|
|
|
|
self.chat_text.insert(END, text)
|
|
|
|
user_input = "Can you tell me about machine learning?"
|
|
|
|
def speak(self, text):
|
|
|
|
|
|
|
|
self.engine.say(text)
|
|
|
|
|
|
|
|
self.engine.runAndWait()
|
|
|
|
|
|
|
|
def main():
|
|
|
|
def main():
|
|
|
|
root = Tk()
|
|
|
|
root = Tk()
|
|
|
|
login_window = LoginWindow(root)
|
|
|
|
login_window = LoginWindow(root)
|
|
|
|
root.mainloop()
|
|
|
|
root.mainloop()
|
|
|
|
if __name__ == "__main__":
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|
|
|
|
main()
|
|
|
|
|
|
|
|
|
|
|
|