-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathchatbot.py
More file actions
154 lines (124 loc) · 6.28 KB
/
chatbot.py
File metadata and controls
154 lines (124 loc) · 6.28 KB
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#Biblioteca de ferramentas que serão utilizadas
import json
import re
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
# --- STEP 1: LOAD THE DATA ---
#Carregar os Dados: A primeira função lê o ficheiro de perguntas e respostas (bijuterias.json).
def load_data(file_path):
"""
Loads the JSON file and returns the content.
"""
with open(file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
return data
try:
intents = load_data('bijuterias.json')['intents']
except FileNotFoundError:
print("Error: 'bijuterias.json' file not found. Please create it in the same folder.")
exit()
# --- STEP 2: TEXT PRE-PROCESSING WITHOUT NLTK ---
# O computador tenta entender a complexidade das palavras alem da ponctuação, Uma vez que è mais facil entender numeros.
def pre_process_text(sentence):
"""
Simple text preprocessing for English without NLTK dependency.
"""
# Convert to lowercase
sentence = sentence.lower()
# Remove punctuation and special characters
sentence = re.sub(r'[^\w\s]', ' ', sentence)
# Basic tokenization using split
words = sentence.split()
# Simple stemming: remove common suffixes
stemmed_words = []
for word in words:
# Basic English stemming rules
if len(word) > 3:
if word.endswith('ing'):
word = word[:-3]
elif word.endswith('ed'):
word = word[:-2]
elif word.endswith('s'):
word = word[:-1]
elif word.endswith('es'):
word = word[:-2]
stemmed_words.append(word)
return ' '.join(stemmed_words)
#---- Lists to store the processed questions and corresponding tags----
# tem a função de armazenar e organizar os dados que o teu chatbot vai usar para o treino.
# Cada pergunta é processada e associada à sua tag correspondente.
# Isso facilita a comparação e a resposta às perguntas dos utilizadores.
# Assim, o chatbot pode aprender a responder com base nas perguntas e respostas fornecidas.
all_questions = []
all_responses = []
for intent in intents:
for pattern in intent['patterns']:
processed_question = pre_process_text(pattern)
all_questions.append(processed_question)
all_responses.append(intent['tag'])
# --- STEP 3: VECTORIZATION AND SIMILARITY CALCULATION ---
#--- Use TF-IDF to convert text into numerical vectors----
# O "STEP 3", é a parte onde o teu chatbot passa a ser um "cérebro".
# É aqui que ele converte o texto em números
# para poder encontrar a melhor resposta para a pergunta do utilizador.
vectorizer = TfidfVectorizer()
X = vectorizer.fit_transform(all_questions)
#--- Function to get the best response based on cosine similarity ----
# Esta função é o "cérebro" do chatbot.
# Ela compara a pergunta do utilizador com as perguntas que o chatbot já conhece.
# Se encontrar uma pergunta semelhante, responde com a resposta associada.
#É nela que toda a magia acontece, desde o momento em que o utilizador faz uma pergunta até o chatbot dar uma resposta.
# Se não encontrar nada parecido, pede ao utilizador para reformular a pergunta.
# A função usa um "limiar" para decidir se a pergunta é suficientemente semelhante.
# Se a semelhança for menor que o limiar, o chatbot não entende a pergunta.
# Se for maior, ele responde com a melhor resposta que encontrou.
# O limiar pode ser ajustado para tornar o chatbot mais ou menos exigente na hora de entender as perguntas.
# Um limiar mais alto significa que o chatbot só responderá a perguntas muito semelhantes às que conhece.
# Um limiar mais baixo permite que ele responda a perguntas mais variadas, mas pode levar a respostas menos precisas.
# Ajustar esse limiar é importante para equilibrar a precisão e a flexibilidade do chatbot.
# É uma parte crucial para garantir que o chatbot funcione bem e atenda às expectativas dos utilizadores
def get_response(user_input, threshold=0.25):
"""
Compares the user's question with the training questions.
"""
# Pre-process the user's question
processed_input = pre_process_text(user_input)
# -----Transform the question into a TF-IDF vector-----
#Transforma a pergunta do utilizador, que já foi limpa, num vetor de números.
# O teu chatbot não entende texto, mas entende números.
input_vector = vectorizer.transform([processed_input])
# Calculate cosine similarity
# Se encontrar a tag, escolhe uma resposta aleatória associada a essa tag.
# Isso torna as respostas do chatbot mais variadas e naturais.
# Se não encontrar, pede ao utilizador para reformular a pergunta
# A similaridade do cosseno é uma maneira de medir o quão semelhantes são duas perguntas.
# Quanto mais próximas forem as perguntas, maior será a similaridade.
similarity = cosine_similarity(input_vector, X)
# Find the most similar question
best_index = np.argmax(similarity)
best_similarity = similarity[0][best_index]
if best_similarity < threshold:
return "I'm sorry, I don't understand your question. Could you rephrase it?"
# Find the tag of the best response
found_tag = all_responses[best_index]
# Look for the corresponding response in the JSON file
for intent in intents:
if intent['tag'] == found_tag:
return np.random.choice(intent['responses'])
# --- STEP 4: RUN THE CHATBOT ---
# RUN THE CHATBOT, é a parte que realmente dá vida ao teu programa,
# Transformando-o num chatbot interativo.
# É aqui que o código sai do "treino" e passa para a "ação",
# interagindo com o utilizador.
# Ele dá as boas-vindas ao utilizador e espera pela sua pergunta.
# Quando o utilizador faz uma pergunta, o chatbot usa a função get_response para encontrar a melhor resposta.
# O chatbot continua a funcionar até o utilizador decidir sair, digitando "exit", "bye", "stop" ou "quit".
print("Hello! Welcome to Saint Germain. I am your virtual assistant. How can I help you?")
while True:
user_input = input("You: ")
if user_input.lower() in ["exit", "bye", "stop", "quit"]:
print("Chatbot: Goodbye! Come back soon.")
break
response = get_response(user_input)
print(f"Chatbot: {response}")