nexus-worker 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 NexusCompute Network
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,130 @@
1
+ Metadata-Version: 2.4
2
+ Name: nexus-worker
3
+ Version: 0.1.0
4
+ Summary: Monetize your GPU by serving open-source AI inference in the NexusCompute decentralized network.
5
+ Author-email: NexusCompute Network <providers@nexuscompute.ai>
6
+ License: MIT
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
11
+ Requires-Python: >=3.9
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: httpx>=0.27.0
15
+ Requires-Dist: websockets>=12.0
16
+ Requires-Dist: click>=8.1.7
17
+ Requires-Dist: rich>=13.7.0
18
+ Dynamic: license-file
19
+
20
+ # ⚡ NexusWorker (`nexus-worker`)
21
+
22
+ [![License: MIT](https://img.shields.io/badge/License-MIT-emerald.svg)](LICENSE)
23
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
24
+ [![Decentralized AI](https://img.shields.io/badge/Mesh-Decentralized%20Inference-teal.svg)](https://nexuscompute.ai)
25
+
26
+ **NexusWorker** is the open-source provider daemon for the **NexusCompute** decentralized AI inference network.
27
+
28
+ Run this lightweight daemon on your PC, mining rig, or server to monetize your idle graphics cards (NVIDIA, AMD, Apple Silicon) by serving inference tokens for open-source LLMs (Llama 3, DeepSeek-R1, Mistral).
29
+
30
+ ---
31
+
32
+ ## 🔒 Security & Privacy (Outbound-Only)
33
+
34
+ NexusWorker was designed from the ground up for strict security:
35
+
36
+ * **Zero Inbound Ports**: The daemon initiates an **outbound-only** encrypted WebSocket connection to the NexusCompute coordinator. You **never** need to configure port forwarding, open firewall rules, or expose a public IP.
37
+ * **Completely Sandboxed**: The worker only communicates with your local inference engine (e.g. Ollama or vLLM) over localhost (`127.0.0.1`).
38
+ * **100% Open Source**: Full transparency—inspect every line of code before running.
39
+
40
+ ---
41
+
42
+ ## 🚀 Quickstart
43
+
44
+ ### 1. Requirements
45
+
46
+ * **OS**: Linux, Windows, or macOS
47
+ * **Python**: 3.9 or higher
48
+ * **Inference Engine**: [Ollama](https://ollama.ai) (recommended for 1-click setup) or [vLLM](https://github.com/vllm-project/vllm).
49
+ * **Hardware**: Any modern GPU with 6GB+ VRAM (e.g. RTX 3060/3080/4090, Apple M-series), or CPU in emulation mode.
50
+
51
+ ---
52
+
53
+ ### 2. Installation
54
+
55
+ Clone and install in a Python virtual environment:
56
+
57
+ ```bash
58
+ git clone https://github.com/nexus-compute-ai/nexus-worker.git
59
+ cd nexus-worker
60
+
61
+ # Create and activate virtual environment
62
+ python -m venv .venv
63
+ # On Windows:
64
+ .\.venv\Scripts\activate
65
+ # On Linux/macOS:
66
+ source .venv/bin/activate
67
+
68
+ # Install package
69
+ pip install -e .
70
+ ```
71
+
72
+ ---
73
+
74
+ ### 3. Check Detected Hardware
75
+
76
+ Verify that your GPU and local models are recognized:
77
+
78
+ ```bash
79
+ nexus-worker info
80
+ ```
81
+
82
+ Example output:
83
+ ```text
84
+ ============================================================
85
+ NEXUSCOMPUTE HARDWARE DETECTOR
86
+ ============================================================
87
+ • GPU: NVIDIA GeForce RTX 4090
88
+ • VRAM: 24,576 MB
89
+ • Backend Engine: Ollama (http://127.0.0.1:11434)
90
+ • Discovered Models:
91
+ - llama3:8b
92
+ - deepseek-r1:7b
93
+ - mistral:7b
94
+ ============================================================
95
+ ```
96
+
97
+ ---
98
+
99
+ ### 4. Connect to Network & Earn
100
+
101
+ Get your node token from the **Provider Dashboard** on NexusCompute, then start the daemon:
102
+
103
+ ```bash
104
+ nexus-worker start --token nx-node-YOUR_TOKEN_HERE
105
+ ```
106
+
107
+ #### CLI Options:
108
+ * `--token TEXT`: Your unique node authorization token *(required)*.
109
+ * `--coordinator TEXT`: Coordinator WebSocket URL (default: `ws://127.0.0.1:8000/api/v1/ws/worker`).
110
+ * `--engine [auto|ollama|vllm|emulate]`: Local inference engine (default: `auto`).
111
+ * `--emulate`: Run in emulation mode for development without downloading weights.
112
+
113
+ ```bash
114
+ # Example with custom coordinator and auto-discovery
115
+ nexus-worker start --token nx-node-0a0a3b29ed4e323af354549a6681821a1b75157e
116
+ ```
117
+
118
+ ---
119
+
120
+ ## 🛠️ Supported Engines
121
+
122
+ 1. **Ollama (Recommended)**: Pull models via `ollama pull llama3:8b`. NexusWorker will auto-detect active models and advertise them to the coordinator.
123
+ 2. **vLLM (High-Throughput)**: Launch with OpenAI-compatible API (`--port 8000`).
124
+ 3. **Emulation Engine**: Built-in mock tokenizer and streaming generator for rapid testing.
125
+
126
+ ---
127
+
128
+ ## 📄 License
129
+
130
+ Distributed under the **MIT License**. See [LICENSE](LICENSE) for more information.
@@ -0,0 +1,111 @@
1
+ # ⚡ NexusWorker (`nexus-worker`)
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-emerald.svg)](LICENSE)
4
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
5
+ [![Decentralized AI](https://img.shields.io/badge/Mesh-Decentralized%20Inference-teal.svg)](https://nexuscompute.ai)
6
+
7
+ **NexusWorker** is the open-source provider daemon for the **NexusCompute** decentralized AI inference network.
8
+
9
+ Run this lightweight daemon on your PC, mining rig, or server to monetize your idle graphics cards (NVIDIA, AMD, Apple Silicon) by serving inference tokens for open-source LLMs (Llama 3, DeepSeek-R1, Mistral).
10
+
11
+ ---
12
+
13
+ ## 🔒 Security & Privacy (Outbound-Only)
14
+
15
+ NexusWorker was designed from the ground up for strict security:
16
+
17
+ * **Zero Inbound Ports**: The daemon initiates an **outbound-only** encrypted WebSocket connection to the NexusCompute coordinator. You **never** need to configure port forwarding, open firewall rules, or expose a public IP.
18
+ * **Completely Sandboxed**: The worker only communicates with your local inference engine (e.g. Ollama or vLLM) over localhost (`127.0.0.1`).
19
+ * **100% Open Source**: Full transparency—inspect every line of code before running.
20
+
21
+ ---
22
+
23
+ ## 🚀 Quickstart
24
+
25
+ ### 1. Requirements
26
+
27
+ * **OS**: Linux, Windows, or macOS
28
+ * **Python**: 3.9 or higher
29
+ * **Inference Engine**: [Ollama](https://ollama.ai) (recommended for 1-click setup) or [vLLM](https://github.com/vllm-project/vllm).
30
+ * **Hardware**: Any modern GPU with 6GB+ VRAM (e.g. RTX 3060/3080/4090, Apple M-series), or CPU in emulation mode.
31
+
32
+ ---
33
+
34
+ ### 2. Installation
35
+
36
+ Clone and install in a Python virtual environment:
37
+
38
+ ```bash
39
+ git clone https://github.com/nexus-compute-ai/nexus-worker.git
40
+ cd nexus-worker
41
+
42
+ # Create and activate virtual environment
43
+ python -m venv .venv
44
+ # On Windows:
45
+ .\.venv\Scripts\activate
46
+ # On Linux/macOS:
47
+ source .venv/bin/activate
48
+
49
+ # Install package
50
+ pip install -e .
51
+ ```
52
+
53
+ ---
54
+
55
+ ### 3. Check Detected Hardware
56
+
57
+ Verify that your GPU and local models are recognized:
58
+
59
+ ```bash
60
+ nexus-worker info
61
+ ```
62
+
63
+ Example output:
64
+ ```text
65
+ ============================================================
66
+ NEXUSCOMPUTE HARDWARE DETECTOR
67
+ ============================================================
68
+ • GPU: NVIDIA GeForce RTX 4090
69
+ • VRAM: 24,576 MB
70
+ • Backend Engine: Ollama (http://127.0.0.1:11434)
71
+ • Discovered Models:
72
+ - llama3:8b
73
+ - deepseek-r1:7b
74
+ - mistral:7b
75
+ ============================================================
76
+ ```
77
+
78
+ ---
79
+
80
+ ### 4. Connect to Network & Earn
81
+
82
+ Get your node token from the **Provider Dashboard** on NexusCompute, then start the daemon:
83
+
84
+ ```bash
85
+ nexus-worker start --token nx-node-YOUR_TOKEN_HERE
86
+ ```
87
+
88
+ #### CLI Options:
89
+ * `--token TEXT`: Your unique node authorization token *(required)*.
90
+ * `--coordinator TEXT`: Coordinator WebSocket URL (default: `ws://127.0.0.1:8000/api/v1/ws/worker`).
91
+ * `--engine [auto|ollama|vllm|emulate]`: Local inference engine (default: `auto`).
92
+ * `--emulate`: Run in emulation mode for development without downloading weights.
93
+
94
+ ```bash
95
+ # Example with custom coordinator and auto-discovery
96
+ nexus-worker start --token nx-node-0a0a3b29ed4e323af354549a6681821a1b75157e
97
+ ```
98
+
99
+ ---
100
+
101
+ ## 🛠️ Supported Engines
102
+
103
+ 1. **Ollama (Recommended)**: Pull models via `ollama pull llama3:8b`. NexusWorker will auto-detect active models and advertise them to the coordinator.
104
+ 2. **vLLM (High-Throughput)**: Launch with OpenAI-compatible API (`--port 8000`).
105
+ 3. **Emulation Engine**: Built-in mock tokenizer and streaming generator for rapid testing.
106
+
107
+ ---
108
+
109
+ ## 📄 License
110
+
111
+ Distributed under the **MIT License**. See [LICENSE](LICENSE) for more information.
@@ -0,0 +1,2 @@
1
+ """NexusCompute Provider Worker Daemon"""
2
+ __version__ = "0.1.0"
@@ -0,0 +1,96 @@
1
+ import sys
2
+ import os
3
+ import asyncio
4
+ import click
5
+ from rich.console import Console
6
+ from rich.panel import Panel
7
+ from rich.table import Table
8
+
9
+ # Add package root to sys.path
10
+ sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
11
+
12
+ from nexus_worker.hardware import detect_hardware
13
+ from nexus_worker.engine import InferenceEngineClient
14
+ from nexus_worker.client import WorkerDaemon
15
+
16
+ console = Console()
17
+
18
+ BANNER = r"""
19
+ [bold cyan] _ _ ____ _ [/bold cyan]
20
+ [bold cyan] | \ | | _____ ___ _ ___ / ___|___ _ __ ___ _ __ _ _| |_ ___ [/bold cyan]
21
+ [bold cyan] | \| |/ _ \ \/ / | | / __| | / _ \| '_ ` _ \| '_ \| | | | __/ _ \[/bold cyan]
22
+ [bold cyan] | |\ | __/> <| |_| \__ \ |__| (_) | | | | | | |_) | |_| | || __/[/bold cyan]
23
+ [bold cyan] |_| \_|\___/_/\_\\__,_|___/\____\___/|_| |_| |_| .__/ \__,_|\__\___|[/bold cyan]
24
+ [bold cyan] |_| [/bold cyan]
25
+ [bold yellow] >>> Decentralized AI Inference Provider Node (Antseed-Compatible) <<< [/bold yellow]
26
+ """
27
+
28
+ @click.group()
29
+ def cli():
30
+ """NexusCompute Worker CLI - Monetize your GPU by serving open-source AI inference."""
31
+ pass
32
+
33
+ @cli.command()
34
+ def info():
35
+ """Display local GPU hardware specifications and discovered AI engines."""
36
+ console.print(BANNER)
37
+ hw = detect_hardware()
38
+
39
+ table = Table(title="Detected Hardware & Compute Environment", style="cyan")
40
+ table.add_column("Property", style="bold white")
41
+ table.add_column("Detected Value", style="green")
42
+
43
+ table.add_row("GPU Model", hw["gpu_name"])
44
+ table.add_row("VRAM Capacity", f"{hw['vram_mb']} MB")
45
+ table.add_row("Platform Backend", hw["platform"])
46
+
47
+ console.print(table)
48
+
49
+ # Check local engines
50
+ console.print("\n[bold yellow]Scanning for Local AI Inference Engines...[/bold yellow]")
51
+ engine = InferenceEngineClient()
52
+ models = engine.discover_models()
53
+
54
+ engine_table = Table(title="Inference Engine Status", style="magenta")
55
+ engine_table.add_column("Engine", style="bold white")
56
+ engine_table.add_column("Available Models", style="green")
57
+ engine_table.add_row(engine.active_engine.upper(), ", ".join(models) if models else "None detected")
58
+ console.print(engine_table)
59
+
60
+ @cli.command()
61
+ @click.option("--token", "-t", required=True, help="Provider node authentication token (nx-node-...) from dashboard.")
62
+ @click.option("--coordinator", "-c", "--server", "-s", default="https://nexus-compute.pages.dev", help="NexusCompute Coordinator URL (e.g. https://nexus-compute.pages.dev).")
63
+ @click.option("--ollama-url", default="http://localhost:11434", help="Local Ollama HTTP endpoint.")
64
+ @click.option("--vllm-url", default="http://localhost:8000", help="Local vLLM HTTP endpoint.")
65
+ @click.option("--emulate", is_flag=True, default=False, help="Enable test emulation mode (simulates GPU streaming without Ollama).")
66
+ @click.option("--prompt-price", default=0.20, type=float, help="Custom price per 1M prompt tokens (in credits).")
67
+ @click.option("--completion-price", default=0.40, type=float, help="Custom price per 1M completion tokens (in credits).")
68
+ def start(token, coordinator, ollama_url, vllm_url, emulate, prompt_price, completion_price):
69
+ """Start the provider daemon and connect outbound to the NexusCompute network."""
70
+ console.print(BANNER)
71
+ console.print(Panel(
72
+ f"[bold green]Node Token:[/bold green] {token[:12]}...\n"
73
+ f"[bold green]Coordinator Target:[/bold green] {coordinator}\n"
74
+ f"[bold green]Pricing Config:[/bold green] ${prompt_price}/M prompt | ${completion_price}/M completion\n"
75
+ f"[bold green]Emulation Mode:[/bold green] {'Active' if emulate else 'Auto-detect'}",
76
+ title="Worker Configuration",
77
+ style="blue"
78
+ ))
79
+
80
+ daemon = WorkerDaemon(
81
+ node_token=token,
82
+ coordinator_url=coordinator,
83
+ ollama_url=ollama_url,
84
+ vllm_url=vllm_url,
85
+ emulate=emulate,
86
+ prompt_price=prompt_price,
87
+ completion_price=completion_price
88
+ )
89
+
90
+ try:
91
+ asyncio.run(daemon.start())
92
+ except KeyboardInterrupt:
93
+ console.print("\n[bold red]Worker shut down gracefully by operator.[/bold red]")
94
+
95
+ if __name__ == "__main__":
96
+ cli()
@@ -0,0 +1,174 @@
1
+ import asyncio
2
+ import json
3
+ import logging
4
+ import time
5
+ import urllib.parse
6
+ from typing import Dict, Any, List, Optional
7
+ import httpx
8
+
9
+ from nexus_worker.hardware import detect_hardware
10
+ from nexus_worker.engine import InferenceEngineClient
11
+
12
+ logger = logging.getLogger("nexus_worker")
13
+
14
+ class WorkerDaemon:
15
+ def __init__(
16
+ self,
17
+ node_token: str,
18
+ coordinator_url: str = "https://nexus-compute.pages.dev",
19
+ ollama_url: str = "http://localhost:11434",
20
+ vllm_url: str = "http://localhost:8000",
21
+ emulate: bool = False,
22
+ prompt_price: float = 0.20,
23
+ completion_price: float = 0.40
24
+ ):
25
+ self.node_token = node_token
26
+ # Normalize coordinator URL
27
+ url = coordinator_url.rstrip("/")
28
+ if url.startswith("ws://"):
29
+ url = url.replace("ws://", "http://", 1)
30
+ elif url.startswith("wss://"):
31
+ url = url.replace("wss://", "https://", 1)
32
+ # Remove trailing path if old /api/v1/ws/worker path was passed
33
+ if "/api/v1/ws/worker" in url:
34
+ url = url.replace("/api/v1/ws/worker", "")
35
+ self.coordinator_url = url
36
+
37
+ self.prompt_price = prompt_price
38
+ self.completion_price = completion_price
39
+ self.engine = InferenceEngineClient(ollama_url=ollama_url, vllm_url=vllm_url, emulate=emulate)
40
+ self.running = False
41
+
42
+ async def start(self):
43
+ self.running = True
44
+
45
+ # 1. Detect hardware
46
+ hw = detect_hardware()
47
+ print(f"\n[NexusCompute Worker] Detected Hardware: {hw['gpu_name']} ({hw['vram_mb']} MB VRAM)")
48
+
49
+ # 2. Discover local models
50
+ models = self.engine.discover_models()
51
+ print(f"[NexusCompute Worker] Engine: {self.engine.active_engine.upper()} | Serving {len(models)} model(s): {', '.join(models)}")
52
+
53
+ # 3. Benchmark tokens/sec
54
+ print("[NexusCompute Worker] Running startup synthetic benchmark probe...")
55
+ bench_speed = await self.engine.run_benchmark()
56
+ print(f"[NexusCompute Worker] Benchmark Result: {bench_speed} tokens/second")
57
+
58
+ models_param = ",".join(models) if models else "llama3:8b,deepseek-r1:7b,mistral:7b"
59
+ headers = {
60
+ "Authorization": f"Bearer {self.node_token}",
61
+ "User-Agent": "NexusWorker/1.0",
62
+ }
63
+
64
+ print(f"[NexusCompute Worker] Connecting to Cloudflare Edge Coordinator: {self.coordinator_url}")
65
+ print("[NexusCompute Worker] Node is ONLINE and actively polling for AI inference jobs...\n")
66
+
67
+ backoff = 2
68
+ async with httpx.AsyncClient(
69
+ headers=headers,
70
+ timeout=httpx.Timeout(connect=10.0, read=35.0, write=10.0, pool=10.0)
71
+ ) as client:
72
+ while self.running:
73
+ try:
74
+ poll_url = (
75
+ f"{self.coordinator_url}/api/v1/jobs/poll"
76
+ f"?models={urllib.parse.quote(models_param)}"
77
+ f"&gpu_name={urllib.parse.quote(hw['gpu_name'])}"
78
+ f"&vram_mb={hw['vram_mb']}"
79
+ f"&tokens_per_sec={bench_speed}"
80
+ )
81
+
82
+ resp = await client.get(poll_url)
83
+ if resp.status_code == 200:
84
+ backoff = 2 # Reset on successful network request
85
+ data = resp.json()
86
+ job_id = data.get("job_id")
87
+
88
+ if job_id:
89
+ # Job acquired! Process and stream tokens
90
+ await self._process_job(client, data)
91
+ else:
92
+ # Timeout / heartbeat ack, continue immediately
93
+ pass
94
+
95
+ elif resp.status_code == 401:
96
+ print(f"[NexusCompute Worker] [ERROR] Authentication failed! Invalid node token: {self.node_token[:12]}...")
97
+ await asyncio.sleep(10)
98
+ else:
99
+ print(f"[NexusCompute Worker] Polling returned status {resp.status_code}. Retrying...")
100
+ await asyncio.sleep(backoff)
101
+ backoff = min(20, backoff * 1.5)
102
+
103
+ except (httpx.ReadTimeout, httpx.ConnectTimeout):
104
+ # Standard long-poll expiration, loop immediately
105
+ continue
106
+ except httpx.RequestError as e:
107
+ print(f"[NexusCompute Worker] Connection error ({type(e).__name__}). Reconnecting in {backoff}s...")
108
+ await asyncio.sleep(backoff)
109
+ backoff = min(20, backoff * 1.5)
110
+ except Exception as e:
111
+ print(f"[NexusCompute Worker] Unexpected error: {e}")
112
+ await asyncio.sleep(backoff)
113
+
114
+ async def _process_job(self, client: httpx.AsyncClient, job_data: dict):
115
+ job_id = job_data.get("job_id")
116
+ model = job_data.get("model")
117
+ messages = job_data.get("messages", [])
118
+ temperature = job_data.get("temperature", 0.7)
119
+ max_tokens = job_data.get("max_tokens", 512)
120
+
121
+ print(f"\n[NexusCompute Worker] >> [CLAIMED] Job {job_id[:8]} for model '{model}'")
122
+ start_time = time.time()
123
+ seq = 0
124
+ prompt_tokens = 15
125
+ completion_tokens = 0
126
+
127
+ try:
128
+ async for chunk in self.engine.stream_chat(
129
+ model=model,
130
+ messages=messages,
131
+ temperature=temperature,
132
+ max_tokens=max_tokens
133
+ ):
134
+ if chunk["type"] == "chunk":
135
+ seq += 1
136
+ completion_tokens += 1
137
+ delta = chunk["delta"]
138
+
139
+ # POST chunk to Cloudflare Edge
140
+ stream_url = f"{self.coordinator_url}/api/v1/jobs/{job_id}/stream"
141
+ try:
142
+ await client.post(stream_url, json={"seq": seq, "delta": delta})
143
+ except Exception as ex:
144
+ logger.warning(f"Failed to post chunk {seq}: {ex}")
145
+
146
+ elif chunk["type"] == "done":
147
+ prompt_tokens = chunk.get("prompt_tokens", 15)
148
+ completion_tokens = chunk.get("completion_tokens", completion_tokens)
149
+ break
150
+
151
+ latency_ms = int((time.time() - start_time) * 1000)
152
+ # Settle completion
153
+ complete_url = f"{self.coordinator_url}/api/v1/jobs/{job_id}/complete"
154
+ await client.post(complete_url, json={
155
+ "prompt_tokens": prompt_tokens,
156
+ "completion_tokens": completion_tokens,
157
+ "latency_ms": latency_ms,
158
+ })
159
+ print(f"[NexusCompute Worker] << [COMPLETED] Job {job_id[:8]} in {latency_ms}ms ({completion_tokens} tokens streamed, payout recorded)!\n")
160
+
161
+ except Exception as e:
162
+ print(f"[NexusCompute Worker] !! [ERROR] Job {job_id[:8]} failed: {e}")
163
+ try:
164
+ await client.post(f"{self.coordinator_url}/api/v1/jobs/{job_id}/stream", json={
165
+ "seq": seq + 1,
166
+ "delta": f"\n[Inference Error: {str(e)}]"
167
+ })
168
+ await client.post(f"{self.coordinator_url}/api/v1/jobs/{job_id}/complete", json={
169
+ "prompt_tokens": prompt_tokens,
170
+ "completion_tokens": completion_tokens,
171
+ "error": str(e)
172
+ })
173
+ except Exception:
174
+ pass
@@ -0,0 +1,146 @@
1
+ import shutil
2
+ import time
3
+ import json
4
+ import asyncio
5
+ from typing import List, Dict, Any, AsyncGenerator
6
+ import httpx
7
+
8
+ class InferenceEngineClient:
9
+ def __init__(self, ollama_url: str = "http://localhost:11434", vllm_url: str = "http://localhost:8000", emulate: bool = False):
10
+ self.ollama_url = ollama_url.rstrip("/")
11
+ self.vllm_url = vllm_url.rstrip("/")
12
+ self.emulate = emulate
13
+ self.active_engine = "none"
14
+
15
+ def discover_models(self) -> List[str]:
16
+ """Discovers locally installed models across Ollama, vLLM, or emulation."""
17
+ if self.emulate:
18
+ self.active_engine = "emulated"
19
+ return ["llama3:8b", "mistral:7b", "deepseek-r1:7b"]
20
+
21
+ # 1. Check if Ollama executable exists on system
22
+ if shutil.which("ollama"):
23
+ try:
24
+ import urllib.request
25
+ req = urllib.request.Request(f"{self.ollama_url}/api/tags", headers={"User-Agent": "NexusWorker"})
26
+ with urllib.request.urlopen(req, timeout=1.0) as response:
27
+ if response.status == 200:
28
+ data = json.loads(response.read().decode())
29
+ models = [m["name"] for m in data.get("models", [])]
30
+ if models:
31
+ self.active_engine = "ollama"
32
+ return models
33
+ except Exception:
34
+ pass
35
+
36
+ # 2. Fallback to Emulated Engine for testing/demo
37
+ self.active_engine = "emulated"
38
+ return ["llama3:8b", "mistral:7b", "deepseek-r1:7b"]
39
+
40
+ async def stream_chat(
41
+ self,
42
+ model: str,
43
+ messages: List[Dict[str, str]],
44
+ temperature: float = 0.7,
45
+ max_tokens: int = 1024
46
+ ) -> AsyncGenerator[Dict[str, Any], None]:
47
+ """Streams tokens from local engine or emulated runtime."""
48
+ if self.active_engine == "ollama":
49
+ async with httpx.AsyncClient(timeout=60.0) as client:
50
+ async with client.stream(
51
+ "POST",
52
+ f"{self.ollama_url}/api/chat",
53
+ json={
54
+ "model": model,
55
+ "messages": messages,
56
+ "options": {"temperature": temperature, "num_predict": max_tokens},
57
+ "stream": True
58
+ }
59
+ ) as response:
60
+ async for line in response.aiter_lines():
61
+ if line:
62
+ data = json.loads(line)
63
+ chunk_text = data.get("message", {}).get("content", "")
64
+ is_done = data.get("done", False)
65
+ prompt_eval = data.get("prompt_eval_count", 0)
66
+ eval_count = data.get("eval_count", 0)
67
+
68
+ if chunk_text:
69
+ yield {"type": "chunk", "delta": chunk_text}
70
+ if is_done:
71
+ yield {
72
+ "type": "done",
73
+ "prompt_tokens": prompt_eval or 15,
74
+ "completion_tokens": eval_count or 40,
75
+ "finish_reason": "stop"
76
+ }
77
+ return
78
+
79
+ elif self.active_engine == "vllm":
80
+ async with httpx.AsyncClient(timeout=60.0) as client:
81
+ async with client.stream(
82
+ "POST",
83
+ f"{self.vllm_url}/v1/chat/completions",
84
+ json={
85
+ "model": model,
86
+ "messages": messages,
87
+ "temperature": temperature,
88
+ "max_tokens": max_tokens,
89
+ "stream": True
90
+ }
91
+ ) as response:
92
+ async for line in response.aiter_lines():
93
+ if line.startswith("data: "):
94
+ body = line[6:].strip()
95
+ if body == "[DONE]":
96
+ yield {"type": "done", "prompt_tokens": 15, "completion_tokens": 40, "finish_reason": "stop"}
97
+ return
98
+ data = json.loads(body)
99
+ delta = data["choices"][0]["delta"].get("content", "")
100
+ if delta:
101
+ yield {"type": "chunk", "delta": delta}
102
+
103
+ else:
104
+ # Emulated engine: streams realistic AI response with realistic latency
105
+ user_prompt = messages[-1]["content"] if messages else "Hello"
106
+
107
+ # Generate thoughtful response text
108
+ simulated_response = (
109
+ f"[NexusCompute Verified Node] Processed request for '{model}'.\n\n"
110
+ f"Here is the generated inference for: \"{user_prompt}\"\n\n"
111
+ "Decentralized AI inference transforms commodity GPUs into an open, permissionless compute fabric. "
112
+ "By decoupling model execution from centralized cloud monopolies, providers earn competitive yields while "
113
+ "developers enjoy low latency, verifiable hardware proofs, and lower token costs."
114
+ )
115
+
116
+ words = simulated_response.split(" ")
117
+ for i, word in enumerate(words):
118
+ chunk = word + (" " if i < len(words) - 1 else "")
119
+ yield {"type": "chunk", "delta": chunk}
120
+ await asyncio.sleep(0.04) # ~25-30 tokens/sec simulated speed
121
+
122
+ yield {
123
+ "type": "done",
124
+ "prompt_tokens": max(5, len(user_prompt.split())),
125
+ "completion_tokens": len(words),
126
+ "finish_reason": "stop"
127
+ }
128
+
129
+ async def run_benchmark(self) -> float:
130
+ """Measures real tokens/sec on startup."""
131
+ start = time.time()
132
+ tokens_emitted = 0
133
+ async for chunk in self.stream_chat(
134
+ model="llama3:8b",
135
+ messages=[{"role": "user", "content": "Benchmark speed test."}],
136
+ max_tokens=30
137
+ ):
138
+ if chunk["type"] == "chunk":
139
+ tokens_emitted += 1
140
+ elif chunk["type"] == "done":
141
+ tokens_emitted = chunk.get("completion_tokens", tokens_emitted)
142
+ break
143
+
144
+ elapsed = max(0.1, time.time() - start)
145
+ tok_sec = round(tokens_emitted / elapsed, 1)
146
+ return max(15.0, tok_sec)
@@ -0,0 +1,56 @@
1
+ import subprocess
2
+ import platform
3
+ import shutil
4
+ from typing import Dict, Any
5
+
6
+ def detect_hardware() -> Dict[str, Any]:
7
+ """Detects local GPU and memory resources with cross-platform fallback."""
8
+ # 1. Check NVIDIA GPU via nvidia-smi
9
+ nvidia_smi = shutil.which("nvidia-smi")
10
+ if nvidia_smi:
11
+ try:
12
+ # Query GPU name and total memory in MB
13
+ result = subprocess.run(
14
+ ["nvidia-smi", "--query-gpu=gpu_name,memory.total", "--format=csv,noheader,nounits"],
15
+ capture_output=True,
16
+ text=True,
17
+ check=True
18
+ )
19
+ line = result.stdout.strip().split("\n")[0]
20
+ parts = line.split(",")
21
+ if len(parts) == 2:
22
+ gpu_name = parts[0].strip()
23
+ vram_mb = int(parts[1].strip())
24
+ return {
25
+ "gpu_name": gpu_name,
26
+ "vram_mb": vram_mb,
27
+ "platform": "nvidia_cuda"
28
+ }
29
+ except Exception:
30
+ pass
31
+
32
+ # 2. Check Apple Silicon (macOS)
33
+ if platform.system() == "Darwin" and platform.machine() == "arm64":
34
+ try:
35
+ sysctl_res = subprocess.run(["sysctl", "-n", "machdep.cpu.brand_string"], capture_output=True, text=True)
36
+ chip_name = sysctl_res.stdout.strip() or "Apple Silicon"
37
+ # Get total RAM
38
+ mem_res = subprocess.run(["sysctl", "-n", "hw.memsize"], capture_output=True, text=True)
39
+ total_bytes = int(mem_res.stdout.strip())
40
+ vram_mb = int(total_bytes / (1024 * 1024))
41
+ return {
42
+ "gpu_name": f"{chip_name} (Unified Memory)",
43
+ "vram_mb": vram_mb,
44
+ "platform": "apple_metal"
45
+ }
46
+ except Exception:
47
+ pass
48
+
49
+ # 3. CPU Fallback
50
+ import os
51
+ cpu_count = os.cpu_count() or 4
52
+ return {
53
+ "gpu_name": f"CPU Node ({cpu_count} cores, {platform.machine()})",
54
+ "vram_mb": 8192,
55
+ "platform": "cpu"
56
+ }
@@ -0,0 +1,130 @@
1
+ Metadata-Version: 2.4
2
+ Name: nexus-worker
3
+ Version: 0.1.0
4
+ Summary: Monetize your GPU by serving open-source AI inference in the NexusCompute decentralized network.
5
+ Author-email: NexusCompute Network <providers@nexuscompute.ai>
6
+ License: MIT
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
11
+ Requires-Python: >=3.9
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: httpx>=0.27.0
15
+ Requires-Dist: websockets>=12.0
16
+ Requires-Dist: click>=8.1.7
17
+ Requires-Dist: rich>=13.7.0
18
+ Dynamic: license-file
19
+
20
+ # ⚡ NexusWorker (`nexus-worker`)
21
+
22
+ [![License: MIT](https://img.shields.io/badge/License-MIT-emerald.svg)](LICENSE)
23
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
24
+ [![Decentralized AI](https://img.shields.io/badge/Mesh-Decentralized%20Inference-teal.svg)](https://nexuscompute.ai)
25
+
26
+ **NexusWorker** is the open-source provider daemon for the **NexusCompute** decentralized AI inference network.
27
+
28
+ Run this lightweight daemon on your PC, mining rig, or server to monetize your idle graphics cards (NVIDIA, AMD, Apple Silicon) by serving inference tokens for open-source LLMs (Llama 3, DeepSeek-R1, Mistral).
29
+
30
+ ---
31
+
32
+ ## 🔒 Security & Privacy (Outbound-Only)
33
+
34
+ NexusWorker was designed from the ground up for strict security:
35
+
36
+ * **Zero Inbound Ports**: The daemon initiates an **outbound-only** encrypted WebSocket connection to the NexusCompute coordinator. You **never** need to configure port forwarding, open firewall rules, or expose a public IP.
37
+ * **Completely Sandboxed**: The worker only communicates with your local inference engine (e.g. Ollama or vLLM) over localhost (`127.0.0.1`).
38
+ * **100% Open Source**: Full transparency—inspect every line of code before running.
39
+
40
+ ---
41
+
42
+ ## 🚀 Quickstart
43
+
44
+ ### 1. Requirements
45
+
46
+ * **OS**: Linux, Windows, or macOS
47
+ * **Python**: 3.9 or higher
48
+ * **Inference Engine**: [Ollama](https://ollama.ai) (recommended for 1-click setup) or [vLLM](https://github.com/vllm-project/vllm).
49
+ * **Hardware**: Any modern GPU with 6GB+ VRAM (e.g. RTX 3060/3080/4090, Apple M-series), or CPU in emulation mode.
50
+
51
+ ---
52
+
53
+ ### 2. Installation
54
+
55
+ Clone and install in a Python virtual environment:
56
+
57
+ ```bash
58
+ git clone https://github.com/nexus-compute-ai/nexus-worker.git
59
+ cd nexus-worker
60
+
61
+ # Create and activate virtual environment
62
+ python -m venv .venv
63
+ # On Windows:
64
+ .\.venv\Scripts\activate
65
+ # On Linux/macOS:
66
+ source .venv/bin/activate
67
+
68
+ # Install package
69
+ pip install -e .
70
+ ```
71
+
72
+ ---
73
+
74
+ ### 3. Check Detected Hardware
75
+
76
+ Verify that your GPU and local models are recognized:
77
+
78
+ ```bash
79
+ nexus-worker info
80
+ ```
81
+
82
+ Example output:
83
+ ```text
84
+ ============================================================
85
+ NEXUSCOMPUTE HARDWARE DETECTOR
86
+ ============================================================
87
+ • GPU: NVIDIA GeForce RTX 4090
88
+ • VRAM: 24,576 MB
89
+ • Backend Engine: Ollama (http://127.0.0.1:11434)
90
+ • Discovered Models:
91
+ - llama3:8b
92
+ - deepseek-r1:7b
93
+ - mistral:7b
94
+ ============================================================
95
+ ```
96
+
97
+ ---
98
+
99
+ ### 4. Connect to Network & Earn
100
+
101
+ Get your node token from the **Provider Dashboard** on NexusCompute, then start the daemon:
102
+
103
+ ```bash
104
+ nexus-worker start --token nx-node-YOUR_TOKEN_HERE
105
+ ```
106
+
107
+ #### CLI Options:
108
+ * `--token TEXT`: Your unique node authorization token *(required)*.
109
+ * `--coordinator TEXT`: Coordinator WebSocket URL (default: `ws://127.0.0.1:8000/api/v1/ws/worker`).
110
+ * `--engine [auto|ollama|vllm|emulate]`: Local inference engine (default: `auto`).
111
+ * `--emulate`: Run in emulation mode for development without downloading weights.
112
+
113
+ ```bash
114
+ # Example with custom coordinator and auto-discovery
115
+ nexus-worker start --token nx-node-0a0a3b29ed4e323af354549a6681821a1b75157e
116
+ ```
117
+
118
+ ---
119
+
120
+ ## 🛠️ Supported Engines
121
+
122
+ 1. **Ollama (Recommended)**: Pull models via `ollama pull llama3:8b`. NexusWorker will auto-detect active models and advertise them to the coordinator.
123
+ 2. **vLLM (High-Throughput)**: Launch with OpenAI-compatible API (`--port 8000`).
124
+ 3. **Emulation Engine**: Built-in mock tokenizer and streaming generator for rapid testing.
125
+
126
+ ---
127
+
128
+ ## 📄 License
129
+
130
+ Distributed under the **MIT License**. See [LICENSE](LICENSE) for more information.
@@ -0,0 +1,15 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ setup.py
5
+ nexus_worker/__init__.py
6
+ nexus_worker/cli.py
7
+ nexus_worker/client.py
8
+ nexus_worker/engine.py
9
+ nexus_worker/hardware.py
10
+ nexus_worker.egg-info/PKG-INFO
11
+ nexus_worker.egg-info/SOURCES.txt
12
+ nexus_worker.egg-info/dependency_links.txt
13
+ nexus_worker.egg-info/entry_points.txt
14
+ nexus_worker.egg-info/requires.txt
15
+ nexus_worker.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ nexus-worker = nexus_worker.cli:cli
@@ -0,0 +1,4 @@
1
+ httpx>=0.27.0
2
+ websockets>=12.0
3
+ click>=8.1.7
4
+ rich>=13.7.0
@@ -0,0 +1 @@
1
+ nexus_worker
@@ -0,0 +1,31 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "nexus-worker"
7
+ version = "0.1.0"
8
+ description = "Monetize your GPU by serving open-source AI inference in the NexusCompute decentralized network."
9
+ readme = "README.md"
10
+ authors = [{ name = "NexusCompute Network", email = "providers@nexuscompute.ai" }]
11
+ license = { text = "MIT" }
12
+ classifiers = [
13
+ "Programming Language :: Python :: 3",
14
+ "License :: OSI Approved :: MIT License",
15
+ "Operating System :: OS Independent",
16
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
17
+ ]
18
+ dependencies = [
19
+ "httpx>=0.27.0",
20
+ "websockets>=12.0",
21
+ "click>=8.1.7",
22
+ "rich>=13.7.0",
23
+ ]
24
+ requires-python = ">=3.9"
25
+
26
+ [project.scripts]
27
+ nexus-worker = "nexus_worker.cli:cli"
28
+
29
+ [tool.setuptools.packages.find]
30
+ where = ["."]
31
+ include = ["nexus_worker*"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,18 @@
1
+ from setuptools import setup, find_packages
2
+
3
+ setup(
4
+ name="nexus-worker",
5
+ version="0.1.0",
6
+ packages=find_packages(),
7
+ install_requires=[
8
+ "httpx>=0.27.0",
9
+ "websockets>=12.0",
10
+ "click>=8.1.7",
11
+ "rich>=13.7.0",
12
+ ],
13
+ entry_points={
14
+ "console_scripts": [
15
+ "nexus-worker = nexus_worker.cli:cli",
16
+ ],
17
+ },
18
+ )