xpyd-proxy 1.2.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.
Files changed (38) hide show
  1. xpyd_proxy-1.2.0/PKG-INFO +307 -0
  2. xpyd_proxy-1.2.0/README.md +281 -0
  3. xpyd_proxy-1.2.0/pyproject.toml +46 -0
  4. xpyd_proxy-1.2.0/setup.cfg +4 -0
  5. xpyd_proxy-1.2.0/xpyd/__init__.py +0 -0
  6. xpyd_proxy-1.2.0/xpyd/circuit_breaker.py +165 -0
  7. xpyd_proxy-1.2.0/xpyd/config.py +631 -0
  8. xpyd_proxy-1.2.0/xpyd/config_fixer.py +585 -0
  9. xpyd_proxy-1.2.0/xpyd/discovery.py +224 -0
  10. xpyd_proxy-1.2.0/xpyd/errors.py +32 -0
  11. xpyd_proxy-1.2.0/xpyd/health_monitor.py +82 -0
  12. xpyd_proxy-1.2.0/xpyd/init_config.py +79 -0
  13. xpyd_proxy-1.2.0/xpyd/metrics.py +256 -0
  14. xpyd_proxy-1.2.0/xpyd/proxy.py +903 -0
  15. xpyd_proxy-1.2.0/xpyd/py.typed +0 -0
  16. xpyd_proxy-1.2.0/xpyd/registry.py +346 -0
  17. xpyd_proxy-1.2.0/xpyd/resilience.py +181 -0
  18. xpyd_proxy-1.2.0/xpyd/routes/__init__.py +17 -0
  19. xpyd_proxy-1.2.0/xpyd/routes/admin.py +102 -0
  20. xpyd_proxy-1.2.0/xpyd/routes/completions.py +551 -0
  21. xpyd_proxy-1.2.0/xpyd/routes/forward.py +61 -0
  22. xpyd_proxy-1.2.0/xpyd/routes/health.py +61 -0
  23. xpyd_proxy-1.2.0/xpyd/scheduler/__init__.py +21 -0
  24. xpyd_proxy-1.2.0/xpyd/scheduler/cache_aware.py +241 -0
  25. xpyd_proxy-1.2.0/xpyd/scheduler/consistent_hash.py +201 -0
  26. xpyd_proxy-1.2.0/xpyd/scheduler/load_balanced.py +213 -0
  27. xpyd_proxy-1.2.0/xpyd/scheduler/policy_registry.py +93 -0
  28. xpyd_proxy-1.2.0/xpyd/scheduler/power_of_two.py +151 -0
  29. xpyd_proxy-1.2.0/xpyd/scheduler/round_robin.py +51 -0
  30. xpyd_proxy-1.2.0/xpyd/scheduler/scheduler_base.py +46 -0
  31. xpyd_proxy-1.2.0/xpyd/topology.py +98 -0
  32. xpyd_proxy-1.2.0/xpyd/utils.py +105 -0
  33. xpyd_proxy-1.2.0/xpyd_proxy.egg-info/PKG-INFO +307 -0
  34. xpyd_proxy-1.2.0/xpyd_proxy.egg-info/SOURCES.txt +36 -0
  35. xpyd_proxy-1.2.0/xpyd_proxy.egg-info/dependency_links.txt +1 -0
  36. xpyd_proxy-1.2.0/xpyd_proxy.egg-info/entry_points.txt +2 -0
  37. xpyd_proxy-1.2.0/xpyd_proxy.egg-info/requires.txt +20 -0
  38. xpyd_proxy-1.2.0/xpyd_proxy.egg-info/top_level.txt +1 -0
@@ -0,0 +1,307 @@
1
+ Metadata-Version: 2.4
2
+ Name: xpyd-proxy
3
+ Version: 1.2.0
4
+ Summary: Lightweight Prefill-Decode proxy for disaggregated LLM serving
5
+ Requires-Python: >=3.10
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: fastapi>=0.110.0
8
+ Requires-Dist: uvicorn>=0.29.0
9
+ Requires-Dist: uvloop>=0.19.0
10
+ Requires-Dist: pydantic>=2.0.0
11
+ Requires-Dist: httpx>=0.27.0
12
+ Requires-Dist: aiohttp>=3.9.0
13
+ Requires-Dist: requests>=2.31.0
14
+ Requires-Dist: colorlog>=6.8.0
15
+ Requires-Dist: transformers>=4.38.0
16
+ Requires-Dist: prometheus-client>=0.20.0
17
+ Requires-Dist: PyYAML>=6.0
18
+ Provides-Extra: dev
19
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
20
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
21
+ Requires-Dist: ruff>=0.4.0; extra == "dev"
22
+ Requires-Dist: isort>=5.13.0; extra == "dev"
23
+ Requires-Dist: tiktoken>=0.7.0; extra == "dev"
24
+ Requires-Dist: pytest-timeout>=2.3.0; extra == "dev"
25
+ Requires-Dist: xpyd-sim>=0.2.0; extra == "dev"
26
+
27
+ # xPyD Proxy
28
+
29
+ A lightweight Prefill-Decode (PD) proxy for disaggregated LLM serving.
30
+
31
+ ## Architecture
32
+
33
+ xPyD Proxy supports two operating modes:
34
+
35
+ ### Prefill-Decode (P/D) Disaggregated Mode
36
+
37
+ Requests are routed through two phases with KV cache transfer:
38
+
39
+ 1. **Prefill** — KV cache preparation on prefill nodes (`max_tokens=1`)
40
+ 2. **Decode** — autoregressive token generation on decode nodes (receives KV cache from prefill)
41
+
42
+ ### Dual-Role Mode
43
+
44
+ A single instance handles both prefill and decode in one pass — no KV transfer needed. This simplifies deployment when disaggregation is not required or for smaller-scale setups.
45
+
46
+ The proxy handles scheduling (load-balanced, round-robin, consistent hash, power-of-two, cache-aware), health monitoring, circuit breaking, and dynamic instance management. Multi-model routing allows serving multiple models through a single proxy with per-model scheduler configuration.
47
+
48
+ See [`docs/architecture.md`](docs/architecture.md) for details.
49
+
50
+ ## Installation
51
+
52
+ ```bash
53
+ pip install .
54
+
55
+ # Verify
56
+ xpyd --version
57
+ ```
58
+
59
+ ## Quick Start
60
+
61
+ ```bash
62
+ # Generate a config template
63
+ xpyd proxy --init-config
64
+
65
+ # Edit xpyd.yaml with your model and node addresses, then:
66
+ xpyd proxy -c xpyd.yaml
67
+ ```
68
+
69
+ ## Configuration
70
+
71
+ All configuration is done via YAML. Three config formats are supported.
72
+
73
+ ### Format 1: Legacy (Single Model)
74
+
75
+ Simple prefill/decode address lists for a single model:
76
+
77
+ ```yaml
78
+ model: /path/to/model
79
+ prefill:
80
+ - "10.0.0.3:8100"
81
+ decode:
82
+ - "10.0.0.1:8200"
83
+ - "10.0.0.2:8200"
84
+ port: 8000
85
+ scheduling: loadbalanced
86
+ ```
87
+
88
+ Topology-style config is also supported in Format 1:
89
+
90
+ ```yaml
91
+ model: /path/to/model
92
+ port: 8868
93
+
94
+ prefill:
95
+ nodes:
96
+ - "10.0.0.1:8100"
97
+ tp_size: 8
98
+ dp_size: 1
99
+ world_size_per_node: 8
100
+
101
+ decode:
102
+ nodes:
103
+ - "10.0.0.2:8200"
104
+ - "10.0.0.3:8200"
105
+ tp_size: 1
106
+ dp_size: 16
107
+ world_size_per_node: 8
108
+ ```
109
+
110
+ ### Format 2: Instances (Multi-Model, Per-Instance Role)
111
+
112
+ Explicit per-instance configuration with role and model assignment. Supports `dual` role:
113
+
114
+ ```yaml
115
+ instances:
116
+ - address: "10.0.0.1:8000"
117
+ role: prefill
118
+ model: llama-3
119
+ - address: "10.0.0.2:8000"
120
+ role: decode
121
+ model: llama-3
122
+ - address: "10.0.0.3:8000"
123
+ role: dual
124
+ model: qwen-2
125
+ port: 8000
126
+ scheduling: loadbalanced
127
+ ```
128
+
129
+ ### Format 3: Models Shorthand (Multi-Model, Per-Model Scheduler)
130
+
131
+ Compact format with per-model scheduler override and `dual` shorthand:
132
+
133
+ ```yaml
134
+ models:
135
+ - name: llama-3
136
+ prefill:
137
+ - "10.0.0.1:8000"
138
+ decode:
139
+ - "10.0.0.2:8000"
140
+ scheduler: round_robin
141
+ - name: qwen-2
142
+ dual:
143
+ - "10.0.0.3:8000"
144
+ - "10.0.0.4:8000"
145
+ scheduler: loadbalanced
146
+ port: 8000
147
+ ```
148
+
149
+ > **Note:** `instances` and `models` cannot be combined. Legacy `prefill`/`decode` lists cannot be used with `instances` or `models`.
150
+
151
+ See [`examples/proxy.yaml`](examples/proxy.yaml) for a fully-commented example.
152
+
153
+ ### CLI Reference
154
+
155
+ ```
156
+ xpyd proxy [OPTIONS]
157
+
158
+ Options:
159
+ --config, -c PATH Path to YAML config (default: ./xpyd.yaml or XPYD_CONFIG env)
160
+ --init-config [PATH] Generate a config template and exit
161
+ --validate-config PATH Validate a config file and exit
162
+ --port PORT Override port from config
163
+ --log-level LEVEL Override log level: debug|info|warning|error
164
+ --version, -V Show version and exit
165
+ ```
166
+
167
+ ```
168
+ xpyd fix-config CONFIG_PATH [OPTIONS]
169
+
170
+ Auto-fix common config mistakes (typos, missing ports, whitespace).
171
+
172
+ Arguments:
173
+ CONFIG_PATH Path to YAML config file to fix
174
+
175
+ Options:
176
+ --write Write fixes back to file (creates timestamped .bak backup).
177
+ Note: does not preserve YAML comments or formatting.
178
+ --interactive Prompt for confirmation on ambiguous suggestions
179
+ ```
180
+
181
+ ### Config resolution order
182
+
183
+ 1. `--config` / `-c` CLI argument
184
+ 2. `XPYD_CONFIG` environment variable
185
+ 3. `./xpyd.yaml` in the current directory
186
+
187
+ ### YAML Config
188
+
189
+ ```yaml
190
+ # Required
191
+ model: /path/to/model
192
+ decode:
193
+ - "10.0.0.1:8200"
194
+ - "10.0.0.2:8200"
195
+
196
+ # Optional
197
+ prefill:
198
+ - "10.0.0.3:8100"
199
+ port: 8000
200
+ log_level: warning
201
+ scheduling: loadbalanced # roundrobin | loadbalanced | consistent_hash | power_of_two | cache_aware
202
+ generator_on_p_node: false
203
+ ```
204
+
205
+ See [`examples/proxy.yaml`](examples/proxy.yaml) for a fully-commented example.
206
+
207
+ ### YAML Fields Reference
208
+
209
+ | Field | Type | Default | Description |
210
+ |---|---|---|---|
211
+ | `model` | string | — | Model name / path (required in Format 1) |
212
+ | `port` | int | 8000 | Proxy listen port |
213
+ | `log_level` | string | warning | Log level: debug, info, warning, error |
214
+ | `prefill` | list or topology | [] | Prefill node config (Format 1) |
215
+ | `decode` | list or topology | — | Decode node config (Format 1, required) |
216
+ | `instances` | list | — | Per-instance config (Format 2): `{address, role, model}` |
217
+ | `models` | list | — | Per-model shorthand (Format 3): `{name, prefill, decode, dual, scheduler}` |
218
+ | `scheduling` | string | loadbalanced | Global scheduling policy |
219
+ | `scheduling_config` | dict | {} | Policy-specific options |
220
+ | `generator_on_p_node` | bool | false | Generate first token on prefill node |
221
+ | `admin_api_key` | string | — | Admin API key (env `ADMIN_API_KEY` overrides) |
222
+ | `openai_api_key` | string | — | OpenAI API key (env `OPENAI_API_KEY` overrides) |
223
+ | `startup.wait_timeout_seconds` | int | 600 | Max wait for nodes at startup |
224
+ | `startup.probe_interval_seconds` | int | 10 | Health probe interval |
225
+
226
+ **Valid `role` values:** `prefill`, `decode`, `dual`
227
+
228
+ **Valid `scheduling` values:** `loadbalanced`, `roundrobin` (alias: `round_robin`), `load_balanced`, `consistent_hash`, `power_of_two`, `cache_aware`
229
+
230
+ ### API
231
+
232
+ The proxy exposes an OpenAI-compatible API:
233
+
234
+ - **`POST /v1/chat/completions`** — Chat completions (streaming and non-streaming)
235
+ - **`POST /v1/completions`** — Text completions (streaming and non-streaming)
236
+ - **`GET /v1/models`** — List all registered models in OpenAI-compatible format
237
+
238
+ ### Startup Node Discovery
239
+
240
+ The proxy returns **503** on business endpoints until the minimum instance requirement is met: at least **1 prefill + 1 decode** node, or **1 dual** node per model must respond healthy. Health/status/metrics endpoints are always available.
241
+
242
+ ## Docker
243
+
244
+ ```bash
245
+ # Full local topology (prefill + decode + proxy)
246
+ docker compose up --build
247
+
248
+ # Proxy only, connecting to existing GPU nodes
249
+ docker build -t xpyd .
250
+ docker run -p 8868:8868 -v ./config.yaml:/app/xpyd.yaml xpyd
251
+ ```
252
+
253
+ See [`docs/deployment.md`](docs/deployment.md) for production deployment.
254
+
255
+ ## Benchmark
256
+
257
+ ```bash
258
+ python -m vllm bench serve \
259
+ --base-url http://localhost:8868 \
260
+ --model DeepSeek-R1 \
261
+ --dataset-name sonnet \
262
+ --sonnet-input-len 1024 \
263
+ --sonnet-output-len 128 \
264
+ --num-prompts 100 \
265
+ --request-rate 10
266
+ ```
267
+
268
+ ## Development
269
+
270
+ ```bash
271
+ # Install in dev mode
272
+ pip install -e ".[dev]"
273
+
274
+ # Run tests
275
+ python -m pytest tests/unit/ tests/integration/ -v
276
+
277
+ # Lint
278
+ pre-commit run --all-files
279
+ ```
280
+
281
+ ### Environment Variables
282
+
283
+ | Variable | Description |
284
+ |---|---|
285
+ | `XPYD_CONFIG` | Default config file path |
286
+ | `ADMIN_API_KEY` | Admin API key (overrides YAML) |
287
+ | `OPENAI_API_KEY` | Bearer token for backend nodes (overrides YAML) |
288
+ | `PREFILL_DELAY_PER_TOKEN` | Simulated prefill latency for dummy nodes (default: 0.001s) |
289
+ | `DECODE_DELAY_PER_TOKEN` | Simulated decode latency for dummy nodes (default: 0.01s) |
290
+
291
+ ## Documentation
292
+
293
+ | Document | Description |
294
+ |---|---|
295
+ | [Architecture](docs/architecture.md) | System architecture overview |
296
+ | [API Reference](docs/api_reference.md) | HTTP API endpoints |
297
+ | [Configuration](docs/configuration.md) | YAML config reference |
298
+ | [CLI](docs/cli.md) | xpyd command-line tool |
299
+ | [Scheduling](docs/scheduling.md) | Load balancing strategies |
300
+ | [Resilience](docs/resilience.md) | Health checks, circuit breakers, retry |
301
+ | [Metrics](docs/metrics.md) | Prometheus metrics endpoint |
302
+ | [Deployment](docs/deployment.md) | Deployment and Docker guide |
303
+ | [Contributing](CONTRIBUTING.md) | Contribution guidelines |
304
+
305
+ ## License
306
+
307
+ Apache-2.0
@@ -0,0 +1,281 @@
1
+ # xPyD Proxy
2
+
3
+ A lightweight Prefill-Decode (PD) proxy for disaggregated LLM serving.
4
+
5
+ ## Architecture
6
+
7
+ xPyD Proxy supports two operating modes:
8
+
9
+ ### Prefill-Decode (P/D) Disaggregated Mode
10
+
11
+ Requests are routed through two phases with KV cache transfer:
12
+
13
+ 1. **Prefill** — KV cache preparation on prefill nodes (`max_tokens=1`)
14
+ 2. **Decode** — autoregressive token generation on decode nodes (receives KV cache from prefill)
15
+
16
+ ### Dual-Role Mode
17
+
18
+ A single instance handles both prefill and decode in one pass — no KV transfer needed. This simplifies deployment when disaggregation is not required or for smaller-scale setups.
19
+
20
+ The proxy handles scheduling (load-balanced, round-robin, consistent hash, power-of-two, cache-aware), health monitoring, circuit breaking, and dynamic instance management. Multi-model routing allows serving multiple models through a single proxy with per-model scheduler configuration.
21
+
22
+ See [`docs/architecture.md`](docs/architecture.md) for details.
23
+
24
+ ## Installation
25
+
26
+ ```bash
27
+ pip install .
28
+
29
+ # Verify
30
+ xpyd --version
31
+ ```
32
+
33
+ ## Quick Start
34
+
35
+ ```bash
36
+ # Generate a config template
37
+ xpyd proxy --init-config
38
+
39
+ # Edit xpyd.yaml with your model and node addresses, then:
40
+ xpyd proxy -c xpyd.yaml
41
+ ```
42
+
43
+ ## Configuration
44
+
45
+ All configuration is done via YAML. Three config formats are supported.
46
+
47
+ ### Format 1: Legacy (Single Model)
48
+
49
+ Simple prefill/decode address lists for a single model:
50
+
51
+ ```yaml
52
+ model: /path/to/model
53
+ prefill:
54
+ - "10.0.0.3:8100"
55
+ decode:
56
+ - "10.0.0.1:8200"
57
+ - "10.0.0.2:8200"
58
+ port: 8000
59
+ scheduling: loadbalanced
60
+ ```
61
+
62
+ Topology-style config is also supported in Format 1:
63
+
64
+ ```yaml
65
+ model: /path/to/model
66
+ port: 8868
67
+
68
+ prefill:
69
+ nodes:
70
+ - "10.0.0.1:8100"
71
+ tp_size: 8
72
+ dp_size: 1
73
+ world_size_per_node: 8
74
+
75
+ decode:
76
+ nodes:
77
+ - "10.0.0.2:8200"
78
+ - "10.0.0.3:8200"
79
+ tp_size: 1
80
+ dp_size: 16
81
+ world_size_per_node: 8
82
+ ```
83
+
84
+ ### Format 2: Instances (Multi-Model, Per-Instance Role)
85
+
86
+ Explicit per-instance configuration with role and model assignment. Supports `dual` role:
87
+
88
+ ```yaml
89
+ instances:
90
+ - address: "10.0.0.1:8000"
91
+ role: prefill
92
+ model: llama-3
93
+ - address: "10.0.0.2:8000"
94
+ role: decode
95
+ model: llama-3
96
+ - address: "10.0.0.3:8000"
97
+ role: dual
98
+ model: qwen-2
99
+ port: 8000
100
+ scheduling: loadbalanced
101
+ ```
102
+
103
+ ### Format 3: Models Shorthand (Multi-Model, Per-Model Scheduler)
104
+
105
+ Compact format with per-model scheduler override and `dual` shorthand:
106
+
107
+ ```yaml
108
+ models:
109
+ - name: llama-3
110
+ prefill:
111
+ - "10.0.0.1:8000"
112
+ decode:
113
+ - "10.0.0.2:8000"
114
+ scheduler: round_robin
115
+ - name: qwen-2
116
+ dual:
117
+ - "10.0.0.3:8000"
118
+ - "10.0.0.4:8000"
119
+ scheduler: loadbalanced
120
+ port: 8000
121
+ ```
122
+
123
+ > **Note:** `instances` and `models` cannot be combined. Legacy `prefill`/`decode` lists cannot be used with `instances` or `models`.
124
+
125
+ See [`examples/proxy.yaml`](examples/proxy.yaml) for a fully-commented example.
126
+
127
+ ### CLI Reference
128
+
129
+ ```
130
+ xpyd proxy [OPTIONS]
131
+
132
+ Options:
133
+ --config, -c PATH Path to YAML config (default: ./xpyd.yaml or XPYD_CONFIG env)
134
+ --init-config [PATH] Generate a config template and exit
135
+ --validate-config PATH Validate a config file and exit
136
+ --port PORT Override port from config
137
+ --log-level LEVEL Override log level: debug|info|warning|error
138
+ --version, -V Show version and exit
139
+ ```
140
+
141
+ ```
142
+ xpyd fix-config CONFIG_PATH [OPTIONS]
143
+
144
+ Auto-fix common config mistakes (typos, missing ports, whitespace).
145
+
146
+ Arguments:
147
+ CONFIG_PATH Path to YAML config file to fix
148
+
149
+ Options:
150
+ --write Write fixes back to file (creates timestamped .bak backup).
151
+ Note: does not preserve YAML comments or formatting.
152
+ --interactive Prompt for confirmation on ambiguous suggestions
153
+ ```
154
+
155
+ ### Config resolution order
156
+
157
+ 1. `--config` / `-c` CLI argument
158
+ 2. `XPYD_CONFIG` environment variable
159
+ 3. `./xpyd.yaml` in the current directory
160
+
161
+ ### YAML Config
162
+
163
+ ```yaml
164
+ # Required
165
+ model: /path/to/model
166
+ decode:
167
+ - "10.0.0.1:8200"
168
+ - "10.0.0.2:8200"
169
+
170
+ # Optional
171
+ prefill:
172
+ - "10.0.0.3:8100"
173
+ port: 8000
174
+ log_level: warning
175
+ scheduling: loadbalanced # roundrobin | loadbalanced | consistent_hash | power_of_two | cache_aware
176
+ generator_on_p_node: false
177
+ ```
178
+
179
+ See [`examples/proxy.yaml`](examples/proxy.yaml) for a fully-commented example.
180
+
181
+ ### YAML Fields Reference
182
+
183
+ | Field | Type | Default | Description |
184
+ |---|---|---|---|
185
+ | `model` | string | — | Model name / path (required in Format 1) |
186
+ | `port` | int | 8000 | Proxy listen port |
187
+ | `log_level` | string | warning | Log level: debug, info, warning, error |
188
+ | `prefill` | list or topology | [] | Prefill node config (Format 1) |
189
+ | `decode` | list or topology | — | Decode node config (Format 1, required) |
190
+ | `instances` | list | — | Per-instance config (Format 2): `{address, role, model}` |
191
+ | `models` | list | — | Per-model shorthand (Format 3): `{name, prefill, decode, dual, scheduler}` |
192
+ | `scheduling` | string | loadbalanced | Global scheduling policy |
193
+ | `scheduling_config` | dict | {} | Policy-specific options |
194
+ | `generator_on_p_node` | bool | false | Generate first token on prefill node |
195
+ | `admin_api_key` | string | — | Admin API key (env `ADMIN_API_KEY` overrides) |
196
+ | `openai_api_key` | string | — | OpenAI API key (env `OPENAI_API_KEY` overrides) |
197
+ | `startup.wait_timeout_seconds` | int | 600 | Max wait for nodes at startup |
198
+ | `startup.probe_interval_seconds` | int | 10 | Health probe interval |
199
+
200
+ **Valid `role` values:** `prefill`, `decode`, `dual`
201
+
202
+ **Valid `scheduling` values:** `loadbalanced`, `roundrobin` (alias: `round_robin`), `load_balanced`, `consistent_hash`, `power_of_two`, `cache_aware`
203
+
204
+ ### API
205
+
206
+ The proxy exposes an OpenAI-compatible API:
207
+
208
+ - **`POST /v1/chat/completions`** — Chat completions (streaming and non-streaming)
209
+ - **`POST /v1/completions`** — Text completions (streaming and non-streaming)
210
+ - **`GET /v1/models`** — List all registered models in OpenAI-compatible format
211
+
212
+ ### Startup Node Discovery
213
+
214
+ The proxy returns **503** on business endpoints until the minimum instance requirement is met: at least **1 prefill + 1 decode** node, or **1 dual** node per model must respond healthy. Health/status/metrics endpoints are always available.
215
+
216
+ ## Docker
217
+
218
+ ```bash
219
+ # Full local topology (prefill + decode + proxy)
220
+ docker compose up --build
221
+
222
+ # Proxy only, connecting to existing GPU nodes
223
+ docker build -t xpyd .
224
+ docker run -p 8868:8868 -v ./config.yaml:/app/xpyd.yaml xpyd
225
+ ```
226
+
227
+ See [`docs/deployment.md`](docs/deployment.md) for production deployment.
228
+
229
+ ## Benchmark
230
+
231
+ ```bash
232
+ python -m vllm bench serve \
233
+ --base-url http://localhost:8868 \
234
+ --model DeepSeek-R1 \
235
+ --dataset-name sonnet \
236
+ --sonnet-input-len 1024 \
237
+ --sonnet-output-len 128 \
238
+ --num-prompts 100 \
239
+ --request-rate 10
240
+ ```
241
+
242
+ ## Development
243
+
244
+ ```bash
245
+ # Install in dev mode
246
+ pip install -e ".[dev]"
247
+
248
+ # Run tests
249
+ python -m pytest tests/unit/ tests/integration/ -v
250
+
251
+ # Lint
252
+ pre-commit run --all-files
253
+ ```
254
+
255
+ ### Environment Variables
256
+
257
+ | Variable | Description |
258
+ |---|---|
259
+ | `XPYD_CONFIG` | Default config file path |
260
+ | `ADMIN_API_KEY` | Admin API key (overrides YAML) |
261
+ | `OPENAI_API_KEY` | Bearer token for backend nodes (overrides YAML) |
262
+ | `PREFILL_DELAY_PER_TOKEN` | Simulated prefill latency for dummy nodes (default: 0.001s) |
263
+ | `DECODE_DELAY_PER_TOKEN` | Simulated decode latency for dummy nodes (default: 0.01s) |
264
+
265
+ ## Documentation
266
+
267
+ | Document | Description |
268
+ |---|---|
269
+ | [Architecture](docs/architecture.md) | System architecture overview |
270
+ | [API Reference](docs/api_reference.md) | HTTP API endpoints |
271
+ | [Configuration](docs/configuration.md) | YAML config reference |
272
+ | [CLI](docs/cli.md) | xpyd command-line tool |
273
+ | [Scheduling](docs/scheduling.md) | Load balancing strategies |
274
+ | [Resilience](docs/resilience.md) | Health checks, circuit breakers, retry |
275
+ | [Metrics](docs/metrics.md) | Prometheus metrics endpoint |
276
+ | [Deployment](docs/deployment.md) | Deployment and Docker guide |
277
+ | [Contributing](CONTRIBUTING.md) | Contribution guidelines |
278
+
279
+ ## License
280
+
281
+ Apache-2.0
@@ -0,0 +1,46 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "xpyd-proxy"
7
+ version = "1.2.0"
8
+ description = "Lightweight Prefill-Decode proxy for disaggregated LLM serving"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ dependencies = [
12
+ "fastapi>=0.110.0",
13
+ "uvicorn>=0.29.0",
14
+ "uvloop>=0.19.0",
15
+ "pydantic>=2.0.0",
16
+ "httpx>=0.27.0",
17
+ "aiohttp>=3.9.0",
18
+ "requests>=2.31.0",
19
+ "colorlog>=6.8.0",
20
+ "transformers>=4.38.0",
21
+ "prometheus-client>=0.20.0",
22
+ "PyYAML>=6.0",
23
+ ]
24
+
25
+ [project.optional-dependencies]
26
+ dev = [
27
+ "pytest>=8.0.0",
28
+ "pytest-asyncio>=0.23.0",
29
+ "ruff>=0.4.0",
30
+ "isort>=5.13.0",
31
+ "tiktoken>=0.7.0",
32
+ "pytest-timeout>=2.3.0",
33
+ "xpyd-sim>=0.2.0",
34
+ ]
35
+
36
+ [project.scripts]
37
+ xpyd = "xpyd.proxy:main"
38
+
39
+ [tool.setuptools.packages.find]
40
+ include = ["xpyd*"]
41
+
42
+ [tool.pytest.ini_options]
43
+ pythonpath = ["."]
44
+ markers = [
45
+ "benchmark: end-to-end benchmark tests (high concurrency, large clusters)",
46
+ ]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
File without changes