urchade commited on
Commit
e17c9d4
Β·
verified Β·
1 Parent(s): 4e873dd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +87 -119
app.py CHANGED
@@ -4,13 +4,10 @@ from gliner2 import GLiNER2
4
  from huggingface_hub import login
5
  import os
6
 
7
- # Get API key from environment variable
8
- hf_token = os.getenv("HF_TOKEN")
9
-
10
  # Authenticate with Hugging Face
 
11
  login(hf_token)
12
 
13
- # β€”β€”β€” Load model once β€”β€”β€”
14
  model = GLiNER2.from_pretrained("fastino/gliner2-base-0207")
15
 
16
  def run_ner(text, types_csv, descs):
@@ -20,6 +17,7 @@ def run_ner(text, types_csv, descs):
20
  res = model.extract_entities(text=text, entity_types=inp, include_confidence=True)
21
  return model.pretty_print_results(res, include_confidence=True)
22
 
 
23
  def run_class(text, task, labels_csv, descs, multi):
24
  labels = [l.strip() for l in labels_csv.split(",") if l.strip()]
25
  desc_map = {k: v for line in descs.split("\n") if ":" in line for k,v in [line.split(":",1)]}
@@ -34,6 +32,7 @@ def run_class(text, task, labels_csv, descs, multi):
34
  res = model.classify_text(text=text, tasks=tasks, include_confidence=True)
35
  return model.pretty_print_results(res, include_confidence=True)
36
 
 
37
  def run_struct(text, struct_json):
38
  try:
39
  cfg = json.loads(struct_json)
@@ -42,143 +41,112 @@ def run_struct(text, struct_json):
42
  res = model.extract_json(text=text, structures=cfg, include_confidence=True)
43
  return model.pretty_print_results(res, include_confidence=True)
44
 
45
- # β€”β€”β€” Clean White Theme & Layout β€”β€”β€”
46
  custom_css = """
47
- body {
48
- background: #ffffff !important;
49
- font-family: 'Helvetica Neue', sans-serif;
50
- color: #333333;
51
- }
52
- .gradio-container {
53
- max-width: 600px;
54
- padding: 0;
55
- background: #ffffff;
56
  }
57
- header, .logo, .subtitle {
58
- border: none !important;
59
- box-shadow: none !important;
 
60
  }
61
- .gradio-container * {
62
- box-shadow: none !important;
 
63
  }
64
- .card {
65
- background: #ffffff;
66
- padding: 15px;
 
67
  }
68
- label {
69
- color: #444444;
70
- font-weight: 600;
 
71
  }
72
- .gr-textbox textarea,
73
- .gr-code,
74
- .gr-dropdown,
75
- .gr-checkbox,
76
- .gr-button {
77
- background: #ffffff !important;
78
- box-shadow: none !important;
79
  }
80
- .accordion-button {
81
- border: none !important;
82
- box-shadow: none !important;
83
- font-weight: 500;
 
 
84
  }
85
  .gr-button.primary {
86
- background: #5b8def;
87
- color: #ffffff;
 
 
88
  }
89
  """
90
 
91
- with gr.Blocks(theme=gr.themes.Base(), css=custom_css) as demo:
92
  # Header
93
- gr.HTML("""
94
- <header style="text-align:center; padding:10px 0;">
95
- <div class="logo" style="font-size:1.8rem; font-weight:700; color:#333333;">🎯 GLiNER2</div>
96
- <div class="subtitle" style="font-size:0.85rem; color:#777777;">Compact β€’ White Theme β€’ Screenshot-Ready</div>
97
- </header>
98
- """)
 
 
99
 
100
  with gr.Tabs():
101
- # Structure Extraction Tab
102
- with gr.TabItem("Hierarchical Structure Extraction"):
103
- with gr.Row(elem_classes="card"):
104
- with gr.Column(scale=2):
105
- txt3 = gr.Textbox(
106
- label="Input text", lines=3,
107
- value=(
108
- "The Acme Pro Laptop 15” features an Intel Core i7 processor, 16GB RAM, 512GB SSD, "
109
- "and a 15.6-inch 4K display. Priced at $1,499, it offers Wi-Fi 6, Bluetooth 5.2, and "
110
- "a backlit keyboard."
111
- )
112
- )
113
- struct3 = gr.Code(
114
- language="json", lines=7,
115
- label = "Schema",
116
- value=json.dumps({
117
- "product": [
118
- "name::str::Product name and model",
119
- "price::str::Product cost",
120
- "features::list::Key product features",
121
- "category::[electronics|software|hardware]::str"
122
- ]
123
- }, indent=2)
124
- )
125
- btn3 = gr.Button("Predict", variant="primary")
126
- with gr.Column(scale=1):
127
- out3 = gr.Code(language="json", lines=8, label="Output")
128
- btn3.click(run_struct, [txt3, struct3], out3)
129
-
130
  # NER Tab
131
- with gr.TabItem("Named Entity Recognition"):
132
- with gr.Row(elem_classes="card"):
133
  with gr.Column(scale=2):
134
- txt1 = gr.Textbox(
135
- label="Text", lines=4,
136
- value=(
137
- "Dr. Alice Smith, Chief Data Scientist at OpenAI, spoke at the AI Summit "
138
- "in San Francisco on June 12, 2025, about advancements in large-scale language "
139
- "models, ethical AI guidelines, and real-world GPT-4 Turbo applications."
140
- )
141
- )
142
- types1 = gr.Textbox(label="Types (csv)", value="person, title, organization, event, location, date, topic")
143
- with gr.Accordion("Descriptions (opt)", open=False):
144
- desc1 = gr.Textbox(lines=4, placeholder=(
145
- "person: Full names\n"
146
- "title: Roles\n"
147
- "organization: Companies\n"
148
- "event: Conferences\n"
149
- "location: Cities\n"
150
- "date: Temporal expressions"
151
- ))
152
- btn1 = gr.Button("Predict", variant="primary")
153
  with gr.Column(scale=1):
154
- out1 = gr.Code(language="json", lines=8)
155
- btn1.click(run_ner, [txt1, types1, desc1], out1)
156
 
157
  # Classification Tab
158
- with gr.TabItem("Text Classification"):
159
- with gr.Row(elem_classes="card"):
160
  with gr.Column(scale=2):
161
- txt2 = gr.Textbox(
162
- label="Text", lines=4,
163
- value=(
164
- "The Q2 2025 financial report shows a 15% revenue increase driven by cloud "
165
- "services, offset by a 12% rise in R&D costs. Overall sentiment is cautiously "
166
- "optimistic among stakeholders."
167
- )
168
- )
169
- task2 = gr.Textbox(label="Task", value="financial_sentiment")
170
- labs2 = gr.Textbox(label="Labels (csv)", value="positive, negative, neutral, mixed, uncertain")
171
- with gr.Accordion("Label Descriptions (opt)", open=False):
172
- desc2 = gr.Textbox(lines=3, placeholder=(
173
- "positive: Favorable outcomes\n"
174
- "negative: Concerns raised\n"
175
- "neutral: Balanced reporting"
176
- ))
177
- multi2 = gr.Checkbox(label="Multi-label?", value=True)
178
- btn2 = gr.Button("Predict", variant="primary")
179
  with gr.Column(scale=1):
180
- out2 = gr.Code(language="json", lines=8)
181
- btn2.click(run_class, [txt2, task2, labs2, desc2, multi2], out2)
182
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
 
184
  demo.launch(share=False)
 
4
  from huggingface_hub import login
5
  import os
6
 
 
 
 
7
  # Authenticate with Hugging Face
8
+ hf_token = os.getenv("HF_TOKEN")
9
  login(hf_token)
10
 
 
11
  model = GLiNER2.from_pretrained("fastino/gliner2-base-0207")
12
 
13
  def run_ner(text, types_csv, descs):
 
17
  res = model.extract_entities(text=text, entity_types=inp, include_confidence=True)
18
  return model.pretty_print_results(res, include_confidence=True)
19
 
20
+
21
  def run_class(text, task, labels_csv, descs, multi):
22
  labels = [l.strip() for l in labels_csv.split(",") if l.strip()]
23
  desc_map = {k: v for line in descs.split("\n") if ":" in line for k,v in [line.split(":",1)]}
 
32
  res = model.classify_text(text=text, tasks=tasks, include_confidence=True)
33
  return model.pretty_print_results(res, include_confidence=True)
34
 
35
+
36
  def run_struct(text, struct_json):
37
  try:
38
  cfg = json.loads(struct_json)
 
41
  res = model.extract_json(text=text, structures=cfg, include_confidence=True)
42
  return model.pretty_print_results(res, include_confidence=True)
43
 
44
+ # Custom CSS for modern look
45
  custom_css = """
46
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap');
47
+ :root {
48
+ --primary: #4f46e5;
49
+ --secondary: #6366f1;
50
+ --background: #f9fafb;
51
+ --card-bg: #ffffff;
52
+ --text: #1f2937;
53
+ --muted: #6b7280;
 
54
  }
55
+ body {
56
+ background: var(--background) !important;
57
+ font-family: 'Inter', sans-serif;
58
+ color: var(--text) !important;
59
  }
60
+ header.brand {
61
+ padding: 2rem 0;
62
+ text-align: center;
63
  }
64
+ header.brand .logo {
65
+ font-size: 2rem;
66
+ font-weight: 700;
67
+ color: var(--primary);
68
  }
69
+ header.brand .subtitle {
70
+ margin-top: 0.2rem;
71
+ font-size: 0.9rem;
72
+ color: var(--muted);
73
  }
74
+ .gradio-container {
75
+ max-width: 800px;
76
+ margin: auto;
77
+ padding: 1rem;
 
 
 
78
  }
79
+ .card {
80
+ background: var(--card-bg);
81
+ padding: 1.5rem;
82
+ border-radius: 0.75rem;
83
+ box-shadow: 0 4px 10px rgba(0,0,0,0.05);
84
+ margin-bottom: 1.5rem;
85
  }
86
  .gr-button.primary {
87
+ background: var(--primary) !important;
88
+ color: #fff !important;
89
+ border-radius: 0.5rem;
90
+ padding: 0.6rem 1.2rem;
91
  }
92
  """
93
 
94
+ with gr.Blocks(theme=gr.themes.Soft(primary_hue="purple", secondary_hue="blue"), css=custom_css) as demo:
95
  # Header
96
+ gr.HTML(
97
+ """
98
+ <header class=\"brand\">
99
+ <div class=\"logo\">✨ GLiNER2</div>
100
+ <div class=\"subtitle\">Compact β€’ Modern β€’ Screenshot-Ready</div>
101
+ </header>
102
+ """
103
+ )
104
 
105
  with gr.Tabs():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
  # NER Tab
107
+ with gr.TabItem("πŸ” Named Entity Recognition"):
108
+ with gr.Row(elem_classes="card", gap="small"):
109
  with gr.Column(scale=2):
110
+ txt1 = gr.Textbox(label="Input Text", lines=5, placeholder="Enter text to extract entities...")
111
+ types1 = gr.Textbox(label="Entity Types (CSV)", value="person, organization, location, date, title, topic")
112
+ with gr.Accordion("Optional Descriptions", open=False):
113
+ desc1 = gr.Textbox(lines=3, placeholder="person: Full name\norganization: Companies\n...")
114
+ btn1 = gr.Button("Extract Entities", variant="primary")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  with gr.Column(scale=1):
116
+ out1 = gr.Code(language="json", label="Results", lines=8)
117
+ btn1.click(run_ner, inputs=[txt1, types1, desc1], outputs=out1)
118
 
119
  # Classification Tab
120
+ with gr.TabItem("πŸ“ Text Classification"):
121
+ with gr.Row(elem_classes="card", gap="small"):
122
  with gr.Column(scale=2):
123
+ txt2 = gr.Textbox(label="Input Text", lines=5, placeholder="Enter text to classify...")
124
+ task2 = gr.Textbox(label="Task Name", value="sentiment_analysis")
125
+ labs2 = gr.Textbox(label="Labels (CSV)", value="positive, negative, neutral")
126
+ with gr.Accordion("Optional Label Descriptions", open=False):
127
+ desc2 = gr.Textbox(lines=3, placeholder="positive: Positive sentiment\n...")
128
+ multi2 = gr.Checkbox(label="Multi-label?", value=False)
129
+ btn2 = gr.Button("Classify Text", variant="primary")
 
 
 
 
 
 
 
 
 
 
 
130
  with gr.Column(scale=1):
131
+ out2 = gr.Code(language="json", label="Results", lines=8)
132
+ btn2.click(run_class, inputs=[txt2, task2, labs2, desc2, multi2], outputs=out2)
133
 
134
+ # Structure Extraction Tab
135
+ with gr.TabItem("πŸ“ Structure Extraction"):
136
+ with gr.Row(elem_classes="card", gap="small"):
137
+ with gr.Column(scale=2):
138
+ txt3 = gr.Textbox(label="Input Text", lines=5, placeholder="Enter text for structure extraction...")
139
+ struct3 = gr.Code(language="json", label="Schema (JSON)", lines=8, value=json.dumps({
140
+ "product": [
141
+ "name::str::Product name and model",
142
+ "price::str::Product price",
143
+ "features::list::Key features",
144
+ "category::str::Product category"
145
+ ]
146
+ }, indent=2))
147
+ btn3 = gr.Button("Extract Structure", variant="primary")
148
+ with gr.Column(scale=1):
149
+ out3 = gr.Code(language="json", label="Results", lines=8)
150
+ btn3.click(run_struct, inputs=[txt3, struct3], outputs=out3)
151
 
152
  demo.launch(share=False)