TensorVizion commited on
Commit
789c331
·
verified ·
1 Parent(s): 7e399de

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +79 -11
app.py CHANGED
@@ -6,7 +6,7 @@ import tempfile
6
  from huggingface_hub import InferenceClient
7
 
8
  # Replace this with your exact model repo ID
9
- MODEL_ID = "meta-llama/Llama-3.1-70B-Instruct"
10
 
11
  # Securely load the Hugging Face token from Space secrets
12
  hf_token = os.environ.get("HF_TOKEN")
@@ -63,12 +63,71 @@ custom_css = """
63
  # -------------------------
64
  # Helper & Extraction Logic
65
  # -------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  def extract_data(raw_text, fields_to_extract):
67
  if not hf_token:
68
- return {"error": "HF_TOKEN secret is missing. Please add your Hugging Face Access Token to the Space Secrets."}, [["Error", "HF_TOKEN missing"]]
 
69
 
70
  if not raw_text.strip() or not fields_to_extract.strip():
71
- return {"error": "Please provide both raw text and fields to extract."}, [["Error", "Incomplete inputs"]]
 
72
 
73
  # Construct the system instruction
74
  system_prompt = (
@@ -115,21 +174,20 @@ def extract_data(raw_text, fields_to_extract):
115
  table_data = []
116
  if isinstance(structured_data, dict):
117
  for k, v in structured_data.items():
118
- # Stringify lists or nested objects to fit cleanly inside cells
119
- val_str = ", ".join(v) if isinstance(v, list) else str(v)
120
  table_data.append([k, val_str])
121
  elif isinstance(structured_data, list):
122
  for idx, item in enumerate(structured_data):
123
  table_data.append([f"Item {idx + 1}", str(item)])
124
 
125
- return structured_data, table_data
126
 
127
  except json.JSONDecodeError:
128
  error_dict = {
129
  "error": "The model failed to return valid JSON. It returned this instead:",
130
  "raw_output": output_text
131
  }
132
- return error_dict, [["Error", "Invalid JSON parsed"]]
133
  except Exception as e:
134
  error_msg = str(e)
135
  if "model_not_found" in error_msg or "does not exist" in error_msg:
@@ -141,8 +199,9 @@ def extract_data(raw_text, fields_to_extract):
141
  "3. GGUF or LoRA adapter models are not directly supported by the Serverless API."
142
  ]
143
  }
144
- return err_dict, [["Connection Error", "Model Not Found"]]
145
- return {"error": error_msg}, [["Error", error_msg]]
 
146
 
147
  def generate_csv(json_data):
148
  """Converts the JSON output into a downloadable CSV file."""
@@ -216,6 +275,15 @@ with gr.Blocks(theme=gr.themes.Soft(), css=custom_css) as demo:
216
 
217
  # Right Column: Multi-view Output Panels
218
  with gr.Column(scale=1):
 
 
 
 
 
 
 
 
 
219
  with gr.Tabs():
220
  with gr.TabItem("📊 Structured Table"):
221
  table_output = gr.Dataframe(
@@ -254,11 +322,11 @@ with gr.Blocks(theme=gr.themes.Soft(), css=custom_css) as demo:
254
  # -------------------------
255
  # Event Connections
256
  # -------------------------
257
- # 1. Connect extraction button to both the Table View and JSON Tree
258
  extract_btn.click(
259
  fn=extract_data,
260
  inputs=[raw_input, schema_input],
261
- outputs=[json_output, table_output]
262
  )
263
 
264
  # 2. Connect CSV generation
 
6
  from huggingface_hub import InferenceClient
7
 
8
  # Replace this with your exact model repo ID
9
+ MODEL_ID = "tensorvizion/O-wen-4.6"
10
 
11
  # Securely load the Hugging Face token from Space secrets
12
  hf_token = os.environ.get("HF_TOKEN")
 
63
  # -------------------------
64
  # Helper & Extraction Logic
65
  # -------------------------
66
+ def generate_kpi_html(structured_data):
67
+ """Generates modern, responsive KPI metrics cards dynamically based on JSON data."""
68
+ if not structured_data or "error" in structured_data:
69
+ return """
70
+ <div style='display: flex; justify-content: center; align-items: center; height: 100px; border: 2px dashed var(--border-color-primary, #e5e7eb); border-radius: 12px; color: var(--text-color-subdued, #9ca3af);'>
71
+ Await extraction to generate KPI metrics...
72
+ </div>
73
+ """
74
+
75
+ cards_html = ""
76
+ if isinstance(structured_data, dict):
77
+ # Pick the top 4 attributes to show as metrics
78
+ items = list(structured_data.items())[:4]
79
+ for key, val in items:
80
+ # Clean up the key label
81
+ display_key = str(key).replace("_", " ").replace("-", " ").title()
82
+
83
+ # Format list value representation
84
+ if isinstance(val, list):
85
+ display_val = ", ".join(map(str, val))
86
+ else:
87
+ display_val = str(val)
88
+
89
+ # Truncate if string is too long for the card layout
90
+ if len(display_val) > 40:
91
+ display_val = display_val[:37] + "..."
92
+
93
+ # Dynamic highlight accents based on field types
94
+ accent_color = "#6366f1" # default Indigo
95
+ if any(x in display_key.lower() for x in ["price", "total", "amount", "cost", "revenue", "budget"]):
96
+ accent_color = "#10b981" # Emerald for cash/costs
97
+ elif any(x in display_key.lower() for x in ["date", "deadline", "due", "time"]):
98
+ accent_color = "#f59e0b" # Amber for dates/reminders
99
+ elif any(x in display_key.lower() for x in ["status", "priority", "importance"]):
100
+ accent_color = "#ef4444" # Crimson for status/alerts
101
+
102
+ cards_html += f"""
103
+ <div style='background: var(--body-background-fill, #ffffff); padding: 1rem; border-radius: 12px; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05); border: 1px solid var(--border-color-primary, #e5e7eb); border-left: 5px solid {accent_color}; min-width: 140px; flex: 1;'>
104
+ <div style='font-size: 0.7rem; color: var(--text-color-subdued, #6b7280); text-transform: uppercase; font-weight: 700; letter-spacing: 0.05em; margin-bottom: 0.25rem;'>{display_key}</div>
105
+ <div style='font-size: 1.05rem; color: var(--body-text-color, #111827); font-weight: 800; word-break: break-word;'>{display_val}</div>
106
+ </div>
107
+ """
108
+ elif isinstance(structured_data, list):
109
+ # Summary KPI for array data structures
110
+ cards_html = f"""
111
+ <div style='background: var(--body-background-fill, #ffffff); padding: 1rem; border-radius: 12px; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05); border: 1px solid var(--border-color-primary, #e5e7eb); border-left: 5px solid #6366f1; min-width: 140px; flex: 1;'>
112
+ <div style='font-size: 0.7rem; color: var(--text-color-subdued, #6b7280); text-transform: uppercase; font-weight: 700; letter-spacing: 0.05em; margin-bottom: 0.25rem;'>Total Records Found</div>
113
+ <div style='font-size: 1.5rem; color: var(--body-text-color, #111827); font-weight: 800;'>{len(structured_data)}</div>
114
+ </div>
115
+ """
116
+
117
+ return f"""
118
+ <div style='display: flex; flex-wrap: wrap; gap: 0.75rem; margin-bottom: 1rem; width: 100%;'>
119
+ {cards_html}
120
+ </div>
121
+ """
122
+
123
  def extract_data(raw_text, fields_to_extract):
124
  if not hf_token:
125
+ err_state = {"error": "HF_TOKEN secret is missing. Please add your Hugging Face Access Token to the Space Secrets."}
126
+ return err_state, [["Error", "HF_TOKEN missing"]], generate_kpi_html(err_state)
127
 
128
  if not raw_text.strip() or not fields_to_extract.strip():
129
+ err_state = {"error": "Please provide both raw text and fields to extract."}
130
+ return err_state, [["Error", "Incomplete inputs"]], generate_kpi_html(err_state)
131
 
132
  # Construct the system instruction
133
  system_prompt = (
 
174
  table_data = []
175
  if isinstance(structured_data, dict):
176
  for k, v in structured_data.items():
177
+ val_str = ", ".join(map(str, v)) if isinstance(v, list) else str(v)
 
178
  table_data.append([k, val_str])
179
  elif isinstance(structured_data, list):
180
  for idx, item in enumerate(structured_data):
181
  table_data.append([f"Item {idx + 1}", str(item)])
182
 
183
+ return structured_data, table_data, generate_kpi_html(structured_data)
184
 
185
  except json.JSONDecodeError:
186
  error_dict = {
187
  "error": "The model failed to return valid JSON. It returned this instead:",
188
  "raw_output": output_text
189
  }
190
+ return error_dict, [["Error", "Invalid JSON parsed"]], generate_kpi_html(error_dict)
191
  except Exception as e:
192
  error_msg = str(e)
193
  if "model_not_found" in error_msg or "does not exist" in error_msg:
 
199
  "3. GGUF or LoRA adapter models are not directly supported by the Serverless API."
200
  ]
201
  }
202
+ return err_dict, [["Connection Error", "Model Not Found"]], generate_kpi_html(err_dict)
203
+ err_state = {"error": error_msg}
204
+ return err_state, [["Error", error_msg]], generate_kpi_html(err_state)
205
 
206
  def generate_csv(json_data):
207
  """Converts the JSON output into a downloadable CSV file."""
 
275
 
276
  # Right Column: Multi-view Output Panels
277
  with gr.Column(scale=1):
278
+ # Dynamic HTML summary cards (Dashboard metrics style)
279
+ kpi_output = gr.HTML(
280
+ value="""
281
+ <div style='display: flex; justify-content: center; align-items: center; height: 100px; border: 2px dashed var(--border-color-primary, #e5e7eb); border-radius: 12px; color: var(--text-color-subdued, #9ca3af);'>
282
+ Await extraction to generate KPI metrics...
283
+ </div>
284
+ """
285
+ )
286
+
287
  with gr.Tabs():
288
  with gr.TabItem("📊 Structured Table"):
289
  table_output = gr.Dataframe(
 
322
  # -------------------------
323
  # Event Connections
324
  # -------------------------
325
+ # 1. Connect extraction button to the Table View, JSON Tree, and KPI output
326
  extract_btn.click(
327
  fn=extract_data,
328
  inputs=[raw_input, schema_input],
329
+ outputs=[json_output, table_output, kpi_output]
330
  )
331
 
332
  # 2. Connect CSV generation