RUNLOCALAIv38
->Will it run?Best GPUCompareTroubleshootStartLearnPulseModelsHardwareToolsBench
Run check
RUNLOCALAI

Independently operated catalog for local-AI hardware and software. Hand-written verdicts. Source-cited claims. Reproducible commands when we have them.

OP·Fredoline Eruo
DIR
  • Models
  • Hardware
  • Tools
  • Benchmarks
TOOLS
  • Will it run?
  • Compare hardware
  • Cost vs cloud
  • Choose my GPU
  • Prompting kits
  • Quick answers
REF
  • All buyer guides
  • Learn local AI
  • Methodology
  • Glossary
  • Errors KB
  • Trust
EDITOR
  • About
  • Author
  • How we make money
  • Editorial policy
  • Contact
LEGAL
  • Privacy
  • Terms
  • Sitemap
MAIL · MONTHLY DIGEST
Get monthly local AI changes
Monthly recap. No spam.
DISCLOSURE

Some links on this site are affiliate links (Amazon Associates and other first-class retailers). When you buy through them, we earn a small commission at no extra cost to you. Affiliate links do not influence our verdicts — there are cards we rate highly that we don't have affiliate relationships with, and cards that sell well that we refuse to recommend. Read more →

© 2026 runlocalai.coIndependently operated
RUNLOCALAI · v38
  1. >
  2. Home
  3. /Learn
  4. /Courses
  5. /Healthcare AI with Local Models
  6. /Ch. 6
Healthcare AI with Local Models

06. SOAP Note Generation

Chapter 6 of 18 · 15 min
KEY INSIGHT

SOAP note generation amplifies both physician productivity and physician risk—draft notes save time but require rigorous physician review before clinical use.

SOAP (Subjective, Objective, Assessment, Plan) notes provide the standard format for documenting patient encounters in many healthcare settings. Generating SOAP notes from encounter data—either raw transcripts or structured intake forms—offers significant workflow improvement.

The subjective section captures patient-reported symptoms and history. The objective section contains measurable findings—vital signs, exam results, lab values. The assessment synthesizes findings into clinical impressions. The plan outlines treatment approach.

# soap_generator.py
from dataclasses import dataclass
from typing import Optional, List

@dataclass
class SOAPNote:
    subjective: str
    objective: str
    assessment: str
    plan: str

class SOAPNoteGenerator:
    """Generate SOAP-formatted clinical notes from encounter data."""
    
    SOAP_TEMPLATE = """Generate a SOAP note from the following encounter data.
    Use professional clinical language appropriate for medical records.
    
    Patient Information:
    {patient_info}
    
    Chief Complaint:
    {chief_complaint}
    
    HPI (History of Present Illness):
    {hpi}
    
    Review of Systems:
    {ros}
    
    Vital Signs:
    {vitals}
    
    Physical Exam Findings:
    {physical_exam}
    
    Lab Results:
    {lab_results}
    
    Assessment and Plan (if available):
    {assessment_plan}
    
    Format the output as:
    
    S: [Subjective section]
    O: [Objective section]
    A: [Assessment section]
    P: [Plan section]
    """
    
    def __init__(self, ollama_client, model: str = "llama3.2"):
        self.ollama = ollama_client
        self.model = model
        
    def generate_from_encounter(self, encounter_data: dict) -> SOAPNote:
        """Generate SOAP note from structured encounter data."""
        # Validate required fields
        required = ["chief_complaint", "hpi"]
        for field in required:
            if not encounter_data.get(field):
                raise ValueError(f"Missing required field: {field}")
        
        prompt = self.SOAP_TEMPLATE.format(
            patient_info=encounter_data.get("patient_info", "Not provided"),
            chief_complaint=encounter_data.get("chief_complaint"),
            hpi=encounter_data.get("hpi"),
            ros=encounter_data.get("ros", "Not provided"),
            vitals=encounter_data.get("vitals", "Not documented"),
            physical_exam=encounter_data.get("physical_exam", "Not documented"),
            lab_results=encounter_data.get("lab_results", "Results pending"),
            assessment_plan=encounter_data.get("assessment_plan", "")
        )
        
        response = self.ollama.generate(prompt, model=self.model)
        return self._parse_soap_response(response)
    
    def generate_from_transcript(self, transcript: str, 
                                  context: Optional[dict] = None) -> SOAPNote:
        """Generate SOAP note from conversation transcript."""
        prompt = f"""Convert this patient encounter transcript into a SOAP note.
        Extract relevant clinical information from the conversation.
        Use professional clinical language.
        
        Transcript:
        {transcript}
        
        Additional Context (if any):
        {context or 'None provided'}
        
        Format as:
        S: [Subjective]
        O: [Objective]
        A: [Assessment]
        P: [Plan]"""
        
        response = self.ollama.generate(prompt)
        return self._parse_soap_response(response)
    
    def _parse_soap_response(self, response: str) -> SOAPNote:
        """Parse LLM output into structured SOAPNote object."""
        sections = {"S": "", "O": "", "A": "", "P": ""}
        current_section = None
        
        for line in response.split("\n"):
            if line.strip().startswith("S:"):
                current_section = "S"
                line = line[2:]
            elif line.strip().startswith("O:"):
                current_section = "O"
                line = line[2:]
            elif line.strip().startswith("A:"):
                current_section = "A"
                line = line[2:]
            elif line.strip().startswith("P:"):
                current_section = "P"
                line = line[2:]
            
            if current_section:
                sections[current_section] += line + "\n"
        
        return SOAPNote(
            subjective=sections["S"].strip(),
            objective=sections["O"].strip(),
            assessment=sections["A"].strip(),
            plan=sections["P"].strip()
        )

A critical failure mode: the model may generate plausible but clinically inappropriate assessments based on incomplete information. SOAP notes generated from encounter data must clearly indicate uncertainty when diagnoses are implied rather than confirmed. Add system prompts instructing the model to use "consistent with" language when suggesting diagnoses.

EXERCISE

Collect a transcript from a standardized patient encounter. Generate a SOAP note, then compare against a gold-standard note written by a clinician. Identify discrepancies in clinical language and assessment accuracy.

← Chapter 5
Clinical Note Processing
Chapter 7 →
Medical Coding Assistance