DEV Community

Kirk Keel
Kirk Keel

Posted on Originally published at eng.kcklayton.com

Air-Gapped Rig-Edge WITSML Telemetry with Local Small Language Models (SLMs)

Originally published with interactive math formulas and diagrams at eng.kcklayton.com

Drilling 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).

Round-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.

To 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.


1. The Architectural Challenge: The Edge Telemetry Firehose

Modern 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:

  • Surface Parameters: Hookload, Standpipe Pressure (SPP), Surface Torque, Rotary RPM, Pit Volume Total (PVT), Flow Out percentage, Mud Gas concentration ($C_1 - C_5$).
  • Downhole MWD/LWD: Continuous Inclination/Azimuth, Gamma Ray, Annular Pressure While Drilling (PWD), Dynamic Shock and Vibration.
flowchart TD
    subgraph RigFloor["Rig Floor & PWD Instrumentation"]
        Sensors["Rig Sensors (Flow, SPP, Pit, Hookload)"]
        PWD["Downhole MWD / PWD Telemetry"]
    end

    subgraph RigEdge["Edge Server (Rig Doghouse / Rig Server Room)"]
        WITSMLAgent["WITSML Edge Agent<br/>(1-sec Poller & In-Memory Ring Buffer)"]
        MathEngine["Deterministic Physics Filters<br/>(Flow In/Out Differential, Pit Rate)"]
        LocalSLM["Local SLM Inference Engine<br/>(Ollama / llama.cpp - Qwen / Mistral)"]
        RigDisplay["Local Rig Doghouse Alarm & HMI"]
    end

    subgraph RemoteCloud["Corporate Headquarters / Real-Time Operations Center (RTOC)"]
        CloudMesh["Event-Driven Telemetry Mesh"]
        RemoteDashboard["Engineering Dashboard"]
    end

    Sensors -->|WITS / WITSML| WITSMLAgent
    PWD -->|Mud Pulse / EM| WITSMLAgent
    WITSMLAgent --> MathEngine
    MathEngine -->|Anomaly Context Window| LocalSLM
    LocalSLM -->|Sub-second Triage & Root Cause| RigDisplay
    WITSMLAgent -.->|Async Delta Sync via VSAT (When Online)| CloudMesh
    CloudMesh -.-> RemoteDashboard

Why Cloud-Only AI Fails on Rigs:

  1. Network Blackouts: Severe storms or satellite handoffs cut off connection right during critical tripping or drilling phases.
  2. Bandwidth Costs & Saturation: Raw 10Hz/1Hz multi-channel telemetry streams saturate satellite uplinks needed for drilling engineering conferences and logistics.
  3. Latency Jitter: A prompt round-trip to an external API (like GPT-4o or Claude) takes $2\text{ to }5\text{ seconds}$ under ideal satellite conditions, and times out entirely under packet loss.

2. Real-Time Deterministic Filtering + SLM Hybrid

Language 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.

The edge agent runs a two-tier architecture:

Tier 1: Deterministic Real-Time Anomaly Windowing

The 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:

  • Rate of Penetration (ROP) Break Detection: Sudden acceleration in ROP without corresponding weight-on-bit (WOB) increase (drilling break).
  • Pit Gain Rate: Positive slope in active pit volume $> 5\text{ bbl/min}$.
  • Flow-Out vs. Pump Rate Incongruence: Flow sensor reading $> 0$ while rig pumps are off, or positive deviation exceeding baseline threshold.

Tier 2: Edge-Local SLM Contextual Triage

When 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.

This payload is dispatched via localhost IPC to 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).


3. Implementation: Fast Edge WITSML Anomaly Dispatch

Here is how the edge agent structures the telemetry window and queries the local edge engine:

import numpy as np
from dataclasses import dataclass
from typing import List, Optional
import httpx

@dataclass
class TelemetryPoint:
    timestamp: float
    depth_ft: float
    rop_fph: float
    spp_psi: float
    flow_out_pct: float
    pit_total_bbl: float
    pumps_active: bool

class RigEdgeAnomalyDetector:
    def __init__(self, ollama_url: str = "http://127.0.0.1:11434"):
        self.buffer: List[TelemetryPoint] = []
        self.max_buffer_size = 300
        self.ollama_url = ollama_url
        self.anomaly_cooldown = 0

    def push(self, point: TelemetryPoint) -> Optional[dict]:
        self.buffer.append(point)
        if len(self.buffer) > self.max_buffer_size:
            self.buffer.pop(0)

        # Require at least 30 seconds of stable baseline
        if len(self.buffer) < 30:
            return None

        # Deterministic trigger checks
        recent = self.buffer[-5:]
        baseline = self.buffer[-30:-5]

        avg_baseline_pit = np.mean([p.pit_total_bbl for p in baseline])
        current_pit = recent[-1].pit_total_bbl
        pit_gain = current_pit - avg_baseline_pit

        # Condition: Flowing with pumps off, or pit gain > 10 bbl
        flow_anomaly = (not recent[-1].pumps_active) and (recent[-1].flow_out_pct > 3.0)
        kick_indicator = pit_gain > 10.0

        if (flow_anomaly or kick_indicator) and self.anomaly_cooldown == 0:
            self.anomaly_cooldown = 60 # Cooldown to avoid prompt flooding
            return self._triage_with_local_slm(point, pit_gain, flow_anomaly)

        if self.anomaly_cooldown > 0:
            self.anomaly_cooldown -= 1

        return None

    def _triage_with_local_slm(self, pt: TelemetryPoint, pit_gain: float, flow_anomaly: bool) -> dict:
        prompt = f"""[RIG ALARM TRIAGE - HIGH PRIORITY]
You are a senior drilling superintendent and well control advisor running on an edge rig computer.
Current Telemetry:
- Hole Depth: {pt.depth_ft:.1f} ft
- Standpipe Pressure: {pt.spp_psi:.0f} psi
- Pumps Active: {pt.pumps_active}
- Flow Out: {pt.flow_out_pct:.1f}%
- Total Pit Gain: {pt.pit_gain:.1f} bbl
- Flow Anomaly Flag: {flow_anomaly}

Provide a concise, 3-bullet assessment:
1. Probable Root Cause (e.g., Formation Influx vs. Pit Transfer vs. Sensor Drift)
2. Immediate Verification Step for Driller (e.g., Space out and perform flow check)
3. Well Control Level (Green / Yellow / Red Alert)
Format response as strictly actionable guidance for the rig crew."""

        try:
            with httpx.Client(timeout=4.0) as client:
                res = client.post(
                    f"{self.ollama_url}/api/generate",
                    json={"model": "mistral:7b-instruct-q4_K_M", "prompt": prompt, "stream": False}
                )
                if res.status_code == 200:
                    return {"status": "ALERT", "assessment": res.json().get("response", "")}
        except Exception as e:
            # Deterministic failsafe if local inference times out
            return {"status": "ALERT", "assessment": "LOCAL SLM TIMEOUT - EXECUTE FLOW CHECK IMMEDIATELY"}
        return {"status": "ALERT", "assessment": "UNVERIFIED ANOMALY - INITIATE FLOW CHECK"}
Enter fullscreen mode Exit fullscreen mode

4. Benchmark Performance on Industrial Edge Hardware

Testing deployed on an industrial fanless rig-floor edge PC (Intel Core i7-12700E, 32GB DDR5, running Ubuntu Core 24.04 LTS):

Model / Quantization Parameter Size Memory Footprint Edge Inference Latency Deterministic Filter Latency Cloud Round-Trip (VSAT)
Deterministic Rule Filter N/A $< 40\text{ MB}$ $0.4\text{ ms}$ Baseline N/A
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}$
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}$
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}$

By running locally:

  1. $4\times$ to $10\times$ faster response times than any cloud-routed API over satellite.
  2. $100\%$ availability guarantee—the system operates seamlessly even if the rig's satellite dish is iced over or misaligned during severe weather.
  3. Zero cloud transmission costs for raw 1-second drilling channels. Only verified summary events and compressed snapshots are synced back to the real-time operations center (RTOC) when the link restores.

5. Summary & Ecosystem Integration

The witsml-edge-agent and ai-gateway-sentinel work alongside our 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.

Top comments (0)