deltacert 1.0.0__py3-none-any.whl
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.
- deltacert/__init__.py +371 -0
- deltacert/cli.py +673 -0
- deltacert/collectors.py +2182 -0
- deltacert/deltacert.py +916 -0
- deltacert/example_certify.py +88 -0
- deltacert/integrations/__init__.py +0 -0
- deltacert/integrations/cicd_hook.py +117 -0
- deltacert/integrations/hf_integration.py +166 -0
- deltacert/integrations/vllm_integration.py +103 -0
- deltacert-1.0.0.dist-info/METADATA +24 -0
- deltacert-1.0.0.dist-info/RECORD +14 -0
- deltacert-1.0.0.dist-info/WHEEL +5 -0
- deltacert-1.0.0.dist-info/entry_points.txt +5 -0
- deltacert-1.0.0.dist-info/top_level.txt +1 -0
deltacert/__init__.py
ADDED
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
"""
|
|
2
|
+
DeltaCert — Universal Bounded Divergence Certification for LLM Serving Systems
|
|
3
|
+
|
|
4
|
+
pip install deltacert
|
|
5
|
+
|
|
6
|
+
Quickstart:
|
|
7
|
+
import deltacert as dc
|
|
8
|
+
|
|
9
|
+
cert = dc.certify_system(
|
|
10
|
+
model="meta-llama/Llama-3.1-8B",
|
|
11
|
+
prompts=my_prompts,
|
|
12
|
+
checks=["engine_swap", "weight_quant", "batch_divergence"],
|
|
13
|
+
output_path="./cert.json",
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
# At server startup — refuses to start if not certified
|
|
17
|
+
dc.enforce("./cert.json")
|
|
18
|
+
|
|
19
|
+
Full check names:
|
|
20
|
+
"engine_swap" — certify vLLM version upgrade / backend migration
|
|
21
|
+
"batch_divergence" — certify batch-size nondeterminism is bounded
|
|
22
|
+
"spec_decoding" — certify speculative decoding ON vs OFF (same engine)
|
|
23
|
+
"sparse_attention" — certify sparse attention mask vs full attention
|
|
24
|
+
"moe_token_dropping" — certify MoE capacity factor token dropping
|
|
25
|
+
"neuron_skipping" — certify runtime neuron pruning (SRED/SNAP)
|
|
26
|
+
"weight_quant" — certify int4/int8 weight quantization
|
|
27
|
+
"kv_cache_quant" — certify KV cache quantization
|
|
28
|
+
"lora" — certify LoRA adapter vs full model
|
|
29
|
+
"allreduce_tp" — certify compressed tensor-parallel AllReduce
|
|
30
|
+
"alltoall_ep" — certify compressed expert-parallel All-to-All
|
|
31
|
+
"pipeline_parallel" — certify compressed pipeline stage activations
|
|
32
|
+
"kv_transfer" — certify compressed prefill→decode KV transfer
|
|
33
|
+
"prefix_cache" — certify prefix/prompt cache reuse
|
|
34
|
+
"activation_quant" — certify activation quantization
|
|
35
|
+
"gradient_compress" — certify gradient compression fidelity (training)
|
|
36
|
+
"model_swap" — certify checkpoint update (old vs new fine-tune)
|
|
37
|
+
"provider_drift" — certify hosted API hasn't drifted from baseline
|
|
38
|
+
"prompt_swap" — certify system prompt edit before shipping
|
|
39
|
+
"trajectory" — certify optimization over full continuations (long-context)
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
from deltacert.collectors import (
|
|
43
|
+
CollectionError,
|
|
44
|
+
collect_allreduce_tp,
|
|
45
|
+
collect_alltoall_ep,
|
|
46
|
+
collect_pipeline_parallel,
|
|
47
|
+
collect_pipeline_parallel_tensors,
|
|
48
|
+
collect_kv_transfer,
|
|
49
|
+
collect_weight_quant,
|
|
50
|
+
collect_kv_cache_quant,
|
|
51
|
+
collect_activation_quant,
|
|
52
|
+
collect_gradient_compress,
|
|
53
|
+
collect_lora,
|
|
54
|
+
collect_prefix_cache,
|
|
55
|
+
collect_engine_swap,
|
|
56
|
+
collect_batch_divergence,
|
|
57
|
+
collect_speculative_decode,
|
|
58
|
+
collect_sparse_attention,
|
|
59
|
+
collect_moe_token_dropping,
|
|
60
|
+
collect_neuron_skipping,
|
|
61
|
+
collect_model_swap,
|
|
62
|
+
capture_logits_openai_api,
|
|
63
|
+
collect_provider_drift,
|
|
64
|
+
collect_prompt_swap,
|
|
65
|
+
d_profile,
|
|
66
|
+
trajectory_layer_result,
|
|
67
|
+
collect_trajectory,
|
|
68
|
+
collect_trajectory_two_models,
|
|
69
|
+
save_logits,
|
|
70
|
+
load_logits,
|
|
71
|
+
capture_logits_hf,
|
|
72
|
+
capture_logits_vllm,
|
|
73
|
+
certify_from_layers,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
from deltacert.deltacert import (
|
|
77
|
+
# Core formula
|
|
78
|
+
d_comm,
|
|
79
|
+
divergence_bound,
|
|
80
|
+
certify_layer,
|
|
81
|
+
calibrate_layer,
|
|
82
|
+
|
|
83
|
+
# Config
|
|
84
|
+
InferenceConfig,
|
|
85
|
+
LayerSpec,
|
|
86
|
+
|
|
87
|
+
# Layer name constants
|
|
88
|
+
LAYER_ALLREDUCE_TP,
|
|
89
|
+
LAYER_ALLTOALL_EP,
|
|
90
|
+
LAYER_PIPELINE_PARALLEL,
|
|
91
|
+
LAYER_KV_TRANSFER,
|
|
92
|
+
LAYER_WEIGHT_QUANT,
|
|
93
|
+
LAYER_KV_CACHE_QUANT,
|
|
94
|
+
LAYER_ACTIVATION_QUANT,
|
|
95
|
+
LAYER_GRADIENT_COMP,
|
|
96
|
+
LAYER_LORA,
|
|
97
|
+
LAYER_PREFIX_CACHE,
|
|
98
|
+
LAYER_ENGINE_SWAP,
|
|
99
|
+
LAYER_BATCH_DIVERGENCE,
|
|
100
|
+
LAYER_SPEC_DECODING,
|
|
101
|
+
LAYER_SPARSE_ATTENTION,
|
|
102
|
+
LAYER_MOE_TOKEN_DROP,
|
|
103
|
+
LAYER_NEURON_SKIPPING,
|
|
104
|
+
LAYER_MODEL_SWAP,
|
|
105
|
+
LAYER_PROVIDER_DRIFT,
|
|
106
|
+
LAYER_PROMPT_SWAP,
|
|
107
|
+
LAYER_TRAJECTORY,
|
|
108
|
+
|
|
109
|
+
# Main API
|
|
110
|
+
certify,
|
|
111
|
+
certify_system,
|
|
112
|
+
load_certificate,
|
|
113
|
+
check_certified,
|
|
114
|
+
enforce,
|
|
115
|
+
compose_bounds,
|
|
116
|
+
summary,
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
def certify_safe(
|
|
120
|
+
baseline,
|
|
121
|
+
candidate=None,
|
|
122
|
+
tokenizer=None,
|
|
123
|
+
prompts=None,
|
|
124
|
+
*,
|
|
125
|
+
check: str = None,
|
|
126
|
+
budget: float = 3.0,
|
|
127
|
+
raise_on_fail: bool = True,
|
|
128
|
+
**kwargs,
|
|
129
|
+
) -> bool:
|
|
130
|
+
"""One call covers all 20 collectors. Raises DeploymentBlocked if not certified.
|
|
131
|
+
|
|
132
|
+
Auto-detects the check for the two most common cases:
|
|
133
|
+
two torch models → weight_quant
|
|
134
|
+
two .npz paths → engine_swap
|
|
135
|
+
http:// string → provider_drift
|
|
136
|
+
|
|
137
|
+
For everything else pass check= explicitly:
|
|
138
|
+
|
|
139
|
+
certify_safe(model, tok, prompts, check="kv_cache_quant",
|
|
140
|
+
compress_fn=c, decompress_fn=d)
|
|
141
|
+
certify_safe(model, tok, prompts, check="lora",
|
|
142
|
+
lora_adapter_path="adapter/")
|
|
143
|
+
certify_safe(model, tok, prompts, check="prefix_cache",
|
|
144
|
+
shared_prefix="You are a helpful assistant.")
|
|
145
|
+
certify_safe("gpt-4o-mini", prompts=prompts, check="provider_drift",
|
|
146
|
+
api_base="https://api.openai.com/v1",
|
|
147
|
+
baseline_path="drift/baseline.npz")
|
|
148
|
+
certify_safe("meta-llama/Llama-3.1-8B", prompts=prompts,
|
|
149
|
+
check="spec_decoding",
|
|
150
|
+
speculative_config={"model": "draft", "num_speculative_tokens": 5})
|
|
151
|
+
"""
|
|
152
|
+
import os
|
|
153
|
+
from deltacert.collectors import (
|
|
154
|
+
collect_weight_quant, collect_engine_swap, collect_model_swap,
|
|
155
|
+
collect_provider_drift, collect_lora, collect_prefix_cache,
|
|
156
|
+
collect_prompt_swap, collect_kv_cache_quant, collect_kv_transfer,
|
|
157
|
+
collect_activation_quant, collect_gradient_compress,
|
|
158
|
+
collect_allreduce_tp, collect_alltoall_ep, collect_pipeline_parallel,
|
|
159
|
+
collect_batch_divergence, collect_speculative_decode,
|
|
160
|
+
collect_sparse_attention, collect_moe_token_dropping,
|
|
161
|
+
collect_neuron_skipping, collect_trajectory_two_models,
|
|
162
|
+
trajectory_layer_result, certify_from_layers, _make_layer_result,
|
|
163
|
+
d_comm as _d_comm, CollectionError,
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
# ── auto-detect check for the common cases ────────────────────────────────
|
|
167
|
+
if check is None:
|
|
168
|
+
try:
|
|
169
|
+
import torch
|
|
170
|
+
if (isinstance(baseline, torch.nn.Module)
|
|
171
|
+
and isinstance(candidate, torch.nn.Module)):
|
|
172
|
+
check = "weight_quant"
|
|
173
|
+
except ImportError:
|
|
174
|
+
pass
|
|
175
|
+
if check is None:
|
|
176
|
+
if (isinstance(baseline, str) and isinstance(candidate, str)
|
|
177
|
+
and baseline.endswith(".npz") and candidate.endswith(".npz")):
|
|
178
|
+
check = "engine_swap"
|
|
179
|
+
elif (isinstance(baseline, str)
|
|
180
|
+
and (baseline.startswith("http://") or baseline.startswith("https://"))):
|
|
181
|
+
check = "provider_drift"
|
|
182
|
+
if check is None:
|
|
183
|
+
raise ValueError(
|
|
184
|
+
"certify_safe: cannot auto-detect check from these arguments. "
|
|
185
|
+
"Pass check='weight_quant' (or any of the 20 collector names). "
|
|
186
|
+
"Full list: deltacert.__all__"
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
# ── route to the right collector ─────────────────────────────────────────
|
|
190
|
+
_trajectory = check == "trajectory"
|
|
191
|
+
|
|
192
|
+
if check == "weight_quant":
|
|
193
|
+
cos_sims = collect_weight_quant(baseline, candidate, tokenizer, prompts)
|
|
194
|
+
elif check == "engine_swap":
|
|
195
|
+
cos_sims = collect_engine_swap(baseline, candidate)
|
|
196
|
+
elif check == "model_swap":
|
|
197
|
+
cos_sims = collect_model_swap(baseline, candidate)
|
|
198
|
+
elif check == "provider_drift":
|
|
199
|
+
api_base = kwargs.pop("api_base", baseline)
|
|
200
|
+
baseline_path = kwargs.pop("baseline_path", "deltacert_baseline.npz")
|
|
201
|
+
api_key = kwargs.pop("api_key", None)
|
|
202
|
+
cos_sims = collect_provider_drift(
|
|
203
|
+
api_base, candidate or kwargs.pop("model", ""), prompts,
|
|
204
|
+
baseline_path, api_key=api_key, **kwargs)
|
|
205
|
+
elif check == "lora":
|
|
206
|
+
cos_sims = collect_lora(baseline, tokenizer, prompts,
|
|
207
|
+
kwargs.pop("lora_adapter_path"), **kwargs)
|
|
208
|
+
elif check == "prefix_cache":
|
|
209
|
+
cos_sims = collect_prefix_cache(baseline, tokenizer, prompts,
|
|
210
|
+
kwargs.pop("shared_prefix"), **kwargs)
|
|
211
|
+
elif check == "prompt_swap":
|
|
212
|
+
cos_sims = collect_prompt_swap(baseline, tokenizer, prompts,
|
|
213
|
+
kwargs.pop("system_prompt_a"),
|
|
214
|
+
kwargs.pop("system_prompt_b"), **kwargs)
|
|
215
|
+
elif check == "kv_cache_quant":
|
|
216
|
+
cos_sims = collect_kv_cache_quant(baseline, tokenizer, prompts,
|
|
217
|
+
kwargs.pop("compress_fn"),
|
|
218
|
+
kwargs.pop("decompress_fn"), **kwargs)
|
|
219
|
+
elif check == "kv_transfer":
|
|
220
|
+
cos_sims = collect_kv_transfer(baseline, tokenizer, prompts,
|
|
221
|
+
kwargs.pop("compress_fn"),
|
|
222
|
+
kwargs.pop("decompress_fn"), **kwargs)
|
|
223
|
+
elif check == "activation_quant":
|
|
224
|
+
cos_sims = collect_activation_quant(baseline, tokenizer, prompts,
|
|
225
|
+
kwargs.pop("quant_fn"), **kwargs)
|
|
226
|
+
elif check == "gradient_compress":
|
|
227
|
+
cos_sims = collect_gradient_compress(baseline, tokenizer, prompts,
|
|
228
|
+
kwargs.pop("compress_fn"), **kwargs)
|
|
229
|
+
elif check == "allreduce_tp":
|
|
230
|
+
cos_sims = collect_allreduce_tp(baseline, tokenizer, prompts,
|
|
231
|
+
kwargs.pop("compress_fn"), **kwargs)
|
|
232
|
+
elif check == "alltoall_ep":
|
|
233
|
+
cos_sims = collect_alltoall_ep(baseline, tokenizer, prompts,
|
|
234
|
+
kwargs.pop("compress_fn"), **kwargs)
|
|
235
|
+
elif check == "pipeline_parallel":
|
|
236
|
+
cos_sims = collect_pipeline_parallel(baseline, tokenizer, prompts,
|
|
237
|
+
kwargs.pop("compress_fn"), **kwargs)
|
|
238
|
+
elif check == "sparse_attention":
|
|
239
|
+
cos_sims = collect_sparse_attention(baseline, tokenizer, prompts,
|
|
240
|
+
kwargs.pop("sparse_context"), **kwargs)
|
|
241
|
+
elif check == "moe_token_dropping":
|
|
242
|
+
cos_sims = collect_moe_token_dropping(baseline, tokenizer, prompts,
|
|
243
|
+
kwargs.pop("set_capacity"), **kwargs)
|
|
244
|
+
elif check == "neuron_skipping":
|
|
245
|
+
cos_sims = collect_neuron_skipping(baseline, tokenizer, prompts,
|
|
246
|
+
kwargs.pop("prune_context"), **kwargs)
|
|
247
|
+
elif check == "batch_divergence":
|
|
248
|
+
cos_sims = collect_batch_divergence(baseline, prompts, **kwargs)
|
|
249
|
+
elif check == "spec_decoding":
|
|
250
|
+
cos_sims = collect_speculative_decode(
|
|
251
|
+
baseline, prompts, kwargs.pop("speculative_config"), **kwargs)
|
|
252
|
+
elif check == "trajectory":
|
|
253
|
+
profiles = collect_trajectory_two_models(
|
|
254
|
+
baseline, candidate, tokenizer, prompts, **kwargs)
|
|
255
|
+
layer = trajectory_layer_result(profiles)
|
|
256
|
+
certified = layer["certified"]
|
|
257
|
+
if not certified and raise_on_fail:
|
|
258
|
+
raise CollectionError(
|
|
259
|
+
f"certify_safe(trajectory): NOT certified — "
|
|
260
|
+
f"d_min={layer['d_comm']:.3f} < budget={budget}.")
|
|
261
|
+
return certified
|
|
262
|
+
else:
|
|
263
|
+
raise ValueError(
|
|
264
|
+
f"certify_safe: unknown check '{check}'. "
|
|
265
|
+
f"Valid checks: {sorted(_VALID_CHECKS)}")
|
|
266
|
+
|
|
267
|
+
layer = _make_layer_result(cos_sims, threshold=budget)
|
|
268
|
+
d = layer["d_comm"]
|
|
269
|
+
certified = d >= budget
|
|
270
|
+
if not certified and raise_on_fail:
|
|
271
|
+
raise CollectionError(
|
|
272
|
+
f"certify_safe({check}): NOT certified — "
|
|
273
|
+
f"d={d:.3f} < budget={budget}. Deploy blocked.")
|
|
274
|
+
return certified
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
_VALID_CHECKS = {
|
|
278
|
+
"weight_quant", "kv_cache_quant", "kv_transfer", "activation_quant",
|
|
279
|
+
"gradient_compress", "lora", "prefix_cache", "engine_swap", "model_swap",
|
|
280
|
+
"batch_divergence", "spec_decoding", "sparse_attention", "moe_token_dropping",
|
|
281
|
+
"neuron_skipping", "allreduce_tp", "alltoall_ep", "pipeline_parallel",
|
|
282
|
+
"provider_drift", "prompt_swap", "trajectory",
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
class DeploymentBlocked(RuntimeError):
|
|
287
|
+
"""Raised by certify_safe when raise_on_fail=True and d < budget."""
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
__version__ = "1.0.0"
|
|
291
|
+
__all__ = [
|
|
292
|
+
# Main API
|
|
293
|
+
"certify_safe",
|
|
294
|
+
"DeploymentBlocked",
|
|
295
|
+
"certify_system",
|
|
296
|
+
"certify",
|
|
297
|
+
"enforce",
|
|
298
|
+
"load_certificate",
|
|
299
|
+
"check_certified",
|
|
300
|
+
"summary",
|
|
301
|
+
"compose_bounds",
|
|
302
|
+
"CollectionError",
|
|
303
|
+
|
|
304
|
+
# Core formula
|
|
305
|
+
"d_comm",
|
|
306
|
+
"divergence_bound",
|
|
307
|
+
"certify_layer",
|
|
308
|
+
"calibrate_layer",
|
|
309
|
+
|
|
310
|
+
# Config
|
|
311
|
+
"InferenceConfig",
|
|
312
|
+
"LayerSpec",
|
|
313
|
+
|
|
314
|
+
# Layer name constants (all 20)
|
|
315
|
+
"LAYER_ALLREDUCE_TP",
|
|
316
|
+
"LAYER_ALLTOALL_EP",
|
|
317
|
+
"LAYER_PIPELINE_PARALLEL",
|
|
318
|
+
"LAYER_KV_TRANSFER",
|
|
319
|
+
"LAYER_WEIGHT_QUANT",
|
|
320
|
+
"LAYER_KV_CACHE_QUANT",
|
|
321
|
+
"LAYER_ACTIVATION_QUANT",
|
|
322
|
+
"LAYER_GRADIENT_COMP",
|
|
323
|
+
"LAYER_LORA",
|
|
324
|
+
"LAYER_PREFIX_CACHE",
|
|
325
|
+
"LAYER_ENGINE_SWAP",
|
|
326
|
+
"LAYER_BATCH_DIVERGENCE",
|
|
327
|
+
"LAYER_SPEC_DECODING",
|
|
328
|
+
"LAYER_SPARSE_ATTENTION",
|
|
329
|
+
"LAYER_MOE_TOKEN_DROP",
|
|
330
|
+
"LAYER_NEURON_SKIPPING",
|
|
331
|
+
"LAYER_MODEL_SWAP",
|
|
332
|
+
"LAYER_PROVIDER_DRIFT",
|
|
333
|
+
"LAYER_PROMPT_SWAP",
|
|
334
|
+
"LAYER_TRAJECTORY",
|
|
335
|
+
|
|
336
|
+
# Collectors (all 20)
|
|
337
|
+
"collect_allreduce_tp",
|
|
338
|
+
"collect_alltoall_ep",
|
|
339
|
+
"collect_pipeline_parallel",
|
|
340
|
+
"collect_pipeline_parallel_tensors",
|
|
341
|
+
"collect_kv_transfer",
|
|
342
|
+
"collect_weight_quant",
|
|
343
|
+
"collect_kv_cache_quant",
|
|
344
|
+
"collect_activation_quant",
|
|
345
|
+
"collect_gradient_compress",
|
|
346
|
+
"collect_lora",
|
|
347
|
+
"collect_prefix_cache",
|
|
348
|
+
"collect_engine_swap",
|
|
349
|
+
"collect_batch_divergence",
|
|
350
|
+
"collect_speculative_decode",
|
|
351
|
+
"collect_sparse_attention",
|
|
352
|
+
"collect_moe_token_dropping",
|
|
353
|
+
"collect_neuron_skipping",
|
|
354
|
+
"collect_model_swap",
|
|
355
|
+
"capture_logits_openai_api",
|
|
356
|
+
"collect_provider_drift",
|
|
357
|
+
"collect_prompt_swap",
|
|
358
|
+
"collect_trajectory",
|
|
359
|
+
"collect_trajectory_two_models",
|
|
360
|
+
|
|
361
|
+
# Trajectory helpers
|
|
362
|
+
"d_profile",
|
|
363
|
+
"trajectory_layer_result",
|
|
364
|
+
|
|
365
|
+
# Capture / persistence utilities
|
|
366
|
+
"save_logits",
|
|
367
|
+
"load_logits",
|
|
368
|
+
"capture_logits_hf",
|
|
369
|
+
"capture_logits_vllm",
|
|
370
|
+
"certify_from_layers",
|
|
371
|
+
]
|