diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 0fec3dc..c71cfaf 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,6 +1,6 @@ ## Summary @@ -27,6 +27,6 @@ Make sure your commits are signed off (`git commit -s`) as described in CONTRIBU ## Checklist - [ ] My commits are signed off (`git commit -s`) -- [ ] I have read [CONTRIBUTING.MD](../CONTRIBUTING.MD) and agree to the [CLA](../CLA.MD) +- [ ] I have read [CONTRIBUTING.md](../CONTRIBUTING.md) - [ ] I have updated documentation where relevant - [ ] I have verified the affected sample runs end-to-end, or explained why that was not possible diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 0000000..f83c9bf --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,30 @@ +name: Pre-commit + +on: + pull_request: + +permissions: + contents: read + +concurrency: + group: pre-commit-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + checks: + name: Run hooks + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.13" + + - name: Install pre-commit + run: python -m pip install pre-commit==4.6.0 + + - name: Run hooks + run: pre-commit run --all-files diff --git a/.markdownlint.yaml b/.markdownlint.yaml new file mode 100644 index 0000000..27e2274 --- /dev/null +++ b/.markdownlint.yaml @@ -0,0 +1,4 @@ +default: true +MD013: false +MD024: + siblings_only: true diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..d24d282 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,23 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: trailing-whitespace + args: [--markdown-linebreak-ext=md] + - id: end-of-file-fixer + - id: mixed-line-ending + args: [--fix=lf] + - id: check-merge-conflict + - id: check-yaml + + - repo: https://github.com/DavidAnson/markdownlint-cli2 + rev: v0.22.1 + hooks: + - id: markdownlint-cli2 + exclude: ^\.github/PULL_REQUEST_TEMPLATE\.md$ + + - repo: https://github.com/tcort/markdown-link-check + rev: v3.11.2 + hooks: + - id: markdown-link-check + args: [-q, --config, ci/markdown-link-check-config.json] diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..e843c35 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,42 @@ +# Repository Agent Guidance + +## Repository Organization + +This repository contains independent samples organized by use case. Read the +nearest README and relevant manifests before changing a sample. + +Place every new sample under the appropriate existing top-level use-case +directory. Do not add samples at the repository root or create overlapping +category structures. Update the root README sample listing when adding or +moving a sample. + +## Working Practices + +- Keep documentation, commands, manifests, and referenced files synchronized. +- Reuse patterns within the affected sample. Avoid cross-sample abstractions + unless several samples have the same demonstrated need. +- Preserve existing user changes and avoid unrelated formatting churn. +- Never commit secrets, credentials, local environment files, or generated + artifacts. +- Do not deploy, modify, or delete cloud resources without explicit + authorization. + +## License Headers + +Preserve existing SPDX headers. For new source, infrastructure, or +configuration files, follow the nearest comparable files. When those files use +SPDX and the format supports comments, use the matching comment syntax with: + +```text +SPDX-FileCopyrightText: Copyright (c) NVIDIA CORPORATION & AFFILIATES. All rights reserved. +SPDX-License-Identifier: Apache-2.0 +``` + +Do not add comment headers to JSON or other formats that prohibit comments. Do +not modify restored or unrelated files solely to add headers. + +## Validation + +Run `pre-commit run --all-files` and the sample-specific checks documented by +the nearest README or manifest. Report skipped or unavailable checks honestly; +do not present dependency-based skips as successful coverage. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bf3625b..be42062 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,6 +13,24 @@ Developer workflow for code contributions is as follows: workflows change. 4. Open a merge request or pull request and complete the checklist. +## Local Checks + +Install and enable the repository's pre-commit hooks: + +```bash +python3 -m pip install pre-commit==4.6.0 +pre-commit install +``` + +Run every check against the full repository: + +```bash +pre-commit run --all-files +``` + +After installation, `git commit` checks staged files. GitHub Actions reruns all +hooks when a pull request is opened or updated. + ## Signing Your Work We require that all contributors sign off on their commits. This certifies that diff --git a/README.md b/README.md index 5282aa1..5fa6a3c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # NVIDIA GPU Accelerated Application Samples on Microsoft Azure -**Table Of Contents** +## Table of Contents + - [Description](#description) - [Support Level](#support-level) - [Requirements](#requirements) @@ -30,7 +31,7 @@ to get help. ## Requirements -- An active [Microsoft Azure](https://azure.microsoft.com/) account with +- An active [Microsoft Azure](https://azure.microsoft.com/en-us) account with permissions to create the resources used by a given sample - Access to NVIDIA GPU-enabled Azure VM sizes in your target Azure region (for example, A10, A100, H100, or H200 GPU families) @@ -42,10 +43,12 @@ to get help. ## Quickstart 1. Clone this repository: + ```bash git clone https://github.com/NVIDIA/nvidia-azure-samples cd nvidia-azure-samples ``` + 2. Browse the [Samples](#samples) section below and pick the one that matches your use case. 3. Follow the README inside that sample's directory for setup and run @@ -89,6 +92,7 @@ or pull request and agreeing to the terms in [CONTRIBUTING.md](CONTRIBUTING.md). ## Support For questions or issues: + - Open an issue in this project for bug reports or feature requests - Refer to each sample's README for sample-specific guidance diff --git a/SECURITY.md b/SECURITY.md index f645e75..61f00b8 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,4 +1,4 @@ -## Security +# Security NVIDIA is dedicated to the security and trust of our software products and services, including source code repositories managed through our organization. @@ -14,7 +14,7 @@ appropriate private disclosure channels. To report a potential security vulnerability in any NVIDIA product: - Web: [Security Vulnerability Submission Form](https://www.nvidia.com/object/submit-security-vulnerability.html) -- E-Mail: psirt@nvidia.com +- E-Mail: - NVIDIA encourages secure email using the [NVIDIA public PGP key](https://www.nvidia.com/en-us/security/pgp-key) - Include the product or project name, affected branch/version, vulnerability type, reproduction steps, proof of concept if available, and potential impact diff --git a/agentic/aca-samples/aiq-aca-ai-search-foundry/README.md b/agentic/aca-samples/aiq-aca-ai-search-foundry/README.md index 924272b..cb53b8e 100644 --- a/agentic/aca-samples/aiq-aca-ai-search-foundry/README.md +++ b/agentic/aca-samples/aiq-aca-ai-search-foundry/README.md @@ -13,7 +13,7 @@ The adapter ([`aiq-azure-ai-search`](aiq-azure-ai-search/)) self-registers via A Three model endpoints feed the agent: | Role | Model | Hosting | -|------|-------|---------| +| --- | --- | --- | | Chat / intent / summary | `Nemotron-3-Nano` | NIM on an Azure ML managed online endpoint (A100) | | Embeddings (2048-dim) | `Llama-3.2-NV-embedqa-1b-v2` | NIM on an Azure ML managed online endpoint (A100) | | Orchestrator / planner | `gpt-oss-120b` | Azure AI Services GlobalStandard (per-token, serverless) | @@ -28,7 +28,7 @@ Two Azure Container Apps run the workload: an **internal-only agent** (the AI-Q - An **Azure subscription** where you can create resource groups and assign roles - **GPU quota:** 48 vCPUs of `Standard NCADSA100v4` family in your chosen region (two `Standard_NC24ads_A100_v4` endpoints, 1×A100 each) - **`gpt-oss-120b` availability** in your chosen region as a GlobalStandard (serverless) deployment, plus one-time Marketplace terms acceptance on first use in a subscription -- A **Tavily API key** for the web-search tool — free tier at [tavily.com](https://app.tavily.com/sign-in) gives 1,000 searches/month +- A **Tavily API key** for the web-search tool — free tier at [tavily.com](https://app.tavily.com/) gives 1,000 searches/month - `git` to clone this repository - A **bash shell** — all commands below use bash syntax (`export`, `$(...)`, `\` line continuations). @@ -349,7 +349,7 @@ az group delete --name "$RG" --yes --no-wait Go deeper on the pieces you just built: -- [NVIDIA Azure Samples](https://github.com/NVIDIA/nvidia-azure-samples) — this sample lives here, with the `aiq-azure-ai-search` adapter source, `Dockerfile`, `config_web_azure.yml`, and `main.bicep`. +- [NVIDIA Azure Samples](../../..) — this sample lives here, with the `aiq-azure-ai-search` adapter source, `Dockerfile`, `config_web_azure.yml`, and `main.bicep`. - [Adding a Data Source — NVIDIA AI-Q Blueprint](https://docs.nvidia.com/aiq-blueprint/2.1.0/extending/adding-a-data-source.html) — the pattern behind the custom Knowledge Layer adapter (`aiq_azure_ai_search`). - [Add a Specialized Deep Research Skill to Agent Harnesses](https://developer.nvidia.com/blog/add-a-specialized-deep-research-skill-to-agent-harnesses/) — a next step: expose an AI-Q server like this one as a reusable "skill" that agent harnesses (Claude Code, Codex, LangChain) can call to delegate research. - [NVIDIA AI-Q Blueprint documentation](https://docs.nvidia.com/aiq-blueprint/2.1.0/) — full docs for the blueprint this workshop is based on. diff --git a/agentic/aca-samples/aiq-aca-ai-search-foundry/aiq-azure-ai-search/README.md b/agentic/aca-samples/aiq-aca-ai-search-foundry/aiq-azure-ai-search/README.md index c221d03..376d3de 100644 --- a/agentic/aca-samples/aiq-aca-ai-search-foundry/aiq-azure-ai-search/README.md +++ b/agentic/aca-samples/aiq-aca-ai-search-foundry/aiq-azure-ai-search/README.md @@ -1,6 +1,6 @@ # aiq-azure-ai-search -Azure AI Search Knowledge Layer adapter for [NVIDIA AI-Q](https://docs.nvidia.com/aiq-blueprint/). +Azure AI Search Knowledge Layer adapter for [NVIDIA AI-Q](https://docs.nvidia.com/aiq-blueprint/latest/). Routes AI-Q's document ingestion and retrieval through **Azure AI Search**, with embeddings from any OpenAI-compatible embedding endpoint (NVIDIA NIM, Azure OpenAI, or build.nvidia.com). AI-Q's source stays untouched — the package self-registers via the `nat.plugins` entry-point group declared in `pyproject.toml`. @@ -31,7 +31,7 @@ End-to-end working against AI-Q v2 (`nvcr.io/nvidia/blueprint/aiq-agent:2.0.0`). ### Compatibility | Component | Tested against | -|---|---| +| --- | --- | | AI-Q | `nvcr.io/nvidia/blueprint/aiq-agent:2.0.0` | | Azure AI Search | Basic SKU with free semantic ranker; vectors with HNSW (cosine) | | Embedding model | `llama-3.2-nv-embedqa-1b-v2` (2048-dim) on a NIM endpoint; any OpenAI-compatible `/v1/embeddings` URL should work | diff --git a/agentic/aks-samples/vss-on-aks/README.md b/agentic/aks-samples/vss-on-aks/README.md index dac61af..88d42d3 100644 --- a/agentic/aks-samples/vss-on-aks/README.md +++ b/agentic/aks-samples/vss-on-aks/README.md @@ -274,7 +274,7 @@ helm upgrade --install "$RELEASE" ./dev-profile-lvs \ ``` > **StorageClass:** `managed-csi-premium` (Premium SSD) is recommended — NIM model caches are ~120 GiB each and benefit from premium throughput on first model load. Run `kubectl get sc` to list available classes; substitute another if your cluster uses one. - +> > **Re-installs with surviving model cache:** the chart sets `helm.sh/resource-policy: keep` on its `NIMCache` resources, so `helm uninstall` does NOT remove the 120 GiB model PVCs. If you re-install on a cluster that still has them, add `--take-ownership` to the `helm upgrade --install` command above so Helm adopts the existing `NIMCache`/PVC/ConfigMap objects instead of erroring on name collision. This saves 15–30 min of NGC re-download. ### 3. Wait for pods to come up @@ -317,7 +317,7 @@ kubectl -n "$NAMESPACE" get pods | grep lvs-server The kept routes: | Hostname | Path | Backend | -|----------|------|---------| +| --- | --- | --- | | `vss..nip.io` | `/` | vss-ui | | `vss..nip.io` | `/api`, `/chat`, `/websocket`, `/static`, `/api/chat` | vss-agent (HTTP + WS) | | `vss..nip.io` | `/vst` | vst-ingress-dev | @@ -345,7 +345,7 @@ kubectl get ingress -n "$NAMESPACE" The ingress should show the nginx LB IP under `ADDRESS` (may take 10–20s for nginx-ingress to publish the status): -``` +```text NAME CLASS HOSTS ADDRESS PORTS AGE vss-lvs-vss-ingress nginx vss..nip.io,kibana.vss..nip.io 80 30s ``` @@ -357,7 +357,7 @@ vss-lvs-vss-ingress nginx vss..nip.io,kibana.vss..nip.io All URLs resolve to the same Azure public IP (`$EXTERNAL_HOST`) via `nip.io`: | Service | URL | -|---------|-----| +| --- | --- | | VSS UI | `http://vss.${EXTERNAL_HOST}.nip.io/` | | VSS Agent HTTP API | `http://vss.${EXTERNAL_HOST}.nip.io/api/v1` | | VSS Agent WebSocket | `ws://vss.${EXTERNAL_HOST}.nip.io/websocket` | diff --git a/agentic/aks-samples/vss-on-aks/aks/ingress/vss-ingress.yaml b/agentic/aks-samples/vss-on-aks/aks/ingress/vss-ingress.yaml new file mode 100644 index 0000000..bb8b30c --- /dev/null +++ b/agentic/aks-samples/vss-on-aks/aks/ingress/vss-ingress.yaml @@ -0,0 +1,84 @@ +# Nginx-class Ingress for VSS LVS on AKS. +# Edit the placeholders below (or substitute with `sed`) before applying. +# +# This deviates from the vss repo's vss-ingress-example.yaml in two ways: +# - ingressClassName: nginx (vs. haproxy) — AKS pattern uses ingress-nginx + LoadBalancer Service. +# - Annotations are nginx-flavored (proxy-body-size, timeouts) — needed for large video uploads +# and long-lived streaming/WebSocket connections. +# +# Paths only cover services that the LVS profile actually deploys. + +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: -vss-ingress + namespace: + annotations: + nginx.ingress.kubernetes.io/proxy-body-size: 2g + nginx.ingress.kubernetes.io/proxy-read-timeout: "3600" + nginx.ingress.kubernetes.io/proxy-send-timeout: "3600" +spec: + ingressClassName: nginx + rules: + - host: vss..nip.io + http: + paths: + - backend: + service: + name: -vss-ui + port: + number: 3000 + path: /api/chat + pathType: Prefix + - backend: + service: + name: -vss-agent + port: + number: 8000 + path: /api + pathType: Prefix + - backend: + service: + name: -vss-agent + port: + number: 8000 + path: /chat + pathType: Prefix + - backend: + service: + name: -vss-agent + port: + number: 8000 + path: /websocket + pathType: Prefix + - backend: + service: + name: -vss-agent + port: + number: 8000 + path: /static + pathType: Prefix + - backend: + service: + name: -vst-ingress-dev + port: + number: 30888 + path: /vst + pathType: Prefix + - backend: + service: + name: -vss-ui + port: + number: 3000 + path: / + pathType: Prefix + - host: kibana.vss..nip.io + http: + paths: + - backend: + service: + name: -kibana + port: + number: 5601 + path: / + pathType: Prefix diff --git a/ci/markdown-link-check-config.json b/ci/markdown-link-check-config.json new file mode 100644 index 0000000..8ab3256 --- /dev/null +++ b/ci/markdown-link-check-config.json @@ -0,0 +1,6 @@ +{ + "timeout": "20s", + "retryOn429": true, + "retryCount": 3, + "fallbackRetryDelay": "30s" +} diff --git a/data-processing/.gitkeep b/data-processing/.gitkeep index 8b13789..e69de29 100644 --- a/data-processing/.gitkeep +++ b/data-processing/.gitkeep @@ -1 +0,0 @@ - diff --git a/industry-solutions/.gitkeep b/industry-solutions/.gitkeep index 8b13789..e69de29 100644 --- a/industry-solutions/.gitkeep +++ b/industry-solutions/.gitkeep @@ -1 +0,0 @@ - diff --git a/inference/.gitkeep b/inference/.gitkeep index 8b13789..e69de29 100644 --- a/inference/.gitkeep +++ b/inference/.gitkeep @@ -1 +0,0 @@ - diff --git a/physical-ai/.gitkeep b/physical-ai/.gitkeep index 8b13789..e69de29 100644 --- a/physical-ai/.gitkeep +++ b/physical-ai/.gitkeep @@ -1 +0,0 @@ - diff --git a/training/.gitkeep b/training/.gitkeep index 8b13789..e69de29 100644 --- a/training/.gitkeep +++ b/training/.gitkeep @@ -1 +0,0 @@ -