Skip to main content

Gym-compatible wrapper for the NornOS Hosted Research API (research.laif2.com).

Project description

nornos-gym

Gym-compatible wrapper for the NornOS Hosted Research API. Pure Python + gymnasium + numpy + requests. No NornOS-internal knowledge required to use.

Status

v0.2.0 — Hosted API + Bearer-Token-Auth + 429-Retry. Skill outputs not yet integrated into reward (fallback uses feature-deviation-from-mean, see PRD-NORNOS-CORE-001 §5.4).

Quickstart (Hosted API — researcher path)

pip install nornos-gym

Request an API key from the operator (see docs/onboarding.md), then:

from nornos_gym import NornOSEnv

env = NornOSEnv(
    base_url="https://research.laif2.com",
    api_key="nornos-research-<your-uuid>",
)
obs, info = env.reset()
for _ in range(100):
    action = env.action_space.sample()
    obs, reward, terminated, truncated, info = env.step(action)
    print(f"reward={reward:.3f} audit={info['auditHash'][:8]}")
env.close()

The client automatically retries with exponential backoff (max 5 attempts) when the server returns 429 Too Many Requests, respects Retry-After headers, and applies ±25% jitter to spread retries.

Error handling

from nornos_gym import NornOSEnv, NornOSAuthError, RateLimitError

try:
    env = NornOSEnv(base_url="https://research.laif2.com", api_key="...")
    obs, info = env.reset()
except NornOSAuthError as e:
    print(f"Token issue: {e}")  # 401 missing, 403 invalid/revoked
except RateLimitError as e:
    print(f"Rate limit persistent after retries: {e}")

Local stack (development)

# 1. Clone repo, then:
docker compose -f docker-compose.research.yml up -d

# 2. Install editable:
pip install -e research/python/

# 3. Run without api_key (local stack has no auth):
python -c "
from nornos_gym import NornOSEnv
env = NornOSEnv(base_url='http://localhost:4400')
obs, info = env.reset()
print(f'entities: {len(info[\"auditHashes\"])}')
env.close()
"

Public API

  • NornOSEnv(base_url, seed_id, entity_filter) — Gym 0.26+ environment
  • NornOSMultiAgentEnv(base_url, seed_id, agent_entity_map) — MARL via ThreadPoolExecutor
  • NornOSAdapter — base class for domain-specific feature extraction + reward shaping

Adapter Quickstart

To plug a domain into NornOS, subclass NornOSAdapter:

from nornos_gym import NornOSAdapter

class CircularEconomyAdapter(NornOSAdapter):
    def __init__(self):
        super().__init__(feature_keys=["material_weight", "recyclability_score", "co2_footprint"])

    def compute_reward(self, skill_outputs):
        f = skill_outputs.get("features", skill_outputs)
        return (1 - float(f.get("recyclability_score", 0.0))) * \
               float(f.get("co2_footprint", 0.0))

5-Step recipe:

  1. Define your domain features as a fixed feature_keys list
  2. Write a custom seed JSON under research/<your-domain>/<name>_seed.json with entityId / entityType / features per entity
  3. Add a COPY line to docker/compose/Dockerfile.event-log-service-research that maps your seed into /app/research/seeds/<your-seed-id>.json
  4. Subclass NornOSAdapter, override compute_reward (and optionally extract_features) with your domain logic
  5. Use the adapter in your training loop alongside NornOSEnv — see research/adapter-example/run_episode.py

Full spec, anti-patterns, testing template: research/docs/adapter-interface.md.

Run the circular-economy example

docker compose -f docker-compose.research.yml up -d
python research/adapter-example/run_episode.py --seed-id circular-economy-default --steps 100

Output: server-reward (deviation fallback) and adapter-reward (domain logic) side by side, plus top-3 most-problematic products by mean adapter score.

Building a custom adapter

Adapters are pure Python — no NornOS internals, no library touch. Three hard rules from adapter-interface.md §4:

  • Bound your rewards. PPO/DQN assume a stable range; clip to [0, 1] or [-1, 1].
  • Stay stateless. Don't hold per-step state on self; the adapter is reused across episodes.
  • Public API only. from nornos_gym import NornOSAdapter is the only NornOS import allowed. No apps/maritime, no services/event-log-service, no internal modules.

Disclaimer

Research-only distribution. Not for clinical, safety-critical, or production use. The Compose stack ships with hardcoded -insecure tokens that must never appear in production deployments.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nornos_gym-0.2.0.tar.gz (16.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nornos_gym-0.2.0-py3-none-any.whl (12.7 kB view details)

Uploaded Python 3

File details

Details for the file nornos_gym-0.2.0.tar.gz.

File metadata

  • Download URL: nornos_gym-0.2.0.tar.gz
  • Upload date:
  • Size: 16.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.6

File hashes

Hashes for nornos_gym-0.2.0.tar.gz
Algorithm Hash digest
SHA256 2bea7654379aa53c21842d48af33ec705036bcc34d574c9fd6d349a6e551659a
MD5 022405a51fca13a83cbceca6e638bfcc
BLAKE2b-256 fa56c4088b119c43c8c44096f43ce16f9edb662d24e982a8df635c5a56105306

See more details on using hashes here.

File details

Details for the file nornos_gym-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: nornos_gym-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 12.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.6

File hashes

Hashes for nornos_gym-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 024252eb3c73e7c5cbd16b4bd0ab36784cee7133cd19a577a19e8a5d5fbc53a6
MD5 eac6fe2c562087abd7584111e098883e
BLAKE2b-256 e84025560099ae1f0c17f69f3d06c15ecf8a4126ec007df744b357eb093b63c0

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page