kramachan commited on
Commit
11abeb5
·
verified ·
1 Parent(s): 9c2ca7e

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +90 -186
src/streamlit_app.py CHANGED
@@ -11,201 +11,105 @@ logger = logging.getLogger(__name__)
11
  GROQ_API_KEY="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"
12
  OPENAI_API_KEY="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"
13
 
14
- logger.info("Design Page...")
15
- # -------------------------------
16
- # PAGE CONFIG (MUST BE FIRST)
17
- # -------------------------------
18
- PORT = int(os.environ.get("PORT", 8501))
19
-
20
- st.markdown("""
21
- <style>
22
- .main-title {
23
- font-size: 52px;
24
- font-weight: 800;
25
- text-align: center;
26
- color: #0B5ED7;
27
- margin-bottom: 5px;
28
- }
29
-
30
- .sub-title {
31
- font-size: 20px;
32
- text-align: center;
33
- color: #555555;
34
- margin-bottom: 30px;
35
- }
36
- </style>
37
- """, unsafe_allow_html=True)
38
-
39
- st.markdown(
40
- '<div class="main-title">💊 AI Medical Labelling System</div>',
41
- unsafe_allow_html=True
42
- )
43
 
44
- st.markdown(
45
- '<div class="sub-title">Simplifying FDA Drug Safety Information using Generative AI & RAG</div>',
46
- unsafe_allow_html=True
 
47
  )
48
 
49
- # -------------------------------
50
- # CUSTOM CSS (FANCY DESIGN)
51
- # -------------------------------
52
- st.markdown("""
53
- <style>
54
- .main {
55
- background-color: #f7f9fc;
56
- }
57
-
58
- .big-title {
59
- font-size:40px;
60
- font-weight:700;
61
- color:#1f4e79;
62
- }
63
-
64
- .subtitle {
65
- font-size:18px;
66
- color:#555;
67
- }
68
-
69
- .result-card {
70
- background-color:white;
71
- padding:20px;
72
- border-radius:12px;
73
- box-shadow:0px 2px 10px rgba(0,0,0,0.08);
74
- margin-top:15px;
75
- }
76
- </style>
77
- """, unsafe_allow_html=True)
78
-
79
- # -------------------------------
80
- # HEADER
81
- # -------------------------------
82
-
83
- st.divider()
84
-
85
- # -------------------------------
86
- # SIDEBAR CONTROLS
87
- # -------------------------------
88
- with st.sidebar:
89
- st.header("⚙️ Search Options")
90
-
91
- drug_name = st.text_input(
92
- "Drug Name",
93
- placeholder="PHENYTOIN SODIUM"
94
- )
95
-
96
- selected_results = st.radio(
97
- "Information Type",
98
- ["Side Effects", "Warnings", "Both"]
99
- )
100
-
101
- run_button = st.button("🔍 Generate Explanation")
102
-
103
- # -------------------------------
104
- # LOAD ENV + MODELS
105
- # -------------------------------
106
-
107
- logger.info("Loading HuggingFace embedding model...")
108
-
109
- load_dotenv()
110
 
111
  working_dir = os.path.dirname(os.path.abspath(__file__))
 
 
 
112
 
113
- embeddings = HuggingFaceEmbeddings(
114
- model_name="sentence-transformers/all-MiniLM-L6-v2"
115
- )
116
 
117
- vectordb = Chroma(
118
- persist_directory=os.path.join(working_dir, "Chroma_db"),
119
- embedding_function=embeddings
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  )
121
 
122
- logger.info("Calling OpenAI model gpt-4o-mini...")
 
 
123
 
124
- llm = ChatOpenAI(
125
- model="gpt-4o-mini",
126
- temperature=0
 
 
 
 
 
 
 
 
 
 
127
  )
128
 
129
- # -------------------------------
130
- # RAG FUNCTION
131
- # -------------------------------
132
- def generate_section(drug_name, section, rules):
133
-
134
- results = vectordb.get(
135
- where={
136
- "$and": [
137
- {"generic_name": drug_name},
138
- {"section": section}
139
- ]
140
- }
141
- )
142
-
143
- documents = results.get("documents", [])
144
-
145
- if not documents:
146
- st.warning(f"No data found for {section}")
147
- return
148
-
149
- context = "\n".join(set(documents))
150
-
151
- prompt = f"""
152
- You are a medical assistant.
153
-
154
- Rewrite the FDA drug information into simplified,
155
- easy-to-understand language.
156
-
157
- Rules:
158
- {rules}
159
-
160
- Drug: {drug_name}
161
-
162
- FDA TEXT:
163
- {context}
164
- """
165
-
166
- with st.spinner("🧠 AI is analysing FDA data..."):
167
- response = llm.invoke(prompt)
168
-
169
- st.markdown(
170
- f'<div class="result-card">{response.content}</div>',
171
- unsafe_allow_html=True
172
- )
173
-
174
- logger.info("Configuring prompt..")
175
- # -------------------------------
176
- # RULES
177
- # -------------------------------
178
- SIDE_EFFECT_RULES = """
179
- - Use simple English
180
- - Bullet points (max 7)
181
- - Group similar side effects
182
- - Separate common vs serious
183
- """
184
-
185
- WARNING_RULES = """
186
- - Use simple English
187
- - Bullet points (max 7)
188
- - Group warnings clearly
189
- """
190
-
191
- SECTION_MAP = {
192
- "Side Effects": [("adverse_reactions", SIDE_EFFECT_RULES)],
193
- "Warnings": [("warnings_and_cautions", WARNING_RULES)],
194
- "Both": [
195
- ("adverse_reactions", SIDE_EFFECT_RULES),
196
- ("warnings_and_cautions", WARNING_RULES),
197
- ],
198
- }
199
-
200
- # -------------------------------
201
- # MAIN ACTION
202
- # -------------------------------
203
- if run_button and drug_name:
204
-
205
- st.subheader(f"Results for: {drug_name.upper()}")
206
-
207
- for section, rules in SECTION_MAP[selected_results]:
208
- generate_section(drug_name, section, rules)
209
-
210
- elif run_button:
211
- st.warning("Please enter a drug name.")
 
11
  GROQ_API_KEY="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"
12
  OPENAI_API_KEY="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"
13
 
14
+ import os
15
+ import logging
16
+ from langchain_core.documents import Document
17
+ from langchain_text_splitters import RecursiveCharacterTextSplitter
18
+ from langchain_huggingface import HuggingFaceEmbeddings
19
+ from langchain_chroma import Chroma
20
+ from langchain_openai import ChatOpenAI
21
+ import json
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
+ # Set up logging configuration
24
+ logging.basicConfig(
25
+ level=logging.INFO,
26
+ format='%(asctime)s - %(levelname)s - %(message)s'
27
  )
28
 
29
+ # Get a logger for this module
30
+ logger = logging.getLogger(__name__)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
 
32
  working_dir = os.path.dirname(os.path.abspath(__file__))
33
+ parent_dir = os.path.dirname(working_dir)
34
+ data_dir = f"{parent_dir}/data"
35
+ vector_db_dir = f"{parent_dir}/vector_db"
36
 
 
 
 
37
 
38
+ logger.info("Reading Files Process Started...")
39
+ all_records = []
40
+
41
+ # loop through all files
42
+ for file_name in os.listdir(data_dir):
43
+ if file_name.endswith(".json"):
44
+ file_path = os.path.join(data_dir, file_name)
45
+
46
+ with open(file_path, "r", encoding="utf-8") as f:
47
+ data = json.load(f)
48
+
49
+ # if JSON contains list of records
50
+ if isinstance(data, list):
51
+ all_records.extend(data)
52
+ else:
53
+ all_records.append(data)
54
+
55
+ print("Total drug records:", len(all_records))
56
+
57
+ documents = []
58
+
59
+ for record in data:
60
+
61
+ drug = record.get("generic_name", ["UNKNOWN"])[0].upper()
62
+
63
+ # choose sections you want in RAG
64
+ sections = [
65
+ "indications_and_usage",
66
+ "warnings_and_cautions",
67
+ "adverse_reactions",
68
+ "drug_interactions"
69
+ ]
70
+
71
+ for section in sections:
72
+ if section in record:
73
+
74
+ for text in record[section]:
75
+
76
+ documents.append(
77
+ Document(
78
+ page_content=text,
79
+ metadata={
80
+ "generic_name": drug,
81
+ "section": section
82
+ }
83
+ )
84
+ )
85
+
86
+ print("Documents created:", len(documents))
87
+
88
+ logger.info("Split chunk Files Process Started...")
89
+ splitter = RecursiveCharacterTextSplitter(
90
+ chunk_size=800,
91
+ chunk_overlap=150
92
  )
93
 
94
+ chunked_docs = splitter.split_documents(documents)
95
+
96
+ print("Chunks created:", len(chunked_docs))
97
 
98
+ logger.info("Embeddings Files Process Started...")
99
+
100
+ embeddings = HuggingFaceEmbeddings(
101
+ model_name="sentence-transformers/all-MiniLM-L6-v2"
102
+ )
103
+ #%%
104
+ print("Chroma ready ✅")
105
+
106
+ logger.info(" VectorDB Process Started...")
107
+ vectordb = Chroma.from_documents(
108
+ documents=chunked_docs,
109
+ embedding=embeddings,
110
+ persist_directory="./chroma_db"
111
  )
112
 
113
+ print("Vector DB created successfully ✅")
114
+ logger.info("VectorDB Process Completed...")
115
+