Saicharan21 commited on
Commit
ea36801
·
verified ·
1 Parent(s): 47d77b9

Upload hf_app_v7.py

Browse files
Files changed (1) hide show
  1. hf_app_v7.py +194 -0
hf_app_v7.py ADDED
@@ -0,0 +1,194 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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:
10
+ MCL: Sylgard 184 PDMS 10:1 ratio 48hr cure, green laser PIV, 70bpm 5L/min flow
11
+ TGT: Arduino Uno + Stepper Motor, 150mL blood, sample 0/20/40/60min, TAT PF1.2 hemolysis platelets
12
+ uPAD: Jaffe reaction creatinine + picric acid = orange-red, normal 0.6-1.2 mg/dL, CKD above 1.5
13
+ 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]:
35
+ try:
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 = ""
56
+ for p in papers:
57
+ title = p.get("title","")
58
+ abstract = (p.get("abstract") or "")[:300]
59
+ year = str(p.get("year",""))
60
+ url = p.get("url","")
61
+ if url:
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)
99
+ sources = pubmed_context + scholar_context
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:
116
+ links += "\n\n📚 VERIFIED PUBMED LINKS:\n" + "\n".join(pubmed_links[:3])
117
+ if scholar_links:
118
+ links += "\n\n🎓 VERIFIED SCHOLAR LINKS:\n" + "\n".join(scholar_links[:3])
119
+
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")
139
+ gr.Markdown("### SJSU Biomedical Engineering | Biomni + Llama 70B + Chat Memory + PubMed")
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)
167
+
168
+ with gr.Tab("PIV Analysis"):
169
+ gr.Markdown("### Analyze PIV flow data from Mock Circulatory Loop")
170
+ v = gr.Number(label="Max Velocity m/s", value=1.8)
171
+ s = gr.Number(label="Shear Stress Pa", value=6.5)
172
+ h = gr.Number(label="Heart Rate bpm", value=72)
173
+ out = gr.Textbox(label="Result", lines=4)
174
+ gr.Button("Analyze PIV").click(piv_tool, inputs=[v,s,h], outputs=out)
175
+
176
+ with gr.Tab("TGT Results"):
177
+ gr.Markdown("### Interpret Thrombogenicity Tester blood results")
178
+ t1 = gr.Number(label="TAT", value=18)
179
+ t2 = gr.Number(label="PF1.2", value=2.5)
180
+ t3 = gr.Number(label="Free Hemoglobin mg/L", value=60)
181
+ t4 = gr.Number(label="Platelet Count", value=140)
182
+ t5 = gr.Number(label="Time minutes", value=40)
183
+ out2 = gr.Textbox(label="Result", lines=5)
184
+ gr.Button("Analyze TGT").click(tgt_tool, inputs=[t1,t2,t3,t4,t5], outputs=out2)
185
+
186
+ with gr.Tab("uPAD CKD"):
187
+ gr.Markdown("### Analyze uPAD colorimetric result - Jaffe Reaction")
188
+ r = gr.Number(label="R value", value=210)
189
+ g = gr.Number(label="G value", value=140)
190
+ b = gr.Number(label="B value", value=80)
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()