afouda commited on
Commit
2ba0e37
·
verified ·
1 Parent(s): 5723a6c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +114 -67
app.py CHANGED
@@ -34,16 +34,16 @@ WEAVIATE_URL="https://xbvlj5rpqyiswspww0tthq.c0.us-west3.gcp.weaviate.cloud"
34
  WEAVIATE_API_KEY="RU9acU1CYnNRTjY1S1ZFc18zNS9tQktaWlcwTzFEUjlscEVCUGF4YU5xRWx2MDhmTUtIdUhnOWdOTGVZPV92MjAw"
35
  DEEPINFRA_API_KEY="285LUJulGIprqT6hcPhiXtcrphU04FG4"
36
  DEEPINFRA_BASE_URL="https://api.deepinfra.com/v1/openai"
37
-
38
  # Initialize OpenAI client
 
39
  openai = OpenAI(
40
  api_key=DEEPINFRA_API_KEY,
41
  base_url="https://api.deepinfra.com/v1/openai",
42
  )
43
-
44
  SESSION_ID = "default"
45
 
46
- # Chat Completion Helper
 
47
  def call_llm(model: str, messages: list[dict], temperature: float = 0.0, **kwargs) -> str:
48
  resp = openai.chat.completions.create(
49
  model=model,
@@ -53,66 +53,77 @@ def call_llm(model: str, messages: list[dict], temperature: float = 0.0, **kwarg
53
  )
54
  return resp.choices[0].message.content.strip()
55
 
56
- # Greeting Detection
57
  def is_greeting(text: str) -> bool:
58
  return bool(re.search(r"\b(hi|hello|hey|good (morning|afternoon|evening))\b", text, re.I))
59
 
60
- # Logging
61
- def _save_process_log(log_lines, filename=None):
62
- logs_dir = os.path.join(os.path.dirname(__file__), "logs")
63
- os.makedirs(logs_dir, exist_ok=True)
64
- log_filename = filename or os.path.join(logs_dir, f"chat_session_{SESSION_ID}.txt")
65
- try:
66
- with open(log_filename, "a", encoding="utf-8") as f:
67
- f.write("=" * 50 + "\n")
68
- for line in log_lines:
69
- f.write(str(line) + "\n\n")
70
- except Exception as e:
71
- print("Logging error:", e)
72
-
73
- # Main Process Function
74
- def process_query(query: str, first_turn: bool = False):
75
  intro = ""
76
  process_log = []
77
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  if first_turn and (not query or query.strip() == ""):
79
  intro = "Hello! I’m Wisal, an AI assistant developed by Compumacy AI, specializing in Autism Spectrum Disorders. How can I help you today?"
80
- process_log.append("User: [empty or first turn]")
81
- process_log.append(f"Wisal: {intro}")
82
  _save_process_log(process_log)
83
  return intro
84
 
85
- process_log.append(f"User: {query}")
86
-
87
  if is_greeting(query):
88
  greeting = intro + "Hello! I’m Wisal, your AI assistant developed by Compumacy AI. How can I help you today?"
89
- process_log.append(f"Wisal: {greeting}")
90
  _save_process_log(process_log)
91
  return greeting
92
 
93
  corrected_query = call_llm(
94
  model="Qwen/Qwen3-32B",
95
- messages=[{"role": "user", "content": Prompt_template_translation.format(query=query)}]
 
96
  )
97
  process_log.append(f"Corrected Query: {corrected_query}")
98
 
99
  relevance = call_llm(
100
  model="Qwen/Qwen3-32B",
101
- messages=[{"role": "user", "content": Prompt_template_relevance.format(corrected_query=corrected_query)}]
 
102
  )
103
- process_log.append(f"Relevance: {relevance}")
 
 
 
 
 
 
 
 
 
 
104
  if relevance != "RELATED":
105
- process_log.append(f"Wisal: {relevance}")
106
  _save_process_log(process_log)
107
- return relevance
 
 
108
 
 
109
  web_search_resp = asyncio.run(search_autism(corrected_query))
110
  web_answer = web_search_resp.get("answer", "")
111
- process_log.append(f"Web Search Answer: {web_answer}")
112
 
 
113
  generated = call_llm(
114
  model="Qwen/Qwen3-32B",
115
- messages=[{"role": "user", "content": Prompt_template_LLM_Generation.format(new_query=corrected_query)}]
 
116
  )
117
  process_log.append(f"LLM Generated: {generated}")
118
 
@@ -120,66 +131,107 @@ def process_query(query: str, first_turn: bool = False):
120
  rag_contexts = rag_resp.get("answer", [])
121
  process_log.append(f"RAG Contexts: {rag_contexts}")
122
 
123
- rag_text = "\n".join(f"[{i+1}] {c}" for i, c in enumerate(rag_contexts))
124
- answers_list = f"[1] {generated}\n[2] {web_answer}\n{rag_text}"
125
  reranked = call_llm(
126
  model="Qwen/Qwen3-32B",
127
- messages=[{"role": "user", "content": Prompt_template_Reranker.format(new_query=corrected_query, answers_list=answers_list)}]
 
128
  )
129
  process_log.append(f"Reranked: {reranked}")
130
 
 
131
  wisal = call_llm(
132
  model="Qwen/Qwen3-32B",
133
- messages=[{"role": "user", "content": Prompt_template_Wisal.format(new_query=corrected_query, document=reranked)}]
 
134
  )
135
- process_log.append(f"Wisal Final Answer: {wisal}")
136
 
 
 
 
 
 
137
  halluc = call_llm(
138
  model="Qwen/Qwen3-32B",
139
- messages=[{"role": "user", "content": Prompt_template_Halluciations.format(new_query=corrected_query, answer=wisal, document=generated)}]
 
140
  )
141
- process_log.append(f"Hallucination Check: {halluc}")
142
- score = int(halluc.split("Score: ")[1]) if "Score: " in halluc else 3
143
 
144
  if score in (2, 3):
145
- paraphrase = call_llm(
146
  model="Qwen/Qwen3-32B",
147
- messages=[{"role": "user", "content": Prompt_template_paraphrasing.format(document=generated)}]
 
148
  )
149
- process_log.append(f"Paraphrased: {paraphrase}")
150
- final_doc = call_llm(
151
  model="Qwen/Qwen3-32B",
152
- messages=[{"role": "user", "content": Prompt_template_Wisal.format(new_query=corrected_query, document=paraphrase)}]
 
153
  )
154
- process_log.append(f"Wisal with Paraphrase: {final_doc}")
155
- else:
156
- final_doc = wisal
157
 
158
  try:
159
- detected_lang = langdetect.detect(query)
160
- except Exception:
161
  detected_lang = "en"
 
162
  if detected_lang != "en":
163
  result = call_llm(
164
  model="Qwen/Qwen3-32B",
165
- messages=[{"role": "user", "content": Prompt_template_Translate_to_original.format(query=query, document=final_doc)}]
 
166
  )
167
  process_log.append(f"Translated Back: {result}")
168
  else:
169
- result = final_doc
170
  process_log.append(f"Final Result: {result}")
171
 
172
- process_log.append(f"Wisal: {result}")
173
  _save_process_log(process_log)
174
- return result
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
 
176
- # Gradio Interface
177
  def main_pipeline_with_doc_and_history(query, doc_file, doc_type, history):
178
  response = main_pipeline_with_doc(query, doc_file, doc_type)
179
  updated_history = history + f"\nUser: {query}\nWisal: {response}\n"
180
  return response, updated_history
181
 
182
  def main_pipeline_with_doc(query, doc_file, doc_type):
 
183
  if doc_file is None or doc_type == "None":
184
  return process_query(query, first_turn=True)
185
 
@@ -189,15 +241,21 @@ def main_pipeline_with_doc(query, doc_file, doc_type):
189
 
190
  save_path = os.path.join(upload_dir, safe_filename)
191
 
 
192
  if hasattr(doc_file, 'read'):
 
193
  file_bytes = doc_file.read()
194
  else:
 
195
  with open(str(doc_file), 'rb') as f:
196
  file_bytes = f.read()
197
 
 
198
  with open(save_path, "wb") as f:
199
  f.write(file_bytes)
200
 
 
 
201
  if doc_type == "Knowledge Document":
202
  status = RAG_Domain_know_doc.ingest_file(save_path)
203
  answer = RAG_Domain_know_doc.answer_question(query)
@@ -212,6 +270,7 @@ def main_pipeline_with_doc(query, doc_file, doc_type):
212
  return f"[Old Document Uploaded]\n{status}\n\n{answer}"
213
  else:
214
  return "Invalid document type."
 
215
  def pipeline_with_history(message, doc_file, doc_type, history):
216
  if not message.strip():
217
  return history, ""
@@ -219,7 +278,6 @@ def pipeline_with_history(message, doc_file, doc_type, history):
219
  history = history + [[message, response]]
220
  return history, ""
221
 
222
-
223
  with gr.Blocks(title="Wisal Chatbot", theme=gr.themes.Base()) as demo:
224
  gr.Markdown("# 🤖 Wisal: Autism AI Assistant")
225
 
@@ -245,17 +303,6 @@ with gr.Blocks(title="Wisal Chatbot", theme=gr.themes.Base()) as demo:
245
  clear_btn = gr.Button("Clear Chat")
246
  clear_btn.click(lambda: [], outputs=[chatbot])
247
 
248
- # with gr.Tab("📘 Domain Knowledge RAG"):
249
- # RAG_Domain_know_doc.demo.render()
250
-
251
- # with gr.Tab("📁 User-Specific Documents"):
252
- # User_Specific_Documents.demo.render()
253
-
254
- # with gr.Tab("🕰️ Old Documents"):
255
- # Old_Document.demo.render()
256
 
257
  if __name__ == "__main__":
258
- demo.launch(debug=True)
259
-
260
-
261
-
 
34
  WEAVIATE_API_KEY="RU9acU1CYnNRTjY1S1ZFc18zNS9tQktaWlcwTzFEUjlscEVCUGF4YU5xRWx2MDhmTUtIdUhnOWdOTGVZPV92MjAw"
35
  DEEPINFRA_API_KEY="285LUJulGIprqT6hcPhiXtcrphU04FG4"
36
  DEEPINFRA_BASE_URL="https://api.deepinfra.com/v1/openai"
 
37
  # Initialize OpenAI client
38
+ env = os.getenv("ENVIRONMENT", "production")
39
  openai = OpenAI(
40
  api_key=DEEPINFRA_API_KEY,
41
  base_url="https://api.deepinfra.com/v1/openai",
42
  )
 
43
  SESSION_ID = "default"
44
 
45
+ pending_clarifications = {}
46
+
47
  def call_llm(model: str, messages: list[dict], temperature: float = 0.0, **kwargs) -> str:
48
  resp = openai.chat.completions.create(
49
  model=model,
 
53
  )
54
  return resp.choices[0].message.content.strip()
55
 
 
56
  def is_greeting(text: str) -> bool:
57
  return bool(re.search(r"\b(hi|hello|hey|good (morning|afternoon|evening))\b", text, re.I))
58
 
59
+ def process_query(query: str, first_turn: bool = False, session_id: str = "default"):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  intro = ""
61
  process_log = []
62
 
63
+ if session_id in pending_clarifications:
64
+ if query.strip().lower() == "yes":
65
+ corrected_query = pending_clarifications.pop(session_id)
66
+ process_log.append(f"User confirmed: {corrected_query}")
67
+ return process_autism_pipeline(corrected_query, process_log, intro)
68
+ else:
69
+ pending_clarifications.pop(session_id)
70
+ redirect = "Hello I’m Wisal, an AI assistant developed by Compumacy AI, and a knowledgeable Autism specialist.\nIf you have any question related to autism please submit a question specifically about autism."
71
+ process_log.append("User rejected clarification.")
72
+ _save_process_log(process_log)
73
+ return redirect
74
+
75
  if first_turn and (not query or query.strip() == ""):
76
  intro = "Hello! I’m Wisal, an AI assistant developed by Compumacy AI, specializing in Autism Spectrum Disorders. How can I help you today?"
77
+ process_log.append(intro)
 
78
  _save_process_log(process_log)
79
  return intro
80
 
 
 
81
  if is_greeting(query):
82
  greeting = intro + "Hello! I’m Wisal, your AI assistant developed by Compumacy AI. How can I help you today?"
83
+ process_log.append(f"Greeting detected.\n{greeting}")
84
  _save_process_log(process_log)
85
  return greeting
86
 
87
  corrected_query = call_llm(
88
  model="Qwen/Qwen3-32B",
89
+ messages=[{"role": "user", "content": Prompt_template_translation.format(query=query)}],
90
+ reasoning_effort="none"
91
  )
92
  process_log.append(f"Corrected Query: {corrected_query}")
93
 
94
  relevance = call_llm(
95
  model="Qwen/Qwen3-32B",
96
+ messages=[{"role": "user", "content": Prompt_template_relevance.format(corrected_query=corrected_query)}],
97
+ reasoning_effort="none"
98
  )
99
+ process_log.append(f"Relevance Check: {relevance}")
100
+
101
+ redirect_message = "Hello I’m Wisal, an AI assistant developed by Compumacy AI, and a knowledgeable Autism specialist.\nIf you have any question related to autism please submit a question specifically about autism."
102
+
103
+ if relevance.startswith("Hello I’m Wisal"):
104
+ clarification = f"Your query was not clearly related to autism. Do you mean:\n\"{corrected_query}\"\nIf yes, please confirm so I can help. If not:\n{redirect_message}"
105
+ pending_clarifications[session_id] = corrected_query
106
+ process_log.append(f"Clarification Prompted: {clarification}")
107
+ _save_process_log(process_log)
108
+ return clarification
109
+
110
  if relevance != "RELATED":
111
+ process_log.append("Query not autism-related.")
112
  _save_process_log(process_log)
113
+ return intro + relevance
114
+
115
+ return process_autism_pipeline(corrected_query, process_log, intro)
116
 
117
+ def process_autism_pipeline(corrected_query, process_log, intro):
118
  web_search_resp = asyncio.run(search_autism(corrected_query))
119
  web_answer = web_search_resp.get("answer", "")
120
+ process_log.append(f"Web Search: {web_answer}")
121
 
122
+ gen_prompt = Prompt_template_LLM_Generation.format(new_query=corrected_query)
123
  generated = call_llm(
124
  model="Qwen/Qwen3-32B",
125
+ messages=[{"role": "user", "content": gen_prompt}],
126
+ reasoning_effort="none"
127
  )
128
  process_log.append(f"LLM Generated: {generated}")
129
 
 
131
  rag_contexts = rag_resp.get("answer", [])
132
  process_log.append(f"RAG Contexts: {rag_contexts}")
133
 
134
+ answers_list = f"[1] {generated}\n[2] {web_answer}\n" + "\n".join(f"[{i+3}] {c}" for i, c in enumerate(rag_contexts))
135
+ rerank_prompt = Prompt_template_Reranker.format(new_query=corrected_query, answers_list=answers_list)
136
  reranked = call_llm(
137
  model="Qwen/Qwen3-32B",
138
+ messages=[{"role": "user", "content": rerank_prompt}],
139
+ reasoning_effort="none"
140
  )
141
  process_log.append(f"Reranked: {reranked}")
142
 
143
+ wisal_prompt = Prompt_template_Wisal.format(new_query=corrected_query, document=reranked)
144
  wisal = call_llm(
145
  model="Qwen/Qwen3-32B",
146
+ messages=[{"role": "user", "content": wisal_prompt}],
147
+ reasoning_effort="none"
148
  )
149
+ process_log.append(f"Wisal Answer: {wisal}")
150
 
151
+ halluc_prompt = Prompt_template_Halluciations.format(
152
+ new_query=corrected_query,
153
+ answer=wisal,
154
+ document=generated
155
+ )
156
  halluc = call_llm(
157
  model="Qwen/Qwen3-32B",
158
+ messages=[{"role": "user", "content": halluc_prompt}],
159
+ reasoning_effort="none"
160
  )
161
+ process_log.append(f"Hallucination Score: {halluc}")
162
+ score = int(halluc.split("Score: ")[-1]) if "Score: " in halluc else 3
163
 
164
  if score in (2, 3):
165
+ paraphrased = call_llm(
166
  model="Qwen/Qwen3-32B",
167
+ messages=[{"role": "user", "content": Prompt_template_paraphrasing.format(document=generated)}],
168
+ reasoning_effort="none"
169
  )
170
+ wisal = call_llm(
 
171
  model="Qwen/Qwen3-32B",
172
+ messages=[{"role": "user", "content": Prompt_template_Wisal.format(new_query=corrected_query, document=paraphrased)}],
173
+ reasoning_effort="none"
174
  )
175
+ process_log.append(f"Paraphrased Wisal: {wisal}")
 
 
176
 
177
  try:
178
+ detected_lang = langdetect.detect(corrected_query)
179
+ except:
180
  detected_lang = "en"
181
+
182
  if detected_lang != "en":
183
  result = call_llm(
184
  model="Qwen/Qwen3-32B",
185
+ messages=[{"role": "user", "content": Prompt_template_Translate_to_original.format(query=corrected_query, document=wisal)}],
186
+ reasoning_effort="none"
187
  )
188
  process_log.append(f"Translated Back: {result}")
189
  else:
190
+ result = wisal
191
  process_log.append(f"Final Result: {result}")
192
 
 
193
  _save_process_log(process_log)
194
+ return intro + result
195
+
196
+
197
+ def _save_process_log(log_lines, filename="process_output.txt"):
198
+ import datetime
199
+ logs_dir = os.path.join(os.path.dirname(__file__), "logs")
200
+ os.makedirs(logs_dir, exist_ok=True)
201
+ timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S_%f")
202
+ log_filename = os.path.join(logs_dir, f"log_{timestamp}.txt")
203
+ with open(log_filename, "w", encoding="utf-8") as f:
204
+ for line in log_lines:
205
+ f.write(str(line) + "\n\n")
206
+
207
+ def _save_process_log(log_lines, filename="process_output.txt"):
208
+ import datetime
209
+ import os
210
+ # Ensure logs directory exists
211
+ logs_dir = os.path.join(os.path.dirname(__file__), "logs")
212
+ os.makedirs(logs_dir, exist_ok=True)
213
+ # Unique filename per question (timestamped)
214
+ timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S_%f")
215
+ log_filename = os.path.join(logs_dir, f"log_{timestamp}.txt")
216
+ try:
217
+ with open(log_filename, "w", encoding="utf-8") as f:
218
+ for line in log_lines:
219
+ f.write(str(line) + "\n\n")
220
+ except Exception as e:
221
+ pass
222
+
223
+
224
+ # Gradio UI for main pipeline, RAG_Domain_know_doc, and User_Specific_Documents , Old_Document
225
+ def main_pipeline_interface(query):
226
+ return process_query(query, first_turn=True)
227
 
 
228
  def main_pipeline_with_doc_and_history(query, doc_file, doc_type, history):
229
  response = main_pipeline_with_doc(query, doc_file, doc_type)
230
  updated_history = history + f"\nUser: {query}\nWisal: {response}\n"
231
  return response, updated_history
232
 
233
  def main_pipeline_with_doc(query, doc_file, doc_type):
234
+ # If no document, use main pipeline
235
  if doc_file is None or doc_type == "None":
236
  return process_query(query, first_turn=True)
237
 
 
241
 
242
  save_path = os.path.join(upload_dir, safe_filename)
243
 
244
+ # 💡 Check if doc_file is file-like (has `.read()`) or path-like (str or NamedString)
245
  if hasattr(doc_file, 'read'):
246
+ # File-like object
247
  file_bytes = doc_file.read()
248
  else:
249
+ # It's a path (NamedString), read from file path
250
  with open(str(doc_file), 'rb') as f:
251
  file_bytes = f.read()
252
 
253
+ # Save the file content
254
  with open(save_path, "wb") as f:
255
  f.write(file_bytes)
256
 
257
+
258
+ # Route to correct document handler
259
  if doc_type == "Knowledge Document":
260
  status = RAG_Domain_know_doc.ingest_file(save_path)
261
  answer = RAG_Domain_know_doc.answer_question(query)
 
270
  return f"[Old Document Uploaded]\n{status}\n\n{answer}"
271
  else:
272
  return "Invalid document type."
273
+
274
  def pipeline_with_history(message, doc_file, doc_type, history):
275
  if not message.strip():
276
  return history, ""
 
278
  history = history + [[message, response]]
279
  return history, ""
280
 
 
281
  with gr.Blocks(title="Wisal Chatbot", theme=gr.themes.Base()) as demo:
282
  gr.Markdown("# 🤖 Wisal: Autism AI Assistant")
283
 
 
303
  clear_btn = gr.Button("Clear Chat")
304
  clear_btn.click(lambda: [], outputs=[chatbot])
305
 
 
 
 
 
 
 
 
 
306
 
307
  if __name__ == "__main__":
308
+ demo.launch(debug=True)