Aadhavan12344 commited on
Commit
e4ddfa4
·
verified ·
1 Parent(s): 959c0bb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +268 -41
app.py CHANGED
@@ -1,70 +1,297 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
  import gradio as gr
2
  from sentence_transformers import SentenceTransformer, util
3
- import torch
4
- import json
5
 
6
- model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
 
 
7
 
8
- # In-memory label store (can be replaced by DB)
9
- LABEL_STORE = {
10
- "chat": ["say hello", "casual talk", "how are you"],
11
- "image_generation": ["generate an image", "draw a picture", "create artwork"],
12
- "action": ["set a timer", "create a reminder"]
13
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
- def classify(text, label_json):
16
- if not text.strip():
17
- return {"error": "Empty input"}
18
 
19
- try:
20
- labels = json.loads(label_json)
21
- except Exception as e:
22
- return {"error": "Invalid label JSON"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
- label_embeddings = {}
25
  for label, examples in labels.items():
26
- if not examples:
 
 
 
27
  continue
28
- emb = model.encode(examples, convert_to_tensor=True)
29
- label_embeddings[label] = emb.mean(dim=0)
30
 
31
- if not label_embeddings:
32
- return {"error": "No valid labels"}
 
 
 
33
 
34
- text_emb = model.encode(text, convert_to_tensor=True)
 
35
 
36
- scores = {}
37
- for label, emb in label_embeddings.items():
38
- scores[label] = float(util.cos_sim(text_emb, emb))
39
 
40
- top_intent = max(scores, key=scores.get)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
 
42
  return {
43
  "text": text,
44
  "top_intent": top_intent,
45
- "scores": scores
 
46
  }
47
 
48
- with gr.Blocks() as demo:
49
- gr.Markdown("## ⚡ Semantic Intent Router Builder")
50
 
51
- user_input = gr.Textbox(label="User Input")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
- label_editor = gr.JSON(
54
- value=LABEL_STORE,
55
- label="Labels & Examples (edit freely, add/remove)"
 
56
  )
57
 
58
- output = gr.JSON(label="Routing Result")
 
 
 
 
 
59
 
60
- classify_btn = gr.Button("Classify")
 
 
 
 
 
 
 
 
 
61
 
62
  classify_btn.click(
63
- classify,
64
- inputs=[user_input, label_editor],
65
- outputs=output
66
  )
67
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  demo.launch(
69
- share=True
70
- )
 
 
 
 
1
+ # ============================================================
2
+ # ⚡ Ultra-Fast Semantic Intent Router
3
+ # MiniLM-based, zero-training, sub-second classification
4
+ # Works on Hugging Face Free CPU
5
+ # ============================================================
6
+
7
+ import json
8
+ import math
9
+ import time
10
+ from typing import Dict, List, Tuple, Any
11
+
12
+ import torch
13
  import gradio as gr
14
  from sentence_transformers import SentenceTransformer, util
 
 
15
 
16
+ # ============================================================
17
+ # 🔧 CONFIG
18
+ # ============================================================
19
 
20
+ MODEL_NAME = "sentence-transformers/all-MiniLM-L6-v2"
21
+ MAX_EXAMPLES_PER_LABEL = 20
22
+ NORMALIZE_SCORES = True
23
+ MIN_CONFIDENCE = 0.05
24
+
25
+ # ============================================================
26
+ # 🧠 MODEL LOAD
27
+ # ============================================================
28
+
29
+ print("🔄 Loading MiniLM model...")
30
+ model = SentenceTransformer(MODEL_NAME, device="cpu")
31
+ print("✅ Model loaded")
32
+
33
+ # ============================================================
34
+ # 🧩 UTILITIES
35
+ # ============================================================
36
+
37
+ def cosine_similarity(a: torch.Tensor, b: torch.Tensor) -> float:
38
+ return util.cos_sim(a, b).item()
39
+
40
+
41
+ def softmax(scores: Dict[str, float]) -> Dict[str, float]:
42
+ if not scores:
43
+ return {}
44
+
45
+ max_val = max(scores.values())
46
+ exp_scores = {k: math.exp(v - max_val) for k, v in scores.items()}
47
+ total = sum(exp_scores.values())
48
+
49
+ if total == 0:
50
+ return {k: 0.0 for k in scores}
51
+
52
+ return {k: v / total for k, v in exp_scores.items()}
53
 
 
 
 
54
 
55
+ # ============================================================
56
+ # 🧱 LABEL PARSING (CRITICAL FIX)
57
+ # ============================================================
58
+
59
+ def parse_labels(raw: Any) -> Dict[str, List[str]]:
60
+ """
61
+ Handles:
62
+ - dict (Gradio JSON component)
63
+ - stringified JSON
64
+ - rejects invalid structures safely
65
+ """
66
+
67
+ if isinstance(raw, dict):
68
+ labels = raw
69
+
70
+ elif isinstance(raw, str):
71
+ try:
72
+ labels = json.loads(raw)
73
+ except Exception as e:
74
+ return {"__error__": f"Invalid JSON: {e}"}
75
+
76
+ else:
77
+ return {"__error__": "Labels must be JSON object"}
78
+
79
+ if not isinstance(labels, dict):
80
+ return {"__error__": "Top-level JSON must be object"}
81
+
82
+ clean = {}
83
 
 
84
  for label, examples in labels.items():
85
+ if not isinstance(label, str):
86
+ continue
87
+
88
+ if not isinstance(examples, list):
89
  continue
 
 
90
 
91
+ cleaned_examples = [
92
+ str(x).strip()
93
+ for x in examples
94
+ if isinstance(x, (str, int, float)) and str(x).strip()
95
+ ][:MAX_EXAMPLES_PER_LABEL]
96
 
97
+ if cleaned_examples:
98
+ clean[label] = cleaned_examples
99
 
100
+ if not clean:
101
+ return {"__error__": "No valid labels found"}
 
102
 
103
+ return clean
104
+
105
+
106
+ # ============================================================
107
+ # 🧠 ROUTER CORE
108
+ # ============================================================
109
+
110
+ def classify_intent(
111
+ text: str,
112
+ labels: Dict[str, List[str]],
113
+ ) -> Dict[str, Any]:
114
+ start = time.time()
115
+
116
+ if not text or not text.strip():
117
+ return {"error": "Input text is empty"}
118
+
119
+ text = text.strip()
120
+
121
+ # Encode input
122
+ input_emb = model.encode(text, convert_to_tensor=True)
123
+
124
+ label_scores: Dict[str, float] = {}
125
+
126
+ for label, examples in labels.items():
127
+ example_embs = model.encode(examples, convert_to_tensor=True)
128
+
129
+ sims = util.cos_sim(input_emb, example_embs)[0]
130
+ score = float(torch.max(sims).item())
131
+
132
+ if score >= MIN_CONFIDENCE:
133
+ label_scores[label] = score
134
+
135
+ if not label_scores:
136
+ return {
137
+ "text": text,
138
+ "top_intent": None,
139
+ "scores": {},
140
+ "latency_ms": round((time.time() - start) * 1000, 2),
141
+ }
142
+
143
+ if NORMALIZE_SCORES:
144
+ label_scores = softmax(label_scores)
145
+
146
+ top_intent = max(label_scores, key=label_scores.get)
147
 
148
  return {
149
  "text": text,
150
  "top_intent": top_intent,
151
+ "scores": dict(sorted(label_scores.items(), key=lambda x: -x[1])),
152
+ "latency_ms": round((time.time() - start) * 1000, 2),
153
  }
154
 
 
 
155
 
156
+ # ============================================================
157
+ # 🌐 API WRAPPER (Gradio-compatible)
158
+ # ============================================================
159
+
160
+ def api_route(text: str, raw_labels: Any) -> Dict[str, Any]:
161
+ labels = parse_labels(raw_labels)
162
+
163
+ if "__error__" in labels:
164
+ return {"error": labels["__error__"]}
165
+
166
+ return classify_intent(text, labels)
167
+
168
+
169
+ # ============================================================
170
+ # 🖥️ DEFAULT LABEL SET
171
+ # ============================================================
172
+
173
+ DEFAULT_LABELS = {
174
+ "chat": [
175
+ "say hello",
176
+ "casual conversation",
177
+ "how are you",
178
+ ],
179
+ "search": [
180
+ "find information",
181
+ "look this up",
182
+ "search online",
183
+ ],
184
+ "image_generation": [
185
+ "generate an image",
186
+ "draw a picture",
187
+ "create artwork",
188
+ ],
189
+ "code": [
190
+ "write code",
191
+ "debug this program",
192
+ "fix this bug",
193
+ ],
194
+ "research": [
195
+ "deep analysis",
196
+ "investigate topic",
197
+ "academic research",
198
+ ],
199
+ "study": [
200
+ "teach me",
201
+ "explain concept",
202
+ "help me learn",
203
+ ],
204
+ "project": [
205
+ "build a project",
206
+ "start a new app",
207
+ "create software",
208
+ ],
209
+ "action": [
210
+ "set a timer",
211
+ "create reminder",
212
+ "schedule event",
213
+ ],
214
+ }
215
+
216
+
217
+ # ============================================================
218
+ # 🎛️ GRADIO UI
219
+ # ============================================================
220
+
221
+ with gr.Blocks(title="⚡ Semantic Intent Router") as demo:
222
+ gr.Markdown(
223
+ """
224
+ # ⚡ Semantic Intent Router Builder
225
+ **MiniLM semantic classifier**
226
+ No training · CPU-only · Sub-second · API ready
227
 
228
+ Edit labels & examples freely
229
+ • Add unlimited labels
230
+ Used for system-prompt injection & MPC routing
231
+ """
232
  )
233
 
234
+ with gr.Row():
235
+ user_input = gr.Textbox(
236
+ label="User Input",
237
+ placeholder="Type anything...",
238
+ lines=2,
239
+ )
240
 
241
+ with gr.Row():
242
+ labels_json = gr.JSON(
243
+ label="Labels & Examples (edit freely, add/remove)",
244
+ value=DEFAULT_LABELS,
245
+ )
246
+
247
+ with gr.Row():
248
+ output = gr.JSON(label="Routing Result")
249
+
250
+ classify_btn = gr.Button("Classify", variant="primary")
251
 
252
  classify_btn.click(
253
+ fn=api_route,
254
+ inputs=[user_input, labels_json],
255
+ outputs=output,
256
  )
257
 
258
+ gr.Markdown(
259
+ """
260
+ ### 🔌 API Usage
261
+
262
+ **POST** to this Space URL:
263
+
264
+ ```json
265
+ {
266
+ "data": [
267
+ "Set a timer for 10 minutes",
268
+ {
269
+ "chat": ["hello", "hi"],
270
+ "action": ["set a timer", "remind me"]
271
+ }
272
+ ]
273
+ }
274
+
275
+ Response:
276
+
277
+ {
278
+ "top_intent": "action",
279
+ "scores": { ... }
280
+ }
281
+
282
+ “””
283
+ )
284
+
285
+ ============================================================
286
+
287
+ 🚀 LAUNCH
288
+
289
+ ============================================================
290
+
291
+ if name == “main”:
292
  demo.launch(
293
+ share=True,
294
+ enable_queue=False,
295
+ )
296
+
297
+ ---