Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions THIRD-PARTY-NOTICES
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ Image: vllm/vllm-openai
License: Apache-2.0 and included component licenses
URL: https://github.com/vllm-project/vllm

Image: node:22-bookworm-slim
License: MIT and included Debian component licenses
URL: https://hub.docker.com/_/node

Image: ollama/ollama
License: MIT and included component licenses
URL: https://github.com/ollama/ollama

================================================================================
Docker Compose Images
================================================================================
Expand Down Expand Up @@ -215,6 +223,46 @@ Project: NVIDIA/OpenShell installer and runtime
License: Apache-2.0
URL: https://github.com/NVIDIA/OpenShell

Project: NVIDIA/NemoClaw source and sandbox base image
License: Apache-2.0 and included component licenses
URL: https://github.com/NVIDIA/NemoClaw

Project: Kubernetes SIG Agent Sandbox controller and API
License: Apache-2.0
URL: https://github.com/kubernetes-sigs/agent-sandbox

Project: Kubernetes and kubectl
License: Apache-2.0
URL: https://github.com/kubernetes/kubernetes

Project: Helm
License: Apache-2.0
URL: https://github.com/helm/helm

Project: Canonical MicroK8s distribution
License: See the project and included component notices
URL: https://github.com/canonical/microk8s

Project: NVIDIA GPU Operator
License: Apache-2.0
URL: https://github.com/NVIDIA/gpu-operator

Project: NVIDIA DCGM Exporter
License: Apache-2.0
URL: https://github.com/NVIDIA/dcgm-exporter

Project: Kubernetes Metrics Server
License: Apache-2.0
URL: https://github.com/kubernetes-sigs/metrics-server

Project: Prometheus Community Helm Charts (kube-prometheus-stack and prometheus-adapter)
License: Apache-2.0 and included component licenses
URL: https://github.com/prometheus-community/helm-charts

Project: Kubernetes ingress-nginx
License: Apache-2.0
URL: https://github.com/kubernetes/ingress-nginx

Project: Astral uv installer and package manager
License: Apache-2.0 OR MIT
URL: https://github.com/astral-sh/uv
Expand All @@ -239,6 +287,10 @@ Model: NVIDIA-Nemotron-3-Ultra-550B-A55B-NVFP4
License: NVIDIA Open Model License
URL: https://huggingface.co/nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-NVFP4

Model: Llama 3.2 3B
License: Llama 3.2 Community License Agreement and Acceptable Use Policy
URL: https://ollama.com/library/llama3.2

Service: GitHub API
Terms: See provider terms
URL: https://docs.github.com/
Expand Down
1 change: 1 addition & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ again by contributor provenance.
| Example | Description |
| --- | --- |
| [Developer Community Chief of Staff](recipes/nvidia/developer-community-chief-of-staff/README.md) | Synthesizes Slack, Outlook, GitHub, and mirrored community signals into operating briefs, gaps, priorities, and follow-up recommendations. |
| [Kubernetes GPU Autoscaling](recipes/nvidia/kubernetes-gpu-autoscaling/README.md) | Runs a CPU-only NemoClaw/OpenClaw sandbox through OpenShell on Kubernetes and autoscales authenticated, GPU-backed Ollama inference pods from DCGM utilization. |
| [NV Tech Assistant](recipes/nvidia/nv-tech-assistant/README.md) | Answers NVIDIA technical questions with cited evidence from allowlisted NVIDIA, GitHub, and arXiv sources. |
| [Payment Operations Hermes Assistant](recipes/nvidia/payment-ops-hermes/README.md) | Demonstrates constrained payment screening, evidence preparation, and a platform-enforced human release boundary. |
| [PR Review Advisor](recipes/nvidia/pr-review-advisor/README.md) | Reviews exact pull request heads with a constrained Hermes workflow, produces attested artifacts, and publishes only through a separate maintainer action. |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.DS_Store
*.swp
*.bak
*.tmp
.git/
14 changes: 14 additions & 0 deletions examples/recipes/nvidia/kubernetes-gpu-autoscaling/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
apiVersion: v2
name: nemoclaw-gpu
description: GPU-backed Ollama inference pods on Kubernetes with GPU utilization HPA
type: application
version: 0.1.0
appVersion: "2026.05.27"
keywords:
- nemoclaw
- ollama
- gpu
maintainers:
- name: maggiezha
1,264 changes: 1,264 additions & 0 deletions examples/recipes/nvidia/kubernetes-gpu-autoscaling/README.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
//
// Shared Prometheus helpers for agent /metrics (LLM latency, HTTP counters).

const configuredLlmLatencyWindow = Number(process.env.LLM_LATENCY_WINDOW_SIZE ?? "128");
const LLM_LATENCY_WINDOW =
Number.isSafeInteger(configuredLlmLatencyWindow) && configuredLlmLatencyWindow > 0
? Math.min(configuredLlmLatencyWindow, 10_000)
: 128;
const llmDurationsMs = [];
let llmDurationSumSec = 0;
let llmDurationCount = 0;
let llmRequestsOk = 0;
let llmRequestsError = 0;
const llmHistogramBucketsSec = [0.25, 0.5, 1, 2.5, 5, 10, 30, 60, 120, 300];
const llmHistogramCounts = Array.from({ length: llmHistogramBucketsSec.length + 1 }, () => 0);

export function recordLlmLatency(durationMs, ok) {
// Normalize once so the rolling window (p50/p95/avg) and the cumulative
// counters/histogram below always agree on the same finite, non-negative value.
const normalizedMs = Number.isFinite(durationMs) ? Math.max(0, durationMs) : 0;
const sec = normalizedMs / 1000;
llmDurationSumSec += sec;
llmDurationCount += 1;
if (ok) llmRequestsOk += 1;
else llmRequestsError += 1;

llmDurationsMs.push(normalizedMs);
if (llmDurationsMs.length > LLM_LATENCY_WINDOW) llmDurationsMs.shift();

let bucketIdx = llmHistogramBucketsSec.findIndex((bound) => sec <= bound);
if (bucketIdx === -1) bucketIdx = llmHistogramBucketsSec.length;
for (let i = bucketIdx; i < llmHistogramCounts.length; i += 1) {
llmHistogramCounts[i] += 1;
}
}

function percentileMs(sorted, p) {
if (!sorted.length) return 0;
const idx = Math.ceil(sorted.length * p) - 1;
return sorted[Math.max(0, idx)];
}

function llmLatencySnapshotMs() {
if (!llmDurationsMs.length) {
return { p50: 0, p95: 0, avg: 0 };
}
const sorted = [...llmDurationsMs].sort((a, b) => a - b);
const sum = sorted.reduce((acc, v) => acc + v, 0);
return {
p50: percentileMs(sorted, 0.5),
p95: percentileMs(sorted, 0.95),
avg: sum / sorted.length,
};
}

export function llmMetricsLines() {
const { p50, p95, avg } = llmLatencySnapshotMs();
const lines = [
"# HELP nemoclaw_llm_requests_total Chat/completions proxied to inference backend",
"# TYPE nemoclaw_llm_requests_total counter",
`nemoclaw_llm_requests_total{result="success"} ${llmRequestsOk}`,
`nemoclaw_llm_requests_total{result="error"} ${llmRequestsError}`,
"# HELP nemoclaw_llm_request_duration_seconds LLM chat/completions end-to-end proxy latency",
"# TYPE nemoclaw_llm_request_duration_seconds histogram",
];

for (let i = 0; i < llmHistogramBucketsSec.length; i += 1) {
lines.push(
`nemoclaw_llm_request_duration_seconds_bucket{le="${llmHistogramBucketsSec[i]}"} ${llmHistogramCounts[i]}`,
);
}
lines.push(
`nemoclaw_llm_request_duration_seconds_bucket{le="+Inf"} ${llmHistogramCounts[llmHistogramCounts.length - 1]}`,
`nemoclaw_llm_request_duration_seconds_sum ${llmDurationSumSec}`,
`nemoclaw_llm_request_duration_seconds_count ${llmDurationCount}`,
"# HELP nemoclaw_llm_latency_p50_milliseconds Rolling p50 LLM latency (recent window)",
"# TYPE nemoclaw_llm_latency_p50_milliseconds gauge",
`nemoclaw_llm_latency_p50_milliseconds ${Math.round(p50)}`,
"# HELP nemoclaw_llm_latency_p95_milliseconds Rolling p95 LLM latency (recent window)",
"# TYPE nemoclaw_llm_latency_p95_milliseconds gauge",
`nemoclaw_llm_latency_p95_milliseconds ${Math.round(p95)}`,
"# HELP nemoclaw_llm_latency_avg_milliseconds Rolling average LLM latency (recent window)",
"# TYPE nemoclaw_llm_latency_avg_milliseconds gauge",
`nemoclaw_llm_latency_avg_milliseconds ${Math.round(avg)}`,
);
return lines;
}
Loading
Loading