SahilRS commited on
Commit
46eb590
Β·
verified Β·
1 Parent(s): c163b54

Upload app_phase4c.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app_phase4c.py +169 -0
app_phase4c.py ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import spaces
3
+ import torch
4
+ from transformers import AutoModelForCausalLM, AutoTokenizer
5
+ import time
6
+ import json
7
+
8
+ # ─── Phase Configuration ───
9
+ PHASE = "Phase 4c: Quality Generation (ZeroGPU)"
10
+ MODEL_NAME = "microsoft/Phi-3-mini-4k-instruct"
11
+ MODEL_CONFIG = {
12
+ "phase": PHASE,
13
+ "model_name": MODEL_NAME,
14
+ "torch_dtype": "float16",
15
+ "quantization": "none",
16
+ "optimization": "sdpa-quality-gen",
17
+ "hardware": "zero-a10g",
18
+ "max_new_tokens": 512,
19
+ "temperature": 1.0,
20
+ "top_p": 0.95,
21
+ "top_k": 100,
22
+ }
23
+
24
+ # ─── Load model with explicit SDPA attention ───
25
+ print("Loading model with SDPA attention...", flush=True)
26
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
27
+ model = AutoModelForCausalLM.from_pretrained(
28
+ MODEL_NAME,
29
+ torch_dtype=torch.float16,
30
+ attn_implementation="sdpa",
31
+ low_cpu_mem_usage=True,
32
+ )
33
+ print("Model loaded successfully with SDPA attention! (Quality generation preset)", flush=True)
34
+
35
+
36
+ @spaces.GPU
37
+ def generate_response(message, history_tuples=None):
38
+ """Core generation logic, returns response + metrics."""
39
+ # Move model to GPU (ZeroGPU provides GPU only inside @spaces.GPU)
40
+ model.to("cuda")
41
+
42
+ messages = []
43
+ if history_tuples:
44
+ for user_msg, assistant_msg in history_tuples:
45
+ messages.append({"role": "user", "content": user_msg})
46
+ messages.append({"role": "assistant", "content": assistant_msg})
47
+ messages.append({"role": "user", "content": message})
48
+
49
+ input_ids = tokenizer.apply_chat_template(
50
+ messages,
51
+ add_generation_prompt=True,
52
+ return_tensors="pt",
53
+ )
54
+ # apply_chat_template may return a tensor or BatchEncoding depending on version
55
+ if hasattr(input_ids, "input_ids"):
56
+ input_ids = input_ids.input_ids
57
+ input_ids = input_ids.to("cuda")
58
+
59
+ input_tokens = input_ids.shape[1]
60
+
61
+ start_time = time.time()
62
+ with torch.no_grad():
63
+ outputs = model.generate(
64
+ input_ids,
65
+ max_new_tokens=MODEL_CONFIG["max_new_tokens"],
66
+ temperature=MODEL_CONFIG["temperature"],
67
+ top_p=MODEL_CONFIG["top_p"],
68
+ top_k=MODEL_CONFIG["top_k"],
69
+ do_sample=True,
70
+ pad_token_id=tokenizer.eos_token_id,
71
+ )
72
+ inference_time = time.time() - start_time
73
+
74
+ output_tokens = outputs.shape[1] - input_tokens
75
+ response = tokenizer.decode(outputs[0][input_tokens:], skip_special_tokens=True)
76
+ tokens_per_sec = round(output_tokens / inference_time, 2) if inference_time > 0 else 0
77
+
78
+ return {
79
+ "response": response,
80
+ "inference_time_s": round(inference_time, 2),
81
+ "input_tokens": input_tokens,
82
+ "output_tokens": output_tokens,
83
+ "tokens_per_sec": tokens_per_sec,
84
+ "model_config": MODEL_CONFIG,
85
+ }
86
+
87
+
88
+ def parse_history(history):
89
+ """Convert Gradio 5 history format to tuples."""
90
+ if not history:
91
+ return None
92
+ tuples = []
93
+ i = 0
94
+ while i < len(history):
95
+ item = history[i]
96
+ if isinstance(item, dict):
97
+ if item.get("role") == "user":
98
+ user_msg = item.get("content", "")
99
+ asst_msg = ""
100
+ if i + 1 < len(history):
101
+ next_item = history[i + 1]
102
+ if isinstance(next_item, dict) and next_item.get("role") == "assistant":
103
+ asst_msg = next_item.get("content", "")
104
+ i += 1
105
+ tuples.append((user_msg, asst_msg))
106
+ elif isinstance(item, (list, tuple)) and len(item) == 2:
107
+ tuples.append(tuple(item))
108
+ i += 1
109
+ return tuples if tuples else None
110
+
111
+
112
+ # ─── Gradio Chat (for HF Spaces UI) ───
113
+ def chat(message, history):
114
+ history_tuples = parse_history(history)
115
+ result = generate_response(message, history_tuples)
116
+ timing = f"\n\n---\n*Inference: {result['inference_time_s']}s | {result['tokens_per_sec']} t/s | SDPA + Quality preset*"
117
+ return result["response"] + timing
118
+
119
+
120
+ # ─── API Endpoint (for React app + benchmark) ───
121
+ def api_chat(message, history_json="[]"):
122
+ try:
123
+ if not history_json or history_json.strip() == "":
124
+ history_json = "[]"
125
+ history = json.loads(history_json) if isinstance(history_json, str) else history_json
126
+ history_tuples = [tuple(h) for h in history] if history else None
127
+ result = generate_response(message, history_tuples)
128
+ return json.dumps(result)
129
+ except Exception as e:
130
+ import traceback
131
+ return json.dumps({"error": str(e), "traceback": traceback.format_exc()})
132
+
133
+
134
+ # ─── Build Gradio App ───
135
+ with gr.Blocks() as demo:
136
+ gr.Markdown(f"# Phi-3 Mini Chatbot ({PHASE})")
137
+ gr.Markdown("Chat UI + API endpoint for benchmarking | SDPA + Quality generation preset")
138
+
139
+ with gr.Tab("Chat"):
140
+ chatbot = gr.ChatInterface(fn=chat)
141
+
142
+ with gr.Tab("API"):
143
+ gr.Markdown("""
144
+ ### API Endpoint
145
+
146
+ **Call `/gradio_api/call/api_chat`** (Gradio 5 SSE format):
147
+
148
+ ```
149
+ POST /gradio_api/call/api_chat
150
+ {"data": ["your question", "[]"]}
151
+ β†’ returns {"event_id": "..."}
152
+
153
+ GET /gradio_api/call/api_chat/{event_id}
154
+ β†’ SSE stream with data: [json_result]
155
+ ```
156
+ """)
157
+ msg_input = gr.Textbox(label="Message", placeholder="Type your question...")
158
+ history_input = gr.Textbox(label="History (JSON)", value="[]", visible=False)
159
+ api_output = gr.Textbox(label="API Response (JSON)", lines=10)
160
+ api_btn = gr.Button("Call API")
161
+ api_btn.click(
162
+ fn=api_chat,
163
+ inputs=[msg_input, history_input],
164
+ outputs=api_output,
165
+ api_name="api_chat",
166
+ )
167
+
168
+ if __name__ == "__main__":
169
+ demo.launch()