-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathbot.py
114 lines (101 loc) · 4.67 KB
/
bot.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
from openai import OpenAI
import pyttsx3
import re
import glob
from threading import Thread
class ChatGPTBot:
"""Define the class for the Chatbot
"""
def __init__(self, api_key: str):
"""Initializer method that is executed when a new ChatGPTBot
object (i.e. bot) is created.
Args:
- api_key (string): The OpenAI API key used to authenticate
with the OpenAI service.
"""
# Instantiate a client object using the api_key
self.client = OpenAI(api_key=api_key)
# Initialize the message history for chat storing
self.message_history = []
def respond(self, user_message: str, model: str = "gpt-4o-mini"):
"""Method to send the user's message to GPT model and receive
API response. This method also documents and updates the message
history between the user and the bot.
Args:
- user_message (string): The user's input message.
- model (string): The GPT model to use. Default is 'gpt-4o-mini'.
"""
# Assemble a request using the user's message and ...
# ...append it to message_history
request = {"role": "user", "content": user_message}
self.message_history.append(request)
# Create a chat completion object
completion = self.client.chat.completions.create(
model=model, messages=self.message_history
)
# Extract bot's message from the API response
bot_message = completion.choices[0].message.content
# Assemble a response using the bot's message and ...
# ...append it to the message_history
response = {"role": "assistant", "content": bot_message}
self.message_history.append(response)
return bot_message
def get_chinese_voice(self, engine: pyttsx3.engine.Engine):
"""Method to retrieve a Chinese voice from pyttsx3 engine
Args:
- engine (pyttsx3.engine.Engine): The pyttsx3 engine instance
for converting text message to speech.
"""
# Retrieve the list of available voices from the engine
voices = engine.getProperty("voices")
# Iterate over each voice in the voices list
for voice in voices:
# Check if the voice has languages attribute and ...
# ...if the first language is "zh-CN"
if voice.languages and voice.languages[0] == "zh-CN":
# Return the current voice as it is a Chinese voice
return voice
# Check if the voice's name contains "Chinese" or "Mandarin"
if "Chinese" in voice.name or "Mandarin" in voice.name.title():
# Return the current voice as it is considered a Chinese voice
return voice
# If no Chinese voice is found among the available voices, ...
# ...raise a RuntimeError
raise RuntimeError(f"No Chinese voice found among {voices}")
def speak(self, bot_message: str):
"""Method to convert bot's text message into speech.
Args:
- bot_message (string): The bot's message to be spoken.
"""
# Initialize the text-to-speech engine
tts_engine = pyttsx3.init()
# Play bot's message in audio - in Chinese or English?
threshold = 0.5
# Get a list of English words from the the bot's message
en_words = re.findall("[a-zA-Z']+", bot_message)
# Get a list of Chinese characters from the bot's message.
# The detected chinese characters will be like ['当', '然', '可', '以']
ch_words = re.findall(
"[\u4e00-\u9FFF]", bot_message
)
# Total number of both Chinese characters and English words
total_len = len(en_words) + len(ch_words)
if total_len > 0:
# Calculate the proportion of Chinese words in the message
prop_ch = len(ch_words) / total_len
# If the proportion of Chinese words is above the threshold, ...
# ...use a Chinese voice
if prop_ch > threshold:
# Retrieve a Chinese voice from the pyttsx3 engine using ...
# ...the get_chinese_voice function
chinese_voice = self.get_chinese_voice(tts_engine)
# Set the voice property of the pyttsx3 engine to the ...
# ...Chinese voice
tts_engine.setProperty("voice", chinese_voice.id)
# Lower the rate of the speech
rate = tts_engine.getProperty("rate")
tts_engine.setProperty("rate", rate - 20)
# Convert the bot's message from text to speech
tts_engine.say(bot_message)
# Wait for the engine to complete speaking the message
tts_engine.runAndWait()