From 97f048ac2529f3d02e759f1b19d21e4e2049398e Mon Sep 17 00:00:00 2001 From: Kiss Date: Wed, 13 May 2026 13:02:48 +0200 Subject: [PATCH 1/7] Add markdown button and make llms.txt available --- docs/conf.py | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/docs/conf.py b/docs/conf.py index 85997cc8..e06ff152 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -5,6 +5,8 @@ author = "Shrey Ajmera, Akhila Yeruva" import os +from pathlib import Path +import shutil html_baseurl = os.environ.get("READTHEDOCS_CANONICAL_URL", "instinct.docs.amd.com") html_context = {} if os.environ.get("READTHEDOCS", "") == "True": @@ -20,6 +22,7 @@ html_theme_options = { "flavor": "instinct", "link_main_doc": True, + "use_download_button": True, # Add any additional theme options here } extensions = [ @@ -41,3 +44,54 @@ tags_intro_text = "" tags_page_title = "Tag page" tags_page_header = "Pages with this tag" + +EXCLUDED_DIRS = { + "_build", + "_templates", + "_static", + ".git", + ".venv", +} + +def should_skip(path: Path) -> bool: + return any(part in EXCLUDED_DIRS for part in path.parts) + + +def generate_combined_markdown(app, exception): + if exception: + return + + docs_root = Path(app.srcdir) + output_file = Path(app.outdir) / "llms.txt" + + print(output_file) + + all_files = sorted(docs_root.rglob("*.md")) + + combined = [] + combined.append("# Combined Documentation\n") + + for doc_file in all_files: + if should_skip(doc_file): + continue + + relative = doc_file.relative_to(docs_root) + + combined.append(f"\n---\n") + combined.append(f"\n# {relative}\n") + + try: + content = doc_file.read_text(encoding="utf-8") + combined.append(content) + combined.append("\n") + + except Exception as e: + combined.append(f"\n[ERROR reading file: {e}]\n") + + output_file.write_text( + "\n".join(combined), + encoding="utf-8", + ) + +def setup(app): + app.connect("build-finished", generate_combined_markdown) From 2b1fa59f7a476e23f7a6259c82cae94340023589 Mon Sep 17 00:00:00 2001 From: Kiss Date: Tue, 19 May 2026 09:47:52 +0200 Subject: [PATCH 2/7] Add base llms.txt, treshold and exclude MyST directives --- docs/conf.py | 92 +++++++++++++++++++++++++++++++++++++++++++-------- docs/llms.txt | 53 +++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+), 13 deletions(-) create mode 100644 docs/llms.txt diff --git a/docs/conf.py b/docs/conf.py index e06ff152..e3f30eee 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -45,6 +45,8 @@ tags_page_title = "Tag page" tags_page_header = "Pages with this tag" +import re + EXCLUDED_DIRS = { "_build", "_templates", @@ -53,43 +55,107 @@ ".venv", } +MARKUP_PREFIXES = ( + ":::", + "```{", + "```", + ":img-top:", + ":class", + ":link:", + ":link-type:", + ":shadow:", + ":columns:", + ":padding:", + ":gutter:", + ":open:", + ":name:", + ":header-rows:", + ":alt:", + "+++", + "<", + "-->", + "{bdg-", +) + +# Matches lines like "align: center", "alt:", "name: foo" (directive options +# not starting with a colon, common in MyST figure/table fences) +_BARE_DIRECTIVE_RE = re.compile(r"^[a-z][a-z_-]*:\s*\S*$") + +# Matches MyST/RST anchor labels like "(some-label)=" +_ANCHOR_LABEL_RE = re.compile(r"^\(\w[\w-]*\)=$") + +MIN_PROSE_LINES = 10 + + def should_skip(path: Path) -> bool: return any(part in EXCLUDED_DIRS for part in path.parts) +def is_prose_line(line: str) -> bool: + stripped = line.strip() + if not stripped: + return False + if stripped.startswith(MARKUP_PREFIXES): + return False + # Drop bare directive-option lines (e.g. "align: center", "alt:") + if _BARE_DIRECTIVE_RE.match(stripped): + return False + # Drop MyST/RST anchor labels (e.g. "(some-label)=") + if _ANCHOR_LABEL_RE.match(stripped): + return False + # Drop lines that contain an HTML tag anywhere (e.g. ".

") + if re.search(r" Deploy and manage AMD AINICs in Kubernetes environments. The AMD Network Operator manages all networking components required to enable RDMA workloads within a Kubernetes cluster, including NIC driver management, device plugin configuration, secondary network CNI plugins, and metrics collection. + +## Overview + +- [Network Operator overview](https://instinct.docs.amd.com/projects/network-operator/en/main/overview.html): Components of the AMD Network Operator and their roles in managing AMD NICs in Kubernetes clusters. +- [Release notes](https://instinct.docs.amd.com/projects/network-operator/en/main/releasenotes.html): Release history and changelog for the AMD Network Operator. + +## Installation + +- [Install with Helm](https://instinct.docs.amd.com/projects/network-operator/en/main/installation/kubernetes-helm.html): Install the AMD Network Operator on a Kubernetes cluster using Helm. +- [Install with GPU Operator and Network Operator together](https://instinct.docs.amd.com/projects/network-operator/en/main/installation/kubernetes-helm-operators.html): Install AMD GPU Operator and AMD Network Operator together in the same Kubernetes cluster. +- [Custom Resource guide](https://instinct.docs.amd.com/projects/network-operator/en/main/installation/networkconfig.html): Configure the NetworkConfig Custom Resource, including driver management, device plugin, and secondary network settings. +- [NetworkConfig full reference](https://instinct.docs.amd.com/projects/network-operator/en/main/installation/networkconfig-full.html): Comprehensive list of NetworkConfig CR configuration options. +- [Deploy a workload with a network device](https://instinct.docs.amd.com/projects/network-operator/en/main/installation/workload.html): Create a NetworkAttachmentDefinition and deploy a workload with an assigned network device. + +## Driver management + +- [Driver management](https://instinct.docs.amd.com/projects/network-operator/en/main/drivers/drivers.html): Manage AMD AI NIC drivers using the AMD Network Operator on Kubernetes clusters. +- [Driver upgrades](https://instinct.docs.amd.com/projects/network-operator/en/main/drivers/upgrading.html): Upgrade AMD Network drivers on worker nodes. + +## Device plugin + +- [Device Plugin and Node Labeller](https://instinct.docs.amd.com/projects/network-operator/en/main/device_plugin/deviceplugin.html): Configure the Device Plugin and Node Labeller via the NetworkConfig Custom Resource. +- [Resource health monitoring](https://instinct.docs.amd.com/projects/network-operator/en/main/device_plugin/resource-health.html): Real-time monitoring and reporting of network device health status integrated with Kubernetes pod scheduling. + +## Secondary networks + +- [Kubernetes integration flow](https://instinct.docs.amd.com/projects/network-operator/en/main/secondary_network/integration-flow.html): How pod network attachment annotations trigger CNI plugins through the Kubernetes networking stack. +- [AMD Host Device CNI plugin](https://instinct.docs.amd.com/projects/network-operator/en/main/secondary_network/amd-host-device-cni.html): Move PF or VF network interfaces from host into pod network namespaces with IP address preservation. +- [Alternative CNI plugins](https://instinct.docs.amd.com/projects/network-operator/en/main/secondary_network/other-cnis.html): Alternative CNI plugins tested with AMD Network Operator via NetworkAttachmentDefinition. + +## Metrics + +- [Metrics Exporter](https://instinct.docs.amd.com/projects/network-operator/en/main/metrics/exporter.html): Configure the Metrics Exporter via the NetworkConfig Custom Resource. +- [Prometheus integration](https://instinct.docs.amd.com/projects/network-operator/en/main/metrics/prometheus.html): Integrate the AMD Network Operator with Prometheus using ServiceMonitor for automatic metrics scraping. +- [Grafana dashboard](https://instinct.docs.amd.com/projects/network-operator/en/main/metrics/grafana_dashboard.html): AINIC System Grafana dashboard for visualizing network metrics. +- [Health checks](https://instinct.docs.amd.com/projects/network-operator/en/main/metrics/health.html): Health monitoring via the metrics exporter gRPC socket for Kubernetes device availability decisions. +- [Kube-RBAC-Proxy](https://instinct.docs.amd.com/projects/network-operator/en/main/metrics/kube-rbac-proxy.html): Secure the metrics endpoint with RBAC or static authorization using the kube-rbac-proxy sidecar. + +## Upgrades + +- [Upgrade](https://instinct.docs.amd.com/projects/network-operator/en/main/upgrades/upgrade.html): Verify cluster readiness and upgrade the AMD Network Operator. +- [Component upgrades](https://instinct.docs.amd.com/projects/network-operator/en/main/upgrades/componentupgrades.html): Upgrade Device Plugin, Node Labeller, Metrics Exporter, and CNI Plugin daemonsets. + +## Operations + +- [Troubleshooting](https://instinct.docs.amd.com/projects/network-operator/en/main/troubleshooting.html): Diagnose and resolve common issues with the AMD Network Operator. +- [Uninstall](https://instinct.docs.amd.com/projects/network-operator/en/main/uninstallation/uninstallation.html): Remove the operator and related resources in the correct sequence. +- [Cluster Validation and Job Scheduling Framework](https://instinct.docs.amd.com/projects/network-operator/en/main/cluster_validation_framework/README.html): Periodically verify worker node health and readiness before scheduling distributed AI and HPC workloads. + +--- From 5d46fa04005a9214c20000cac43904c8618c1a6f Mon Sep 17 00:00:00 2001 From: Kiss Date: Thu, 21 May 2026 12:29:30 +0200 Subject: [PATCH 3/7] Add llms-full.txt and keep the llms.txt as base --- docs/conf.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index e3f30eee..9464e28e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -84,6 +84,9 @@ # Matches MyST/RST anchor labels like "(some-label)=" _ANCHOR_LABEL_RE = re.compile(r"^\(\w[\w-]*\)=$") +# Matches RST section underlines (e.g. "====", "----", "~~~~") +_RST_UNDERLINE_RE = re.compile(r"^[=\-~^\"\'#*+]{3,}$") + MIN_PROSE_LINES = 10 @@ -106,6 +109,15 @@ def is_prose_line(line: str) -> bool: # Drop lines that contain an HTML tag anywhere (e.g. ".

") if re.search(r" Date: Fri, 29 May 2026 12:00:01 +0200 Subject: [PATCH 4/7] Update the filter function of llms-full.txt generation --- docs/conf.py | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 9464e28e..0c5d70d1 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -87,6 +87,9 @@ # Matches RST section underlines (e.g. "====", "----", "~~~~") _RST_UNDERLINE_RE = re.compile(r"^[=\-~^\"\'#*+]{3,}$") +# Matches RST code block directives (e.g. ".. code-block:: cpp", ".. code:: sh") +_RST_CODE_BLOCK_RE = re.compile(r"^\.\.\s+(code-block|code|sourcecode)::") + MIN_PROSE_LINES = 10 @@ -106,14 +109,13 @@ def is_prose_line(line: str) -> bool: # Drop MyST/RST anchor labels (e.g. "(some-label)=") if _ANCHOR_LABEL_RE.match(stripped): return False - # Drop lines that contain an HTML tag anywhere (e.g. ".

") - if re.search(r"` describes..."). + if re.match(r"^:[A-Za-z][A-Za-z0-9_-]*:(\s|$)", stripped): return False # Drop RST section underlines (e.g. "====", "----", "~~~~") if _RST_UNDERLINE_RE.match(stripped): @@ -160,10 +162,32 @@ def generate_combined_markdown(app, exception): continue relative = doc_file.relative_to(docs_root) - cleaned = "\n".join( - line for line in lines - if line.strip() == "" or is_prose_line(line) - ) + in_backtick_fence = False + in_rst_code_block = False + kept = [] + for line in lines: + stripped = line.strip() + # Backtick fences (MyST/Markdown) + if stripped.startswith("```"): + in_backtick_fence = not in_backtick_fence + kept.append(line) + continue + if in_backtick_fence: + kept.append(line) + continue + # RST code block: exit when a non-blank, non-indented line appears + if in_rst_code_block: + if not stripped or line[0] in (" ", "\t"): + kept.append(line) + continue + in_rst_code_block = False + # RST code block: enter on directive line (directive itself is dropped) + if _RST_CODE_BLOCK_RE.match(stripped): + in_rst_code_block = True + continue + if not stripped or is_prose_line(line): + kept.append(line) + cleaned = "\n".join(kept) combined.append(f"\n\n---\n\n# {relative}\n") combined.append(cleaned.strip()) From 3621c25a9fe3dd260894dafdf9e0250b443924b9 Mon Sep 17 00:00:00 2001 From: Kiss Date: Fri, 29 May 2026 13:07:09 +0200 Subject: [PATCH 5/7] sync llms filter fixes from rocm-docs-core --- docs/conf.py | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 0c5d70d1..f7450bd4 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -72,7 +72,6 @@ ":header-rows:", ":alt:", "+++", - "<", "-->", "{bdg-", ) @@ -90,6 +89,17 @@ # Matches RST code block directives (e.g. ".. code-block:: cpp", ".. code:: sh") _RST_CODE_BLOCK_RE = re.compile(r"^\.\.\s+(code-block|code|sourcecode)::") +# Matches markdown table separator rows (e.g. "|---|---|", "| :--- | ---: |"). +_MD_TABLE_SEP_RE = re.compile(r"^\|[\s|:\-]+\|$") + +# Matches RST directives whose indented body should be discarded (e.g. raw HTML). +_RST_SKIP_BLOCK_RE = re.compile(r"^\.\.\s+raw::") + +# Matches HTML tags (e.g. "
", "

", ") - Add in_html_open_tag state to discard multi-line HTML opening tag continuations --- docs/conf.py | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index f7450bd4..afed319f 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -100,6 +100,10 @@ # URL schemes so that multi-line RST inline hyperlinks are preserved. _HTML_TAG_RE = re.compile(r"^<(?!https?://|ftp://|mailto:)[a-zA-Z/!]") +# Matches trailing HTML close tags at the end of a prose line +# (e.g. "Browse blogs.

", "See the guide."). +_TRAILING_HTML_CLOSE_RE = re.compile(r"()+\s*$") + MIN_PROSE_LINES = 10 @@ -186,6 +190,8 @@ def generate_combined_markdown(app, exception): in_backtick_fence = False in_rst_code_block = False in_rst_skip_block = False + in_html_comment = False # inside block + in_html_open_tag = False # inside a multi-line HTML opening tag kept = [] for line in lines: stripped = line.strip() @@ -197,6 +203,11 @@ def generate_combined_markdown(app, exception): if in_backtick_fence: kept.append(line) continue + # HTML comment block (): discard all content until --> + if in_html_comment: + if "-->" in stripped: + in_html_comment = False + continue # RST skip block (e.g. .. raw::): discard all indented content if in_rst_skip_block: if not stripped or line[0] in (" ", "\t"): @@ -216,8 +227,26 @@ def generate_combined_markdown(app, exception): if _RST_CODE_BLOCK_RE.match(stripped): in_rst_code_block = True continue - if not stripped or is_prose_line(line): + # HTML comment open (): discard opener and enter state + if stripped.startswith("" not in stripped: + in_html_comment = True + continue + # Multi-line HTML opening tag: skip continuation lines until > + if in_html_open_tag: + if ">" in stripped: + in_html_open_tag = False + continue + # Detect HTML opening tags that wrap across lines (no > on this line) + if _HTML_TAG_RE.match(stripped) and ">" not in stripped: + in_html_open_tag = True + continue + if not stripped: kept.append(line) + elif is_prose_line(line): + # Strip trailing HTML close tags (e.g. "See the guide.

") + cleaned = _TRAILING_HTML_CLOSE_RE.sub("", line).rstrip() + kept.append(cleaned if cleaned.strip() else line) cleaned = "\n".join(kept) combined.append(f"\n\n---\n\n# {relative}\n") From f994cef411d2ac7534b35d36db4badf2cdded438 Mon Sep 17 00:00:00 2001 From: Kiss Date: Fri, 29 May 2026 14:20:04 +0200 Subject: [PATCH 7/7] llms: drop punctuation-only lines after stripping trailing HTML close tags Lines like ".

" from sphinx-design grid cards pass _is_prose_line because they start with ".". After stripping "

", the remaining content is a bare "." with no word characters and should be discarded. Co-Authored-By: Claude Sonnet 4.6 --- docs/conf.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index afed319f..7f0888e2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -246,7 +246,15 @@ def generate_combined_markdown(app, exception): elif is_prose_line(line): # Strip trailing HTML close tags (e.g. "See the guide.

") cleaned = _TRAILING_HTML_CLOSE_RE.sub("", line).rstrip() - kept.append(cleaned if cleaned.strip() else line) + cleaned_stripped = cleaned.strip() + if not cleaned_stripped: + # Entire line was HTML close tags — keep original (shouldn't + # normally reach here since _is_prose_line filters HTML). + kept.append(line) + elif re.search(r"\w", cleaned_stripped): + # Line has real word content after stripping close tags. + kept.append(cleaned) + # else: only punctuation remains (e.g. bare ".") — discard. cleaned = "\n".join(kept) combined.append(f"\n\n---\n\n# {relative}\n")