DEV Community

shashank ms
shashank ms

Posted on

The Role of LLMs in Medical Diagnosis: A Comprehensive Guide

We are going to build a clinical decision support agent that consumes free-text symptom descriptions and returns structured differential diagnoses with confidence scores, reasoning, and safety disclaimers. This tool is aimed at healthcare developers who need to prototype clinical NLP pipelines without managing infrastructure. Because Oxlo.ai uses flat per-request pricing instead of per-token metering, iterating on long patient histories stays predictable as context grows. See https://oxlo.ai/pricing for details.

What You'll Need

1. Set Up the Oxlo.ai Client

First, we instantiate the OpenAI-compatible client pointing at Oxlo.ai and verify connectivity with a lightweight ping. I use llama-3.3-70b here because it is a reliable general-purpose flagship for structured tasks.

from openai import OpenAI
import os

client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key=os.environ.get("OXLO_API_KEY"))

response = client.chat.completions.create(
    model="llama-3.3-70b",
    messages=[
        {"role": "user", "content": "Respond with OK"}
    ],
    max_tokens=10
)

print(response.choices[0].message.content)

2. Define the System Prompt

The system prompt constrains the model to act as a clinical decision support assistant. It demands structured JSON, confidence scores, and a mandatory disclaimer that this is not a substitute for a licensed clinician.

SYSTEM_PROMPT = """You are a clinical decision support assistant. Your job is to suggest possible differential diagnoses based on the symptoms and history provided by a clinician.

Rules:
- Output ONLY valid JSON. Do not include markdown fences.
- Include a top-level field "disclaimer" with the exact text: "This is not medical advice. Final diagnosis requires evaluation by a qualified healthcare professional."
- Include "differentials": a list of up to 5 objects.
- Each object must have:
  - "condition": string
  - "confidence": integer between 1 and 100
  - "reasoning": one-sentence clinical justification
  - "recommended_tests": list of suggested tests or evaluations
- Rank by confidence, highest first.
- If symptoms are vague or life-threatening, note urgency in a top-level "urgency_note" field."""

print("System prompt loaded.")

3. Build the Diagnosis Function

Next, we wrap the API call in a function that accepts a raw symptom string, injects it into the user message, and parses the JSON response. I enable JSON mode via response_format to avoid parsing brittle text.

import json
from openai import OpenAI
import os

client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key=os.environ.get("OXLO_API_KEY"))

def generate_differentials(symptoms_text: str) -> dict:
    user_message = f"Patient presentation: {symptoms_text}"

    response = client.chat.completions.create(
        model="llama-3.3-70b",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": user_message},
        ],
        response_format={"type": "json_object"},
        temperature=0.2,
        max_tokens=1024
    )

    raw = response.choices[0].message.content
    return json.loads(raw)

4. Add Validation and Safety Guardrails

Before we hit the API, we validate that the input is non-empty and reasonably bounded. After the response, we enforce that the disclaimer field exists. This layer keeps the tool predictable in a clinical workflow.

def safe_diagnose(symptoms_text: str) -> dict:
    if not symptoms_text or len(symptoms_text.strip()) < 5:
        raise ValueError("Symptom description is too short.")

    if len(symptoms_text) > 8000:
        raise ValueError("Input exceeds safe context window for this endpoint.")

    result = generate_differentials(symptoms_text)

    if "disclaimer" not in result:
        result["disclaimer"] = (
            "This is not medical advice. Final diagnosis requires evaluation "
            "by a qualified healthcare professional."
        )

    return result

5. Create a Simple CLI

Finally, we add a small interactive loop so we can test cases quickly from the terminal. It catches JSON errors and prints formatted output.

import json

if __name__ == "__main__":
    print("Clinical Decision Support Agent")
    print("Type symptoms and press Enter. Ctrl+C to exit.\n")

    while True:
        try:
            user_input = input("Symptoms: ").strip()
            if not user_input:
                continue

            output = safe_diagnose(user_input)
            print(json.dumps(output, indent=2))
            print("-" * 40)
        except KeyboardInterrupt:
            print("\nExiting.")
            break
        except Exception as e:
            print(f"Error: {e}")
            print("-" * 40)

Run It

Export your key and run the script. Here is a real session using the example input.

$ export OXLO_API_KEY="sk-oxlo.ai-..."
$ python diagnose.py

Clinical Decision Support Agent
Type symptoms and press Enter. Ctrl+C to exit.

Symptoms: 38-year-old male, fever 39C for 3 days, severe headache, neck stiffness, photophobia. No rash.

{
  "disclaimer": "This is not medical advice. Final diagnosis requires evaluation by a qualified healthcare professional.",
  "urgency_note": "Possible acute CNS infection. Urgent evaluation required.",
  "differentials": [
    {
      "condition": "Acute Bacterial Meningitis",
      "confidence": 85,
      "reasoning": "Classic triad of fever, headache, and nuchal rigidity with photophobia strongly suggests meningeal irritation.",
      "recommended_tests": ["Lumbar puncture with CSF analysis", "Blood cultures", "CT head before LP if indicated"]
    },
    {
      "condition": "Viral Meningitis",
      "confidence": 60,
      "reasoning": "Similar presentation but often less severe; remains a key differential in the absence of rash.",
      "recommended_tests": ["Lumbar puncture with CSF PCR panel", "Basic metabolic panel"]
    },
    {
      "condition": "Subarachnoid Hemorrhage",
      "confidence": 25,
      "reasoning": "Sudden severe headache can indicate SAH, though fever is less typical.",
      "recommended_tests": ["Non-contrast CT head", "CT angiography if CT negative"]
    }
  ]
}

Next Steps

Wire this agent into a FastAPI service and store outputs in a PostgreSQL audit table for clinician review. If you want to ground the reasoning in recent literature, pipe the condition names through Oxlo.ai's embeddings endpoint with BGE-Large and query a vector store of PubMed abstracts before returning results.

Top comments (0)