Spaces:
Sleeping
Sleeping
| """ | |
| Gradio Space: K8s Multi-Agent Debate Demo | |
| HuggingFace Space: roanbrasil/k8s-multi-agent | |
| """ | |
| import json | |
| import gradio as gr | |
| HARD8_RESULTS = [ | |
| {"resource": "Deployment", "rounds": 4, "time": 9.05, | |
| "manifest": """apiVersion: apps/v1 | |
| kind: Deployment | |
| metadata: | |
| name: java-app | |
| spec: | |
| replicas: 2 | |
| selector: | |
| matchLabels: | |
| app: java-app | |
| template: | |
| metadata: | |
| labels: | |
| app: java-app | |
| spec: | |
| containers: | |
| - name: java-app | |
| image: openjdk:17 | |
| resources: | |
| limits: | |
| memory: "512Mi\""""}, | |
| {"resource": "HorizontalPodAutoscaler", "rounds": 4, "time": 10.27, | |
| "manifest": """apiVersion: autoscaling/v2 | |
| kind: HorizontalPodAutoscaler | |
| metadata: | |
| name: api-hpa | |
| spec: | |
| scaleTargetRef: | |
| apiVersion: apps/v1 | |
| kind: Deployment | |
| name: api-server | |
| minReplicas: 2 | |
| maxReplicas: 10 | |
| metrics: | |
| - type: Resource | |
| resource: | |
| name: cpu | |
| target: | |
| type: Utilization | |
| averageUtilization: 50"""}, | |
| {"resource": "StatefulSet", "rounds": 4, "time": 7.63, | |
| "manifest": """apiVersion: apps/v1 | |
| kind: StatefulSet | |
| metadata: | |
| name: kafka | |
| spec: | |
| serviceName: kafka | |
| replicas: 3 | |
| selector: | |
| matchLabels: | |
| app: kafka | |
| template: | |
| metadata: | |
| labels: | |
| app: kafka | |
| spec: | |
| containers: | |
| - name: kafka | |
| image: confluentinc/cp-kafka:7.4.0 | |
| volumeMounts: | |
| - name: kafka-data | |
| mountPath: /var/lib/kafka/data | |
| volumeClaimTemplates: | |
| - metadata: | |
| name: kafka-data | |
| spec: | |
| accessModes: ["ReadWriteOnce"] | |
| resources: | |
| requests: | |
| storage: 1Gi"""}, | |
| {"resource": "Ingress (TLS)", "rounds": 4, "time": 8.33, | |
| "manifest": """apiVersion: networking.k8s.io/v1 | |
| kind: Ingress | |
| metadata: | |
| name: secure-ingress | |
| spec: | |
| tls: | |
| - hosts: | |
| - secure.example.com | |
| secretName: tls-secret | |
| rules: | |
| - host: secure.example.com | |
| http: | |
| paths: | |
| - path: / | |
| pathType: Prefix | |
| backend: | |
| service: | |
| name: example-service | |
| port: | |
| number: 80"""}, | |
| {"resource": "PersistentVolumeClaim", "rounds": 4, "time": 6.81, | |
| "manifest": """apiVersion: v1 | |
| kind: PersistentVolumeClaim | |
| metadata: | |
| name: postgres-pvc | |
| namespace: database | |
| spec: | |
| accessModes: | |
| - ReadWriteOnce | |
| resources: | |
| requests: | |
| storage: 1Gi"""}, | |
| {"resource": "CronJob", "rounds": 4, "time": 9.26, | |
| "manifest": """apiVersion: batch/v1 | |
| kind: CronJob | |
| metadata: | |
| name: db-backup | |
| spec: | |
| schedule: "0 2 * * *" | |
| jobTemplate: | |
| spec: | |
| template: | |
| spec: | |
| containers: | |
| - name: backup | |
| image: postgres:15 | |
| command: ["/bin/sh", "-c", "pg_dump $DATABASE_URL > /backup/dump.sql"] | |
| restartPolicy: OnFailure"""}, | |
| {"resource": "NetworkPolicy", "rounds": 4, "time": 8.29, | |
| "manifest": """apiVersion: networking.k8s.io/v1 | |
| kind: NetworkPolicy | |
| metadata: | |
| name: api-netpol | |
| namespace: production | |
| spec: | |
| podSelector: | |
| matchLabels: | |
| app: api | |
| policyTypes: | |
| - Ingress | |
| - Egress | |
| ingress: | |
| - from: | |
| - podSelector: | |
| matchLabels: | |
| role: frontend | |
| ports: | |
| - protocol: TCP | |
| port: 80"""}, | |
| {"resource": "ClusterRole", "rounds": 4, "time": 8.67, | |
| "manifest": """apiVersion: rbac.authorization.k8s.io/v1 | |
| kind: ClusterRole | |
| metadata: | |
| name: pod-reader | |
| rules: | |
| - apiGroups: [""] | |
| resources: ["pods"] | |
| verbs: ["get", "list", "watch"]"""}, | |
| ] | |
| SINGLE_MODEL_RESULTS = { | |
| "Baseline GPT (46M)": {"yaml": 30.0, "k8s": 36.7, "sem": 96.9, "lat": 0.35}, | |
| "AttnRes GPT (48M)": {"yaml": 26.7, "k8s": 36.7, "sem": 97.8, "lat": 0.75}, | |
| "Qwen2.5-Coder (7B)": {"yaml": 40.0, "k8s": 33.3, "sem": 98.1, "lat": 1.27}, | |
| "DeepSeek-Coder (6.7B)":{"yaml": 16.7, "k8s": 33.3, "sem": 95.0, "lat": 1.61}, | |
| } | |
| ARCHITECTURE_MD = """ | |
| ## System Architecture | |
| ``` | |
| Problem β BM25 RAG (4,794 K8s docs) | |
| β | |
| Agent 1 (AttnRes GPT 48M) | |
| Fast domain specialist | |
| β draft | |
| kubeconform --strict | |
| β error report | |
| Agent 2 (Qwen2.5-Coder 7B) | |
| Reasoning critic | |
| β critique + instruction | |
| Agent 1 retries (max 3 rounds) | |
| β if not solved | |
| Agent 2 generates directly (fallback) | |
| ``` | |
| **Key design choices:** | |
| - **Asymmetric roles**: small model drafts fast, large model reasons deeply | |
| - **External validator**: kubeconform provides ground-truth schema signal (no hallucinated validation) | |
| - **BM25 RAG**: top-3 K8s-specific documents grounded to each problem | |
| - **Max 3 rounds**: bounded latency (~30s worst case) | |
| """ | |
| def show_hard8_result(resource_name): | |
| for r in HARD8_RESULTS: | |
| if r["resource"] == resource_name: | |
| summary = f"**Resource:** {r['resource']} \n" | |
| summary += f"**Debate rounds:** {r['rounds']} \n" | |
| summary += f"**Total time:** {r['time']:.2f}s \n" | |
| summary += f"**Solved by:** Agent 2 (Qwen2.5-Coder fallback) \n" | |
| summary += f"**Single-model K8s%:** 0% (all 4 models failed)\n" | |
| return summary, r["manifest"] | |
| return "Not found", "" | |
| def show_benchmark_table(): | |
| rows = [] | |
| for model, m in SINGLE_MODEL_RESULTS.items(): | |
| rows.append([model, f"{m['yaml']:.1f}%", f"{m['k8s']:.1f}%", | |
| f"{m['sem']:.1f}%", f"{m['lat']:.2f}s"]) | |
| return rows | |
| with gr.Blocks(title="K8s Multi-Agent Debate Demo", theme=gr.themes.Soft()) as demo: | |
| gr.Markdown("# K8s Multi-Agent Debate (MDA) System") | |
| gr.Markdown( | |
| "Combines **AttnRes GPT (48M)** + **Qwen2.5-Coder-7B** + **BM25 RAG** + **kubeconform** " | |
| "to generate valid Kubernetes manifests. Achieves **100% schema compliance** on the " | |
| "Hard-8 subset where all single models fail.\n\n" | |
| "π [Paper](https://github.com/roanbrasil/llm-pocs) | " | |
| "π€ [Model](https://huggingface.co/roanbrasil/attnres-devops-gpt) | " | |
| "π [K8sBench](https://huggingface.co/datasets/roanbrasil/k8sbench)" | |
| ) | |
| with gr.Tabs(): | |
| with gr.Tab("Hard-8 Results"): | |
| gr.Markdown("### Hard-8 Subset: Resources all single models fail (0% K8s%)") | |
| gr.Markdown("The MDA system solves all 8 via the Agent 2 fallback after 3 debate rounds.") | |
| resource_dd = gr.Dropdown( | |
| choices=[r["resource"] for r in HARD8_RESULTS], | |
| value="HorizontalPodAutoscaler", | |
| label="Select K8s resource" | |
| ) | |
| result_info = gr.Markdown() | |
| manifest_out = gr.Code(language="yaml", label="Final valid manifest (kubeconform β)") | |
| resource_dd.change(show_hard8_result, | |
| inputs=resource_dd, | |
| outputs=[result_info, manifest_out]) | |
| demo.load(lambda: show_hard8_result("HorizontalPodAutoscaler"), | |
| outputs=[result_info, manifest_out]) | |
| with gr.Tab("K8sBench Leaderboard"): | |
| gr.Markdown("### K8sBench: 30-prompt evaluation across 4 models") | |
| leaderboard = gr.Dataframe( | |
| headers=["Model", "YAML%", "K8s%", "Sem%", "Latency"], | |
| value=show_benchmark_table(), | |
| label="K8sBench Results", | |
| interactive=False | |
| ) | |
| gr.Markdown( | |
| "**K8s%** = kubeconform --strict schema compliance \n" | |
| "Domain-specific 48M models **match or exceed** 7B generalists on schema compliance " | |
| "while being **3β4Γ faster**." | |
| ) | |
| with gr.Tab("Architecture"): | |
| gr.Markdown(ARCHITECTURE_MD) | |
| gr.Markdown(""" | |
| ### Agent Roles | |
| | Agent | Model | Role | | |
| |-------|-------|------| | |
| | **Agent 1** | AttnRes GPT (48M, local GPU) | Fast domain specialist β generates initial draft | | |
| | **Agent 2** | Qwen2.5-Coder-7B (Ollama) | Reasoning critic β diagnoses kubeconform errors, instructs Agent 1, generates final manifest on fallback | | |
| | **Validator** | kubeconform --strict | External schema arbitrator β provides ground-truth correctness signal | | |
| | **RAG** | BM25Okapi over 4,794 K8s docs | Retrieves top-3 relevant examples per problem | | |
| """) | |
| with gr.Tab("About"): | |
| gr.Markdown(""" | |
| ## About | |
| This demo presents results from: | |
| > Brasil, R. (2025). *Can Small Domain-Specific LLMs Compete with General 7B Models on Kubernetes Configuration Generation?* | |
| ### Key Findings | |
| 1. A **48M domain-specific model** matches **7B generalists** on Kubernetes schema compliance (36.7% vs 33.3%) while being **3.4Γ faster** | |
| 2. **All single models fail** on HPA, StatefulSet, Ingress, PVC (cross-field constraint resources) | |
| 3. The **MDA system achieves 100%** on the Hard-8 subset via asymmetric debate with external validation | |
| 4. **AttnRes** architectural improvement: β2.1% perplexity, β44% convergence steps | |
| ### Resources | |
| - π Code: https://github.com/roanbrasil/llm-pocs | |
| - π€ Model: https://huggingface.co/roanbrasil/attnres-devops-gpt | |
| - π Training corpus: https://huggingface.co/datasets/roanbrasil/devops-gitops-corpus | |
| - π K8sBench: https://huggingface.co/datasets/roanbrasil/k8sbench | |
| - π RAG corpus: https://huggingface.co/datasets/roanbrasil/k8s-rag-corpus | |
| """) | |
| demo.launch() | |