argus-cache 0.1.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.
- argus_cache/__init__.py +43 -0
- argus_cache/core/__init__.py +1 -0
- argus_cache/core/dashboard.py +132 -0
- argus_cache/core/memory_manager.py +1057 -0
- argus_cache/core/quantization.py +250 -0
- argus_cache/core/triton_kernels.py +405 -0
- argus_cache/models/__init__.py +1 -0
- argus_cache/models/attention_wrapper.py +173 -0
- argus_cache-0.1.0.dist-info/METADATA +264 -0
- argus_cache-0.1.0.dist-info/RECORD +13 -0
- argus_cache-0.1.0.dist-info/WHEEL +5 -0
- argus_cache-0.1.0.dist-info/licenses/LICENSE +189 -0
- argus_cache-0.1.0.dist-info/top_level.txt +1 -0
argus_cache/__init__.py
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from .models.attention_wrapper import PagedDynamicQuantizedCache
|
|
2
|
+
from .core.memory_manager import PagedDynamicKVCache
|
|
3
|
+
|
|
4
|
+
def patch_model_with_argus(
|
|
5
|
+
model,
|
|
6
|
+
page_size=4096,
|
|
7
|
+
max_active_pages=2,
|
|
8
|
+
max_fp8_pages=2,
|
|
9
|
+
max_int8_pages=2,
|
|
10
|
+
max_int4_pages=2,
|
|
11
|
+
max_int2_pages=2,
|
|
12
|
+
max_one_bit_pages=2,
|
|
13
|
+
sink_tokens=4
|
|
14
|
+
):
|
|
15
|
+
"""
|
|
16
|
+
Patches a HuggingFace causal language model to automatically use
|
|
17
|
+
the ARGUS (PagedDynamicQuantizedCache) KV Cache manager.
|
|
18
|
+
"""
|
|
19
|
+
original_prep = model.prepare_inputs_for_generation
|
|
20
|
+
|
|
21
|
+
def prepare_inputs_for_generation_argus(*args, **kwargs):
|
|
22
|
+
past_key_values = kwargs.get("past_key_values", None)
|
|
23
|
+
if past_key_values is None:
|
|
24
|
+
kwargs["past_key_values"] = PagedDynamicQuantizedCache(
|
|
25
|
+
page_size=page_size,
|
|
26
|
+
max_active_pages=max_active_pages,
|
|
27
|
+
max_fp8_pages=max_fp8_pages,
|
|
28
|
+
max_int8_pages=max_int8_pages,
|
|
29
|
+
max_int4_pages=max_int4_pages,
|
|
30
|
+
max_int2_pages=max_int2_pages,
|
|
31
|
+
max_one_bit_pages=max_one_bit_pages,
|
|
32
|
+
sink_tokens=sink_tokens
|
|
33
|
+
)
|
|
34
|
+
return original_prep(*args, **kwargs)
|
|
35
|
+
|
|
36
|
+
model.prepare_inputs_for_generation = prepare_inputs_for_generation_argus
|
|
37
|
+
return model
|
|
38
|
+
|
|
39
|
+
__all__ = [
|
|
40
|
+
"PagedDynamicQuantizedCache",
|
|
41
|
+
"PagedDynamicKVCache",
|
|
42
|
+
"patch_model_with_argus"
|
|
43
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Core packaging
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
def render_dashboard(cache, step, mode="paged_quantized", text_output="", prefetch_hits=0, prefetch_misses=0):
|
|
5
|
+
"""
|
|
6
|
+
Renders an elite, high-fidelity terminal dashboard showing real-time KV Cache metrics,
|
|
7
|
+
7-tier page allocations, VRAM savings, and speculative prefetch statistics.
|
|
8
|
+
"""
|
|
9
|
+
# ANSI color codes
|
|
10
|
+
CYAN = "\033[96m"
|
|
11
|
+
BLUE = "\033[94m"
|
|
12
|
+
GREEN = "\033[92m"
|
|
13
|
+
YELLOW = "\033[93m"
|
|
14
|
+
MAGENTA = "\033[95m"
|
|
15
|
+
RED = "\033[91m"
|
|
16
|
+
PURPLE = "\033[35m"
|
|
17
|
+
BOLD = "\033[1m"
|
|
18
|
+
RESET = "\033[0m"
|
|
19
|
+
WHITE = "\033[97m"
|
|
20
|
+
GRAY = "\033[90m"
|
|
21
|
+
|
|
22
|
+
# Try getting terminal width, default to 80
|
|
23
|
+
try:
|
|
24
|
+
columns, _ = os.get_terminal_size()
|
|
25
|
+
except OSError:
|
|
26
|
+
columns = 80
|
|
27
|
+
|
|
28
|
+
width = min(columns - 4, 76)
|
|
29
|
+
|
|
30
|
+
# Clear terminal step-by-step
|
|
31
|
+
sys.stdout.write("\033[H")
|
|
32
|
+
|
|
33
|
+
print(f"\n{CYAN}{BOLD}⚡ ARGUS: ANCHORED RANDOM GEOMETRIC UNBIASED STORAGE{RESET}".center(width + 15))
|
|
34
|
+
print(f"{GRAY}{'─' * width}{RESET}")
|
|
35
|
+
|
|
36
|
+
# Mode and status info
|
|
37
|
+
status_str = f"{GREEN}{BOLD}RUNNING (ACTIVE){RESET}"
|
|
38
|
+
if hasattr(cache, "is_swapped_out") and cache.is_swapped_out:
|
|
39
|
+
status_str = f"{YELLOW}{BOLD}SWAPPED TO HOST RAM (GUARD ACTIVE){RESET}"
|
|
40
|
+
|
|
41
|
+
print(f"{BOLD}Serving Mode: {RESET}{mode.upper():<20} | {BOLD}Status: {RESET}{status_str}")
|
|
42
|
+
print(f"{BOLD}Current Generation Step: {RESET}{step:<10} | {BOLD}Prefetch Hits: {RESET}{GREEN}{prefetch_hits}{RESET} / Miss: {RED}{prefetch_misses}{RESET}")
|
|
43
|
+
print(f"{GRAY}{'─' * width}{RESET}")
|
|
44
|
+
|
|
45
|
+
# Page tiers and VRAM calculation
|
|
46
|
+
# Retrieve metadata from cache
|
|
47
|
+
# If the input cache is a wrapper (PagedDynamicQuantizedCache), get layer 0 cache
|
|
48
|
+
if hasattr(cache, "layer_caches"):
|
|
49
|
+
layer_cache = cache.layer_caches.get(0)
|
|
50
|
+
else:
|
|
51
|
+
layer_cache = cache
|
|
52
|
+
|
|
53
|
+
if layer_cache is not None:
|
|
54
|
+
# Determine dimensions
|
|
55
|
+
heads = 4
|
|
56
|
+
head_dim = 16
|
|
57
|
+
if layer_cache.sink_k is not None:
|
|
58
|
+
heads = layer_cache.sink_k.shape[1]
|
|
59
|
+
head_dim = layer_cache.sink_k.shape[3]
|
|
60
|
+
elif layer_cache.k_buffer is not None:
|
|
61
|
+
heads = layer_cache.k_buffer.shape[1]
|
|
62
|
+
head_dim = layer_cache.k_buffer.shape[3]
|
|
63
|
+
|
|
64
|
+
p_size = layer_cache.page_size
|
|
65
|
+
|
|
66
|
+
# Get tier page lists
|
|
67
|
+
t1 = len(layer_cache.active_pages)
|
|
68
|
+
t2 = len(layer_cache.fp8_pages)
|
|
69
|
+
t3 = len(layer_cache.int8_pages)
|
|
70
|
+
t4 = len(layer_cache.int4_pages)
|
|
71
|
+
t5 = len(layer_cache.int2_pages)
|
|
72
|
+
t6 = len(layer_cache.one_bit_pages)
|
|
73
|
+
t7 = len(layer_cache.jl_pages)
|
|
74
|
+
|
|
75
|
+
sink_tokens = layer_cache.sink_k.shape[-2] if layer_cache.sink_k is not None else 0
|
|
76
|
+
anchor_tokens = layer_cache.anchor_k.shape[-2] if layer_cache.anchor_k is not None else 0
|
|
77
|
+
buffer_tokens = layer_cache.k_buffer.shape[-2] if layer_cache.k_buffer is not None else 0
|
|
78
|
+
|
|
79
|
+
total_tokens = sink_tokens + anchor_tokens + buffer_tokens + (t1 + t2 + t3 + t4 + t5 + t6 + t7) * p_size
|
|
80
|
+
|
|
81
|
+
# Standard VRAM in bytes (FP16 = 2 bytes per element, key and value)
|
|
82
|
+
std_bytes = total_tokens * 2 * heads * head_dim * 2
|
|
83
|
+
paged_bytes = cache.get_vram_usage()
|
|
84
|
+
|
|
85
|
+
saving = 0.0
|
|
86
|
+
if std_bytes > 0:
|
|
87
|
+
saving = ((std_bytes - paged_bytes) / std_bytes) * 100
|
|
88
|
+
|
|
89
|
+
# Draw Tiers progress bar
|
|
90
|
+
print(f"{BOLD}7-Tier Page Distribution Queue:{RESET}\n")
|
|
91
|
+
|
|
92
|
+
def make_bar(pages, color, label):
|
|
93
|
+
block_char = "█"
|
|
94
|
+
empty_char = "░"
|
|
95
|
+
bar_len = 10
|
|
96
|
+
filled = min(pages, bar_len)
|
|
97
|
+
bar = f"{color}{block_char * filled}{GRAY}{empty_char * (bar_len - filled)}{RESET}"
|
|
98
|
+
print(f" {label:<28} : {bar} | {BOLD}{pages}{RESET} pages ({pages * p_size} tokens)")
|
|
99
|
+
|
|
100
|
+
make_bar(t1, CYAN, "Tier 1: FP16 (Active Pages)")
|
|
101
|
+
make_bar(t2, BLUE, "Tier 2: FP8 (Light Quant)")
|
|
102
|
+
make_bar(t3, GREEN, "Tier 3: INT8 (Medium Quant)")
|
|
103
|
+
make_bar(t4, YELLOW, "Tier 4: INT4 (Heavy Quant)")
|
|
104
|
+
make_bar(t5, MAGENTA, "Tier 5: INT2 (Super Heavy)")
|
|
105
|
+
make_bar(t6, RED, "Tier 6: 1-Bit (Binarized)")
|
|
106
|
+
make_bar(t7, PURPLE, "Tier 7: JL Ortho (Archive)")
|
|
107
|
+
|
|
108
|
+
print(f"\n {GRAY}Attention Sinks: {sink_tokens} | VIP Anchors: {anchor_tokens} | Temp Buffer: {buffer_tokens}{RESET}")
|
|
109
|
+
print(f"{GRAY}{'─' * width}{RESET}")
|
|
110
|
+
|
|
111
|
+
# Memory metrics
|
|
112
|
+
print(f"{BOLD}VRAM Telemetry:{RESET}")
|
|
113
|
+
std_kb = std_bytes / 1024
|
|
114
|
+
pg_kb = paged_bytes / 1024
|
|
115
|
+
saving_color = GREEN if saving > 0 else RED
|
|
116
|
+
|
|
117
|
+
print(f" - Standard FP16 KV Cache VRAM : {CYAN}{std_kb:7.2f} KB{RESET}")
|
|
118
|
+
print(f" - ARGUS Paged Quantized Cache : {MAGENTA}{pg_kb:7.2f} KB{RESET}")
|
|
119
|
+
print(f" - Net GPU VRAM Savings : {saving_color}{BOLD}{saving:6.2f}%{RESET}")
|
|
120
|
+
else:
|
|
121
|
+
print(f" {GRAY}No active KV cache tracked yet.{RESET}")
|
|
122
|
+
print(f"{GRAY}{'─' * width}{RESET}")
|
|
123
|
+
|
|
124
|
+
print(f"{GRAY}{'─' * width}{RESET}")
|
|
125
|
+
print(f"{BOLD}Autoregressive Generation:{RESET}")
|
|
126
|
+
# Print trailing 60 chars of text output elegantly
|
|
127
|
+
clean_text = text_output.replace('\n', ' ')
|
|
128
|
+
if len(clean_text) > width:
|
|
129
|
+
clean_text = "..." + clean_text[-(width-5):]
|
|
130
|
+
print(f" {WHITE}\"{clean_text}\"{RESET}")
|
|
131
|
+
print(f"{GRAY}{'─' * width}{RESET}\n")
|
|
132
|
+
sys.stdout.flush()
|