muddasser commited on
Commit
753a52f
·
verified ·
1 Parent(s): 2714b57

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +93 -25
app.py CHANGED
@@ -56,16 +56,73 @@ print("✅ BioGPT ready!\n")
56
 
57
 
58
  # ── 2. BioGPT LLM — subclasses BaseLLM, bypasses LiteLLM ──────────
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  class BioGPTLLM(BaseLLM):
60
  """
61
  Subclassing BaseLLM routes CrewAI agent calls directly to the local
62
- BioGPT HuggingFace pipeline. LiteLLM is never invoked, which
63
- eliminates the starlette/streamlit/gradio version conflicts.
 
 
 
64
  """
65
 
66
  def __init__(self):
67
  super().__init__(model="biogpt-local", temperature=0.65)
68
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  def call(
70
  self,
71
  messages: Union[str, List[Dict[str, str]]],
@@ -74,31 +131,42 @@ class BioGPTLLM(BaseLLM):
74
  available_functions: Optional[Dict[str, Any]] = None,
75
  **kwargs,
76
  ) -> str:
77
- # Flatten CrewAI message list → single prompt string
78
- if isinstance(messages, str):
79
- prompt = messages
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  else:
81
- parts = []
82
- for m in messages:
83
- role = m.get("role", "")
84
- content = m.get("content", "")
85
- if role == "system":
86
- parts.append(f"[System] {content}")
87
- elif role in ("user", "human"):
88
- parts.append(content)
89
- prompt = "\n".join(parts).strip()
90
-
91
- if not prompt:
92
- return "No prompt received."
93
-
94
- raw = _pipe(prompt)[0]["generated_text"]
95
- generated = raw[len(prompt):].strip()
96
-
97
- # Trim to last complete sentence
98
- if "." in generated:
99
- generated = generated[: generated.rfind(".") + 1]
100
 
101
- return generated or "Insufficient data. Please consult a licensed physician."
102
 
103
  def supports_function_calling(self) -> bool:
104
  return False
 
56
 
57
 
58
  # ── 2. BioGPT LLM — subclasses BaseLLM, bypasses LiteLLM ──────────
59
+ # BioGPT is a causal LM trained on PubMed abstracts — it is NOT
60
+ # instruction-tuned. It works by completing a biomedical sentence/phrase.
61
+ # CrewAI passes a large system+user message block; we extract the clinical
62
+ # case from it and build a tight completion-style prompt BioGPT can handle.
63
+
64
+ def _extract_case(messages) -> str:
65
+ """Pull the raw clinical case text out of CrewAI message list."""
66
+ full = ""
67
+ if isinstance(messages, str):
68
+ full = messages
69
+ else:
70
+ for m in messages:
71
+ full += " " + m.get("content", "")
72
+ # Look for our case marker
73
+ m = re.search(r"(\d+-year-old .+?\.)", full, re.S)
74
+ if m:
75
+ return m.group(1).strip()
76
+ # Fallback: last non-empty content block
77
+ if isinstance(messages, list):
78
+ for m in reversed(messages):
79
+ c = m.get("content", "").strip()
80
+ if c:
81
+ return c[:300]
82
+ return full.strip()[:300]
83
+
84
+
85
+ def _biogpt_complete(prompt: str, max_new: int = 200) -> str:
86
+ """Run BioGPT completion and return only the generated portion."""
87
+ raw = _pipe(prompt, max_new_tokens=max_new)[0]["generated_text"]
88
+ generated = raw[len(prompt):].strip()
89
+ # Trim to last complete sentence
90
+ if "." in generated:
91
+ generated = generated[: generated.rfind(".") + 1]
92
+ return generated or "Insufficient data generated."
93
+
94
+
95
  class BioGPTLLM(BaseLLM):
96
  """
97
  Subclassing BaseLLM routes CrewAI agent calls directly to the local
98
+ BioGPT HuggingFace pipeline. LiteLLM is never invoked.
99
+
100
+ Key insight: BioGPT is a PubMed completion model, not an instruction
101
+ follower. We detect which agent role is calling from the system message
102
+ and craft a tight domain-specific completion prompt accordingly.
103
  """
104
 
105
  def __init__(self):
106
  super().__init__(model="biogpt-local", temperature=0.65)
107
 
108
+ def _detect_role(self, messages) -> str:
109
+ """Detect which agent is calling by scanning the system message."""
110
+ system_text = ""
111
+ if isinstance(messages, list):
112
+ for m in messages:
113
+ if m.get("role") == "system":
114
+ system_text = m.get("content", "").lower()
115
+ break
116
+ if "diagnos" in system_text:
117
+ return "diagnosis"
118
+ if "treatment" in system_text or "pharmacol" in system_text:
119
+ return "treatment"
120
+ if "precaution" in system_text or "lifestyle" in system_text:
121
+ return "precaution"
122
+ if "coordinat" in system_text or "synthesise" in system_text or "summary" in system_text:
123
+ return "summary"
124
+ return "general"
125
+
126
  def call(
127
  self,
128
  messages: Union[str, List[Dict[str, str]]],
 
131
  available_functions: Optional[Dict[str, Any]] = None,
132
  **kwargs,
133
  ) -> str:
134
+ role = self._detect_role(messages)
135
+ case = _extract_case(messages)
136
+
137
+ # Build tight PubMed-style completion prompts per agent role
138
+ if role == "diagnosis":
139
+ prompt = (
140
+ f"A {case} "
141
+ f"The differential diagnosis includes:"
142
+ )
143
+ elif role == "treatment":
144
+ prompt = (
145
+ f"For a patient with {case} "
146
+ f"The recommended treatment includes:"
147
+ )
148
+ elif role == "precaution":
149
+ prompt = (
150
+ f"For a patient with {case} "
151
+ f"Important precautions and follow-up recommendations include:"
152
+ )
153
+ elif role == "summary":
154
+ # For coordinator: re-run all three and concatenate
155
+ diag = _biogpt_complete(
156
+ f"A {case} The differential diagnosis includes:", 150)
157
+ treat = _biogpt_complete(
158
+ f"For a patient with {case} The recommended treatment includes:", 150)
159
+ prec = _biogpt_complete(
160
+ f"For a patient with {case} Important precautions include:", 150)
161
+ return (
162
+ f"## Diagnosis\n{diag}\n\n"
163
+ f"## Treatment\n{treat}\n\n"
164
+ f"## Precautions\n{prec}"
165
+ )
166
  else:
167
+ prompt = f"The clinical findings for {case} suggest:"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
 
169
+ return _biogpt_complete(prompt)
170
 
171
  def supports_function_calling(self) -> bool:
172
  return False