StKirill commited on
Commit
b91bd2c
·
verified ·
1 Parent(s): 716cef9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +230 -6
app.py CHANGED
@@ -1,4 +1,9 @@
1
- # import parsing # decomment to download data from the website and parse it
 
 
 
 
 
2
 
3
  import pandas as pd
4
  import nltk
@@ -12,6 +17,8 @@ from nltk import pos_tag # for parts of speech
12
  from sklearn.metrics import pairwise_distances # cosine similarity
13
  from nltk import word_tokenize
14
  from nltk.corpus import stopwords
 
 
15
  from sklearn.metrics.pairwise import cosine_similarity
16
  import gradio as gr
17
  import time
@@ -74,6 +81,7 @@ x_tfidf = tfidf.fit_transform(df['Normalized and StopWords question']).toarray()
74
  features_tfidf = tfidf.get_feature_names_out() # use function to get all the normalized words
75
  df_tfidf = pd.DataFrame(x_tfidf, columns = features_tfidf) # create dataframe to show the 0, 1 value for each word
76
 
 
77
  def chat_tfidf(question):
78
  tidy_question = text_normalization(removeStopWords(question)) # clean & lemmatize the question
79
  tf = tfidf.transform([tidy_question]).toarray() # convert the question into a vector
@@ -83,23 +91,239 @@ def chat_tfidf(question):
83
  answer = df['answer'].loc[index_value]
84
  return answer
85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
 
 
87
 
 
 
 
 
88
 
 
 
89
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  def echo(message, history, model):
91
- print(model)
92
- print(history)
 
 
 
 
 
 
 
 
 
 
 
 
93
  if model=="TF-IDF":
94
- answer = chat_tfidf(message)
 
95
  return answer
96
 
97
  elif model=="W2V":
98
- answer = chat_word2vec(message)
 
99
  return answer
100
 
101
  elif model=="BERT":
102
- answer = chat_bert(message)
103
  return answer
104
 
105
 
 
1
+ # import parsing # decomment to download data from the website and parse it # string, gensim, tqdm, transformers, torch
2
+ from string import punctuation
3
+ from tqdm.auto import tqdm, trange
4
+
5
+ import torch
6
+ from transformers import AutoTokenizer, AutoModel
7
 
8
  import pandas as pd
9
  import nltk
 
17
  from sklearn.metrics import pairwise_distances # cosine similarity
18
  from nltk import word_tokenize
19
  from nltk.corpus import stopwords
20
+ from gensim.models import Word2Vec, KeyedVectors
21
+ import gensim.downloader as api
22
  from sklearn.metrics.pairwise import cosine_similarity
23
  import gradio as gr
24
  import time
 
81
  features_tfidf = tfidf.get_feature_names_out() # use function to get all the normalized words
82
  df_tfidf = pd.DataFrame(x_tfidf, columns = features_tfidf) # create dataframe to show the 0, 1 value for each word
83
 
84
+ # bot tf idf algorithm without context
85
  def chat_tfidf(question):
86
  tidy_question = text_normalization(removeStopWords(question)) # clean & lemmatize the question
87
  tf = tfidf.transform([tidy_question]).toarray() # convert the question into a vector
 
91
  answer = df['answer'].loc[index_value]
92
  return answer
93
 
94
+ # bot tf idf algorithm with context
95
+ def chat_tfidf_context(question, history):
96
+
97
+ len_history = len(history)
98
+
99
+ if len_history > 1:
100
+ memory_weights = np.array([0.1, 0.3, 1.0]) # .reshape((3,1))
101
+ # take last two sentences in accordance to bot's memory
102
+ history = history[-2:]
103
+
104
+ else:
105
+ memory_weights = np.array([0.3, 1.0])
106
+
107
+ history_sentence = np.zeros(shape=(len_history+1, 5024))
108
+
109
+ for ind, h in enumerate(history):
110
+ # normalize first question from context
111
+ tidy_question = text_normalization(removeStopWords(h[0]))
112
+ # pass via tfidf
113
+ tf = tfidf.transform([tidy_question]).toarray()
114
+
115
+ # assign tf idf vector to history sentence
116
+ history_sentence[ind] = tf * memory_weights[ind]
117
+
118
+ tidy_question = text_normalization(removeStopWords(question))
119
+ tf = tfidf.transform([tidy_question]).toarray()
120
+
121
+ history_sentence[-1] = tf
122
+ history_sentence = history_sentence.mean(axis=0).reshape(1,-1)
123
+
124
+ cos = 1- pairwise_distances(df_tfidf, history_sentence, metric = 'cosine')
125
+ index_value = cos.argmax()
126
+ answer = df['answer'].loc[index_value]
127
+
128
+ return answer
129
+ #------------------------------------------------------------------------------------------------#
130
+ punkt = [p for p in punctuation] + ["`", "``" ,"''", "'"]
131
+
132
+ def tokenize(sent: str) -> str:
133
+ tokens = nltk.word_tokenize(sent.lower()) # tokenize words
134
+ return ' '.join([word for word in tokens if word not in stop and word not in punkt])
135
+
136
+ questions_preprocessed = []
137
+ for question in df["question"].tolist() + df["answer"].tolist():
138
+ questions_preprocessed.append(tokenize(question))
139
+
140
+ questions_w2v = [sent.split(" ") for sent in questions_preprocessed]
141
+
142
+ w2v = KeyedVectors.load('w2v.bin')
143
+ unknown_vector = np.random.uniform(low=-0.2, high=0.2, size=(25,))
144
+
145
+ # define function to form sentences with w2v
146
+ def w2v_get_vector_for_sentence(sentence):
147
+ sent = nltk.word_tokenize(sentence.lower())
148
+ sent = [word for word in sent if word not in punkt]
149
+ sentence_vector = []
150
+ if len(sent)==0:
151
+ sentence_vector.append(unknown_vector)
152
+ else:
153
+ for word in sent:
154
+ if word in w2v.key_to_index:
155
+ sentence_vector.append(w2v[word])
156
+ else:
157
+ sentence_vector.append(unknown_vector)
158
+
159
+ return np.array(sentence_vector).mean(axis=0)
160
+
161
+ # create base for w2v
162
+ base = np.zeros(shape=(len(df.question), 25))
163
+ for ind, sentence in enumerate(df['question']): # df[df['question'].str.len() >= 1]
164
+ base[ind] = w2v_get_vector_for_sentence(sentence)
165
+
166
+ # bot w2v algorithm without context
167
+ def chat_word2vec(question):
168
+ question = [w2v_get_vector_for_sentence(question)]
169
+ cos = 1-pairwise_distances(base, question, metric = 'cosine') # calculate the cosine value
170
+ index_value = cos.argmax() # find the index of the maximum cosine value
171
+ answer = df['answer'].loc[index_value]
172
+ return answer
173
+
174
+ # bot w2v algorithm with context
175
+ def chat_word2vec_context(question, history):
176
+
177
+ len_history = len(history)
178
+
179
+ if len_history > 1:
180
+ memory_weights = np.array([0.1, 0.3, 1.0]) # .reshape((3,1))
181
+ # take last two sentences in accordance to bot's memory
182
+ history = history[-2:]
183
+
184
+ else:
185
+ memory_weights = np.array([0.3, 1.0])
186
+
187
+ history_sentence = np.zeros(shape=(len_history+1, 25))
188
+
189
+ for ind, h in enumerate(history):
190
+ sentence = w2v_get_vector_for_sentence(h[0])
191
+ history_sentence[ind] = sentence * memory_weights[ind]
192
+
193
+ question = w2v_get_vector_for_sentence(question)
194
+
195
+ history_sentence[-1] = question
196
+ history_sentence = history_sentence.mean(axis=0).reshape(1, -1)
197
+
198
+ cos = 1-pairwise_distances(base, history_sentence, metric = 'cosine')
199
+ index_value = cos.argmax()
200
+ answer = df['answer'].loc[index_value]
201
 
202
+ return answer
203
 
204
+ #------------------------------------------------------------------------------------------------#
205
+ # Let's try bert model by elastic and with e5
206
+ model_name = "elastic/multilingual-e5-small-optimized"
207
+ device = "cpu"
208
 
209
+ tokenizer = AutoTokenizer.from_pretrained(model_name)
210
+ model = AutoModel.from_pretrained(model_name)
211
 
212
+ class BERTSearchEngine:
213
+ def __init__(self, model, tokenizer):
214
+ self.raw_procesed_data = [self.preprocess(sample, tokenizer) for sample in text_database]
215
+ self.base = []
216
+ self.retriever = None
217
+ self.inverted_index = {}
218
+ self._init_retriever(model, tokenizer, text_database)
219
+ self._init_inverted_index(text_database)
220
+
221
+ @staticmethod
222
+ def preprocess(sentence: str, tokenizer):
223
+ return tokenizer(sentence, padding=True, truncation=True, return_tensors='pt')
224
+
225
+ def _embed_bert_cls(self, tokenized_text: dict[torch.Tensor]) -> np.array:
226
+ with torch.no_grad():
227
+ model_output = self.retriever(**{k: v.to(self.retriever.device) for k, v in tokenized_text.items()})
228
+ embeddings = model_output.last_hidden_state[:, 0, :]
229
+ embeddings = torch.nn.functional.normalize(embeddings)
230
+ return embeddings[0].cpu().numpy()
231
+
232
+ def _init_retriever(self, model, tokenizer, text_database):
233
+ self.retriever = model
234
+ self.tokenizer = tokenizer
235
+ self.base = None #np.array([self._embed_bert_cls(self.preprocess(text, tokenizer)) for text in tqdm(text_database)])
236
+
237
+ def retrieve(self, query: str) -> np.array:
238
+ return self._embed_bert_cls(self.preprocess(query, self.tokenizer))
239
+
240
+ def retrieve_documents(self, query: str, top_k=3) -> list[int]:
241
+ query_vector = self.retrieve(query)
242
+ cosine_similarities = cosine_similarity([query_vector], self.base).flatten()
243
+ relevant_indices = np.argsort(cosine_similarities, axis=0)[::-1][:top_k]
244
+ return relevant_indices.tolist()
245
+
246
+ def _init_inverted_index(self, text_database: list[str]):
247
+ self.inverted_index = dict(enumerate(text_database))
248
+
249
+ def display_relevant_docs(self, query, full_database, top_k=3) -> list[int]:
250
+ docs_indexes = self.retrieve_documents(query, top_k=top_k)
251
+ return [self.inverted_index[ind] for ind in docs_indexes]
252
+
253
+ def find_answer(self, query: str) -> int:
254
+ query_vector = self.retrieve(query)
255
+ cosine_similarities = cosine_similarity([query_vector], self.base).flatten()
256
+ relevant_indice = np.argmax(cosine_similarities, axis=0)
257
+ return relevant_indice
258
+
259
+ simple_search_engine = BERTSearchEngine(model, tokenizer)
260
+ simple_search_engine.bert = np.load(bert_base.npy)
261
+
262
+ # bot bert algorithm without context
263
+ def chat_bert(question):
264
+ ind = simple_search_engine.find_answer(question)
265
+ answer = df['answer'].iloc[ind]
266
+ return answer
267
+
268
+ # bot bert algorithm with context
269
+ def chat_bert_context(question, history):
270
+
271
+ len_history = len(history)
272
+
273
+ if len_history > 1:
274
+ memory_weights = np.array([0.1, 0.3, 1.0]) # .reshape((3,1))
275
+ # take last two sentences in accordance to bot's memory
276
+ history = history[-2:]
277
+
278
+ else:
279
+ memory_weights = np.array([0.3, 1.0])
280
+
281
+ history_sentence = np.zeros(shape=(len_history+1, 384))
282
+
283
+ for ind, h in enumerate(history):
284
+
285
+ sentence = simple_search_engine.retrieve(h)
286
+ history_sentence[ind] = sentence * memory_weights[ind]
287
+
288
+ question = simple_search_engine.retrieve(question)
289
+
290
+ history_sentence[-1] = question
291
+ history_sentence = history_sentence.mean(axis=0).reshape(1, -1)
292
+
293
+ cosine_similarities = cosine_similarity(history_sentence, simple_search_engine.base).flatten()
294
+ relevant_indice = np.argmax(cosine_similarities, axis=0)
295
+ answer = df['answer'].loc[relevant_indice]
296
+
297
+ return answer
298
+ #------------------------------------------------------------------------------------------------#
299
+ # gradio part
300
  def echo(message, history, model):
301
+ # print(model)
302
+ # print(history)
303
+ # if model=="TF-IDF":
304
+ # answer = chat_tfidf(message)
305
+ # return answer
306
+
307
+ # elif model=="W2V":
308
+ # answer = chat_word2vec(message)
309
+ # return answer
310
+
311
+ # elif model=="BERT":
312
+ # answer = chat_bert(message)
313
+ # return answer
314
+
315
  if model=="TF-IDF":
316
+ # answer = chat_tfidf(message)
317
+ answer = chat_tfidf_context(message, history)
318
  return answer
319
 
320
  elif model=="W2V":
321
+ # answer = chat_word2vec(message)
322
+ answer = chat_word2vec_context(message, history)
323
  return answer
324
 
325
  elif model=="BERT":
326
+ answer = chat_bert_context(message, history)
327
  return answer
328
 
329