Skip to content

About

General simulation is a neo4j backed simulation framework.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

General Simulation & Impact-Reasoning Platform (MVP)

A domain-agnostic simulation and impact-reasoning platform built on:

Concern Technology
Inference & embeddings Llama Stack (OpenAI-compatible /v1); modes: OpenAI upstream or in-cluster vLLM
Vector / RAG pgvector (queried directly via asyncpg)
Dependency graph Neo4j (native async driver, Cypher queries)
Live / geo snapshot PostGIS, queried directly
API FastAPI
Admin API JSON endpoints at /admin/* (automation / scripts)
Dependency management uv

Core design rule: Live ground-truth data is never mutated by a simulation. Simulations are overlays applied at query time.


Table of contents


What this platform does

This system answers impact and response questions about a live operational environment when a disruptive event is layered on top of it. In plain terms: it takes a real-time picture of what is happening, overlays a hypothetical or unfolding disruption, and reasons over the combination to answer questions like “how does this event affect the current situation?” and “how should things be rerouted or rescheduled in response?”

The design is deliberately domain-agnostic. The original framing is a supply-chain scenario — a port closure or volcanic ash disrupting flights — but the same machinery applies unchanged to a manufacturing plant, where the disruption is a machine breakdown or material shortage. The core abstraction is the same in both: live data + a dependency graph + a simulation-event overlay + staged reasoning.

The whole platform is built to run on OpenShift, which is a hard constraint that shapes every technology choice below.

The one-sentence model: A simulation event is an overlay; the LLM agent investigates it by calling graph-traversal, solver, vector-search, and ingestion tools in whatever order the question demands — then explains the result grounded in the numbers those tools returned.


System at a glance

The platform is a small number of cooperating layers running inside one OpenShift cluster. The diagram below shows how they stack: an API and an orchestrator at the top, the three reasoning stages beneath, the LLM client as the inference/vector backend, and separate Neo4j and Postgres instances for graph and geo/vector state. Two things are worth noticing immediately — the reasoning stages are colour-coded by whether they use the LLM, and both the graph (Neo4j) and geo (PostGIS) paths bypass the LLM client to be queried directly.

Layered system overview

Figure 1 — Layered system overview. Everything runs inside OpenShift. The LLM client fronts inference and vector/RAG; graph (Neo4j) and live/geo (PostGIS) are queried directly.

The remaining sections walk through each component: what it is, why it is there, and how it relates to its neighbours.


The components and how they relate

OpenShift — the platform

OpenShift is the deployment substrate and a fixed requirement, not an interchangeable choice. Every other component is selected partly because it runs cleanly on OpenShift: Postgres via an operator, vLLM via OpenShift AI / KServe, and the application services as ordinary Deployments and CronJobs. Treating OpenShift as the constant is what lets the rest of the stack stay portable across domains.

Llama Stack — inference gateway

On OpenShift, the API and ingestion CronJob always call Llama Stack (http://llamastack:8321/v1). Stack fronts three modes:

Mode Upstream When to use
maas (default) LiteMaaS (external-model/llama-scout-17b) Workshop / shared MaaS endpoint
openai OpenAI API No GPU / quickest path
local In-cluster llm-service (vLLM on OpenShift AI) Keep weights inside the cluster

LLM client — the inference and RAG backend

The app talks to any OpenAI-compatible inference endpoint through lib/llm/openai_client.py. Cluster defaults point at Stack; local-dev can still point at OpenAI or a laptop vLLM:

Provider LLM_BASE_URL LLM_BACKEND
Llama Stack (OpenShift default) http://llamastack:8321/v1 openai
OpenAI (local dev) https://api.openai.com/v1 openai
vLLM (local laptop) http://localhost:8080/v1 openai
Llama Stack SDK http://llamastack:8321 llamastack
Tests / no GPU (any) fake

Vector/RAG operations (embed, ingest, search) go directly to pgvector via asyncpg — no intermediate server required. A single llm_embeddings table in Postgres stores all collections.

Design rule: Application code goes through LLMClientBase (lib/llm/) for anything involving the model, embeddings, or vector search — never calling any inference API or pgvector SQL directly. The sole exceptions are graph (Neo4j) and live/geo (PostGIS), which are queried directly.

Neo4j — the property graph

Neo4j holds the dependency graph and simulation-event overlays. It is queried directly via the official async Python driver using native Cypher. Entities and their dependency edges live here; SimulationEvent nodes are injected as overlays and can be removed without touching any other data. Neo4j runs as a StatefulSet in the cluster, deployed via the official neo4j/neo4j Helm chart.

PostgreSQL — two jobs, two extensions

Postgres carries the remaining two persistence concerns. The dependency graph has moved to Neo4j, so the custom Postgres image only needs pgvector + PostGIS — no AGE extension required.

Extension Role Accessed via
pgvector Embeddings and RAG. Stores simulation-event narratives, playbooks, and precedent for retrieval. Directly via asyncpg
PostGIS The live “current situation” snapshot — entity positions, states, geospatial data — written by ingestion. Directly via asyncpg

Ingestion — getting live data in

Ingestion adapters live under domain/<name>/adapters/. Each pulls from one external source and normalises into a single canonical schema (id, type, optional geometry, timestamp, status, and a free-form attributes field). The shared runner in lib/ingestion/ upserts into PostGIS only — ground truth, never the simulation overlay. Which domain packages load is controlled by ENABLED_DOMAINS; which adapter a CronJob runs is --adapter / Helm adapterId. Details: ADD_DOMAIN.md. Cursor paste-prompts: docs/prompts/add-domain/README.md.

Each adapter runs two ways: as a scheduled OpenShift CronJob for steady polling, and as an on-demand callable that the reasoning agent can trigger mid-query when it needs current data.

Admin JSON API

REST endpoints under /admin support automation: ingestion runs, graph browsing, scenario injection, and imports. Use seed-demo and POST /query for post-deploy smoke tests (see Demo against a live deployment).

Route Description
GET /admin/stats Aggregate counts from Postgres and Neo4j
GET /admin/entity-types Distinct entity types in the live store
GET /admin/entities Paginated entity list with search/filter
GET /admin/entities/geojson GeoJSON FeatureCollection for entities with geometry
GET /admin/entities/{id} Entity detail and state history
GET /admin/entities/in-bbox Entity IDs inside a WGS84 bounding box
GET /admin/data/sync-status Postgres vs Neo4j entity drift
GET /admin/ingestion/adapters List enabled ingestion adapters
POST /admin/ingestion/run On-demand adapter run
GET /admin/platform/config Read-only platform settings
POST /admin/platform/bootstrap Idempotent schema bootstrap
GET /admin/imports/formats Supported import formats and edge types
POST /admin/imports/preview Validate an import file
POST /admin/imports/commit Commit entities + dependency edges
GET /admin/graph/nodes Entity nodes from Neo4j
GET /admin/graph/scenarios Distinct scenario IDs
GET /admin/graph/events SimulationEvent nodes (optional scenario filter)
GET /admin/graph/edges All dependency / AFFECTED_BY edges
POST /admin/graph/events Inject a new simulation event overlay
POST /admin/graph/scenarios/{id}/sync-spatial Refresh AFFECTED_BY edges from PostGIS bbox
POST /admin/graph/dependency-edges Create or merge a dependency edge
DELETE /admin/graph/dependency-edges Remove a dependency edge
DELETE /admin/graph/scenarios/{id} Remove a scenario from the graph and vector store

A web UI is not shipped in the current release; a separate UI will be added in a future release (exact form TBD).

The ReAct agent pipeline

The pipeline (lib/reasoning/pipeline.py) is a ReAct (Reason + Act) agent loop: the LLM is the top-level orchestrator. It decides which tools to call, in what order, and when it has gathered enough information to answer. A safety cap of six rounds prevents unbounded loops.

The LLM has four tools:

Tool Module What it does
get_affected_subgraph lib/graph/tool.py Neo4j Cypher traversal — finds every entity reachable from the simulation event via dependency edges, plus entity attributes (callsign, route, etc.)
solve_impact lib/reasoning/pipeline.py Runs the Stage-2 solver on the affected subgraph — returns impact score, chain length, value at risk, ranked response options, and recommended reroutes
search_scenario_context lib/reasoning/search_tool.py pgvector semantic search over the scenario's event-narrative collection
run_ingestion_pull lib/ingestion/tool.py On-demand live data refresh from a registered adapter

The agent typically calls tools in the order above, but nothing enforces that sequence: a question about current positions may start with run_ingestion_pull; a simple clarification may skip the solver entirely. The tool_call_trace field in every POST /query response exposes each call the agent made and what it returned, making the reasoning fully auditable.

The three underlying data-access functions (Neo4j traversal, PostGIS + solver, pgvector search) are kept as independent modules (stage1.py, stage2.py, stage3.py). Each is independently testable and can be called directly — they are the tools' implementation, not the orchestration logic.


How a query flows through the system

A POST /query request kicks off the ReAct agent loop. The diagram below captures the most common investigation path; the actual sequence depends on what the LLM decides to call.

The query lifecycle

Figure 2 — The ReAct query lifecycle. The LLM decides which tools to call; every tool invocation and its result appear in the tool_call_trace field of the response.

Typical agent sequence for an impact question:

POST /query  { question, scenario_id }
        │
        │  Round 1 — LLM calls get_affected_subgraph(scenario_id)
        ├────── Neo4j traversal → entity IDs + dependency edges + attributes
        │
        │  Round 2 — LLM calls solve_impact(scenario_id)
        ├────── PostGIS live state read + StubSolver → impact score + response options
        │
        │  Round 3 (optional) — LLM calls search_scenario_context(query, scenario_id)
        ├────── pgvector search → event narrative chunks
        │
        └────── LLM produces final answer grounded in tool outputs
                ↓
        QueryResponse { answer, affected_entities, solver, tool_call_trace }

The tool_call_trace in the response is the audit trail — it shows what the agent investigated and what each data source returned before the LLM wrote its answer.


How the simulation actually works

The most important architectural decision is that a simulation never mutates live data. A simulation event is an overlay applied at query time: it is a node injected into the graph, connected by AFFECTED_BY edges to the entities it perturbs, with its narrative embedded separately in the vector store. The live snapshot is read through the lens of that event, but is left untouched.

This is what makes multiple concurrent what-if scenarios trivial — each is an independent overlay tagged by its own scenario id — and what makes them fully reversible: removing the event node resets everything in a single operation.

The overlay mechanism

Figure 3 — The overlay mechanism. Ground truth (left) is read-only at query time. The event and its affected-entity references (right) are injected and removable, leaving the base graph intact.

What kind of simulation this is (and isn’t): This is a dependency-and-impact reasoning engine: it propagates effects through a known graph and applies solver logic on top. It is not a tick-by-tick discrete-event physics simulation (e.g. AnyLogic). That is an intentional trade: you gain explainability, speed, and concurrent what-if scenarios; you give up stochastic second-by-second temporal dynamics. Because the Stage 2 solver is pluggable, a full discrete-event engine can be dropped into that slot later without changing anything else.


Why the same design serves multiple domains

The platform is best understood as a domain-agnostic skeleton with well-defined swap points. The skeleton — OpenShift, vLLM (optional), Postgres, Neo4j, the ReAct pipeline, and the overlay mechanism — stays identical. Domain-specific code lives under top-level domain/<name>/ packages (adapters, optional solvers). Which packages load is controlled by ENABLED_DOMAINS (see ADD_DOMAIN.md; Cursor: docs/prompts/add-domain/README.md).

Fixed core vs. swap seams

Figure 4 — The fixed core (left) versus the per-domain swap seams (right). Domain adaptation touches only the right-hand column.

The reason this works is that impact propagation is graph traversal in every domain. A port closure cascading through dependent routes and a stopped machine cascading through dependent cells are the same Cypher traversal over a different schema. The table below makes the mapping concrete.

Layer Supply chain Manufacturing plant
Ingestion Flight / AIS / freight APIs (domain/…/adapters) OPC-UA, MQTT, SCADA, historian
Graph schema Port, Route, Region ISA-95: Site → Area → Work Cell → Equipment
Simulation event Port closure, volcanic ash Machine breakdown, material shortage
Solver (Stage 2) Route pathfinding (domain/…/solver.py) Production rescheduling / line balancing
RAG context Logistics precedent SOPs, maintenance manuals, playbooks

A manufacturing note worth flagging: plant sensor data is far higher-frequency than logistics data, so that domain leans harder on the historian/time-series side and may add a time-series extension or a downsampling step in ingestion. That is an ingestion-layer concern — it does not disturb the core.

Shipped today:

Domain id Package Adapters
aviation domain/aviation/ opensky_flights (live OpenSky)
shipping domain/shipping/ shipping_demo (synthetic fixture; swap fetch for a live API)

Disruptions (port closures, airspace shutdowns, etc.) are simulation event overlays, not separate domains — see scripts/seed_demo.py (aviation) and scripts/seed_shipping.py (LA port strike).

ENABLED_DOMAINS=aviation,shipping   # default
uv run ingest-run --adapter opensky_flights
uv run ingest-run --adapter shipping_demo
uv run python scripts/seed_shipping.py   # ingest + graph + LA closure scenario

Key decisions and risks to watch

  1. Two separate graph stores (Neo4j for the dependency graph, Postgres for live data and embeddings) keep concerns cleanly separated; validate Neo4j connectivity and the Helm chart deployment early.
  2. The vLLM model must support structured tool calling, with tool-calling enabled at serve time (--enable-auto-tool-choice) — the ReAct pipeline depends on the model correctly emitting tool calls and text completions.
  3. The agent loop owns orchestration; the data-access modules stay pure. stage1.py, stage2.py, and stage3.py contain no agent logic — they are called by the pipeline dispatcher and remain independently testable.
  4. Graph stays in Neo4j, geo stays in Postgres. The LLM client owns inference, embeddings, and vector search only — it is not a front door for all state.
  5. Live data and simulation knowledge stay separate. The overlay must never mutate ground truth; this is what enables concurrent, reversible what-if scenarios.
  6. The tool_call_trace is the reasoning audit trail. Every QueryResponse includes the ordered list of tool calls the agent made — use this to debug or explain any answer.

In short: a fixed OpenShift-native skeleton handles platform, inference, storage, and agentic reasoning identically across domains, while domain packages under domain/ — adapters, optional solvers, and related wiring — are all that change to retarget it from supply chains to manufacturing plants. See ADD_DOMAIN.md.


Repository layout

domain/                      # Domain packages (adapters, optional solvers)
  aviation/
    adapters/                # e.g. opensky_flights
  shipping/
    adapters/                # e.g. shipping_demo (synthetic → live API)
    bootstrap_graph.py       # Neo4j edges + scenario overlay
lib/
  core/                      # Domain-agnostic abstractions, interfaces, and Settings
  ingestion/
    registry.py              # ENABLED_DOMAINS catalog + adapter/solver resolution
    runner.py                # Canonical ingest loop
    tool.py                  # run_ingestion_pull tool schema + callable
  graph/
    bootstrap.py             # Idempotent DDL for Postgres + Neo4j
    nodes.py                 # Entity CRUD + dependency edge helpers
    events.py                # SimulationEvent overlay inject / remove
    cypher.py                # neo4j_session() context manager
    tool.py                  # get_affected_subgraph tool schema + callable
  reasoning/
    pipeline.py              # ReAct agent loop — top-level orchestrator
    stage1.py                # Neo4j graph traversal (called by pipeline dispatcher)
    stage2.py                # PostGIS live state read + solver (called by pipeline dispatcher)
    stage3.py                # Standalone synthesis helper (vector search + single generate())
    search_tool.py           # search_scenario_context tool schema + callable
    types.py                 # QueryRequest / QueryResponse / ToolCallRecord
  solver/
    stub.py                  # StubSolver (fallback; domain solvers live under domain/)
    tool.py                  # solve_impact tool schema + legacy callable
  llm/
    base.py                  # LLMClientBase protocol
    openai_client.py         # OpenAI-compatible inference + pgvector RAG
    fake.py                  # FakeLLMClient for tests (supports response_sequence)
    types.py                 # Message / ToolCall / GenerateResult / Chunk
apps/
  api/                       # FastAPI entrypoint + JSON admin API (/admin/*)
deploy/                      # Containerfiles, Helm chart, local dev compose
  local/
    composefile.yml          # Postgres + Neo4j for local development
  container_files/
    api/                     # FastAPI app Containerfile
    postgres/                # Custom Postgres image (pgvector + PostGIS)
  helm/                      # Umbrella Helm chart (authoritative deploy path)
    templates/
      api/                   # API Deployment, Service, Route
      bootstrap/             # Schema bootstrap Job
      ingestion/             # CronJob + hook Job
      neo4j/                 # neo4j-auth Secret, SA, SCC binding
      postgres/              # Postgres StatefulSet + Services
tests/

Quickstart (local dev)

1. Install dependencies

uv sync --all-extras

2. Configure environment

cp .env.example .env
# Defaults match compose (Postgres on 5433 — not 5432, to avoid Postgres.app clashes):
#   POSTGRES_DSN=postgresql://sim:sim@localhost:5433/sim
#   NEO4J_URI=bolt://localhost:7687
#   NEO4J_USER=neo4j
#   NEO4J_PASSWORD=simsimsim
#   ENABLED_DOMAINS=aviation,shipping

3. Start local services (Postgres + Neo4j)

make local-up
# or: podman compose -f deploy/local/composefile.yml up -d --wait

This starts Postgres (pgvector + PostGIS) on port 5433 and Neo4j on ports 7474 (Browser UI) and 7687 (Bolt). --wait blocks until healthchecks pass.

4. Bootstrap schema

make local-bootstrap
# or: uv run python -m lib.graph.bootstrap

5. Run the API

uv run python -m apps.api.main
# or:
uv run uvicorn apps.api.app:app --reload

Visit http://localhost:8000/health — returns {"status": "ok", "db": "reachable"} when Postgres is reachable.

6. Run tests (no GPU or live Llama Stack required)

make test-unit
# or: uv run pytest

6. Demo against a live deployment

CLI helpers for smoke-testing a running cluster (UK airspace closure scenario):

# Seed demo entities + UK closure overlay, then POST /query
make smoke-test
# or with in-cluster seeding after deploy:
SEED_MODE=cluster NAMESPACE=general-simulation make smoke-test

# Seed only (local or in-cluster)
uv run seed-demo

# Query only against a running API (defaults to UK airspace closure)
./scripts/smoke-uk-closure.sh   # set SEED_MODE=skip to skip seeding

# Shipping LA-closure demo (fixture ingest + graph + overlay)
uv run python scripts/seed_shipping.py

seed-demo / scripts/seed_demo.py create sample aircraft, dependency edges, and the opensky-uk-closure-001 simulation event so the full pipeline can be exercised end to end.


Running without hardware (CI / dev laptops)

Set LLM_BACKEND=fake in .env (or the environment). This swaps in FakeLLMClient which returns canned completions, embeddings, and vector search hits, so the full reasoning pipeline can be exercised in tests without a GPU or a running Llama Stack server.


LLM backend configuration

The app uses any OpenAI-compatible inference endpoint. The backend is selected by the LLM_BACKEND environment variable.

Pointing at a self-hosted vLLM for local dev

  1. Start vLLM locally with tool-calling enabled:
export HF_TOKEN=<your-hf-token>   # Llama-derived weights are gated
vllm serve RedHatAI/Meta-Llama-3.1-8B-Instruct-FP8 \
    --enable-auto-tool-choice \
    --tool-call-parser llama3_json \
    --max-model-len 8192
  1. Set in .env:
LLM_BASE_URL=http://localhost:8080/v1
OPENAI_API_KEY=unused
LLM_BACKEND=openai
GENERATION_MODEL_ID=RedHatAI/Meta-Llama-3.1-8B-Instruct-FP8
EMBEDDING_MODEL_ID=all-MiniLM-L6-v2
EMBEDDING_DIMENSION=384

Pointing at Llama Stack

OpenShift umbrella deploys set this automatically. For local overrides:

LLM_BASE_URL=http://llamastack:8321/v1
OPENAI_API_KEY=unused
LLM_BACKEND=openai
GENERATION_MODEL_ID=openai/gpt-4o-mini   # or llama-3-2-3b-instruct/meta-llama/Llama-3.2-3B-Instruct

OpenShift Deployment

Deployment is driven by a Makefile that wraps podman build/push for images and Helm for all Kubernetes resources. Each component has its own Helm chart under deploy/helm/ so components can be upgraded independently.

Prerequisites

Requirement Notes
OpenShift 4.13+ Tested against OCP 4.14/4.15
oc CLI logged in oc login ... — needs cluster-admin (or a role covering Deployments, StatefulSets, Services, Routes, Jobs, CronJobs, Secrets, ConfigMaps, ServiceAccounts, and ClusterRoleBindings)
helm 3.x Install Helm
podman To build and push images
GPU nodes Required only when enabling llm-service on GPU
NVIDIA GPU Operator Required for GPU llm-service device profile
Red Hat OpenShift AI Required for in-cluster llm-service (KServe ServingRuntime / InferenceService)

Core platform components (Postgres, Neo4j, API, ingestion) need no extra operators. Postgres runs as a plain StatefulSet. In-cluster vLLM uses the shared llm-service chart on OpenShift AI.


Quick start — full deploy

# 1. Log in to quay.io so podman can push images
podman login quay.io

# 2. Configure secrets (required before deploy)
cp deploy/helm/values-secrets.yaml.example deploy/helm/values-secrets.yaml
# edit deploy/helm/values-secrets.yaml — passwords, API tokens, hf_token

# 3. Build and push container images
make build

# 4. One umbrella release (Postgres + Neo4j + Llama Stack + API + ingestion)
make deploy

Default toggles in deploy/helm/values.yaml: ingestion.enabled: false (CronJob off until you turn it on), llm-service.enabled: true (requires GPU + OpenShift AI unless you disable it).

make deploy installs the umbrella chart as a single Helm release, creates templates/neo4j/ resources (neo4j-sa, anyuid SCC, Secret neo4j-auth when openshift.neo4j.scc.enabled), and wires Llama Stack to enabled global.models providers.


Helm chart overview

Chart Path Key resources
general-simulation deploy/helm/ Inline templates: postgres/, neo4j/, bootstrap/, api/, ingestion/
neo4j external dep Official Neo4j StatefulSet (reads Secret neo4j-auth)
llama-stack external dep Inference gateway (llamastack:8321)
llm-service external dep In-cluster vLLM; enable via llm-service.enabled

Step 1 — Build and push container images

# Default: push to quay.io/rh-ai-quickstart/
make build

# Local testing — your Quay org (match APP_IMAGE_NAME to your repo names):
make build REGISTRY=quay.io/robertsandoval APP_IMAGE_NAME=general-sim-api

# Or build individual images:
make build-postgres
make build-app

Override the registry or tag if needed:

make build REGISTRY=quay.io/myorg TAG=v1.2.3

Step 2 — Deploy (recommended)

Use the single umbrella release — Postgres, Neo4j, bootstrap, Llama Stack, API, and ingestion are all in deploy/helm/:

make deploy

Secrets must be in deploy/helm/values-secrets.yaml (see deploy/helm/values-secrets.yaml.example).

Component toggles live in deploy/helm/values.yaml under postgres.enabled, api.enabled, etc.


Neo4j Browser access

Neo4j is deployed by the umbrella chart (neo4j.enabled in deploy/helm/values.yaml). OpenShift wiring (neo4j-sa, SCC, neo4j-auth) is rendered from deploy/helm/templates/neo4j/ when openshift.neo4j.scc.enabled is true.

For local Browser + Bolt access (Bolt cannot be proxied through a Route):

make neo4j-connect

In-cluster vLLM

Set llm-service.enabled: true in deploy/helm/values.yaml and enable the in-cluster model under global.models. Llama Stack points at the InferenceService (<model-key>-vllm). Set llm-service.secret.hf_token in deploy/helm/values-secrets.yaml.

Requires Red Hat OpenShift AI (KServe). First start downloads model weights and can take several minutes. Do not point the API at vLLM directly — Stack is the only client of that Service.


Per-component upgrades

After changing code, rebuild and redeploy the umbrella chart:

make build-app
make deploy

To change config, edit deploy/helm/values.yaml and/or deploy/helm/values-secrets.yaml, then run make deploy.


Tear-down

make undeploy
# PVCs are NOT deleted automatically — remove manually if needed:
# oc delete pvc -n general-simulation --all

Makefile reference

make help
make build
make deploy
make neo4j-connect
make status
make lint-charts
make undeploy
Variable Default Description
REGISTRY quay.io/rh-ai-quickstart Image registry root
APP_IMAGE_NAME general-sim-api App image name under REGISTRY
NAMESPACE general-simulation Target OpenShift namespace
TAG latest Image tag
DEPLOY_TIMEOUT 25m Helm --wait timeout

In-cluster service names

Short names resolve inside the release namespace (standalone or when this chart is a subchart). Cross-namespace clients should use <service>.<namespace>.svc.

Service Same namespace Cross-namespace example
Postgres postgres:5432 postgres.general-simulation.svc:5432
Neo4j Bolt bolt://neo4j:7687 bolt://neo4j.general-simulation.svc:7687
Neo4j HTTP http://neo4j:7474 http://neo4j.general-simulation.svc:7474
Llama Stack http://llamastack:8321 http://llamastack.<ns>.svc:8321
vLLM (llm-service) http://<model-key>-vllm http://<model-key>-vllm.<ns>.svc
API http://general-sim-api:8000 http://general-sim-api.general-simulation.svc:8000

The umbrella chart under deploy/helm/ is the primary install path (make deploy). See deploy/helm/README.md.


Pre-Helm Kubernetes manifests are preserved under deploy/archived/openshift/ for reference. The Helm chart under deploy/helm/ is the authoritative deployment path.

About

General simulation is a neo4j backed simulation framework.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages