Rezuwan commited on
Commit
a016803
·
verified ·
1 Parent(s): 3dc7e93

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +164 -11
app.py CHANGED
@@ -1,7 +1,10 @@
1
  import os
2
  import warnings
3
  import gradio as gr
 
 
4
  from dotenv import load_dotenv
 
5
 
6
  from langchain.schema import SystemMessage, HumanMessage
7
  from langchain.chains import RetrievalQA
@@ -30,6 +33,128 @@ vectorstore = FAISS.load_local(
30
  "faiss_index_unmad_magz", embeddings, allow_dangerous_deserialization=True
31
  )
32
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  # Initialize gpt-4o Chat model
34
  llm = ChatOpenAI(
35
  model_name="gpt-4o",
@@ -38,25 +163,53 @@ llm = ChatOpenAI(
38
  openai_api_key=OPENAI_API_KEY
39
  )
40
 
41
- # Satirical QA function
42
  def custom_unmad_satirical_bot(message, history, top_k=3):
43
- retriever = vectorstore.as_retriever()
44
- docs = retriever.invoke(message)
45
- top_contexts = "\n\n---\n\n".join([doc.page_content for doc in docs[:top_k]])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
  messages = [
48
  SystemMessage(content="""
49
- তুমি 'উন্মাদ' ম্যাগাজিনের একজন পুরানো ব্যঙ্গাত্মক লেখক। তোমার কাজ হলো ব্যবহারকারীর প্রশ্ন শুনে স্যাটাার, কটাক্ষ, রসিকতা, ঠাট্টা, আর একটু জ্ঞান মিশিে উত্তর দেওা — যাতে লোক হাসে, চিন্তা করে, আবার নতুন কিছু শিখে।
50
- তুমি কখনোই একদম সোজাসাপ্টা উত্তর দেবে না — বরং একটু অভিন করে, অবাক হে, ঠাট্টা করে, খোঁচা মেরে দেবে।
51
- **নিচের নির্দেশনাগুলো অবশ্যই মেনে চলবে**
52
- ১। কোন ইমোজি (EMOJI) ব্যবহার করবো।
53
- । কোন ইংলি টেক্সট ব্যবহার করবে না।
 
 
 
 
 
54
  """),
55
  HumanMessage(content=f"""
56
- 🔍 প্রসঙ্গ:
57
  {top_contexts}
 
58
  প্রশ্ন: {message}
59
- উত্তর দাও উন্মাদ ম্যাগাজিনের স্টাইলে — বাংলায়, ব্যঙ্গ করে, কল্পনা আর অতিরঞ্জন দিয়ে।
 
60
  """)
61
  ]
62
 
 
1
  import os
2
  import warnings
3
  import gradio as gr
4
+ import numpy as np
5
+ import re
6
  from dotenv import load_dotenv
7
+ from sklearn.metrics.pairwise import cosine_similarity
8
 
9
  from langchain.schema import SystemMessage, HumanMessage
10
  from langchain.chains import RetrievalQA
 
33
  "faiss_index_unmad_magz", embeddings, allow_dangerous_deserialization=True
34
  )
35
 
36
+ def clean_bangla_content(text):
37
+ """
38
+ Clean the retrieved content to remove English watermarks, scan text, and unwanted content.
39
+ Keep only Bengali content.
40
+ """
41
+ # Common English watermarks and scan text to remove
42
+ english_patterns = [
43
+ r'scanned by \w+',
44
+ r'found in \w+',
45
+ r'www\.\w+\.\w+',
46
+ r'http[s]?://[^\s]+',
47
+ r'\.pdf',
48
+ r'\.com',
49
+ r'\.org',
50
+ r'\.net',
51
+ r'banglapdf',
52
+ r'sadaqpdf',
53
+ r'pdf scanner',
54
+ r'scan by',
55
+ r'converted by',
56
+ r'page \d+',
57
+ r'source:',
58
+ r'reference:',
59
+ r'[a-zA-Z]+@[a-zA-Z]+\.[a-zA-Z]+', # emails
60
+ r'\b[A-Z][a-z]+ [A-Z][a-z]+\b', # English names
61
+ r'\b[A-Z]{2,}\b', # Uppercase abbreviations
62
+ ]
63
+
64
+ # Remove lines containing English patterns
65
+ lines = text.split('\n')
66
+ cleaned_lines = []
67
+
68
+ for line in lines:
69
+ line = line.strip()
70
+
71
+ # Skip empty lines
72
+ if not line:
73
+ continue
74
+
75
+ # Check if line contains English patterns
76
+ contains_english = False
77
+ for pattern in english_patterns:
78
+ if re.search(pattern, line, re.IGNORECASE):
79
+ contains_english = True
80
+ break
81
+
82
+ # Check if line is mostly English (contains more English than Bengali)
83
+ english_chars = len(re.findall(r'[a-zA-Z]', line))
84
+ bengali_chars = len(re.findall(r'[\u0980-\u09FF]', line)) # Bengali Unicode range
85
+
86
+ # If line has more English than Bengali, skip it
87
+ if english_chars > bengali_chars and english_chars > 3:
88
+ contains_english = True
89
+
90
+ # Only keep lines that don't contain English patterns and have Bengali content
91
+ if not contains_english and bengali_chars > 0:
92
+ cleaned_lines.append(line)
93
+
94
+ return '\n'.join(cleaned_lines)
95
+
96
+ def maximal_marginal_relevance_search(query, vectorstore, k=10, lambda_param=0.5, top_k=3):
97
+ """
98
+ Implement Maximal Marginal Relevance (MMR) for diverse document retrieval.
99
+ """
100
+ # Get initial candidate documents (more than needed)
101
+ candidate_docs = vectorstore.similarity_search_with_score(query, k=k)
102
+
103
+ if not candidate_docs:
104
+ return []
105
+
106
+ # Extract documents and their embeddings
107
+ docs = [doc for doc, score in candidate_docs]
108
+
109
+ # Get query embedding
110
+ query_embedding = np.array(embeddings.embed_query(query)).reshape(1, -1)
111
+
112
+ # Get document embeddings
113
+ doc_embeddings = []
114
+ for doc in docs:
115
+ doc_embedding = np.array(embeddings.embed_documents([doc.page_content])[0])
116
+ doc_embeddings.append(doc_embedding)
117
+
118
+ doc_embeddings = np.array(doc_embeddings)
119
+
120
+ # MMR Selection Algorithm
121
+ selected_docs = []
122
+ selected_indices = []
123
+ remaining_indices = list(range(len(docs)))
124
+
125
+ for _ in range(min(top_k, len(docs))):
126
+ mmr_scores = []
127
+
128
+ for i in remaining_indices:
129
+ # Calculate relevance score (similarity to query)
130
+ relevance = cosine_similarity(query_embedding, doc_embeddings[i].reshape(1, -1))[0][0]
131
+
132
+ # Calculate diversity score (max similarity to already selected docs)
133
+ if selected_indices:
134
+ diversity_scores = []
135
+ for j in selected_indices:
136
+ similarity = cosine_similarity(
137
+ doc_embeddings[i].reshape(1, -1),
138
+ doc_embeddings[j].reshape(1, -1)
139
+ )[0][0]
140
+ diversity_scores.append(similarity)
141
+ diversity = max(diversity_scores)
142
+ else:
143
+ diversity = 0
144
+
145
+ # Calculate MMR score
146
+ mmr_score = lambda_param * relevance - (1 - lambda_param) * diversity
147
+ mmr_scores.append((mmr_score, i))
148
+
149
+ # Select document with highest MMR score
150
+ if mmr_scores:
151
+ best_score, best_idx = max(mmr_scores, key=lambda x: x[0])
152
+ selected_docs.append(docs[best_idx])
153
+ selected_indices.append(best_idx)
154
+ remaining_indices.remove(best_idx)
155
+
156
+ return selected_docs
157
+
158
  # Initialize gpt-4o Chat model
159
  llm = ChatOpenAI(
160
  model_name="gpt-4o",
 
163
  openai_api_key=OPENAI_API_KEY
164
  )
165
 
166
+ # Satirical QA function with MMR and content cleaning
167
  def custom_unmad_satirical_bot(message, history, top_k=3):
168
+ # Use MMR search with default parameters
169
+ docs = maximal_marginal_relevance_search(
170
+ query=message,
171
+ vectorstore=vectorstore,
172
+ k=15, # Consider more candidates for better diversity
173
+ lambda_param=0.6, # Slightly favor relevance over diversity
174
+ top_k=top_k
175
+ )
176
+
177
+ # Extract context from MMR-selected documents with cleaning
178
+ if docs:
179
+ # Clean each document's content before joining
180
+ cleaned_contexts = []
181
+ for doc in docs:
182
+ cleaned_content = clean_bangla_content(doc.page_content)
183
+ if cleaned_content.strip(): # Only add if there's meaningful Bengali content
184
+ cleaned_contexts.append(cleaned_content)
185
+
186
+ if cleaned_contexts:
187
+ top_contexts = "\n\n---\n\n".join(cleaned_contexts)
188
+ else:
189
+ top_contexts = "প্রাসঙ্গিক বাংলা তথ্য পাওয়া যায়নি।"
190
+ else:
191
+ top_contexts = "কোন প্রাসঙ্গিক তথ্য পাওয়া যায়নি।"
192
 
193
  messages = [
194
  SystemMessage(content="""
195
+ তুমি 'উন্মাদ' ম্যাগাজিনের একজন পুরানো ব্যঙ্গাত্মক লেখক। তোমার কাজ হলো ব্যবহারকারীর প্রশ্ন শুনে স্যাটায়ার, কটাক্ষ, রসিকতা, ঠাট্টা, আর একটু জ্ঞান মিশিয়ে উত্তর দেওয়া — যাতে লোক হাসে, চিন্তা করে, আবার নতুন কিছু শিখে।
196
+ তুমি কখনোই একদম সোজাসাপ্টা উত্তর দেবে না — বরং একটু অভিনয় করে, অবাক হয়ে, ঠাট্টা করে, খোঁচা মেরে দেবে।
197
+
198
+ **এইির্দেশনাগুলো অবশ্য েনে চলবে - কোন ব্যতিেই**
199
+ । কোন ইমোজি (EMOJI) ব্যবহার করবে না - একটিও না
200
+ ২। কোন ইংরেজি টেক্সট ব্যবহার করবে না - একটি শব্দও না।
201
+ ৩। কোন ইংরেজি সংখ্যা বা চিহ্ন লিখবে না (যেমন: PDF, URL, www, .com, scanned by, found in ইত্যাদি)।
202
+ ৪। প্রসঙ্গের মধ্যে যেসব ইংরেজি টেক্সট, স্ক্যান ওয়াটারমার্ক, ওয়েবসাইট নাম, বা প্রযুক্তিগত শব্দ আছে সেগুলো একেবারেই উল্লেখ করবে না।
203
+ ৫। শুধুমাত্র বাংলা ভাষায় লেখা বিষয়বস্তু ব্যবহার করবে।
204
+ ৬। যদি প্রসঙ্গে কোন বাংলা কন্টেন্ট না থাকে, তাহলে নিজের সাধারণ জ্ঞান দিয়ে উত্তর দেবে।
205
  """),
206
  HumanMessage(content=f"""
207
+ প্রসঙ্গ (নির্বাচিত বাংলা তথ্য):
208
  {top_contexts}
209
+
210
  প্রশ্ন: {message}
211
+
212
+ নির্দেশনা: উপরের প্রসঙ্গ থেকে শুধুমাত্র বাংলা ভা���ার বিষয়বস্তু ব্যবহার করে উন্মাদ ম্যাগাজিনের স্টাইলে উত্তর দাও। কোন ইংরেজি শব্দ, ইমোজি, বা স্ক্যান ওয়াটারমার্ক উল্লেখ করবে না। সম্পূর্ণ বাংলায় ব্যঙ্গাত্মক ও মজার উত্তর লেখো।
213
  """)
214
  ]
215