Hamza4100 commited on
Commit
663f2bd
·
verified ·
1 Parent(s): 0b8ae89

Update app/services/rag_service.py

Browse files
Files changed (1) hide show
  1. app/services/rag_service.py +71 -5
app/services/rag_service.py CHANGED
@@ -1,6 +1,7 @@
1
  from app.config import settings
2
  from sqlalchemy.orm import Session
3
  from app.services.search_service import SearchService
 
4
 
5
  try:
6
  from groq import Groq
@@ -25,17 +26,22 @@ class RAGService:
25
 
26
  @staticmethod
27
  def format_search_results(search_results: list) -> str:
28
- """Format search results as context"""
29
  if not search_results:
30
  return "No previous pathology records retrieved for this query.\n\n"
31
  context = "RELEVANT MEDICAL DOCUMENTS FROM EMR DATABASE:\n\n"
32
  for i, result in enumerate(search_results, 1):
33
  context += f"Document #{i} (ID: {result.get('document_id', 'Unknown')})\n"
34
  context += f" Patient Name: {result.get('patient_name', 'Unknown')}\n"
 
35
  context += f" Test Type: {result.get('test_type', 'Unknown')}\n"
36
- context += f" Diagnosis: {result.get('diagnosis', 'Unknown')}\n"
37
  context += f" Report Summary: {result.get('summary', 'Unknown')}\n"
38
- context += f" Text Content Preview: {result.get('text_preview', '')}\n\n"
 
 
 
 
39
  return context
40
 
41
  def answer_question(
@@ -51,15 +57,75 @@ class RAGService:
51
  "source_documents": [],
52
  }
53
 
54
- # 1. Retrieve semantically relevant documents if available in DB
55
  results_list = []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  try:
57
  search_result = SearchService.semantic_search(db, question, top_k=3)
58
  if search_result.get("status") == "success":
59
- results_list = search_result.get("results", [])
 
 
 
 
60
  except Exception as search_err:
61
  print(f"[WARN] Vector search lookup skipped: {search_err}")
62
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  # 2. Format context from search results
64
  context = self.format_search_results(results_list)
65
 
 
1
  from app.config import settings
2
  from sqlalchemy.orm import Session
3
  from app.services.search_service import SearchService
4
+ from app.models.database_models import PathologyReport
5
 
6
  try:
7
  from groq import Groq
 
26
 
27
  @staticmethod
28
  def format_search_results(search_results: list) -> str:
29
+ """Format search results as detailed medical context"""
30
  if not search_results:
31
  return "No previous pathology records retrieved for this query.\n\n"
32
  context = "RELEVANT MEDICAL DOCUMENTS FROM EMR DATABASE:\n\n"
33
  for i, result in enumerate(search_results, 1):
34
  context += f"Document #{i} (ID: {result.get('document_id', 'Unknown')})\n"
35
  context += f" Patient Name: {result.get('patient_name', 'Unknown')}\n"
36
+ context += f" Patient ID / MRN: {result.get('patient_id', 'Unknown')}\n"
37
  context += f" Test Type: {result.get('test_type', 'Unknown')}\n"
38
+ context += f" Diagnosis / Assessment: {result.get('diagnosis', 'Unknown')}\n"
39
  context += f" Report Summary: {result.get('summary', 'Unknown')}\n"
40
+ if result.get('findings'):
41
+ context += f" Biomarker Findings / Lab Results: {result.get('findings')}\n"
42
+ elif result.get('text_preview'):
43
+ context += f" Text Content Preview: {result.get('text_preview', '')}\n"
44
+ context += "\n"
45
  return context
46
 
47
  def answer_question(
 
57
  "source_documents": [],
58
  }
59
 
60
+ # 1. Retrieve relevant documents: Direct Patient/MRN lookup + Semantic vector search
61
  results_list = []
62
+ seen_doc_ids = set()
63
+
64
+ # A. Direct query matching for patient name, MRN, document ID, and test type
65
+ import re
66
+ tokens = [t for t in re.findall(r'[a-zA-Z0-9_-]+', question) if len(t) >= 3 and t.lower() not in ['summarize', 'diagnostic', 'history', 'abnormal', 'flags', 'findings', 'what', 'with', 'from', 'explain', 'show', 'tell', 'about', 'report', 'reports', 'test', 'results']]
67
+
68
+ for token in tokens:
69
+ matched_reports = (
70
+ db.query(PathologyReport)
71
+ .filter(
72
+ (PathologyReport.patient_id.ilike(f"%{token}%")) |
73
+ (PathologyReport.patient_name.ilike(f"%{token}%")) |
74
+ (PathologyReport.document_id.ilike(f"%{token}%")) |
75
+ (PathologyReport.test_type.ilike(f"%{token}%"))
76
+ )
77
+ .limit(5)
78
+ .all()
79
+ )
80
+ for r in matched_reports:
81
+ if r.document_id not in seen_doc_ids:
82
+ seen_doc_ids.add(r.document_id)
83
+ results_list.append({
84
+ "document_id": r.document_id,
85
+ "patient_name": r.patient_name or "Unknown",
86
+ "patient_id": r.patient_id or "Unknown",
87
+ "test_type": r.test_type or "Pathology Report",
88
+ "diagnosis": r.diagnosis or "Normal",
89
+ "summary": r.summary or "Diagnostic report recorded in EMR",
90
+ "findings": r.findings or "",
91
+ "text_preview": r.summary or "",
92
+ })
93
+
94
+ # B. Vector / Semantic search fallback
95
  try:
96
  search_result = SearchService.semantic_search(db, question, top_k=3)
97
  if search_result.get("status") == "success":
98
+ for res in search_result.get("results", []):
99
+ doc_id = res.get("document_id")
100
+ if doc_id and doc_id not in seen_doc_ids:
101
+ seen_doc_ids.add(doc_id)
102
+ results_list.append(res)
103
  except Exception as search_err:
104
  print(f"[WARN] Vector search lookup skipped: {search_err}")
105
 
106
+ # C. If still 0 documents found, check if there are existing reports in DB as contextual fallback
107
+ if len(results_list) == 0:
108
+ all_recent = db.query(PathologyReport).order_by(PathologyReport.created_at.desc()).limit(3).all()
109
+ for r in all_recent:
110
+ # If query mentions any part of patient name or diagnosis
111
+ pname = (r.patient_name or "").lower()
112
+ diag = (r.diagnosis or "").lower()
113
+ ttype = (r.test_type or "").lower()
114
+ q_lower = question.lower()
115
+ if any(part in q_lower for part in pname.split() if len(part) > 2) or any(part in q_lower for part in ttype.split() if len(part) > 2):
116
+ if r.document_id not in seen_doc_ids:
117
+ seen_doc_ids.add(r.document_id)
118
+ results_list.append({
119
+ "document_id": r.document_id,
120
+ "patient_name": r.patient_name or "Unknown",
121
+ "patient_id": r.patient_id or "Unknown",
122
+ "test_type": r.test_type or "Pathology Report",
123
+ "diagnosis": r.diagnosis or "Normal",
124
+ "summary": r.summary or "Diagnostic report recorded in EMR",
125
+ "findings": r.findings or "",
126
+ "text_preview": r.summary or "",
127
+ })
128
+
129
  # 2. Format context from search results
130
  context = self.format_search_results(results_list)
131