YoniFriedman commited on
Commit
b591b61
·
verified ·
1 Parent(s): 8350ba2

updating app.py

Browse files
Files changed (1) hide show
  1. app.py +136 -183
app.py CHANGED
@@ -1,177 +1,114 @@
 
 
 
 
1
  import os
2
- os.environ["OPENAI_API_KEY"]
3
-
4
- from llama_index.llms.openai import OpenAI
5
- from llama_index.core.schema import MetadataMode
6
- import openai
7
- from openai import OpenAI as OpenAIOG
8
  import logging
9
  import sys
10
- llm = OpenAI(temperature=0.0, model="gpt-3.5-turbo")
11
- client = OpenAIOG()
12
-
13
- from langdetect import detect
14
- from langdetect import DetectorFactory
15
- DetectorFactory.seed = 0
16
- from deep_translator import GoogleTranslator
17
  from lingua import Language, LanguageDetectorBuilder
 
 
 
 
 
18
 
19
- # Load index
20
- from llama_index.core import VectorStoreIndex
21
- from llama_index.core import StorageContext
22
- from llama_index.core import load_index_from_storage
23
- storage_context = StorageContext.from_defaults(persist_dir="arv_metadata")
24
- index = load_index_from_storage(storage_context)
25
- query_engine = index.as_query_engine(similarity_top_k=3, llm=llm)
26
- retriever = index.as_retriever(similarity_top_k = 3)
27
 
28
- import gradio as gr
 
 
29
 
30
- import re
31
- import json
32
- from datetime import datetime
 
33
 
34
- acknowledgment_keywords_sw = ["sawa", "ndiyo", "naam", "hakika", "asante", "nimeelewa", "nimekupata", "ni kweli",
35
- "kwa hakika", "nimesikia"]
36
  acknowledgment_keywords_en = ["thanks", "thank you", "thx", "ok", "okay", "great", "got it", "appreciate", "good", "makes sense"]
37
- follow_up_keywords = ["but", "also", "and", "what", "how", "why", "when", "is", "?",
38
- "lakini", "pia", "na", "nini", "vipi", "kwanini", "wakati"]
39
  greeting_keywords_sw = ["sasa", "niaje", "habari", "mambo", "jambo", "shikamoo", "marahaba", "hujambo", "hamjambo", "salama", "vipi"]
40
  greeting_keywords_en = ["hi", "hello", "hey", "how's it", "what's up", "yo", "howdy"]
 
 
41
 
42
  def contains_exact_word_or_phrase(text, keywords):
 
43
  text = text.lower()
44
- for keyword in keywords:
45
- if re.search(r'\b' + re.escape(keyword) + r'\b', text):
46
- return True
47
- return False
48
 
49
- def contains_greeting_sw(question):
50
- # Check if the question contains acknowledgment keywords
51
- return contains_exact_word_or_phrase(question, greeting_keywords_sw)
52
 
53
- def contains_greeting_en(question):
54
- # Check if the question contains acknowledgment keywords
55
- return contains_exact_word_or_phrase(question, greeting_keywords_en)
56
 
57
- def contains_acknowledgment_sw(question):
58
- # Check if the question contains acknowledgment keywords
59
- return contains_exact_word_or_phrase(question, acknowledgment_keywords_sw)
60
 
61
- def contains_acknowledgment_en(question):
62
- # Check if the question contains acknowledgment keywords
63
- return contains_exact_word_or_phrase(question, acknowledgment_keywords_en)
64
 
65
- def contains_follow_up(question):
66
- # Check if the question contains follow-up indicators
67
- return contains_exact_word_or_phrase(question, follow_up_keywords)
68
 
69
  def convert_to_date(date_str):
70
- return datetime.strptime(date_str, "%Y%m%d")
71
-
72
- def detect_language(question):
73
- # Check if the text has less than 5 words
74
- if len(question.split()) < 5:
75
- languages = [Language.ENGLISH, Language.SWAHILI] # Add more languages as needed
 
 
 
 
76
  detector = LanguageDetectorBuilder.from_languages(*languages).build()
77
- detected_language = detector.detect_language_of(question)
78
- # Return language code for consistency
79
- if detected_language == Language.SWAHILI:
80
- return "sw"
81
- elif detected_language == Language.ENGLISH:
82
- return "en"
83
- else:
84
- try:
85
- lang_detect = detect(question)
86
- return lang_detect
87
- except Exception as e:
88
- print(f"Error with langdetect: {e}")
89
- return "unknown"
90
-
91
- def nishauri(question: str, conversation_history: list[str]):
92
-
93
- # Get conversation history
94
- context = " ".join([item["user"] + " " + item["chatbot"] for item in conversation_history])
95
-
96
- ## Process greeting
97
- # greet_response = process_greeting_response(question)
98
- if contains_greeting_en(question) and not contains_follow_up(question):
99
- greeting = (
100
- f" The user previously asked and answered the following: {context}. "
101
- f" The user just provided the following greeting: {question}. "
102
- "Please respond accordingly in English."
103
- )
104
- completion = client.chat.completions.create(
105
- model="gpt-4o",
106
- messages=[
107
- {"role": "user", "content": greeting}
108
- ]
109
- )
110
- reply_to_user = completion.choices[0].message.content
111
- conversation_history.append({"user": question, "chatbot": reply_to_user})
112
- return reply_to_user, conversation_history
113
-
114
- if contains_greeting_sw(question) and not contains_follow_up(question):
115
- greeting = (
116
- f" The user previously asked and answered the following: {context}. "
117
- f" The user just provided the following greeting: {question}. "
118
- "Please respond accordingly in Swahili."
119
- )
120
- completion = client.chat.completions.create(
121
- model="gpt-4o",
122
- messages=[
123
- {"role": "user", "content": greeting}
124
- ]
125
- )
126
- reply_to_user = completion.choices[0].message.content
127
- conversation_history.append({"user": question, "chatbot": reply_to_user})
128
- return reply_to_user, conversation_history
129
 
130
- ## Process acknowledgment
131
- if contains_acknowledgment_en(question) and not contains_follow_up(question):
132
- acknowledgment = (
133
- f" The user previously asked and answered the following: {context}. "
134
- f" The user just provided the following acknowledgement: {question}. "
135
- "Please respond accordingly in English."
136
- )
137
- completion = client.chat.completions.create(
138
- model="gpt-4o",
139
- messages=[
140
- {"role": "user", "content": acknowledgment}
141
- ]
142
- )
143
- reply_to_user = completion.choices[0].message.content
144
- conversation_history.append({"user": question, "chatbot": reply_to_user})
145
- return reply_to_user, conversation_history
146
-
147
- if contains_acknowledgment_sw(question) and not contains_follow_up(question):
148
- acknowledgment = (
149
- f" The user previously asked and answered the following: {context}. "
150
- f" The user just provided the following acknowledgment: {question}. "
151
- "Please respond accordingly in Swahili."
152
- )
153
- completion = client.chat.completions.create(
154
- model="gpt-4o",
155
- messages=[
156
- {"role": "user", "content": acknowledgment}
157
- ]
158
- )
159
- reply_to_user = completion.choices[0].message.content
160
- conversation_history.append({"user": question, "chatbot": reply_to_user})
161
- return reply_to_user, conversation_history
162
-
163
- ## If not greeting or acknowledgement, then proceed with RAG
164
-
165
- ## Detect language of question - if Swahili, translate to English
166
  lang_question = detect_language(question)
167
- if lang_question=="sw":
168
  question = GoogleTranslator(source='sw', target='en').translate(question)
169
-
170
- # Now, retrieve relevant sources
171
  sources = retriever.retrieve(question)
172
- source0 = sources[0].text
173
- source1 = sources[1].text
174
- source2 = sources[2].text
175
 
176
  source1return = ("File Name: " +
177
  sources[0].metadata["file_name"] +
@@ -194,51 +131,67 @@ def nishauri(question: str, conversation_history: list[str]):
194
  "\n Source Text: " +
195
  sources[2].text)
196
 
197
-
198
- background = ("The person who asked the question is a person living with HIV."
199
- " They are asking questions about HIV. Do not talk about anything that is not related to HIV. "
200
- " Recognize that they already have HIV and do not suggest that they have to get tested"
201
- " for HIV or take post-exposure prophylaxis, as that is not relevant, though their partners perhaps should."
202
- " Do not suggest anything that is not relevant to someone who already has HIV."
203
- " Do not mention in the response that the person is living with HIV."
204
- " The following information about viral loads is authoritative for any question about viral loads:"
205
- # " Under 50 copies/ml is low detectable level,"
206
- # " 50 - 199 copies/ml is low level viremia, 200 - 999 is high level viremia, and "
207
- # " 1000 and above is suspected treatment failure."
208
- " A high viral load or non-suppressed viral load is any viral load above 200 copies/ml."
209
- " A viral load above 1000 copies/ml suggests treatment failure."
210
- " A suppressed viral load is one below 200 copies / ml.")
211
-
212
  question_final = (
213
- f" The user previously asked and answered the following: {context}. "
214
- f" The user just asked the following question: {question}."
215
- f" Please use the following content to generate a response: {source0} {source1} {source2}."
216
- f" Please consider the following background information when generating a response: {background}."
217
- " Keep answers brief and limited to the question that was asked."
218
- " If they share a greeting, just greet them in return and ask if they have a question."
219
- " Do not change the subject or address anything the user didn't directly ask about."
220
- " If they respond with an acknowledgement, simply thank them."
221
- " Do not discuss anything other than HIV. If they ask a question that is not about HIV, respond that"
222
- " you are only able to discuss HIV."
223
- " Keep the response to under 50 words and use simple language. The person asking the question does not know technical terms."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
  )
 
 
 
 
 
 
 
 
225
 
 
 
 
 
226
  completion = client.chat.completions.create(
227
- model="gpt-4o",
228
- messages=[
229
- {"role": "user", "content": question_final}
230
- ]
231
  )
232
 
 
233
  reply_to_user = completion.choices[0].message.content
234
-
 
 
 
 
235
  if lang_question=="sw":
236
- reply_to_user = GoogleTranslator(source='auto', target='sw').translate(reply_to_user)
237
-
238
- conversation_history.append({"user": question, "chatbot": reply_to_user})
239
 
240
- return reply_to_user, source1return, source2return, source3return, conversation_history
 
241
 
 
242
  demo = gr.Interface(
243
  title = "Nuru Chatbot Demo",
244
  description="Enter a question and see the processed outputs in collapsible boxes.",
 
1
+ #%% md
2
+ # ## Nuru HIV Informational Chatbot
3
+ #%%
4
+ # Import libraries
5
  import os
 
 
 
 
 
 
6
  import logging
7
  import sys
8
+ import re
9
+ import json
 
 
 
 
 
10
  from lingua import Language, LanguageDetectorBuilder
11
+ import gradio as gr
12
+ from openai import OpenAI as OpenAIOG
13
+ from llama_index.llms.openai import OpenAI
14
+ from llama_index.core import VectorStoreIndex, StorageContext, load_index_from_storage
15
+ from deep_translator import GoogleTranslator
16
 
17
+ # Set OpenAI API Key (Ensure this is set in the environment)
18
+ # load_dotenv("config.env")
19
+ os.environ.get("OPENAI_API_KEY")
 
 
 
 
 
20
 
21
+ # Initialize OpenAI clients
22
+ llm = OpenAI(temperature=0.0, model="gpt-4o")
23
+ client = OpenAIOG()
24
 
25
+ # Load index for retrieval
26
+ storage_context = StorageContext.from_defaults(persist_dir="arv_metadata")
27
+ index = load_index_from_storage(storage_context)
28
+ retriever = index.as_retriever(similarity_top_k=3)
29
 
30
+ # Define keyword lists
31
+ acknowledgment_keywords_sw = ["sawa", "ndiyo", "naam", "hakika", "asante", "nimeelewa", "nimekupata", "ni kweli", "kwa hakika", "nimesikia", "ahsante"]
32
  acknowledgment_keywords_en = ["thanks", "thank you", "thx", "ok", "okay", "great", "got it", "appreciate", "good", "makes sense"]
33
+ follow_up_keywords = ["but", "also", "and", "what", "how", "why", "when", "is", "?", "lakini", "pia", "na", "nini", "vipi", "kwanini", "wakati"]
 
34
  greeting_keywords_sw = ["sasa", "niaje", "habari", "mambo", "jambo", "shikamoo", "marahaba", "hujambo", "hamjambo", "salama", "vipi"]
35
  greeting_keywords_en = ["hi", "hello", "hey", "how's it", "what's up", "yo", "howdy"]
36
+ #%%
37
+ # Define helper functions
38
 
39
  def contains_exact_word_or_phrase(text, keywords):
40
+ """Check if the given text contains any exact keyword from the list."""
41
  text = text.lower()
42
+ return any(re.search(r'\b' + re.escape(keyword) + r'\b', text) for keyword in keywords)
 
 
 
43
 
44
+ def contains_greeting_sw(text):
45
+ return contains_exact_word_or_phrase(text, greeting_keywords_sw)
 
46
 
47
+ def contains_greeting_en(text):
48
+ return contains_exact_word_or_phrase(text, greeting_keywords_en)
 
49
 
50
+ def contains_acknowledgment_sw(text):
51
+ return contains_exact_word_or_phrase(text, acknowledgment_keywords_sw)
 
52
 
53
+ def contains_acknowledgment_en(text):
54
+ return contains_exact_word_or_phrase(text, acknowledgment_keywords_en)
 
55
 
56
+ def contains_follow_up(text):
57
+ return contains_exact_word_or_phrase(text, follow_up_keywords)
 
58
 
59
  def convert_to_date(date_str):
60
+ """Convert date string in YYYYMMDD format to YYYY-MM-DD."""
61
+ try:
62
+ return datetime.strptime(date_str, "%Y%m%d").strftime("%Y-%m-%d")
63
+ except ValueError:
64
+ return "Unknown Date"
65
+
66
+ def detect_language(text):
67
+ """Detect language of a given text using Lingua for short texts and langdetect for longer ones."""
68
+ if len(text.split()) < 5:
69
+ languages = [Language.ENGLISH, Language.SWAHILI]
70
  detector = LanguageDetectorBuilder.from_languages(*languages).build()
71
+ detected_language = detector.detect_language_of(text)
72
+ return "sw" if detected_language == Language.SWAHILI else "en"
73
+ try:
74
+ return detect(text)
75
+ except Exception as e:
76
+ logging.warning(f"Language detection error: {e}")
77
+ return "unknown"
78
+ #%%
79
+ # Define Gradio function
80
+ def nishauri(question, conversation_history: list[str]):
81
+
82
+ """Process user query, detect language, handle greetings, acknowledgments, and retrieve relevant information."""
83
+ context = " ".join([item["user"] + " " + item["chatbot"] for item in conversation_history])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
 
85
+ # Process greetings and acknowledgments
86
+ for lang, contains_greeting, contains_acknowledgment in [("en", contains_greeting_en, contains_acknowledgment_en), ("sw", contains_greeting_sw, contains_acknowledgment_sw)]:
87
+ if contains_greeting(question) and not contains_follow_up(question):
88
+ prompt = f"The user said: {question}. Respond accordingly in {lang}."
89
+ elif contains_acknowledgment(question) and not contains_follow_up(question):
90
+ prompt = f"The user acknowledged: {question}. Respond accordingly in {lang}."
91
+ else:
92
+ continue
93
+ completion = client.chat.completions.create(
94
+ model="gpt-4o",
95
+ messages=[{"role": "user", "content": prompt}]
96
+ )
97
+ reply_to_user = completion.choices[0].message.content
98
+ conversation_history.append({"user": question, "chatbot": reply_to_user})
99
+ Source1Return = ""
100
+ Source2Return = ""
101
+ Source3Return = ""
102
+ return reply_to_user, source1return, source2return, source3return, conversation_history
103
+
104
+ # Detect language and translate if needed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  lang_question = detect_language(question)
106
+ if lang_question == "sw":
107
  question = GoogleTranslator(source='sw', target='en').translate(question)
108
+
109
+ # Retrieve relevant sources
110
  sources = retriever.retrieve(question)
111
+ retrieved_text = "\n\n".join([f"Source {i+1}: {source.text}" for i, source in enumerate(sources[:3])])
 
 
112
 
113
  source1return = ("File Name: " +
114
  sources[0].metadata["file_name"] +
 
131
  "\n Source Text: " +
132
  sources[2].text)
133
 
134
+ # Combine into new user question - conversation history, new question, retrieved sources
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  question_final = (
136
+ f"The user asked the following question: \"{question}\"\n\n"
137
+ f"Use only the content below to answer the question:\n\n{retrieved_text}\n\n"
138
+ "Guidelines:\n"
139
+ "- Only answer the question that was asked.\n"
140
+ "- Do not change the subject or include unrelated information.\n"
141
+ "- Only discuss HIV. If the question is not about HIV, say that you can only answer HIV-related questions.\n"
142
+ )
143
+
144
+ # Set LLM instructions. If user consented, add user parameters, otherwise proceed without
145
+ system_prompt = (
146
+ "You are a helpful assistant who only answers questions about HIV.\n"
147
+ "- Do not answer questions about other topics (e.g., malaria or tuberculosis).\n"
148
+ "- If a question is unrelated to HIV, politely respond that you can only answer HIV-related questions.\n\n"
149
+
150
+ "The person asking the question is living with HIV.\n"
151
+ "- Do not suggest they get tested for HIV or take post-exposure prophylaxis (PEP).\n"
152
+ "- You may mention that their partners might benefit from testing or PEP, if relevant.\n"
153
+ "- Do not mention in your response that the person is living with HIV.\n"
154
+ "- Only suggest things relevant to someone who already has HIV.\n\n"
155
+ "- Keep the answer under 50 words.\n"
156
+ "- Use simple, easy-to-understand language. Avoid medical jargon.\n"
157
+
158
+ "Use the following authoritative information about viral loads:\n"
159
+ "- A high or non-suppressed viral load is above 200 copies/ml.\n"
160
+ "- A viral load above 1000 copies/ml suggests treatment failure.\n"
161
+ "- A suppressed viral load is one below 200 copies/ml.\n\n"
162
  )
163
+
164
+ # Start with context
165
+ messages = [{"role": "system", "content": system_prompt}]
166
+
167
+ # Add conversation history
168
+ for turn in conversation_history:
169
+ messages.append({"role": "user", "content": turn["user"]})
170
+ messages.append({"role": "assistant", "content": turn["chatbot"]})
171
 
172
+ # Finally, add the current question
173
+ messages.append({"role": "user", "content": question_final})
174
+
175
+ # Generate response
176
  completion = client.chat.completions.create(
177
+ model="gpt-4o",
178
+ messages=messages
 
 
179
  )
180
 
181
+ # Collect response
182
  reply_to_user = completion.choices[0].message.content
183
+
184
+ # add question and reply to conversation history
185
+ conversation_history.append({"user": question, "chatbot": reply_to_user})
186
+
187
+ # If initial question was in swahili, translate response to swahili
188
  if lang_question=="sw":
189
+ reply_to_user = GoogleTranslator(source='auto', target='sw').translate(reply_to_user)
 
 
190
 
191
+ # return system_prompt, conversation_history
192
+ return reply_to_user, source1return, source2return, source3return, conversation_history
193
 
194
+ #%%
195
  demo = gr.Interface(
196
  title = "Nuru Chatbot Demo",
197
  description="Enter a question and see the processed outputs in collapsible boxes.",