{"slug": "air-gapped-rig-edge-witsml-telemetry-with-local-small-language-models-slms", "title": "Air-Gapped Rig-Edge WITSML Telemetry with Local Small Language Models (SLMs)", "summary": "A drilling engineer built an air-gapped edge intelligence stack that runs deterministic physics filters and quantized small language models (7B or 3B, via Ollama or llama.cpp) directly on rig-site hardware to triage WITSML/WITS telemetry, avoiding the 600–1200 ms satellite round-trip latency of cloud inference. The two-tier design uses a Rust/Python physics worker for flow-differential and standpipe-pressure checks, then passes a structured JSON context window to a local SLM for sub-second anomaly triage and root-cause classification, with asynchronous delta sync to headquarters only when connectivity allows.", "body_md": "*Originally published with interactive math formulas and diagrams at [eng.kcklayton.com](https://eng.kcklayton.com/blog/rig-edge-witsml-local-slm-telemetry/)*\n\nDrilling rigs—whether stationed offshore in deepwater or operating across remote onshore basins—share a common operational reality: **high-latency, bandwidth-constrained, and intermittent satellite connectivity (VSAT)**.\n\nRound-trip satellite pings routinely exceed $600\\text{ to }1200\\text{ ms}$, with atmospheric attenuation or antenna line-of-sight blockage causing frequent dropouts. When a high-pressure gas influx (kick) enters the wellbore, or when a bottom-hole assembly (BHA) experiences catastrophic stick-slip oscillation, seconds count. Routing real-time sensor telemetry to a remote cloud datacenter for LLM inference or anomaly classification introduces unacceptable operational latency and single-point-of-failure exposure.\n\nTo solve this, our drilling architecture decouples real-time rig surveillance into an **Air-Gapped Edge Intelligence Stack** running local deterministic filters and quantized Small Language Models (SLMs) directly on rig-site hardware.\n\nModern drilling rigs generate high-frequency telemetry across dozens of channels via the **WITSML** (Wellsite Information Transfer Standard Markup Language) and **WITS** (Wellsite Information Transfer Specification) standards:\n\n```\nflowchart TD\n    subgraph RigFloor[\"Rig Floor & PWD Instrumentation\"]\n        Sensors[\"Rig Sensors (Flow, SPP, Pit, Hookload)\"]\n        PWD[\"Downhole MWD / PWD Telemetry\"]\n    end\n\n    subgraph RigEdge[\"Edge Server (Rig Doghouse / Rig Server Room)\"]\n        WITSMLAgent[\"WITSML Edge Agent<br/>(1-sec Poller & In-Memory Ring Buffer)\"]\n        MathEngine[\"Deterministic Physics Filters<br/>(Flow In/Out Differential, Pit Rate)\"]\n        LocalSLM[\"Local SLM Inference Engine<br/>(Ollama / llama.cpp - Qwen / Mistral)\"]\n        RigDisplay[\"Local Rig Doghouse Alarm & HMI\"]\n    end\n\n    subgraph RemoteCloud[\"Corporate Headquarters / Real-Time Operations Center (RTOC)\"]\n        CloudMesh[\"Event-Driven Telemetry Mesh\"]\n        RemoteDashboard[\"Engineering Dashboard\"]\n    end\n\n    Sensors -->|WITS / WITSML| WITSMLAgent\n    PWD -->|Mud Pulse / EM| WITSMLAgent\n    WITSMLAgent --> MathEngine\n    MathEngine -->|Anomaly Context Window| LocalSLM\n    LocalSLM -->|Sub-second Triage & Root Cause| RigDisplay\n    WITSMLAgent -.->|Async Delta Sync via VSAT (When Online)| CloudMesh\n    CloudMesh -.-> RemoteDashboard\n```\n\nLanguage models should never replace basic physics calculations. Calculating flow differential ($\\Delta Q = Q_{\\text{out}} - Q_{\\text{in}}$) or standpipe pressure derivatives ($\\frac{dP}{dt}$) requires deterministic arithmetic, not probabilistic token generation.\n\nThe edge agent runs a **two-tier architecture**:\n\nThe [`witsml-edge-agent`](https://github.com/Greybeard00007/witsml-edge-agent) maintains a rolling in-memory ring buffer (defaulting to 300 seconds of 1-second records). A high-speed Rust/Python physics worker evaluates:\n\nWhen Tier 1 triggers an anomaly condition, it compiles a structured JSON context payload capturing the pre-event baseline, trigger metrics, current rig state (drilling, tripping, circulating, reaming), and recent downhole events.\n\nThis payload is dispatched via localhost IPC to [`ai-gateway-sentinel`](https://github.com/Greybeard00007/ai-gateway-sentinel), which interfaces directly with an embedded Ollama or `llama.cpp` instance running a quantized $7\\text{B}$ or $3\\text{B}$ parameter model (e.g., `mistral-7b-instruct-q4_K_M` or `qwen2.5-coder-7b`).\n\nHere is how the edge agent structures the telemetry window and queries the local edge engine:\n\n``` python\nimport numpy as np\nfrom dataclasses import dataclass\nfrom typing import List, Optional\nimport httpx\n\n@dataclass\nclass TelemetryPoint:\n    timestamp: float\n    depth_ft: float\n    rop_fph: float\n    spp_psi: float\n    flow_out_pct: float\n    pit_total_bbl: float\n    pumps_active: bool\n\nclass RigEdgeAnomalyDetector:\n    def __init__(self, ollama_url: str = \"http://127.0.0.1:11434\"):\n        self.buffer: List[TelemetryPoint] = []\n        self.max_buffer_size = 300\n        self.ollama_url = ollama_url\n        self.anomaly_cooldown = 0\n\n    def push(self, point: TelemetryPoint) -> Optional[dict]:\n        self.buffer.append(point)\n        if len(self.buffer) > self.max_buffer_size:\n            self.buffer.pop(0)\n\n        # Require at least 30 seconds of stable baseline\n        if len(self.buffer) < 30:\n            return None\n\n        # Deterministic trigger checks\n        recent = self.buffer[-5:]\n        baseline = self.buffer[-30:-5]\n\n        avg_baseline_pit = np.mean([p.pit_total_bbl for p in baseline])\n        current_pit = recent[-1].pit_total_bbl\n        pit_gain = current_pit - avg_baseline_pit\n\n        # Condition: Flowing with pumps off, or pit gain > 10 bbl\n        flow_anomaly = (not recent[-1].pumps_active) and (recent[-1].flow_out_pct > 3.0)\n        kick_indicator = pit_gain > 10.0\n\n        if (flow_anomaly or kick_indicator) and self.anomaly_cooldown == 0:\n            self.anomaly_cooldown = 60 # Cooldown to avoid prompt flooding\n            return self._triage_with_local_slm(point, pit_gain, flow_anomaly)\n\n        if self.anomaly_cooldown > 0:\n            self.anomaly_cooldown -= 1\n\n        return None\n\n    def _triage_with_local_slm(self, pt: TelemetryPoint, pit_gain: float, flow_anomaly: bool) -> dict:\n        prompt = f\"\"\"[RIG ALARM TRIAGE - HIGH PRIORITY]\nYou are a senior drilling superintendent and well control advisor running on an edge rig computer.\nCurrent Telemetry:\n- Hole Depth: {pt.depth_ft:.1f} ft\n- Standpipe Pressure: {pt.spp_psi:.0f} psi\n- Pumps Active: {pt.pumps_active}\n- Flow Out: {pt.flow_out_pct:.1f}%\n- Total Pit Gain: {pt.pit_gain:.1f} bbl\n- Flow Anomaly Flag: {flow_anomaly}\n\nProvide a concise, 3-bullet assessment:\n1. Probable Root Cause (e.g., Formation Influx vs. Pit Transfer vs. Sensor Drift)\n2. Immediate Verification Step for Driller (e.g., Space out and perform flow check)\n3. Well Control Level (Green / Yellow / Red Alert)\nFormat response as strictly actionable guidance for the rig crew.\"\"\"\n\n        try:\n            with httpx.Client(timeout=4.0) as client:\n                res = client.post(\n                    f\"{self.ollama_url}/api/generate\",\n                    json={\"model\": \"mistral:7b-instruct-q4_K_M\", \"prompt\": prompt, \"stream\": False}\n                )\n                if res.status_code == 200:\n                    return {\"status\": \"ALERT\", \"assessment\": res.json().get(\"response\", \"\")}\n        except Exception as e:\n            # Deterministic failsafe if local inference times out\n            return {\"status\": \"ALERT\", \"assessment\": \"LOCAL SLM TIMEOUT - EXECUTE FLOW CHECK IMMEDIATELY\"}\n        return {\"status\": \"ALERT\", \"assessment\": \"UNVERIFIED ANOMALY - INITIATE FLOW CHECK\"}\n```\n\nTesting deployed on an industrial fanless rig-floor edge PC (Intel Core i7-12700E, 32GB DDR5, running Ubuntu Core 24.04 LTS):\n\n| Model / Quantization | Parameter Size | Memory Footprint | Edge Inference Latency | Deterministic Filter Latency | Cloud Round-Trip (VSAT) | \n|---|---|---|---|---|---|\n| **Deterministic Rule Filter** | N/A | $< 40\\text{ MB}$ | **$0.4\\text{ ms}$** | Baseline | N/A | \n| **Qwen 2.5 3B (Q4_K_M)** | $3.1\\text{B}$ | $1.9\\text{ GB}$ | **$210\\text{ ms}$** | $+0.4\\text{ ms}$ | $1,800\\text{ ms}$ | \n| **Mistral 7B Instruct (Q4_K_M)** | $7.2\\text{B}$ | $4.4\\text{ GB}$ | **$490\\text{ ms}$** | $+0.4\\text{ ms}$ | $2,100\\text{ ms}$ | \n| **Llama 3.1 8B (Q4_K_M)** | $8.0\\text{B}$ | $4.9\\text{ GB}$ | **$580\\text{ ms}$** | $+0.4\\text{ ms}$ | $2,300\\text{ ms}$ | \n\nBy running locally:\n\nThe [`witsml-edge-agent`](https://github.com/Greybeard00007/witsml-edge-agent) and [` ai-gateway-sentinel`](https://github.com/Greybeard00007/ai-gateway-sentinel) work alongside our [`kill-sheet-calculations`](https://github.com/Greybeard00007/kill-sheet-calculations) library. When a kick is verified, the edge agent can automatically push shut-in drillpipe pressure (SIDPP), shut-in casing pressure (SICP), and pit volume gain into the kill calculation engine, rendering a fully populated, IADC-compliant kill sheet within seconds of well shut-in.", "url": "https://wpnews.pro/news/air-gapped-rig-edge-witsml-telemetry-with-local-small-language-models-slms", "canonical_source": "https://dev.to/greybeard00007/air-gapped-rig-edge-witsml-telemetry-with-local-small-language-models-slms-165m", "published_at": "2026-11-05 04:42:33+00:00", "updated_at": "2026-11-05 04:56:15.054382+00:00", "lang": "en", "topics": ["ai-agents", "large-language-models", "ai-infrastructure", "ai-tools", "mlops"], "entities": ["Ollama", "llama.cpp", "Qwen", "Mistral", "witsml-edge-agent", "ai-gateway-sentinel"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/air-gapped-rig-edge-witsml-telemetry-with-local-small-language-models-slms", "markdown": "https://wpnews.pro/news/air-gapped-rig-edge-witsml-telemetry-with-local-small-language-models-slms.md", "text": "https://wpnews.pro/news/air-gapped-rig-edge-witsml-telemetry-with-local-small-language-models-slms.txt", "jsonld": "https://wpnews.pro/news/air-gapped-rig-edge-witsml-telemetry-with-local-small-language-models-slms.jsonld"}}