c-ho commited on
Commit
7a1582c
·
verified ·
1 Parent(s): 88af0ff

Create app_2.py

Browse files
Files changed (1) hide show
  1. app_2.py +246 -0
app_2.py ADDED
@@ -0,0 +1,246 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from transformers import pipeline
3
+
4
+ # ---------------------------------------------------
5
+ # Models
6
+ # ---------------------------------------------------
7
+
8
+ MODEL_NAMES = [
9
+ "c-ho/2026-04-24-crf-classweights-clean",
10
+ "c-ho/2026-04-23-crf-classweights-clean",
11
+ ]
12
+
13
+ EXAMPLE_TEXT = (
14
+ "As a result, Indo-European developed a minimal vowel system "
15
+ "combined with a very large consonant inventory including "
16
+ "glottalized stops, also grammatical gender and adjectival agreement."
17
+ )
18
+
19
+ # ---------------------------------------------------
20
+ # Lazy model cache
21
+ # ---------------------------------------------------
22
+
23
+ model_cache = {}
24
+
25
+ def get_model(model_name):
26
+ if model_name not in model_cache:
27
+ model_cache[model_name] = pipeline(
28
+ "ner",
29
+ model=model_name,
30
+ aggregation_strategy="simple"
31
+ )
32
+ return model_cache[model_name]
33
+
34
+ # ---------------------------------------------------
35
+ # Model info
36
+ # ---------------------------------------------------
37
+
38
+ model_info = {
39
+ m: {
40
+ "link": f"https://huggingface.co/{m}",
41
+ "usage": f'''from transformers import pipeline
42
+
43
+ ner = pipeline(
44
+ "ner",
45
+ model="{m}",
46
+ aggregation_strategy="simple"
47
+ )
48
+
49
+ result = ner("Hello world")
50
+ print(result)
51
+ '''
52
+ }
53
+ for m in MODEL_NAMES
54
+ }
55
+
56
+ # ---------------------------------------------------
57
+ # UI helper
58
+ # ---------------------------------------------------
59
+
60
+ def display_model_info(model_name):
61
+ info = model_info[model_name]
62
+
63
+ return (
64
+ info["usage"],
65
+ f"[Open model page]({info['link']})"
66
+ )
67
+
68
+ # ---------------------------------------------------
69
+ # Merge subwords into full spans
70
+ # ---------------------------------------------------
71
+
72
+ def merge_subwords(results):
73
+ merged = []
74
+
75
+ current = None
76
+
77
+ for token in results:
78
+ word = token.get("word", "")
79
+ label = token.get(
80
+ "entity_group",
81
+ token.get("entity", "UNK")
82
+ )
83
+
84
+ score = token.get("score", 0.0)
85
+
86
+ start = token.get("start", 0)
87
+ end = token.get("end", 0)
88
+
89
+ # Continuation token
90
+ if word.startswith("##") and current is not None:
91
+ current["word"] += word[2:]
92
+ current["end"] = end
93
+ current["score"] = max(current["score"], score)
94
+
95
+ else:
96
+ # flush previous
97
+ if current is not None:
98
+ merged.append(current)
99
+
100
+ current = {
101
+ "word": word,
102
+ "start": start,
103
+ "end": end,
104
+ "entity_group": label,
105
+ "score": score
106
+ }
107
+
108
+ if current is not None:
109
+ merged.append(current)
110
+
111
+ return merged
112
+
113
+ # ---------------------------------------------------
114
+ # Main inference function
115
+ # ---------------------------------------------------
116
+
117
+ def analyze_text(text, model_name):
118
+ ner = get_model(model_name)
119
+
120
+ results = ner(text)
121
+
122
+ results = merge_subwords(results)
123
+
124
+ entities = []
125
+
126
+ table_rows = []
127
+
128
+ for ent in results:
129
+ label = ent["entity_group"]
130
+
131
+ entities.append({
132
+ "start": ent["start"],
133
+ "end": ent["end"],
134
+ "label": label,
135
+ })
136
+
137
+ table_rows.append([
138
+ ent["word"],
139
+ label,
140
+ round(ent["score"], 3)
141
+ ])
142
+
143
+ highlighted_output = {
144
+ "text": text,
145
+ "entities": entities
146
+ }
147
+
148
+ return highlighted_output, table_rows
149
+
150
+ # ---------------------------------------------------
151
+ # Entity colors
152
+ # ---------------------------------------------------
153
+
154
+ COLOR_MAP = {
155
+ "LanguageRelatedTerm": "#ffcc00",
156
+ "OtherLinguisticTerm": "#99ccff",
157
+ "PhonologicalPhenomenon": "#ff9999",
158
+ "MorphosyntacticPhenomenon": "#99ff99",
159
+ "TOPNODE_DUMMY": "#dddddd",
160
+ }
161
+
162
+ # ---------------------------------------------------
163
+ # UI
164
+ # ---------------------------------------------------
165
+
166
+ with gr.Blocks(title="Linguistic Annotation Demo") as demo:
167
+
168
+ gr.Markdown(
169
+ """
170
+ # Linguistic Annotation Demo
171
+
172
+ This Space demonstrates custom linguistic sequence tagging models
173
+ for detecting linguistic terminology and phenomena.
174
+ """
175
+ )
176
+
177
+ with gr.Row():
178
+
179
+ with gr.Column(scale=1):
180
+
181
+ model_selector = gr.Dropdown(
182
+ choices=MODEL_NAMES,
183
+ value=MODEL_NAMES[0],
184
+ label="Select Model"
185
+ )
186
+
187
+ text_input = gr.Textbox(
188
+ label="Input Text",
189
+ lines=8,
190
+ value=EXAMPLE_TEXT
191
+ )
192
+
193
+ run_button = gr.Button("Run Annotation")
194
+
195
+ with gr.Column(scale=1):
196
+
197
+ code_output = gr.Code(
198
+ label="Transformers Usage"
199
+ )
200
+
201
+ link_output = gr.Markdown()
202
+
203
+ highlighted_output = gr.HighlightedText(
204
+ label="Annotated Text",
205
+ combine_adjacent=True,
206
+ color_map=COLOR_MAP,
207
+ show_legend=True
208
+ )
209
+
210
+ entity_table = gr.Dataframe(
211
+ headers=["Text", "Label", "Confidence"],
212
+ datatype=["str", "str", "number"],
213
+ interactive=False,
214
+ label="Detected Entities"
215
+ )
216
+
217
+ # -------------------------
218
+ # Events
219
+ # -------------------------
220
+
221
+ run_button.click(
222
+ analyze_text,
223
+ inputs=[text_input, model_selector],
224
+ outputs=[highlighted_output, entity_table]
225
+ )
226
+
227
+ model_selector.change(
228
+ display_model_info,
229
+ inputs=model_selector,
230
+ outputs=[code_output, link_output]
231
+ )
232
+
233
+ demo.load(
234
+ display_model_info,
235
+ inputs=model_selector,
236
+ outputs=[code_output, link_output]
237
+ )
238
+
239
+ # ---------------------------------------------------
240
+ # Launch
241
+ # ---------------------------------------------------
242
+
243
+ demo.launch(
244
+ server_name="0.0.0.0",
245
+ server_port=7860
246
+ )