System

2026-07-16T04:40:35Z
Environment
PROD
KG Version
combined-vm
Uptime
30h 7m
Git
prod (0be790c28a585b1358ec711ff0daa7cd8a84ce70)
Ontology (medical evidence IR)
v4 evidence-text (39 fields)
V3 + optional evidence_text field (verbatim paper quote). Extraction pipelines that opt in require the quote; baselines leave it empty. Schema-compatible with V3 (default '').
Deployment Topology#
Probing live topology...
PMC Daily Copy (S3 → Azure)#
Probing copy job...
Manuscript Pipeline#
Probing pipeline health...
Redis Cache#
Probing Redis...
Loading git info...
Probing services...
Loading Azure resources...
Loading Databricks...
User Activity#
Loading user activity...
Aligned Compile Workflows (same grammar / domain ontology / IR family)#
graph LR
    subgraph BUILD["COMPILE KG WORKFLOW (offline, Databricks)"]
        direction LR
        P[paper] --> EX[Semantic Parser\nLLM] --> F[findingsIR] --> R1[Resolve\nper entity type] --> CY1[compile to\nCypher query]
    end

    subgraph QUERY["COMPILE QUERY WORKFLOW (online, website)"]
        direction LR
        Q[question] --> DE[Semantic Parser\nLLM] --> M[queryIR\nlogical form for eval] --> R2[Resolve\nper entity type] --> CY2[compile to\nCypher query]
    end

    CY2 -->|"execute cypher query"| NEO["KG Instance\non Neo4j"]
    CY1 -->|"execute cypher merge"| NEO
    NEO --> SG["subgraph\nfor eval"] --> SYN["LLM synopsis\nanswer for eval"]

    style M fill:#f3e8ff,stroke:#7c3aed,stroke-width:2px
    style SG fill:#f3e8ff,stroke:#7c3aed,stroke-width:2px
    style SYN fill:#f3e8ff,stroke:#7c3aed,stroke-width:2px
            
Query Workflow (end-to-end)#
graph LR
    U["User\nquestion"] --> W["Website\nFastAPI"]
    W --> LLM1["LLM Service\ndecompose\n(PICO extraction)"]
    LLM1 --> CR["Concept Resolver\nregex → UMLS → LLM → embed\n(4-step, cached)"]
    CR --> NEO["Neo4j\nCypher query\n(broad recall)"]
    NEO --> LLM2["LLM Service\npertinence filter\n(concurrent fan-out)"]
    LLM2 --> LLM3["LLM Service\nsynopsis\n(structured citations)"]
    LLM3 --> U2["User\nevidence + synopsis"]

    style CR fill:#e3f2fd,stroke:#1976d2
    style NEO fill:#e8f5e9,stroke:#388e3c
    style LLM1 fill:#fff3e0,stroke:#f57c00
    style LLM2 fill:#fff3e0,stroke:#f57c00
    style LLM3 fill:#fff3e0,stroke:#f57c00
            
Query Latency Breakdown
StepTimeWhat
LLM decompose~1.0sgpt-4.1 structured output — extract PICO mentions from question
Concept resolver~0.2sUMLS lookup per mention (2 HTTP calls for typical query)
Graph expansion~0.2sNeo4j query: what conditions are linked to these interventions?
Neo4j Cypher~0.1sBroad recall: LIMIT 100 with CONTAINS matching
Pertinence filter~0.5sgpt-4.1-mini per finding, all concurrent via asyncio.gather
Total~2sEnd-to-end, warm cache. Test: /smoke/query?q=exercise+for+depression
LLM Gateway — all calls through one service#

Every LLM call in the entire system goes through the LLM Service (cached gateway). Zero direct Azure OpenAI calls. One gateway, one cache, one place to observe.

ComponentLLM calls viaStatus
Website (decompose, filter, synopsis) LLM ServiceLive
Extraction LLM ServiceCode ready
Canonicalization LLM ServiceCode ready
Pertinence filter LLM ServiceCode ready
Concept resolver (Step 3) LLM ServiceCode ready
Deploy Pipeline#
graph LR
    subgraph CI["GITHUB ACTIONS"]
        direction LR
        PUSH["push to prod"] --> BUILD["Build\nDocker image\n→ ACR"]
        BUILD --> STAGING["Deploy to\nSTAGING"]
        STAGING --> TEST{"E2E Smoke Test\nALL blue pills\nvia /smoke/query"}
        TEST -->|"all pass"| PROD["Deploy to\nPROD"]
        TEST -->|"any fail"| BLOCK["BLOCKED\nprod not updated"]
    end

    subgraph APPS["CONTAINER APPS"]
        S["nobsmed-staging\n0-1 replicas"]
        P["nobsmed.com\n1-10 replicas"]
        MCPAPP["nobsmcpserver\n1 replica (always on)\n/mcp + /health"]
    end

    STAGING --> S
    PROD --> P

    subgraph MCP_CI["MCP SERVER CI/CD"]
        direction LR
        MPUSH["push to prod\napps/mcp-server/**"] --> MBUILD["Build\nDocker image\n→ ACR"]
        MBUILD --> MDEPLOY["Deploy to\nnobsmcpserver"]
        MDEPLOY --> MHEALTH{"Health check\n+ MCP handshake"}
    end

    MDEPLOY --> MCPAPP

    style BLOCK fill:#f8d7da,stroke:#dc3545
    style TEST fill:#fff3cd,stroke:#ffc107
    style PROD fill:#d4edda,stroke:#198754
    style MCPAPP fill:#e3f2fd,stroke:#1976d2
    style MHEALTH fill:#e3f2fd,stroke:#1976d2
            
MCP Server — AI Client Integration#

Single MCP server serves all AI clients. 2 read-only clinical evidence tools. No Custom GPT Actions — MCP-first architecture.

EndpointURLStatus
MCP (streamable-http) nobsmcpserver.../mcp Live
Health check nobsmcpserver.../health Live
ToolPurposeInputOutput
lookup Resolve user language → canonical concepts name, entity_type? canonical name, type, aliases, score
evidence Retrieve clinical findings from KG intervention?, condition?, outcome? claim, effect_direction, effect_size, CI, study_title, pmc_id
AI ClientProtocolStatus
Claude DesktopMCP streamable-http Ready
Claude CodeMCP streamable-http Ready
ChatGPT App DirectoryMCP via Apps SDKPending submission
Positioning: Clinical evidence retrieval for health questions. Not medical advice.
Infra: Azure Container App, 1 replica (always on), 0.5 CPU, 1 GB. CI/CD: .github/workflows/deploy-mcp-server.yml
Reference: docs/mcp-app-reference.md
KG Hierarchy#
graph TD
    KG[":KG name"] --> META[":KGMeta\nrole, schema_version"]
    META -->|HAS_BUILD| BUILD[":BuildInfo\nstatus, resolver, git_commit"]
    META -->|HAS_AUDIT| AUDIT[":AuditReport\nresolved_ratio, smoke_test"]
    META -->|HAS_SHOWCASE| PILL[":ShowcaseQuestion\nquestion, score, blue"]

    META --> EV[":Evidence (unified label)"]

    EV --> FIND[":Finding:Evidence\nclinical study"]
    FIND -->|tested| INT[":Intervention"]
    FIND -->|for_condition| COND[":Condition"]
    FIND -->|on_outcome| OUT[":Outcome"]
    FIND -->|reported_in| STUDY[":Study pmc"]

    EV --> EXP[":Experience:Evidence\nReddit / anecdotal"]
    EXP -->|tested| INT2[":Intervention"]
    EXP -->|for_condition| COND2[":Condition"]
            
Problems driving design#

The drivers below are payoffs of three decisions: (1) canonical identity (resolver + SNOMED) → dedup, IS-A recall, pooling; (2) ontology-as-code (one schema, projected + constrained) → zero drift + no-hallucination; (3) typed artifacts, not prose → debuggable reasoning, re-runnable lineage, gradeable output.

Driver / capabilityMin rungBeneficiary
Deterministic, reproducible queriesSQLAgent / Business
Citation on every finding (no fabrication)SQLUser / Business
Surface facts, not paraphrase (IP posture)SQLBusiness
Flywheel CI — optimize the extractor vs gold (no GEPA / manual prompt-search)SQLDeveloper
Gradeable audit — score/benchmark the audit output (precision/recall vs gold) = the graderSQLBusiness
Zero drift (one grammar → models/prompts/schema)SQLDeveloper
Debuggable intermediate artifacts + stratified re-runSQLDeveloper
Exact-match dedupSQL
Multi-hop / causal-chain reasoningKGAgent / User
Semantic dedup (synonyms)SNOMED
Like-family / IS-A reasoningSNOMEDAgent
Cross-study / cross-patient poolingSNOMEDAgent / User
EHR interoperabilitySNOMEDBusiness
Full writeup & the capability ladder: graph-rationale.
Knowledge Graphs ...#
Probing KG instances...
Experiment Surface#
Loading experiment surface...