vineelagampa ashrith repaka commited on
Commit
ee41b72
·
verified ·
1 Parent(s): 7b25c8c

Update backend.py (#52)

Browse files

- Update backend.py (6213b11ef7a2345f46c3f331ea1b3ae9c719d25b)


Co-authored-by: ashrith repaka <godtier812@users.noreply.huggingface.co>

Files changed (1) hide show
  1. backend.py +14 -56
backend.py CHANGED
@@ -74,7 +74,6 @@ safety_settings = [
74
  {"category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_MEDIUM_AND_ABOVE"},
75
  ]
76
 
77
- # --- Pydantic Models for API Endpoints ---
78
  class ChatRequest(BaseModel):
79
  user_id: Optional[str] = "anonymous"
80
  question: str
@@ -86,27 +85,18 @@ class TextRequest(BaseModel):
86
  text: str
87
 
88
  system_prompt = """ You are a highly skilled medical practitioner specializing in medical image and document analysis. You will be given either a medical image or a PDF.
89
-
90
  Your responsibilities are:
91
-
92
  1. **Extract Text**: If the input is a PDF or image, first extract all the text content (lab values, notes, measurements, etc.). Do not summarize — keep the extracted text verbatim.
93
-
94
  2. **Detailed Analysis**: Use both the extracted text and the visual features of the image to identify any anomalies, diseases, or health issues.
95
-
96
  3. **Finding Report**: Document all observed anomalies or signs of disease.
97
  - Include any measurements (e.g., triglycerides, HBa1c, HDL) in the format:
98
  `{"findings": "Condition only if risky: measurement type -- value with unit(current range)"}`
99
  - Simplify the finding in **3 words** at the beginning when helpful.
100
-
101
  4. **Checking for Past**: If a disease is family history or previously recovered, mark severity as:
102
  `"severity": "severity of anomaly (Past Anomaly but Still Under Risk)"`
103
-
104
  5. **Recommendations and Next Steps**: Provide detailed recommendations (tests, follow-ups, consultations).
105
-
106
  6. **Treatment Suggestions**: Offer preliminary treatments or interventions.
107
-
108
  7. **Output Format**: Always return a JSON object containing both the raw extracted text and the structured analysis, like this:
109
-
110
  ```json
111
  {
112
  "ocr_text": "<<<FULL VERBATIM TEXT FROM THE PDF/IMAGE>>>",
@@ -127,7 +117,6 @@ Your responsibilities are:
127
  }
128
  ]
129
  }
130
-
131
  Important Notes:
132
  1. Scope of Response: Only respond if the image pertains to a human health issue.
133
  2. Clarity of Image: Ensure the image is clear and suitable for accurate analysis.
@@ -136,33 +125,24 @@ Important Notes:
136
  5. Completely UPPERCASE the main concern in the finding """
137
 
138
  system_prompt_chat = """
139
- *** Role: Medical Guidance Facilitator
140
- *** Objective:
141
- Analyze medical data, provide concise, evidence-based insights, and recommend actionable next steps for patient care. This includes suggesting local physicians or specialists within a user-specified mile radius, prioritizing in-network options when insurance information is available, and maintaining strict safety compliance with appropriate disclaimers.
142
- *** Capabilities:
143
- 1. Report Analysis Review and interpret findings in uploaded medical reports.
144
- 2. Historical Context Compare current findings with any available previous reports.
145
- 3. Medical Q&A Answer specific questions about the report using trusted medical sources.
146
- 4. Specialist Matching Recommend relevant physician specialties for identified conditions.
147
- 5. Local Physician Recommendations – List at least two real physician or clinic options within the user-specified mile radius (include name, specialty, address, distance from user, and contact info) based on the patient’s location and clinical need.
148
- 6. Insurance Guidance – If insurance/network information is provided, prioritize in-network physicians.
149
- 7. Safety Protocols – Include a brief disclaimer encouraging users to verify information, confirm insurance coverage, and consult providers directly.
150
- *** Response Structure:
151
- Start with a direct answer to the user’s primary question (maximum 4 concise sentences, each on a new line).
152
- If a physician/specialist is needed, recommend at least two local providers within the requested radius (include name, specialty, address, distance, and contact info).
153
- If insurance details are available, indicate which physicians are in-network.
154
- End with a short safety disclaimer.
155
- ***Input Fields:
156
- Provided Document Text: {document_text}
157
  User Question: {user_question}
158
- Assistant Answer:
159
  """
160
 
161
- # Initialize model
162
  model = genai.GenerativeModel(model_name="gemini-2.5-flash-lite")
163
 
164
  async def _call_model_blocking(request_inputs, generation_cfg, safety_cfg):
165
- """Run blocking model call in threadpool (so uvicorn's event loop isn't blocked)."""
166
  fn = functools.partial(
167
  model.generate_content,
168
  request_inputs,
@@ -172,7 +152,6 @@ async def _call_model_blocking(request_inputs, generation_cfg, safety_cfg):
172
  loop = asyncio.get_event_loop()
173
  return await loop.run_in_executor(None, fn)
174
 
175
-
176
  async def analyze_image(image_bytes: bytes, mime_type: str, prompt: Optional[str] = None) -> Any:
177
  base64_img = base64.b64encode(image_bytes).decode("utf-8")
178
  text_prompt = (prompt or system_prompt).strip()
@@ -206,7 +185,6 @@ async def analyze_image(image_bytes: bytes, mime_type: str, prompt: Optional[str
206
  match = re.search(r"(\[.*\]|\{.*\})", clean, re.DOTALL)
207
  if match:
208
  try:
209
-
210
  parsed = json.loads(match.group(1)), None
211
  ocr_text = parsed["ocr_text"]
212
  analysis = parsed["analysis"]
@@ -226,16 +204,10 @@ def get_past_reports_from_sqllite(user_id: str):
226
  history_text = "No past reports found for this user."
227
  return history_text
228
 
229
-
230
  @app.post("/chat/", response_model=ChatResponse)
231
  async def chat_endpoint(request: ChatRequest):
232
  global result
233
  print(f"Received chat request for user: {request.user_id}")
234
- """
235
- Chatbot endpoint that answers questions based on the last analyzed document and user history.
236
- """
237
-
238
- #history_text = get_past_reports_from_firestore(request.user_id)
239
  full_document_text = get_past_reports_from_sqllite(request.user_id.strip())
240
 
241
  full_document_text = EXTRACTED_TEXT_CACHE+"\n\n" + "PAST REPORTS:\n" + full_document_text
@@ -243,7 +215,6 @@ async def chat_endpoint(request: ChatRequest):
243
  if not full_document_text:
244
  raise HTTPException(status_code=400, detail="No past reports or current data exists for this user")
245
 
246
-
247
  try:
248
  full_prompt = system_prompt_chat.format(
249
  document_text=full_document_text,
@@ -258,20 +229,13 @@ async def chat_endpoint(request: ChatRequest):
258
 
259
  @app.post("/analyze")
260
  async def analyze_endpoint(file: UploadFile = File(...), prompt: str = Form(None)):
261
-
262
- """
263
- Upload an image file (field name `file`) and optional text `prompt`.
264
- Returns parsed JSON (or raw model output if JSON couldn't be parsed).
265
- """
266
-
267
  global result,EXTRACTED_TEXT_CACHE
268
 
269
  filename = file.filename.lower()
270
  print(f"Received analyze request for file {filename}")
271
- contents = await file.read() # <-- this gets the uploaded file bytes
272
  mime = file.content_type or "image/png"
273
 
274
- #result = await analyze_image(contents, mime, prompt)
275
  try:
276
  result, ocr_text = await analyze_image(contents, mime, prompt)
277
  EXTRACTED_TEXT_CACHE = ocr_text
@@ -301,16 +265,12 @@ def _log_routes():
301
  if isinstance(r, APIRoute):
302
  print(" ", r.path, r.methods)
303
 
304
-
305
-
306
  def main():
307
- """Run the application."""
308
  try:
309
  logger.info(f"Starting server on 8000")
310
  logger.info(f"Debug mode: true")
311
 
312
  if Config.DEBUG:
313
- # Use import string for reload mode
314
  uvicorn.run(
315
  "main:app",
316
  host="localhost",
@@ -319,7 +279,6 @@ def main():
319
  log_level="debug"
320
  )
321
  else:
322
- # Use app instance for production
323
  uvicorn.run(
324
  app,
325
  host="localhost",
@@ -332,6 +291,5 @@ def main():
332
  logger.error(f"Failed to start server: {e}")
333
  raise
334
 
335
-
336
  if __name__ == "__main__":
337
- main()
 
74
  {"category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_MEDIUM_AND_ABOVE"},
75
  ]
76
 
 
77
  class ChatRequest(BaseModel):
78
  user_id: Optional[str] = "anonymous"
79
  question: str
 
85
  text: str
86
 
87
  system_prompt = """ You are a highly skilled medical practitioner specializing in medical image and document analysis. You will be given either a medical image or a PDF.
 
88
  Your responsibilities are:
 
89
  1. **Extract Text**: If the input is a PDF or image, first extract all the text content (lab values, notes, measurements, etc.). Do not summarize — keep the extracted text verbatim.
 
90
  2. **Detailed Analysis**: Use both the extracted text and the visual features of the image to identify any anomalies, diseases, or health issues.
 
91
  3. **Finding Report**: Document all observed anomalies or signs of disease.
92
  - Include any measurements (e.g., triglycerides, HBa1c, HDL) in the format:
93
  `{"findings": "Condition only if risky: measurement type -- value with unit(current range)"}`
94
  - Simplify the finding in **3 words** at the beginning when helpful.
 
95
  4. **Checking for Past**: If a disease is family history or previously recovered, mark severity as:
96
  `"severity": "severity of anomaly (Past Anomaly but Still Under Risk)"`
 
97
  5. **Recommendations and Next Steps**: Provide detailed recommendations (tests, follow-ups, consultations).
 
98
  6. **Treatment Suggestions**: Offer preliminary treatments or interventions.
 
99
  7. **Output Format**: Always return a JSON object containing both the raw extracted text and the structured analysis, like this:
 
100
  ```json
101
  {
102
  "ocr_text": "<<<FULL VERBATIM TEXT FROM THE PDF/IMAGE>>>",
 
117
  }
118
  ]
119
  }
 
120
  Important Notes:
121
  1. Scope of Response: Only respond if the image pertains to a human health issue.
122
  2. Clarity of Image: Ensure the image is clear and suitable for accurate analysis.
 
125
  5. Completely UPPERCASE the main concern in the finding """
126
 
127
  system_prompt_chat = """
128
+ *** Role: Medical Chat Assistant ***
129
+ You are a concise and empathetic medical chatbot. Your job is to give clear, short answers (max 3-4 sentences) based only on the provided medical report text.
130
+
131
+ Rules:
132
+ - Avoid repeating the entire report; focus only on what is directly relevant to the user’s question.
133
+ - Give top 2 actionable steps if needed.
134
+ - If condition is serious, suggest consulting a doctor immediately.
135
+ - Always end with: "Check with your physician before acting."
136
+
137
+ Input:
138
+ Report Text: {document_text}
 
 
 
 
 
 
 
139
  User Question: {user_question}
140
+ Response:
141
  """
142
 
 
143
  model = genai.GenerativeModel(model_name="gemini-2.5-flash-lite")
144
 
145
  async def _call_model_blocking(request_inputs, generation_cfg, safety_cfg):
 
146
  fn = functools.partial(
147
  model.generate_content,
148
  request_inputs,
 
152
  loop = asyncio.get_event_loop()
153
  return await loop.run_in_executor(None, fn)
154
 
 
155
  async def analyze_image(image_bytes: bytes, mime_type: str, prompt: Optional[str] = None) -> Any:
156
  base64_img = base64.b64encode(image_bytes).decode("utf-8")
157
  text_prompt = (prompt or system_prompt).strip()
 
185
  match = re.search(r"(\[.*\]|\{.*\})", clean, re.DOTALL)
186
  if match:
187
  try:
 
188
  parsed = json.loads(match.group(1)), None
189
  ocr_text = parsed["ocr_text"]
190
  analysis = parsed["analysis"]
 
204
  history_text = "No past reports found for this user."
205
  return history_text
206
 
 
207
  @app.post("/chat/", response_model=ChatResponse)
208
  async def chat_endpoint(request: ChatRequest):
209
  global result
210
  print(f"Received chat request for user: {request.user_id}")
 
 
 
 
 
211
  full_document_text = get_past_reports_from_sqllite(request.user_id.strip())
212
 
213
  full_document_text = EXTRACTED_TEXT_CACHE+"\n\n" + "PAST REPORTS:\n" + full_document_text
 
215
  if not full_document_text:
216
  raise HTTPException(status_code=400, detail="No past reports or current data exists for this user")
217
 
 
218
  try:
219
  full_prompt = system_prompt_chat.format(
220
  document_text=full_document_text,
 
229
 
230
  @app.post("/analyze")
231
  async def analyze_endpoint(file: UploadFile = File(...), prompt: str = Form(None)):
 
 
 
 
 
 
232
  global result,EXTRACTED_TEXT_CACHE
233
 
234
  filename = file.filename.lower()
235
  print(f"Received analyze request for file {filename}")
236
+ contents = await file.read()
237
  mime = file.content_type or "image/png"
238
 
 
239
  try:
240
  result, ocr_text = await analyze_image(contents, mime, prompt)
241
  EXTRACTED_TEXT_CACHE = ocr_text
 
265
  if isinstance(r, APIRoute):
266
  print(" ", r.path, r.methods)
267
 
 
 
268
  def main():
 
269
  try:
270
  logger.info(f"Starting server on 8000")
271
  logger.info(f"Debug mode: true")
272
 
273
  if Config.DEBUG:
 
274
  uvicorn.run(
275
  "main:app",
276
  host="localhost",
 
279
  log_level="debug"
280
  )
281
  else:
 
282
  uvicorn.run(
283
  app,
284
  host="localhost",
 
291
  logger.error(f"Failed to start server: {e}")
292
  raise
293
 
 
294
  if __name__ == "__main__":
295
+ main()