Saicharan21 commited on
Commit
2ddb9a9
·
verified ·
1 Parent(s): ea36801

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +66 -67
app.py CHANGED
@@ -1,9 +1,8 @@
1
  import gradio as gr
2
- import os, requests
3
- from groq import Groq
4
 
5
- GROQ_KEY = os.environ.get("GROQ_API_KEY","")
6
- client = Groq(api_key=GROQ_KEY)
7
 
8
  KNOWHOW = """
9
  SJSU CardioLab Know-How:
@@ -14,21 +13,28 @@ FSI: COMSOL ALE mesh, blood 1060 kg/m3, 0.0035 Pa.s, St Jude geometry
14
  MHV: 27mm SJM Regent, bileaflet trileaflet monoleaflet pediatric
15
  CKD Stages: 1 below 1.5, 2 1.5-3.0, 3-4 3.0-6.0, 5 above 6.0 mg/dL
16
  Equipment: Heska HT5, time-resolved PIV, Tygon tubing, Arduino
17
- 13 Projects: MCL/PIV, TGT, FSI simulation, uPAD CKD diagnostics
18
  """
19
 
20
  def search_pubmed(query, n=3):
21
  try:
22
- r = requests.get("https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi",
23
- params={"db":"pubmed","term":query,"retmax":n,"retmode":"json","sort":"date"}, timeout=10)
 
 
 
24
  ids = r.json()["esearchresult"]["idlist"]
25
- if not ids: return [], ""
26
- r2 = requests.get("https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi",
27
- params={"db":"pubmed","id":",".join(ids),"retmode":"xml","rettype":"abstract"}, timeout=10)
 
 
 
 
28
  import xmltodict
29
  data = xmltodict.parse(r2.content)
30
  articles = data.get("PubmedArticleSet",{}).get("PubmedArticle",[])
31
- if isinstance(articles, dict): articles = [articles]
 
32
  real_links = []
33
  context = ""
34
  for a in articles[:n]:
@@ -36,20 +42,27 @@ def search_pubmed(query, n=3):
36
  c = a["MedlineCitation"]
37
  title = str(c["Article"]["ArticleTitle"])
38
  abstract = c["Article"].get("Abstract",{}).get("AbstractText","")
39
- if isinstance(abstract, list): abstract = " ".join([str(x) for x in abstract])
40
- if isinstance(abstract, dict): abstract = str(abstract.get("#text",""))
 
 
41
  pmid = str(c["PMID"]["#text"] if isinstance(c["PMID"],dict) else c["PMID"])
42
- real_url = "https://pubmed.ncbi.nlm.nih.gov/" + pmid
43
- real_links.append("- " + title[:100] + "\n " + real_url)
44
  context += "[PubMed:" + pmid + "] " + title + ". " + str(abstract)[:300] + "\n"
45
- except: continue
 
46
  return real_links, context
47
- except: return [], ""
 
48
 
49
  def search_scholar(query, n=3):
50
  try:
51
- r = requests.get("https://api.semanticscholar.org/graph/v1/paper/search",
52
- params={"query":query,"limit":n,"fields":"title,abstract,year,url"}, timeout=10)
 
 
 
53
  papers = r.json().get("data",[])
54
  real_links = []
55
  context = ""
@@ -62,37 +75,30 @@ def search_scholar(query, n=3):
62
  real_links.append("- " + title[:100] + " (" + year + ")\n " + url)
63
  context += "[Scholar " + year + "] " + title + ". " + abstract + "\n"
64
  return real_links, context
65
- except: return [], ""
 
66
 
67
  def ask_with_memory(message, history):
68
  if not GROQ_KEY:
69
  return "Error: GROQ_API_KEY not set in Space secrets."
70
 
71
- # Build messages with full history for memory
 
 
 
 
 
72
  messages = [
73
  {
74
  "role": "system",
75
- "content": """You are CardioLab AI built on Biomni from Stanford SNAP Lab.
76
- Expert in SJSU Biomedical Engineering research.
77
- You remember everything said in this conversation.
78
- NEVER invent paper titles or URLs.
79
- ONLY cite papers from the search results provided.
80
-
81
- CARDIOLAB KNOW-HOW:
82
- """ + KNOWHOW
83
  }
84
  ]
85
 
86
- # Add chat history — new Gradio format uses dicts
87
  for msg in history:
88
  if isinstance(msg, dict):
89
  messages.append({"role": msg["role"], "content": msg["content"]})
90
- else:
91
- # fallback for tuple format
92
- messages.append({"role": "user", "content": str(msg[0])})
93
- messages.append({"role": "assistant", "content": str(msg[1])})
94
 
95
- # Search papers
96
  cardio_query = message + " mechanical heart valve OR microfluidic OR CKD creatinine OR PIV OR thrombogenicity"
97
  pubmed_links, pubmed_context = search_pubmed(cardio_query, n=3)
98
  scholar_links, scholar_context = search_scholar(message + " biomedical", n=3)
@@ -100,16 +106,18 @@ CARDIOLAB KNOW-HOW:
100
 
101
  messages.append({
102
  "role": "user",
103
- "content": message + "\n\nReal papers (ONLY use these):\n" + sources[:3000]
104
  })
105
 
106
- response = client.chat.completions.create(
107
- model="llama-3.3-70b-versatile",
108
- messages=messages,
109
- max_tokens=800
110
- )
111
-
112
- answer = response.choices[0].message.content
 
 
113
 
114
  links = ""
115
  if pubmed_links:
@@ -120,19 +128,25 @@ CARDIOLAB KNOW-HOW:
120
  return answer + links
121
 
122
  def piv_tool(velocity, shear, hr):
123
- v = "HIGH - stenosis risk" if float(velocity)>2.0 else "NORMAL"
124
- s = "HIGH - thrombosis risk" if float(shear)>10 else "ELEVATED - monitor" if float(shear)>5 else "NORMAL"
125
- return "Velocity: "+str(velocity)+" m/s - "+v+"\nShear: "+str(shear)+" Pa - "+s+"\nHeart Rate: "+str(hr)+" bpm"
126
 
127
  def tgt_tool(tat, pf12, hemo, platelets, time):
128
  risk = sum([float(tat)>15, float(pf12)>2.0, float(hemo)>50, float(platelets)<150])
129
  overall = "HIGH THROMBOGENIC RISK" if risk>=3 else "MODERATE RISK" if risk>=2 else "LOW RISK"
130
- return "TAT:"+str(tat)+" PF1.2:"+str(pf12)+" Hemo:"+str(hemo)+" Platelets:"+str(platelets)+"\nTime:"+str(time)+"min\nResult: "+overall
131
 
132
  def upad_tool(r, g, b):
133
  creatinine = max(0, round(0.02*(float(r)-float(b))-0.5, 2))
134
  stage = "Normal" if creatinine<1.2 else "Borderline" if creatinine<1.5 else "Stage 2 CKD" if creatinine<3.0 else "Stage 3-4 CKD" if creatinine<6.0 else "Stage 5 CKD"
135
- return "Creatinine: "+str(creatinine)+" mg/dL\nStage: "+stage+"\nConfirm with: Heska Element HT5"
 
 
 
 
 
 
136
 
137
  with gr.Blocks(title="CardioLab AI - SJSU") as demo:
138
  gr.Markdown("# CardioLab AI Agent")
@@ -140,27 +154,12 @@ with gr.Blocks(title="CardioLab AI - SJSU") as demo:
140
  gr.Markdown("GitHub: github.com/pranatechsol/Cardio-Lab-Ai")
141
 
142
  with gr.Tab("Research Chat"):
143
- gr.Markdown("### Chat with memory — remembers your full conversation like ChatGPT")
144
- chatbot = gr.Chatbot(
145
- label="CardioLab AI",
146
- height=500,
147
- type="messages"
148
- )
149
- msg = gr.Textbox(
150
- label="Your message",
151
- placeholder="Ask anything about CardioLab research...",
152
- lines=2
153
- )
154
  with gr.Row():
155
  send = gr.Button("Send", variant="primary")
156
  clear = gr.Button("Clear Chat")
157
-
158
- def respond(message, history):
159
- bot_message = ask_with_memory(message, history)
160
- history.append({"role": "user", "content": message})
161
- history.append({"role": "assistant", "content": bot_message})
162
- return "", history
163
-
164
  send.click(respond, inputs=[msg, chatbot], outputs=[msg, chatbot])
165
  msg.submit(respond, inputs=[msg, chatbot], outputs=[msg, chatbot])
166
  clear.click(lambda: [], None, chatbot)
@@ -191,4 +190,4 @@ with gr.Blocks(title="CardioLab AI - SJSU") as demo:
191
  out3 = gr.Textbox(label="Result", lines=4)
192
  gr.Button("Analyze uPAD").click(upad_tool, inputs=[r,g,b], outputs=out3)
193
 
194
- demo.launch()
 
1
  import gradio as gr
2
+ import os
3
+ import requests
4
 
5
+ GROQ_KEY = os.environ.get("GROQ_API_KEY", "")
 
6
 
7
  KNOWHOW = """
8
  SJSU CardioLab Know-How:
 
13
  MHV: 27mm SJM Regent, bileaflet trileaflet monoleaflet pediatric
14
  CKD Stages: 1 below 1.5, 2 1.5-3.0, 3-4 3.0-6.0, 5 above 6.0 mg/dL
15
  Equipment: Heska HT5, time-resolved PIV, Tygon tubing, Arduino
 
16
  """
17
 
18
  def search_pubmed(query, n=3):
19
  try:
20
+ r = requests.get(
21
+ "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi",
22
+ params={"db":"pubmed","term":query,"retmax":n,"retmode":"json","sort":"date"},
23
+ timeout=10
24
+ )
25
  ids = r.json()["esearchresult"]["idlist"]
26
+ if not ids:
27
+ return [], ""
28
+ r2 = requests.get(
29
+ "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi",
30
+ params={"db":"pubmed","id":",".join(ids),"retmode":"xml","rettype":"abstract"},
31
+ timeout=10
32
+ )
33
  import xmltodict
34
  data = xmltodict.parse(r2.content)
35
  articles = data.get("PubmedArticleSet",{}).get("PubmedArticle",[])
36
+ if isinstance(articles, dict):
37
+ articles = [articles]
38
  real_links = []
39
  context = ""
40
  for a in articles[:n]:
 
42
  c = a["MedlineCitation"]
43
  title = str(c["Article"]["ArticleTitle"])
44
  abstract = c["Article"].get("Abstract",{}).get("AbstractText","")
45
+ if isinstance(abstract, list):
46
+ abstract = " ".join([str(x) for x in abstract])
47
+ if isinstance(abstract, dict):
48
+ abstract = str(abstract.get("#text",""))
49
  pmid = str(c["PMID"]["#text"] if isinstance(c["PMID"],dict) else c["PMID"])
50
+ url = "https://pubmed.ncbi.nlm.nih.gov/" + pmid
51
+ real_links.append("- " + title[:100] + "\n " + url)
52
  context += "[PubMed:" + pmid + "] " + title + ". " + str(abstract)[:300] + "\n"
53
+ except:
54
+ continue
55
  return real_links, context
56
+ except:
57
+ return [], ""
58
 
59
  def search_scholar(query, n=3):
60
  try:
61
+ r = requests.get(
62
+ "https://api.semanticscholar.org/graph/v1/paper/search",
63
+ params={"query":query,"limit":n,"fields":"title,abstract,year,url"},
64
+ timeout=10
65
+ )
66
  papers = r.json().get("data",[])
67
  real_links = []
68
  context = ""
 
75
  real_links.append("- " + title[:100] + " (" + year + ")\n " + url)
76
  context += "[Scholar " + year + "] " + title + ". " + abstract + "\n"
77
  return real_links, context
78
+ except:
79
+ return [], ""
80
 
81
  def ask_with_memory(message, history):
82
  if not GROQ_KEY:
83
  return "Error: GROQ_API_KEY not set in Space secrets."
84
 
85
+ try:
86
+ from groq import Groq
87
+ client = Groq(api_key=GROQ_KEY)
88
+ except Exception as e:
89
+ return "Error loading Groq: " + str(e)
90
+
91
  messages = [
92
  {
93
  "role": "system",
94
+ "content": "You are CardioLab AI built on Biomni from Stanford SNAP Lab. Expert in SJSU Biomedical Engineering. NEVER invent paper titles or URLs. Only cite papers from search results.\n\nCARDIOLAB KNOW-HOW:\n" + KNOWHOW
 
 
 
 
 
 
 
95
  }
96
  ]
97
 
 
98
  for msg in history:
99
  if isinstance(msg, dict):
100
  messages.append({"role": msg["role"], "content": msg["content"]})
 
 
 
 
101
 
 
102
  cardio_query = message + " mechanical heart valve OR microfluidic OR CKD creatinine OR PIV OR thrombogenicity"
103
  pubmed_links, pubmed_context = search_pubmed(cardio_query, n=3)
104
  scholar_links, scholar_context = search_scholar(message + " biomedical", n=3)
 
106
 
107
  messages.append({
108
  "role": "user",
109
+ "content": message + "\n\nReal papers found (ONLY use these):\n" + sources[:3000]
110
  })
111
 
112
+ try:
113
+ response = client.chat.completions.create(
114
+ model="llama-3.3-70b-versatile",
115
+ messages=messages,
116
+ max_tokens=800
117
+ )
118
+ answer = response.choices[0].message.content
119
+ except Exception as e:
120
+ return "Error from Groq: " + str(e)
121
 
122
  links = ""
123
  if pubmed_links:
 
128
  return answer + links
129
 
130
  def piv_tool(velocity, shear, hr):
131
+ v = "HIGH - stenosis risk" if float(velocity) > 2.0 else "NORMAL"
132
+ s = "HIGH - thrombosis risk" if float(shear) > 10 else "ELEVATED - monitor" if float(shear) > 5 else "NORMAL"
133
+ return "Velocity: " + str(velocity) + " m/s - " + v + "\nShear: " + str(shear) + " Pa - " + s + "\nHeart Rate: " + str(hr) + " bpm"
134
 
135
  def tgt_tool(tat, pf12, hemo, platelets, time):
136
  risk = sum([float(tat)>15, float(pf12)>2.0, float(hemo)>50, float(platelets)<150])
137
  overall = "HIGH THROMBOGENIC RISK" if risk>=3 else "MODERATE RISK" if risk>=2 else "LOW RISK"
138
+ return "TAT:" + str(tat) + " PF1.2:" + str(pf12) + " Hemo:" + str(hemo) + " Platelets:" + str(platelets) + "\nTime:" + str(time) + " min\nResult: " + overall
139
 
140
  def upad_tool(r, g, b):
141
  creatinine = max(0, round(0.02*(float(r)-float(b))-0.5, 2))
142
  stage = "Normal" if creatinine<1.2 else "Borderline" if creatinine<1.5 else "Stage 2 CKD" if creatinine<3.0 else "Stage 3-4 CKD" if creatinine<6.0 else "Stage 5 CKD"
143
+ return "Creatinine: " + str(creatinine) + " mg/dL\nStage: " + stage + "\nConfirm with: Heska Element HT5"
144
+
145
+ def respond(message, history):
146
+ bot_message = ask_with_memory(message, history)
147
+ history.append({"role": "user", "content": message})
148
+ history.append({"role": "assistant", "content": bot_message})
149
+ return "", history
150
 
151
  with gr.Blocks(title="CardioLab AI - SJSU") as demo:
152
  gr.Markdown("# CardioLab AI Agent")
 
154
  gr.Markdown("GitHub: github.com/pranatechsol/Cardio-Lab-Ai")
155
 
156
  with gr.Tab("Research Chat"):
157
+ gr.Markdown("### Chat with memory — like ChatGPT but for CardioLab research")
158
+ chatbot = gr.Chatbot(label="CardioLab AI", height=500, type="messages")
159
+ msg = gr.Textbox(label="Your message", placeholder="Ask anything about CardioLab research...", lines=2)
 
 
 
 
 
 
 
 
160
  with gr.Row():
161
  send = gr.Button("Send", variant="primary")
162
  clear = gr.Button("Clear Chat")
 
 
 
 
 
 
 
163
  send.click(respond, inputs=[msg, chatbot], outputs=[msg, chatbot])
164
  msg.submit(respond, inputs=[msg, chatbot], outputs=[msg, chatbot])
165
  clear.click(lambda: [], None, chatbot)
 
190
  out3 = gr.Textbox(label="Result", lines=4)
191
  gr.Button("Analyze uPAD").click(upad_tool, inputs=[r,g,b], outputs=out3)
192
 
193
+ demo.launch()