Skip to content
KeepmeCompanyAIPublic

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Repository files navigation

KeepMeCompany Backend

Production multi-agent voice AI backend for clinical documentation. CE/UKCA Class I Medical Device


What It Does

KeepMeCompany replaces the GP practice phone queue with an AI voice agent pipeline that handles patient intake, post-consultation follow-up, and real-time crisis detection -- all in English and Spanish.

  • Inbound AI Intake -- Verifies patient identity, gathers symptoms, generates structured medical summaries. Patient wait time: 30+ min down to seconds.
  • Outbound Follow-up Calls -- Medication adherence, test result delivery (3 protocols by severity), immunisation reminders, early discharge monitoring. Clinician-configurable objectives and scheduling.
  • Real-Time Crisis Detection (Escalator) -- Two-stage pipeline running on every call: symptom identification, then crisis confirmation. Triggers on chest pain, stroke (FAST), severe breathing difficulty, loss of consciousness. Injects Priority-1 goals.

Product demos:

Architecture

                         Twilio (mu-law 8kHz WebSocket)
                                    |
                                    v
                    +-------------------------------+
                    |     Django Channels / ASGI     |
                    |         (Daphne + Redis)       |
                    +-------------------------------+
                                    |
                    +---------------+---------------+
                    |                               |
                    v                               v
          +----------------+             +-------------------+
          | Silero VAD     |             | Streaming STT     |
          | (Voicemail     |             | Google Speech v2   |
          |  Detection)    |             | or Speechmatics    |
          +----------------+             +-------------------+
                                                |
                                    Partial transcripts
                                                |
        +-------+-------+-------+-------+------+------+
        |       |       |       |       |             |
        v       v       v       v       v             v
   +--------+ +------+ +------+ +------+ +----------+ +----------+
   | Talker | | Goals| | Goals| | Node | |Controller| |Escalator |
   |        | |Track.| | Gen. | | Sel. | |          | |          |
   | Top-2  | | Eval | | Dyn. | | Next | | 5 action | | Crisis   |
   | active | | goal | | goal | | node | | triggers | | detect   |
   | goals  | | satis| | from | | in   | | per turn | | (standalone
   |        | | per  | | ctxt | | graph| |          | |  due to  |
   |        | | turn | |      | |      | |          | |  risk)   |
   +--------+ +------+ +------+ +------+ +----------+ +----------+
        |                                                    |
        v                                                    v
   +-------------------+                          +------------------+
   | LLM Abstraction   |                          | Node Graph       |
   | Layer             |                          | (Firestore)      |
   |                   |                          | Directed graph   |
   | Anthropic Claude  |                          | of conversation  |
   | OpenAI GPT        |                          | flow nodes       |
   | Groq (Llama)      |                          +------------------+
   | Cerebras          |
   +-------------------+
        |
        v
   +-------------------+       +-------------------+
   | TTS               |       | Post-Processing   |
   | ElevenLabs        |       | Summary (PDF)     |
   | (phrase-level     |       | Tagger + SMS      |
   |  streaming +      |       | via Twilio        |
   |  GCS cache)       |       +-------------------+
   +-------------------+
        |
        v
   Twilio (audio back to caller)

Agent System

Six LLM agents run concurrently on every live call, coordinated through a node-based goal architecture:

Node System -- Conversation flow is a directed graph stored in Firestore. Each node carries activation instructions, objectives (per language), and transition paths. Global nodes (emergency escalation, call termination) are reachable from any point.

Goals System -- Each node defines objectives. GoalsTracker evaluates goal completion after every user turn. GoalsGenerator creates dynamic follow-up goals from conversation context (for nodes without hardcoded objectives). The Talker agent always works on the top-2 active goals, with Priority-1 injection during crisis mode.

Controller -- Runs on every turn, detecting five boolean action triggers: emergency, bad_intentioned_user, medical_advice, increase_volume, decrease_volume. Acts as a parallel safety and routing layer alongside the main conversation agents.

Escalator -- Deliberately separated from the Controller into a standalone agent due to the severity of its risk domain. Handles only crisis detection (chest pain, stroke signs, severe breathing difficulty, loss of consciousness) with no other responsibilities that could introduce failure modes. When triggered: Priority-1 goal injection, all non-critical goals paused, GoalsGenerator disabled, structured clinical handoff with embedded patient information. CQC-compliant: system calls 999 directly, never redirects patient.

Streaming Pipeline -- LLM responses are streamed token-by-token, split at punctuation boundaries into phrases. While TTS renders phrase N, the next LLM chunk is pre-fetched. Interruption detection runs at every stage -- if the patient speaks mid-response, the current stream is cancelled and a new interaction starts.

Patient Verification -- Two-stage (DOB then name). Name matching uses algorithmic scoring first (word overlap + Levenshtein similarity), with LLM as fallback only when ambiguous. Max 8 attempts with consecutive failure limits.

Multi-Provider LLM Layer -- Each agent is independently configurable to use any of four providers (Anthropic, OpenAI, Groq, Cerebras). Model selection based on latency/quality benchmarking per agent role.

Post-Call Agents -- MedicalSummaries (structured clinical notes), Tagger (call classification), QuestionsGenerator (follow-up questions from GP instructions), AnswersParser (follow-up response classification with concern levels).


🧪 Evaluation System

Every agent has evaluation methods matched to the nature of its output. The result is a three-tier system: code-based assertions for deterministic checks, LLM-as-a-judge for subjective quality dimensions, and human expert review for calibration and ground truth.

GoalsTracker — Deterministic Assertions

The GoalsTracker evaluates sub-goal completion after every user turn. Test cases define expected completion states as fractions (e.g., 1/4, 0/4), and assertions compare the agent's output against expected values.

Insight surfaced by evals: The original design used binary complete / not-complete per goal. Evaluation revealed the LLM was unreliable with binary classification — it would lazily over- or under-assign completeness. Switching to fractional sub-goal counting (3 out of 4 sub-goals completed) dramatically improved accuracy. This architectural change was a direct product of the eval system catching a systemic failure mode.

We also evaluated fine-tuning the GoalsTracker to reduce latency and cost. The eval data showed no meaningful improvement on either axis, so we kept the prompted version.

GoalsGenerator — LLM-as-a-Judge + Pairwise Comparison

The GoalsGenerator dynamically creates follow-up goals based on conversation context. It evolved across architecture versions: in the early linear architecture (single large node), it generated 2 goals at a time; after moving to the node-based directed graph, it was redesigned to generate 1 goal at a time, and only for nodes without hardcoded objectives.

Quality was evaluated with an LLM judge against defined criteria:

  • Goals must not repeat earlier goals in the conversation
  • Goals must not include prohibited question categories
  • Overly generic goals must be decomposed into specific, self-contained sub-goals

For model selection, we ran pairwise comparisons across ChatGPT, Claude, and Llama. Human evaluators independently performed the same comparisons, and we measured alignment between human and LLM judgments over time.

Talker — Multi-Dimensional Evaluation

The Talker is the patient-facing conversational agent and the most complex to evaluate, requiring different eval strategies per quality dimension:

Dimension Method Detail
Medical advice detection Code assertion Fine-tuned model outputs a specific refusal phrase; assertion checks for exact match
Medical advice (defense-in-depth) Controller agent Controller detects medical_advice: true and interjects independently — deliberately overly cautious given Class I Medical Device regulatory profile
Tone Human + LLM-as-a-judge Both evaluated the same conversations; alignment validated before trusting the LLM judge at scale
Filler word compliance Code assertion Responses must begin with a phrase from an expanding compendium of filler words/phrases (latency-masking strategy)

Fine-tuning: The Talker was fine-tuned in both English and Spanish. Evaluation showed slight improvements in latency and quality with language-specific models. We eventually converged to a single model — eval data showed the quality delta was marginal relative to the maintenance cost of two models.

Controller — Deterministic Assertions

The Controller classifies every turn into five boolean triggers. Code assertions verified correct classification across labeled test scenarios for all five triggers.

Escalator (Crisis Detection) — Deterministic Assertions

Deliberately separated from the Controller into a standalone agent due to the severity of its risk domain. Evaluated across three scenario categories:

  1. No emergency — agent should not trigger
  2. Clear emergency — agent must trigger with correct classification and structured handoff
  3. Suspicion of emergency — agent should flag for further assessment

Each scenario has a defined expected response. Code assertions verify correct classification.

NodeSelector / Router — Deterministic Assertions

Given conversation context and current position in the node graph, assertions verify the agent selects the correct next node.

Post-Call & Async Agents

MedicalSummaries, Tagger, QuestionsGenerator, and AnswersParser have well-constrained output formats (structured XML/JSON) and lower variability — validated with format assertions and clinical team spot-checks rather than full eval infrastructure.

Datasets

Evaluation datasets were primarily hand-curated to ensure high quality on the most critical dimensions: tone, conciseness, and the Talker's two-goal-at-a-time conversational logic. Manual curation was necessary because the Talker needed to manage two active goals seamlessly while giving the other agents time to process — without the patient noticing any coordination overhead.

As the system processed 2,000+ real patient calls, production edge cases were incorporated into the eval dataset, creating a feedback loop between live usage and evaluation coverage.

Eval Coverage Summary

┌─────────────────┬────────────┬───────────────┬──────────┬──────────────┐
│ Agent           │ Assertions │ LLM-as-Judge  │ Pairwise │ Human Review │
├─────────────────┼────────────┼───────────────┼──────────┼──────────────┤
│ GoalsTracker    │     ✅     │               │          │              │
│ GoalsGenerator  │            │      ✅       │    ✅    │      ✅      │
│ Talker (med.)   │     ✅     │               │          │              │
│ Talker (tone)   │            │      ✅       │          │      ✅      │
│ Talker (filler) │     ✅     │               │          │              │
│ Controller      │     ✅     │               │          │              │
│ Escalator       │     ✅     │               │          │              │
│ NodeSelector    │     ✅     │               │          │              │
│ Post-call*      │     ✅     │               │          │      ✅      │
│ Model selection │            │      ✅       │    ✅    │      ✅      │
└─────────────────┴────────────┴───────────────┴──────────┴──────────────┘
* MedicalSummaries, Tagger, QuestionsGenerator, AnswersParser

Tech Stack

Layer Technology
Language Python
Framework Django 4.2, Django REST Framework, Django Channels 4
Server Daphne (ASGI), Redis (channel layer + message broker)
Database Firebase / Firestore
Storage Google Cloud Storage (TTS cache, model files)
STT Google Speech-to-Text v2 (streaming), Speechmatics (real-time WebSocket)
TTS ElevenLabs (flash + multilingual models), phrase-level GCS cache
LLMs Claude Haiku/Sonnet, GPT-4o, Groq (Llama), Cerebras
Telephony Twilio (voice streaming + SMS)
VAD Silero VAD (PyTorch, answering machine detection)
Fine-tuning Custom Scenario Builder (YAML), Llama fine-tuning
Deploy Heroku + Docker

Key Results

Metric Result
Patient calls completed 2,000+
Patient wait time 30+ min reduced to seconds for intake
GP consult time saved ~2 min/consult (~20% reduction)
Call capture rate 100% (zero missed calls)

Regulatory

CE Mark + UKCA Mark (Class I Medical Device). MHRA registered. GDPR compliant (Articles 6(1)(a), 9(2)(a)). DSP Toolkit, DTAC, Cyber Essentials, DCB1596, CQC compliant. ISO 9001 + ISO 13485. AES-256 encryption, 2FA, RBAC, automatic data deletion after GP transmission.


About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages