astroknotsheep/meridian-api
Meridian โ Clinical-Grade Mental Health AI
Meridian is a highly autonomous, agentic mental health platform designed to operate between the lines of passive symptom tracking and structured therapeutic intervention. The platform relies on a sophisticated LangGraph orchestrator to enforce rigorous deterministic safety protocols, alongside a MentalRoBERTa-based ONNX pipeline for quantitative depression screening and an OpenAI-backed conversational agent using ChromaDB RAG for persistent in-session memory.
๐๏ธ System Architecture & Stateful Orchestration
The core engine of Meridian is a directed cyclic graph (DCG) managed by LangGraph. This architecture ensures every message passes through mandatory, deterministic guardrails before an LLM or ML classifier is ever invoked.
State Schema (ClinicalState)
The global state passed between nodes is strongly typed using Python's TypedDict and utilizes custom LangGraph reducers to manage accumulation fields safely across turns.
class ClinicalState(TypedDict):
# Core Communication
messages: Annotated[Sequence, add_messages] # Full history (append-only)
current_message: str # Latest input (post-redaction)
session_id: str # Frontend-generated UUID
# Guardrail & Safety Flags
guardian_blocked: bool
guardian_reason: str
mode_suggestion: str
crisis_detected: bool
phi_redacted: bool
# Routing & UI State
mode: Literal["diagnosis", "therapy"]
modality: Optional[str]
# Analytics & Diagnosis Accumulators
embedding_buffer: Annotated[List[List[float]], _append_embeddings]
char_buffer_total: Annotated[int, _add_ints]
diagnosis_ready: bool
risk_scores: Dict[str, float]
metrics: Dict[str, float]Routing Logic
- Guardian Node: Evaluates input against scope and abuse lists. If blocked, sets
guardian_blocked = Trueand short-circuits toguardian_block_node-> END. - Security Node: Analyzes text for PHI and deterministic crisis keywords. Sets
crisis_detectedandcurrent_message(redacted). - Supervisor Router:
- If
crisis_detected == True-> routes tocrisis_response_node-> END - If
mode == "therapy"AND every 5th AI turn -> routes tophq9_node-> END - If
mode == "diagnosis"-> routes todiagnosis_node-> END - Else -> routes to
therapy_node-> END
๐ง Core Technical Components
1. Guardian Agent (Outermost Gate)
The Guardian acts as an absolute perimeter defense to ensure the system is not utilized as a general-purpose LLM, maintaining strict clinical scope.
- Off-Topic Classification: Checks input against a heuristic set of domain-specific stop words (e.g., coding, mathematics, business, entertainment).
- Cumulative Drift Detection: Scans the
messageshistory in the state. Ifโฅ 3consecutive user inputs trigger the off-topic filter, it hard-blocks the session. - Vulgarity Moderation: Blocks slurs and sexual content, but utilizes an intentional exclusion list for emotional profanity (e.g., "I feel like shit"), recognizing this as valid therapeutic expression.
- Mode Consistency Engine: If the user is operating in
diagnosismode but emits high-distress vectors (e.g., "I need help", "I feel lost"), it setsmode_suggestion = "therapy"to append a non-intrusive UI prompt suggesting a shift to active support.
2. Security Agent & PHI Redaction
To maintain HIPAA/GDPR conceptual compliance at the protocol level, no personally identifiable information (PHI) ever reaches the OpenAI API or ML classifier.
- Presidio Engine: Uses
presidio_analyzerandpresidio_anonymizerrunning locally (viaen_core_web_lgspaCy model). - Redaction Targets:
PERSON,LOCATION,PHONE_NUMBER,EMAIL_ADDRESS,US_SSN,CREDIT_CARD. - Crisis Overrides: A purely deterministic text-matching array checks for 15+ acute crisis indicators. If matched,
crisis_detectedis set toTrue, triggering a hardcoded response containing verified crisis hotlines, bypassing all LLM generation.
3. Therapy Agent (LLM + RAG)
The active intervention pipeline utilizes the OpenAI Chat Completions API, constrained by modality-specific prompts and session-persistent memory.
- LLM: Defaults to
gpt-4o-mini(configurable viaTHERAPY_MODEL). - Modality Injectors: System prompts dynamically adjust based on the selected modality (CBT, ACT, DBT, Mindfulness, SFBT), modifying the assistant's analytical framework (e.g., Cognitive Restructuring vs. Defusion).
- ChromaDB RAG Memory:
- Each
session_idinstantiates a unique, isolated Chroma collection using cosine similarity{"hnsw:space": "cosine"}. - Previous exchanges (User + AI) are embedded using
sentence-transformersvia Chroma'sDefaultEmbeddingFunction. - The agent retrieves the top
n_results=2similar past exchanges and injects them into the system prompt to prevent repetitive advice and maintain deep thematic context across long sessions. - Output Guardrails: Post-generation regex filters ensure the LLM does not hallucinate diagnoses or prescribe medication (e.g., blocking phrases like "you have depression", "take this medication").
4. Diagnosis Agent (ML Screening Pipeline)
Instead of relying on LLM self-analysis for diagnostics, Meridian uses a robust, deterministic Machine Learning pipeline.
The ML Pipeline Architecture
- Accumulation & Progressive Probing:
- A single message lacks statistical significance. The node requires
char_buffer_total โฅ 800characters. - While accumulating, the agent dynamically generates empathetic follow-up questions focused on PHQ-9 clinical domains (Sleep, Energy, Appetite, Anhedonia) using a secondary LLM call to draw out highly relevant linguistic data.
- Tokenization: Input is processed via HuggingFace
AutoTokenizer(max length 96 tokens, matches original training topology). - Inference (MentalRoBERTa ONNX):
- The tokenized text is passed to an
onnxruntime.InferenceSessionutilizing theCPUExecutionProvider. - The engine handles dynamic input graphs (determining if
token_type_idsare required by the specific export). - Mean Pooling:
- Extracted token embeddings of shape
(1, SequenceLength, 768)are multiplied against theattention_mask. - The masked embeddings are summed and divided by the clamped mask sum to generate a single, dense semantic vector of shape
(1, 768). - Turn Aggregation: Mean-pooled vectors from every turn in the active session are stored in
embedding_bufferand vertically stacked (np.vstack) to compute the final, session-wide average embedding. - Classification & Calibration:
- The aggregated vector is normalized using a pre-fitted
StandardScaler(scaler.joblib). - The scaled vector is passed to a
CalibratedLinearSVC(svm_depression.joblib), which outputs a bounded probability[0.0, 1.0]. - The probability is mapped to risk tiers (Low < 30%, Moderate < 60%, Elevated โฅ 60%).
๐ Setup & Installation
Prerequisites
- Python 3.11+
- OpenAI API Key
- ONNX Runtime and Joblib (for ML pipeline)
Local Development
- Clone and setup virtual environment:
git clone <repository_url>
cd Prod
python -m venv .venv
source .venv/bin/activate- Install dependencies:
pip install -r requirements.txt
python -m spacy download en_core_web_lg- Configure Environment Variables:
cp .env.example .env
# Edit .env and set OPENAI_API_KEY- Verify Models: Ensure
models/mentalroberta_onnx/model.onnx,models/svm_depression.joblib, andmodels/scaler.joblibare present. (Run Colab notebooktrain_classifiers.ipynbto generate them if missing).
- Start the Application:
uvicorn backend.main:app --reload --host 0.0.0.0 --port 8000Navigate to `http://localhost:8000` to interact with the platform.
๐ Ephemeral Execution & Privacy
Traditional clinical intake relies on permanent records, exposing vulnerable populations to data breaches. Meridian is intentionally ephemeral. The platform operates statelessly beyond the immediate browser session, requiring zero account creation and retaining zero long-term data. In-memory ChromaDB collections and LangGraph states are instantly discarded upon server restart or session expiration.
