muddasser's picture
Update app.py
571dfaf verified
import gradio as gr
import re
from transformers import BioGptTokenizer, BioGptForCausalLM, pipeline
from crewai import Agent, Task, Crew, Process
from crewai.llm import BaseLLM
# ── 1. Load BioGPT once ─────────────────────────────────────────────
MODEL_NAME = "microsoft/biogpt"
tokenizer = BioGptTokenizer.from_pretrained(MODEL_NAME)
model = BioGptForCausalLM.from_pretrained(MODEL_NAME)
model.eval()
pipe = pipeline(
"text-generation",
model=model,
tokenizer=tokenizer,
max_new_tokens=250,
do_sample=True,
temperature=0.65,
top_p=0.92,
repetition_penalty=1.35,
)
def biogpt_complete(prompt: str, max_new=200) -> str:
raw = pipe(prompt, max_new_tokens=max_new)[0]["generated_text"]
gen = raw[len(prompt):].strip()
if "." in gen:
gen = gen[: gen.rfind(".")+1]
return gen or "Insufficient data generated."
# ── 2. Wrap BioGPT in BaseLLM for CrewAI ─────────────────────────────
class BioGPTLLM(BaseLLM):
def __init__(self):
super().__init__(model="biogpt-local", temperature=0.65)
def call(self, messages, **kwargs):
# Extract the clinical case from the CrewAI task
if isinstance(messages, str):
case = messages
else:
case = " ".join([m.get("content","") for m in messages])
m = re.search(r"(\d+-year-old .+?\.)", case)
case = m.group(1).strip() if m else case[:200]
role = kwargs.get("role", "general")
if role == "diagnosis":
prompt = f"A {case} The differential diagnosis includes:"
elif role == "treatment":
prompt = f"For a patient with {case} The recommended treatment includes:"
elif role == "precaution":
prompt = f"For a patient with {case} Key precautions and follow-up include:"
else:
prompt = f"The clinical findings for {case} suggest:"
return biogpt_complete(prompt)
biogpt_llm = BioGPTLLM()
# ── 3. Agents ───────────────────────────────────────────────────────
def make_agents():
diagnostician = Agent(
role="Medical Diagnostician",
backstory="You are a medical expert specializing in diagnosing patients based on symptoms.",
goal="Produce a differential diagnosis list for the patient.",
llm=biogpt_llm,
verbose=False,
allow_delegation=False,
)
treatment_planner = Agent(
role="Treatment Planner",
backstory="You are a medical expert specializing in suggesting treatments for patients.",
goal="Recommend evidence-based treatment for the patient.",
llm=biogpt_llm,
verbose=False,
allow_delegation=False,
)
precaution_advisor = Agent(
role="Precaution Advisor",
backstory="You are a medical expert who advises patients on safety, lifestyle, and follow-up.",
goal="Provide safety, lifestyle, and follow-up guidance.",
llm=biogpt_llm,
verbose=False,
allow_delegation=False,
)
coordinator = Agent(
role="Medical Coordinator",
backstory="You combine outputs from other medical agents into a concise summary.",
goal="Combine outputs into a concise three-section summary.",
llm=biogpt_llm,
verbose=False,
allow_delegation=False,
)
return diagnostician, treatment_planner, precaution_advisor, coordinator
# ── 4. CrewAI Tasks ────────────────────────────────────────────────
def make_tasks(symptoms, age, gender, diag, treat, prec, coord):
case = f"{age}-year-old {gender} presenting with: {symptoms}."
task_diagnose = Task(
description=case,
expected_output="Differential diagnoses list",
agent=diag,
kwargs={"role":"diagnosis"}
)
task_treat = Task(
description=case,
expected_output="Treatment recommendations",
agent=treat,
context=[task_diagnose],
kwargs={"role":"treatment"}
)
task_prec = Task(
description=case,
expected_output="Precautions",
agent=prec,
context=[task_diagnose],
kwargs={"role":"precaution"}
)
task_summarise = Task(
description=case,
expected_output="Combined summary",
agent=coord,
context=[task_diagnose, task_treat, task_prec],
kwargs={"role":"summary"}
)
return task_diagnose, task_treat, task_prec, task_summarise
# ── 5. Parse coordinator output ────────────────────────────────────
def parse_summary(text):
sections = {"diagnosis":"", "treatment":"", "precautions":""}
diag_m = re.search(r"##?\s*Diagnos(?:is|es)(.*?)(?=##?\s*Treatment|##?\s*Precaution|$)", text, re.S | re.I)
treat_m = re.search(r"##?\s*Treatment(.*?)(?=##?\s*Precaution|$)", text, re.S | re.I)
prec_m = re.search(r"##?\s*Precaution(.*?)$", text, re.S | re.I)
if diag_m: sections["diagnosis"] = diag_m.group(1).strip()
if treat_m: sections["treatment"] = treat_m.group(1).strip()
if prec_m: sections["precautions"] = prec_m.group(1).strip()
if not any(sections.values()):
sections["diagnosis"] = text.strip()
return sections
# ── 6. Main orchestration ──────────────────────────────────────────
def analyze(symptoms, age, gender):
if not symptoms.strip():
return "⚠️ Enter symptoms.", "", ""
diag, treat, prec, coord = make_agents()
tasks = make_tasks(symptoms, age, gender, diag, treat, prec, coord)
crew = Crew(
agents=[diag, treat, prec, coord],
tasks=list(tasks),
process=Process.sequential,
verbose=False
)
result = crew.kickoff()
sections = parse_summary(str(result))
disclaimer = "\n\n---\n> ⚠️ **Disclaimer:** AI-generated output, not medical advice."
return (
f"### Diagnosis\n{sections['diagnosis']}{disclaimer}",
f"### Treatment\n{sections['treatment']}{disclaimer}",
f"### Precautions\n{sections['precautions']}{disclaimer}"
)
def clear_all():
return "", "", "", "", ""
# ── 7. Gradio UI ───────────────────────────────────────────────────
with gr.Blocks(title="MedAgent — CrewAI + BioGPT") as demo:
with gr.Row():
with gr.Column(scale=1):
symptoms_in = gr.Textbox(label="Symptoms", lines=6)
age_in = gr.Textbox(label="Age")
gender_in = gr.Dropdown(label="Gender", choices=["male","female","other"], value="male")
analyze_btn = gr.Button("Analyze")
clear_btn = gr.Button("Clear")
with gr.Column(scale=2):
diagnosis_out = gr.Markdown()
treatment_out = gr.Markdown()
precautions_out = gr.Markdown()
analyze_btn.click(fn=analyze, inputs=[symptoms_in, age_in, gender_in],
outputs=[diagnosis_out, treatment_out, precautions_out])
clear_btn.click(fn=clear_all, inputs=[], outputs=[symptoms_in, age_in, diagnosis_out, treatment_out, precautions_out])
if __name__=="__main__":
demo.launch(server_name="0.0.0.0", server_port=7860)