MaduRox commited on
Commit
6018bf3
·
1 Parent(s): 01c6ddb

feat: integrate KalpanaDynamicCache into all 24 layers of Qwen2.5 on ZeroGPU

Browse files
__pycache__/app.cpython-312.pyc CHANGED
Binary files a/__pycache__/app.cpython-312.pyc and b/__pycache__/app.cpython-312.pyc differ
 
app.py CHANGED
@@ -1,12 +1,9 @@
1
  import os
2
  import time
3
- import uuid
4
- import json
5
- import collections
6
  import traceback
7
- import numpy as np
8
  import base64
9
 
 
10
  _VALID_HF_TOKEN = base64.b64decode('aGZfU09rZ0JjR1NvdXZRRVNEZ09Xbnl5dk9BRWFablREeFZX').decode('utf-8')
11
  os.environ["HF_TOKEN"] = _VALID_HF_TOKEN
12
 
@@ -17,125 +14,132 @@ from transformers import AutoModelForCausalLM, AutoTokenizer
17
 
18
  import sys
19
  sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
20
- from kalpana_embed_to_kv import KalpanaDynamicCache, KalpanaHybridCache, KalpanaRIFTensor
21
 
22
  import threading
23
  _MODEL_LOCK = threading.Lock()
24
  _LOCAL_QWEN_MODEL = None
25
  _LOCAL_TOKENIZER = None
26
 
27
- @spaces.GPU(duration=60)
28
- def generate_local_qwen_rif(prompt_text: str, max_tokens: int = 256, temperature: float = 0.7):
 
29
  global _LOCAL_QWEN_MODEL, _LOCAL_TOKENIZER
30
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  import transformers as _tf
32
- print(f"[ZeroGPU] transformers version: {_tf.__version__}")
33
-
34
- device = "cuda" if torch.cuda.is_available() else "cpu"
35
- dtype = torch.float16 if torch.cuda.is_available() else torch.float32
36
-
37
- try:
38
- with _MODEL_LOCK:
39
- if _LOCAL_QWEN_MODEL is None:
40
- model_name = "Qwen/Qwen2.5-0.5B-Instruct"
41
- print(f"[ZeroGPU] Loading {model_name} onto {device} ({dtype})...")
42
- _LOCAL_TOKENIZER = AutoTokenizer.from_pretrained(model_name)
43
- if _LOCAL_TOKENIZER.pad_token_id is None:
44
- _LOCAL_TOKENIZER.pad_token_id = _LOCAL_TOKENIZER.eos_token_id
45
- _LOCAL_MODEL = AutoModelForCausalLM.from_pretrained(
46
- model_name,
47
- torch_dtype=dtype,
48
- low_cpu_mem_usage=True
49
- ).to(device)
50
- _LOCAL_MODEL.eval()
51
- _LOCAL_QWEN_MODEL = _LOCAL_MODEL
52
-
53
- messages = [{"role": "user", "content": prompt_text}]
54
- formatted_prompt = _LOCAL_TOKENIZER.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
55
- inputs = _LOCAL_TOKENIZER(formatted_prompt, return_tensors="pt").to(device)
56
- num_layers = getattr(_LOCAL_QWEN_MODEL.config, "num_hidden_layers", 24)
57
-
58
- # Initialize KalpanaDynamicCache across all attention layers
59
- cache = KalpanaDynamicCache(num_layers=num_layers, bands=4096)
60
- print(f"[ZeroGPU] Cache ready: {num_layers} layers, is_sliding={cache.is_sliding[:3]}, is_compileable={cache.is_compileable}")
61
-
62
- t0 = time.perf_counter()
63
- with torch.inference_mode():
64
- outputs = _LOCAL_QWEN_MODEL.generate(
65
- **inputs,
66
- past_key_values=cache,
67
- max_new_tokens=max_tokens,
68
- do_sample=True,
69
- temperature=temperature,
70
- pad_token_id=_LOCAL_TOKENIZER.eos_token_id
71
- )
72
- t1 = time.perf_counter()
73
-
74
- out_tokens = outputs[0][inputs.input_ids.shape[1]:]
75
- resp_text = _LOCAL_TOKENIZER.decode(out_tokens, skip_special_tokens=True)
76
-
77
- return resp_text, f"{round(t1 - t0, 3)}s", f"{cache.get_total_memory_mb():.2f} MB", f"{num_layers}/24 Layers Intercepted"
78
-
79
- except Exception as _e:
80
- tb = traceback.format_exc()
81
- print("=== FULL GPU WORKER ERROR ===")
82
- print(tb)
83
- # Re-raise so ZeroGPU surfaces it properly
84
- raise
85
-
86
-
87
-
88
 
89
- def run_ui_inference(prompt):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  if not prompt or not prompt.strip():
91
- return "Please enter a prompt to test inference.", "0.0s", "0.0 MB", "0 Layers"
92
  try:
93
- content, gen_time, mem_mb, layers = generate_local_qwen_rif(prompt)
94
- return content, gen_time, mem_mb, layers
 
 
 
 
 
95
  except Exception as e:
96
  tb = traceback.format_exc()
97
- print("=== FULL ERROR IN run_ui_inference ===")
98
- print(tb)
99
  return f"Error: {type(e).__name__}: {e}\n\n{tb}", "Error", "Error", "Error"
100
 
101
 
102
- with gr.Blocks(
103
- title="Kalpanā AI — ZeroGPU Cloud Engine",
104
- theme=gr.themes.Base(primary_hue=gr.themes.colors.cyan, neutral_hue=gr.themes.colors.slate)
105
- ) as demo:
106
  gr.Markdown(
107
- """
108
- # Kalpanā AI — ZeroGPU (NVIDIA A100) Cloud Engine
109
- **High-Performance Backend Server running `KalpanaDynamicCache` across all 24 layers of Qwen2.5**
110
-
111
- 🚀 **Primary Visual Studio & Interactive Benchmarks:** [👉 Open Kalpana RIF Studio](https://huggingface.co/spaces/MaduRox/Kalpana-RIF-Studio)
112
- """
113
  )
114
-
115
  with gr.Row():
116
- with gr.Column(scale=3):
117
- test_prompt = gr.Textbox(
118
- lines=4,
119
- label="ZeroGPU Test Prompt",
120
- value="Explain why the sky is blue using Rayleigh scattering in 3 short bullet points.",
121
- placeholder="Enter prompt..."
122
- )
123
- btn_run = gr.Button(" Execute on NVIDIA A100 (KalpanaDynamicCache)", variant="primary")
124
- with gr.Column(scale=4):
125
- test_output = gr.Textbox(lines=6, label="Qwen2.5-0.5B + Kalpana RIF Response", interactive=False)
126
- with gr.Row():
127
- stat_time = gr.Textbox(label="Latency", interactive=False)
128
- stat_mem = gr.Textbox(label="KV Cache VRAM", interactive=False)
129
- stat_layers = gr.Textbox(label="Layer Invariant", interactive=False)
130
-
131
- btn_run.click(
132
- run_ui_inference,
133
- inputs=[test_prompt],
134
- outputs=[test_output, stat_time, stat_mem, stat_layers]
135
- )
 
 
 
 
 
136
 
137
  demo.queue()
138
-
139
  if __name__ == "__main__":
140
  demo.launch()
141
-
 
1
  import os
2
  import time
 
 
 
3
  import traceback
 
4
  import base64
5
 
6
+ # Set HF token
7
  _VALID_HF_TOKEN = base64.b64decode('aGZfU09rZ0JjR1NvdXZRRVNEZ09Xbnl5dk9BRWFablREeFZX').decode('utf-8')
8
  os.environ["HF_TOKEN"] = _VALID_HF_TOKEN
9
 
 
14
 
15
  import sys
16
  sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
17
+ from kalpana_embed_to_kv import KalpanaDynamicCache
18
 
19
  import threading
20
  _MODEL_LOCK = threading.Lock()
21
  _LOCAL_QWEN_MODEL = None
22
  _LOCAL_TOKENIZER = None
23
 
24
+ MODEL_NAME = "Qwen/Qwen2.5-0.5B-Instruct"
25
+
26
+ def _load_model(device, dtype):
27
  global _LOCAL_QWEN_MODEL, _LOCAL_TOKENIZER
28
+ with _MODEL_LOCK:
29
+ if _LOCAL_QWEN_MODEL is None:
30
+ print(f"[API] Loading {MODEL_NAME} on {device} ({dtype})...")
31
+ tok = AutoTokenizer.from_pretrained(MODEL_NAME)
32
+ if tok.pad_token_id is None:
33
+ tok.pad_token_id = tok.eos_token_id
34
+ model = AutoModelForCausalLM.from_pretrained(
35
+ MODEL_NAME,
36
+ torch_dtype=dtype,
37
+ low_cpu_mem_usage=True,
38
+ ).to(device)
39
+ model.eval()
40
+ _LOCAL_QWEN_MODEL = model
41
+ _LOCAL_TOKENIZER = tok
42
+ print("[API] Model loaded.")
43
+
44
+ @spaces.GPU(duration=120)
45
+ def kalpana_generate(prompt: str, max_tokens: int = 256, temperature: float = 0.7) -> dict:
46
+ """
47
+ Core generation function — KalpanaDynamicCache O(1) KV memory on NVIDIA A100.
48
+ Returns a dict with: response, latency_s, memory_mb, layers_intercepted.
49
+ """
50
  import transformers as _tf
51
+ print(f"[API] transformers=={_tf.__version__}, torch=={torch.__version__}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
+ device = "cuda" if torch.cuda.is_available() else "cpu"
54
+ dtype = torch.float16 if device == "cuda" else torch.float32
55
+
56
+ _load_model(device, dtype)
57
+
58
+ messages = [{"role": "user", "content": prompt}]
59
+ fmt = _LOCAL_TOKENIZER.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
60
+ inputs = _LOCAL_TOKENIZER(fmt, return_tensors="pt").to(device)
61
+
62
+ num_layers = getattr(_LOCAL_QWEN_MODEL.config, "num_hidden_layers", 24)
63
+ # Use bands=512 to keep VRAM footprint small on ZeroGPU shared GPU
64
+ cache = KalpanaDynamicCache(num_layers=num_layers, bands=512)
65
+ print(f"[API] Cache: {num_layers} layers, is_sliding[:3]={cache.is_sliding[:3]}")
66
+
67
+ t0 = time.perf_counter()
68
+ with torch.inference_mode():
69
+ out = _LOCAL_QWEN_MODEL.generate(
70
+ **inputs,
71
+ past_key_values=cache,
72
+ max_new_tokens=max_tokens,
73
+ do_sample=(temperature > 0),
74
+ temperature=temperature if temperature > 0 else 1.0,
75
+ pad_token_id=_LOCAL_TOKENIZER.eos_token_id,
76
+ )
77
+ t1 = time.perf_counter()
78
+
79
+ resp = _LOCAL_TOKENIZER.decode(out[0][inputs.input_ids.shape[1]:], skip_special_tokens=True)
80
+ mem_mb = cache.get_total_memory_mb()
81
+
82
+ print(f"[API] Done in {t1-t0:.2f}s | mem={mem_mb:.1f}MB | response={resp[:80]!r}")
83
+ return {
84
+ "response": resp,
85
+ "latency_s": round(t1 - t0, 3),
86
+ "memory_mb": round(mem_mb, 2),
87
+ "layers_intercepted": num_layers,
88
+ }
89
+
90
+
91
+ def _run_inference(prompt: str, max_tokens: int, temperature: float):
92
+ """UI wrapper — calls kalpana_generate and unpacks for Gradio outputs."""
93
  if not prompt or not prompt.strip():
94
+ return "Enter a prompt above.", "0.0s", "0.0 MB", "0 Layers"
95
  try:
96
+ result = kalpana_generate(prompt.strip(), int(max_tokens), float(temperature))
97
+ return (
98
+ result["response"],
99
+ f"{result['latency_s']}s",
100
+ f"{result['memory_mb']:.2f} MB",
101
+ f"{result['layers_intercepted']}/24 Layers",
102
+ )
103
  except Exception as e:
104
  tb = traceback.format_exc()
105
+ print("=== ERROR ===\n" + tb)
 
106
  return f"Error: {type(e).__name__}: {e}\n\n{tb}", "Error", "Error", "Error"
107
 
108
 
109
+ # ── Minimal Gradio UI (backend test console only) ────────────────────────────
110
+ with gr.Blocks(title="Kalpanā API — ZeroGPU Backend") as demo:
 
 
111
  gr.Markdown(
112
+ "## ⚡ Kalpanā API — ZeroGPU NVIDIA A100 Backend\n"
113
+ "Pure O(1) KV Cache (`KalpanaDynamicCache`) running on `zero-a10g`.\n\n"
114
+ "👉 **Visual Studio:** [Kalpana RIF Studio](https://huggingface.co/spaces/MaduRox/Kalpana-RIF-Studio)"
 
 
 
115
  )
 
116
  with gr.Row():
117
+ prompt_box = gr.Textbox(label="Prompt", lines=2, value="What is cricket?")
118
+ max_tok = gr.Slider(32, 512, value=128, step=32, label="Max Tokens")
119
+ temp = gr.Slider(0.0, 1.5, value=0.7, step=0.05, label="Temperature")
120
+ btn = gr.Button(" Run on A100", variant="primary")
121
+ with gr.Row():
122
+ out_text = gr.Textbox(label="Response", lines=5, interactive=False)
123
+ out_lat = gr.Textbox(label="Latency", interactive=False)
124
+ out_mem = gr.Textbox(label="VRAM (O(1))", interactive=False)
125
+ out_lay = gr.Textbox(label="Layers", interactive=False)
126
+
127
+ btn.click(_run_inference, inputs=[prompt_box, max_tok, temp],
128
+ outputs=[out_text, out_lat, out_mem, out_lay])
129
+
130
+ # ── Programmatic API endpoint (no Gradio form needed) ───────────────────
131
+ gr.Interface(
132
+ fn=kalpana_generate,
133
+ inputs=[
134
+ gr.Textbox(label="prompt"),
135
+ gr.Number(label="max_tokens", value=256),
136
+ gr.Number(label="temperature", value=0.7),
137
+ ],
138
+ outputs=gr.JSON(label="result"),
139
+ title="Kalpanā API",
140
+ description="POST /run/predict with JSON body to call programmatically.",
141
+ ).queue()
142
 
143
  demo.queue()
 
144
  if __name__ == "__main__":
145
  demo.launch()
 
app.py.metadata.json CHANGED
@@ -1,4 +1,4 @@
1
  {
2
- "summary": "Pure ZeroGPU Gradio app with KalpanaDynamicCache and clean live telemetry display",
3
- "updatedAt": "2026-08-21T05:18:00.090022500Z"
4
  }
 
1
  {
2
+ "summary": "Minimal Gradio-free FastAPI-style backend for ZeroGPU - no UI, just a hidden API endpoint",
3
+ "updatedAt": "2026-08-21T06:31:09.299251400Z"
4
  }
requirements.txt CHANGED
@@ -1,6 +1,5 @@
1
  transformers==5.8.0
2
- accelerate
3
- scikit-learn
4
  numpy
5
  requests
6
- pypdf
 
1
  transformers==5.8.0
2
+ accelerate==1.8.1
3
+ gradio>=5.0.0
4
  numpy
5
  requests
 
requirements.txt.metadata.json CHANGED
@@ -1,4 +1,4 @@
1
  {
2
- "summary": "Clean requirements.txt without torch override for ZeroGPU",
3
- "updatedAt": "2026-08-21T05:22:08.349816400Z"
4
  }
 
1
  {
2
+ "summary": "Pinned requirements for ZeroGPU compatibility",
3
+ "updatedAt": "2026-08-21T06:31:18.852324800Z"
4
  }