Skip to content

Repository files navigation

HSE-AI Insight Platform

CI NestJS Next.js TypeScript PostgreSQL RabbitMQ OpenSearch Ollama Docker GitHub Actions

HSE-AI Insight Platform is a full-stack Oil & Gas safety analytics application that converts free-text HSE incident reports into structured data and actionable insights. The platform uses a local open-source LLM served by Ollama to extract entities, classify events, infer severity, and feed a dark-themed operational dashboard for proactive risk management.

Technologies

Core stack

  • Frontend: Next.js, React, TypeScript, CSS Modules, Recharts
  • Backend API: NestJS, Node.js, TypeScript
  • Worker: Node.js, TypeScript
  • Data layer: PostgreSQL
  • Messaging: RabbitMQ
  • Search and analytics: OpenSearch
  • AI runtime: Ollama with qwen2:7b
  • Containers and local orchestration: Docker, Docker Compose
  • CI: GitHub Actions

Development Methodology

This project follows Specification-Driven Development (SDD).

What SDD means here

Every feature begins with a formal specification, not with code. Specifications are the single source of truth for contracts between services, and they live in the specs/ directory alongside the implementation.

specs/
├── api/
│   └── openapi.yaml          ← REST API contract (OpenAPI 3.0)
├── messaging/
│   └── asyncapi.yaml         ← RabbitMQ message contract (AsyncAPI 2.6)
└── ai/
    └── extraction-schema.json ← AI extraction output schema (JSON Schema draft-07)

SDD workflow

1. Write or update the spec  →  specs/api/openapi.yaml (or messaging, ai)
2. Implement to satisfy it   →  src/ code, DTOs, services
3. Write spec-driven tests   →  test/*.spec.ts — assertions reference the spec
4. CI validates everything   →  build + test jobs on every push

Key contracts

Contract File Validates
REST API specs/api/openapi.yaml All request/response shapes
RabbitMQ messages specs/messaging/asyncapi.yaml Queue payload schema
AI extraction output specs/ai/extraction-schema.json LLM/fallback JSON output

Interactive API docs

When the backend is running, the live OpenAPI docs are available at:

http://localhost:3001/api/docs

The Swagger UI is generated directly from the NestJS decorators and stays in sync with the specs/api/openapi.yaml contract.

Adding a new feature

  1. Update or add the relevant spec file under specs/.
  2. Implement the feature so it satisfies the spec.
  3. Add tests in apps/backend/test/ that assert the response shape matches the spec.
  4. Run npm test from apps/backend to verify.

Continuous Integration

This repository includes a GitHub Actions workflow at .github/workflows/ci.yml.

The pipeline:

  • installs dependencies for backend, worker, and frontend
  • runs the build step for each app
  • runs spec-driven tests for the backend
  • validates the docker-compose.yml file syntax

Product walkthrough

The README uses a static high-resolution preview because GitHub renders PNG images much more sharply than large animated GIFs. This keeps the product walkthrough clear, readable, and professional.

HSE-AI Insight Platform Overview

What the walkthrough shows:

  1. A user pastes a free-text HSE incident report.
  2. The frontend submits the report to the NestJS API.
  3. The API queues the job in RabbitMQ for asynchronous processing.
  4. The worker uses Ollama + Qwen2 to extract entities and classify severity.
  5. The dashboard refreshes with KPIs, tags, and recent incident records.

A static preview is used here intentionally to avoid blurred frames, oversized captions, and poor readability inside the GitHub README.

Why this project exists

HSE data in Oil & Gas environments is often captured as unstructured text. Valuable signals about unsafe conditions, recurring root causes, and injury patterns stay buried in narrative reports. This project turns those narratives into searchable, analyzable, and operationally useful data.

Core capabilities

  • Submit free-text incident reports from the UI.
  • Process reports asynchronously through RabbitMQ.
  • Use Ollama + Qwen2 for structured AI extraction.
  • Persist original and normalized incident data in PostgreSQL.
  • Index reports in OpenSearch for text search and analytics.
  • Display KPIs, trends, recent incidents, and extracted tags in a modern dashboard.
  • Run the full development stack locally with Docker Compose.

Architecture

Next.js SPA
   |
   v
NestJS API ---> RabbitMQ ---> Worker ---> Ollama (Qwen2)
   |                               |            |
   |                               v            |
   +--------------------------> PostgreSQL <----+
                                   |
                                   v
                              OpenSearch

Monorepo structure

hse-ai-insight-platform/
├── .github/
│   └── workflows/
│       └── ci.yml
├── apps/
│   ├── backend/
│   │   └── test/               ← spec-driven tests
│   ├── frontend/
│   └── worker/
├── docs/
│   └── demo/
├── infrastructure/
│   └── postgres/
├── specs/
│   ├── api/
│   │   └── openapi.yaml        ← REST API contract
│   ├── messaging/
│   │   └── asyncapi.yaml       ← RabbitMQ message contract
│   └── ai/
│       └── extraction-schema.json ← AI extraction output schema
├── docker-compose.yml
├── .env.example
├── Makefile
└── README.md

User workflow

  1. An operator pastes a free-text HSE report into the left control panel.
  2. The frontend sends the payload to the NestJS ingestion endpoint.
  3. The API stores the report with status QUEUED and publishes a message to RabbitMQ.
  4. The worker consumes the message and calls Ollama with a structured extraction prompt.
  5. The worker updates PostgreSQL with classification, severity, tags, summary, and entities.
  6. The worker indexes the enriched document into OpenSearch.
  7. The dashboard refreshes and shows updated KPIs, recent incidents, trends, and extracted tags.

Quick start

1. Copy environment variables

cp .env.example .env

2. Start the stack

docker compose up --build -d

3. Pull the LLM model inside Ollama

docker compose exec ollama ollama pull qwen2:7b

4. Open the apps

  • Frontend: http://localhost:3000
  • Backend API: http://localhost:3001
  • API docs (Swagger UI): http://localhost:3001/api/docs
  • RabbitMQ Management: http://localhost:15672
  • OpenSearch: http://localhost:9200
  • OpenSearch Dashboards: http://localhost:5601
  • Ollama API: http://localhost:11434

Default RabbitMQ credentials:

  • Username: guest
  • Password: guest

Demo mode and fallback behavior

For local demos, AI_FALLBACK_ENABLED=true is enabled by default. If Ollama is running but the model is not yet available, or if the LLM response is invalid, the worker falls back to a deterministic rules-based extractor so the platform still behaves end-to-end.

To force only LLM-based processing, set:

AI_FALLBACK_ENABLED=false

API endpoints

Full contract: specs/api/openapi.yaml

Submit a report

POST /api/reports
Content-Type: application/json

{
  "reportText": "Worker observed gas detector alarm near compressor station C2 after valve inspection. No injury, area isolated, likely loose fitting."
}

Fetch dashboard summary

GET /api/dashboard/summary

Fetch trends

GET /api/dashboard/trends?days=14

Fetch recent incidents

GET /api/reports/recent?limit=10

Fetch one incident

GET /api/reports/:id

Sample AI schema

Defined in specs/ai/extraction-schema.json. The worker asks the model to produce JSON with fields similar to these:

{
  "classification": "Near Miss",
  "severity": "Medium",
  "equipment": "Mud pump skid",
  "location": "Well pad A17",
  "injuryType": "Minor wrist pain",
  "probableRootCause": "Poor housekeeping / slippery surface",
  "summary": "Short operational summary",
  "tags": ["slip", "maintenance", "housekeeping"]
}

Running tests

cd apps/backend
npm install
npm test

Tests in apps/backend/test/ are spec-driven: each test file references the spec it validates and asserts that responses conform to the shapes defined in specs/api/openapi.yaml.

Frontend design notes

The UI is implemented as a dark-mode single-page dashboard with two main areas:

  • Left panel: free-text input, analyze button, latest extracted tags.
  • Right panel: KPI cards, line chart for incident trend, severity distribution, and recent incident table.

Local development without Docker

Each app can also run independently:

cd apps/backend && npm install && npm run start:dev
cd apps/worker && npm install && npm run dev
cd apps/frontend && npm install && npm run dev

You still need PostgreSQL, RabbitMQ, OpenSearch, and Ollama available locally.

Suggested next steps

  • Add authentication and role-based access control.
  • Add report attachments and image support.
  • Add vector search for semantically similar incidents.
  • Add WebSocket or Server-Sent Events for real-time UI updates.
  • Add Prometheus and Grafana for observability.
  • Add incident recommendation workflows and corrective action tracking.
  • Add contract testing with Pact to validate the RabbitMQ AsyncAPI contract at runtime.
  • Add OpenAPI response validation middleware to enforce the spec at the HTTP boundary.

Notes on compatibility

This project uses a stack aligned with the current official documentation for NestJS, Next.js App Router, OpenSearch local Docker deployments, and the Ollama local generation API with qwen2:7b.

License

MIT

About

AI-powered full-stack platform for Oil & Gas HSE incident analysis, turning unstructured safety reports into searchable data, risk insights, and interactive dashboards using NestJS, Next.js, PostgreSQL, RabbitMQ, OpenSearch, and Ollama.

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages