kapllan commited on
Commit
ccd6617
·
1 Parent(s): bb6a3b4

First commit.

Browse files
Files changed (3) hide show
  1. app.py +96 -0
  2. id2label.json +227 -0
  3. requirements.txt +20 -0
app.py ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json as js
2
+ import os
3
+ import re
4
+ from typing import List
5
+
6
+ import fasttext
7
+ import gradio as gr
8
+ import joblib
9
+ import omikuji
10
+ from huggingface_hub import snapshot_download
11
+
12
+ # Download the model files from Hugging Face
13
+ for repo_id in ['kapllan/omikuji-bonsai-parliament-de-spacy', 'kapllan/omikuji-bonsai-parliament-fr-spacy',
14
+ 'kapllan/omikuji-bonsai-parliament-it-spacy']:
15
+ if not os.path.exists(repo_id):
16
+ os.makedirs(repo_id)
17
+ model_dir = snapshot_download(repo_id=repo_id, local_dir=repo_id)
18
+
19
+ lang_model = fasttext.load_model('lid.176.bin')
20
+
21
+ with open('./id2label.json', 'r') as f:
22
+ id2label = js.load(f)
23
+
24
+
25
+ def map_language(language: str) -> str:
26
+ language_mapping = {'de': 'German',
27
+ 'it': 'Italian',
28
+ 'fr': 'French'}
29
+ if language in language_mapping.keys():
30
+ return language_mapping[language]
31
+ else:
32
+ return language
33
+
34
+
35
+ def find_model(language: str):
36
+ vectorizer, model = None, None
37
+ if language in ['de', 'fr', 'it']:
38
+ path_to_vectorizer = f'./kapllan/omikuji-bonsai-parliament-{language}-spacy/vectorizer'
39
+ path_to_model = f'./kapllan/omikuji-bonsai-parliament-{language}-spacy/omikuji-model'
40
+ vectorizer = joblib.load(path_to_vectorizer)
41
+ model = omikuji.Model.load(path_to_model)
42
+ return vectorizer, model
43
+
44
+
45
+ def predict_lang(text: str) -> str:
46
+ predictions = lang_model.predict(text, k=1) # returns top 2 matching languages
47
+ language = predictions[0][0] # returns top 2 matching languages
48
+ language = re.sub(r'__label__', '', language) # returns top 2 matching languages
49
+ return language
50
+
51
+
52
+ def predict_topic(text: str) -> [List[str], str]:
53
+ results = []
54
+ language = predict_lang(text)
55
+ vectorizer, model = find_model(language)
56
+ language = map_language(language)
57
+ if vectorizer is not None:
58
+ texts = [text]
59
+ vector = vectorizer.transform(texts)
60
+ for row in vector:
61
+ if row.nnz == 0: # All zero vector, empty result
62
+ continue
63
+ feature_values = [(col, row[0, col]) for col in row.nonzero()[1]]
64
+ for subj_id, score in model.predict(feature_values, top_k=1000):
65
+ results.append((id2label[str(subj_id)], score))
66
+ return results, language
67
+
68
+
69
+ def topic_modeling(text: str, threshold: float) -> [List[str], str]:
70
+ # Prepare labels and scores for the plot
71
+ sorted_topics, language = predict_topic(text)
72
+ if len(sorted_topics) > 0 and language in ['German', 'French', 'Italian']:
73
+ sorted_topics = [t for t in sorted_topics if t[1] >= threshold]
74
+ else:
75
+ sorted_topics = []
76
+ return sorted_topics, language
77
+
78
+
79
+ with gr.Blocks() as iface:
80
+ gr.Markdown("# Topic Modeling")
81
+ gr.Markdown("Enter a documents and get each topic along with its score.")
82
+
83
+ with gr.Row():
84
+ with gr.Column():
85
+ input_text = gr.Textbox(lines=10, placeholder="Enter documents separated by newline...")
86
+ submit_button = gr.Button("Submit")
87
+ threshold_slider = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label="Score Threshold", value=0.0)
88
+ language_text = gr.Textbox(lines=1, placeholder="Detected language will be shown here...",
89
+ interactive=False, label="Detected Language")
90
+ with gr.Column():
91
+ output_data = gr.Dataframe(headers=["Label", "Score"])
92
+
93
+ submit_button.click(topic_modeling, inputs=[input_text, threshold_slider], outputs=[output_data, language_text])
94
+
95
+ # Launch the app
96
+ iface.launch()
id2label.json ADDED
@@ -0,0 +1,227 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "0": "AHV",
3
+ "1": "Abfall",
4
+ "2": "Abgabe",
5
+ "3": "Agrarpolitik",
6
+ "4": "Agrarproduktion",
7
+ "5": "Altersfragen",
8
+ "6": "Arbeit",
9
+ "7": "Arbeitslosenversicherung",
10
+ "8": "Arbeitslosigkeit",
11
+ "9": "Arbeitsmarkt",
12
+ "10": "Arbeitsrecht",
13
+ "11": "Armee",
14
+ "12": "Armut/Ungleichheit",
15
+ "13": "Artenvielfalt",
16
+ "14": "Asylpolitik",
17
+ "15": "Auslandschweizer",
18
+ "16": "Ausländerpolitik",
19
+ "17": "Aussenpolitik : Ausland",
20
+ "18": "Aussenpolitik : Schweiz",
21
+ "19": "Aussenwirtschaftspolitik",
22
+ "20": "Bankenkrise",
23
+ "21": "Bauwesen/Immobilien",
24
+ "22": "Behinderung",
25
+ "23": "Berg",
26
+ "24": "Berufliche Vorsorge",
27
+ "25": "Berufsbildung",
28
+ "26": "Beschwerderecht",
29
+ "27": "Beschäftigung und Arbeit",
30
+ "28": "Bewaffnung",
31
+ "29": "Beziehung Schweiz - EU",
32
+ "30": "Bildung",
33
+ "31": "Boden",
34
+ "32": "Bürgerrecht",
35
+ "33": "Datenschutz",
36
+ "34": "Demokratie",
37
+ "35": "Digitalisierung",
38
+ "36": "Diplomatie",
39
+ "37": "Diskriminierung",
40
+ "38": "Elektrizität",
41
+ "39": "Energie",
42
+ "40": "Energiepolitik",
43
+ "41": "Erberecht",
44
+ "42": "Ernährung",
45
+ "43": "Erwerbsersatzordnung",
46
+ "44": "Europapolitik",
47
+ "45": "Europarat",
48
+ "46": "Europarecht",
49
+ "47": "Europäische Union",
50
+ "48": "Europäisches Parlament",
51
+ "49": "Exekutive",
52
+ "50": "Familienfragen",
53
+ "51": "Familienrecht",
54
+ "52": "Familienzulage",
55
+ "53": "Finanzausgleich",
56
+ "54": "Finanzmarkt",
57
+ "55": "Finanzplatz",
58
+ "56": "Finanzrecht",
59
+ "57": "Finanzwesen",
60
+ "58": "Flüchtling",
61
+ "59": "Forschung",
62
+ "60": "Fortpflanzung",
63
+ "61": "Fossile Energie",
64
+ "62": "Föderalismus",
65
+ "63": "Geld- und Währungspolitik",
66
+ "64": "Geldwäscherei",
67
+ "65": "Gentechnologie",
68
+ "66": "Gerichtswesen",
69
+ "67": "Geschichte Ausland",
70
+ "68": "Geschichte Schweiz",
71
+ "69": "Geschlechterfragen",
72
+ "70": "Gesellschaftsfragen",
73
+ "71": "Gesundheit",
74
+ "72": "Gesundheitspolitik",
75
+ "73": "Gewalt",
76
+ "74": "Gewerkschaft",
77
+ "75": "Globalisierung",
78
+ "76": "Grenze",
79
+ "77": "Grundrechte",
80
+ "78": "Güterverkehr",
81
+ "79": "Handel",
82
+ "80": "Heil- und Hilfsmittel",
83
+ "81": "Informatik",
84
+ "82": "Information",
85
+ "83": "Informationswissenschaft",
86
+ "84": "Internationale Politik",
87
+ "85": "Internationales Recht",
88
+ "86": "Internet und soziale Medien",
89
+ "87": "Interventionspolitik",
90
+ "88": "Invalidenversicherung",
91
+ "89": "Jagd und Fischerei",
92
+ "90": "Kapital",
93
+ "91": "Katastrophe",
94
+ "92": "Kernenergie",
95
+ "93": "Kinder- und Jugendfragen",
96
+ "94": "Kinderrechte",
97
+ "95": "Kindes- und Erwachsenenschutzrecht",
98
+ "96": "Klimafragen",
99
+ "97": "Konkursrecht",
100
+ "98": "Konsum",
101
+ "99": "Korruption",
102
+ "100": "Krankenversicherung",
103
+ "101": "Krieg",
104
+ "102": "Krise",
105
+ "103": "Kultur",
106
+ "104": "Landwirtschaft",
107
+ "105": "Luft",
108
+ "106": "Luftfahrt",
109
+ "107": "Lärm",
110
+ "108": "Medien",
111
+ "109": "Medien / Kommunikation",
112
+ "110": "Medienrecht",
113
+ "111": "Medizinalberuf",
114
+ "112": "Menschenrechte",
115
+ "113": "Miet- und Wohnungswesen",
116
+ "114": "Migration",
117
+ "115": "Migrationsbewegung",
118
+ "116": "Mutterschaftsversicherung",
119
+ "117": "Nationalbank",
120
+ "118": "Obligationenrecht",
121
+ "119": "Parlament",
122
+ "120": "Parlament Ausland",
123
+ "121": "Parlament Schweiz",
124
+ "122": "Patient",
125
+ "123": "Personenrecht",
126
+ "124": "Pflege",
127
+ "125": "Post",
128
+ "126": "Presse",
129
+ "127": "Privatversicherung",
130
+ "128": "Produktion",
131
+ "129": "Radio und Fernsehen",
132
+ "130": "Rassismus",
133
+ "131": "Ratsmitglied",
134
+ "132": "Raumplanung",
135
+ "133": "Raumplanung und Wohnungswesen",
136
+ "134": "Recht Allgemein",
137
+ "135": "Rechte und Freiheiten",
138
+ "136": "Rechtswissenschaft",
139
+ "137": "Religionsfragen",
140
+ "138": "Sachenrecht",
141
+ "139": "Sans-Papiers",
142
+ "140": "Schiedsgerichtsbarkeit",
143
+ "141": "Schienenverkehr",
144
+ "142": "Schifffahrt",
145
+ "143": "Schule",
146
+ "144": "Service public",
147
+ "145": "Sicherheitspolitik",
148
+ "146": "Sicherheitspolitik/Friedenspolitik",
149
+ "147": "Soziale Fragen",
150
+ "148": "Sozialer Schutz",
151
+ "149": "Sozialhilfe",
152
+ "150": "Sozialpolitik",
153
+ "151": "Sozialversicherung",
154
+ "152": "Spiel",
155
+ "153": "Spital",
156
+ "154": "Sport",
157
+ "155": "Sprache",
158
+ "156": "Staat",
159
+ "157": "Staatspolitik",
160
+ "158": "Staatssouveränität",
161
+ "159": "Sterben und Tod",
162
+ "160": "Steuer",
163
+ "161": "Steuerhinterziehung",
164
+ "162": "Steuerrecht",
165
+ "163": "Steuerwettbewerb",
166
+ "164": "Stiftung",
167
+ "165": "Strafprozessordnung",
168
+ "166": "Strafrecht",
169
+ "167": "Straftat",
170
+ "168": "Strassenverkehr",
171
+ "169": "Sucht",
172
+ "170": "Telefonie",
173
+ "171": "Terrorismus",
174
+ "172": "Tierschutz",
175
+ "173": "Tierversuch",
176
+ "174": "Tourismus",
177
+ "175": "Umwelt",
178
+ "176": "Umweltpolitik",
179
+ "177": "Umweltschutz",
180
+ "178": "Unfallversicherung",
181
+ "179": "Universität/Hochschule/Fachhochschule",
182
+ "180": "Unternehmen",
183
+ "181": "Urheberrecht",
184
+ "182": "Verfahrensrecht",
185
+ "183": "Verfassung",
186
+ "184": "Vergaberecht",
187
+ "185": "Verkehr",
188
+ "186": "Verkehrspolitik",
189
+ "187": "Vertrag",
190
+ "188": "Verwaltungsrecht",
191
+ "189": "Volksabstimmung",
192
+ "190": "Vorrechte und Immunität",
193
+ "191": "Wahlen",
194
+ "192": "Wald",
195
+ "193": "Wasser",
196
+ "194": "Weiterbildung",
197
+ "195": "Wettbewerb",
198
+ "196": "Wirtschaft",
199
+ "197": "Wirtschaftsleben",
200
+ "198": "Wirtschaftspolitik",
201
+ "199": "Wissenschaft / Forschung",
202
+ "200": "Zivilprozessordnung",
203
+ "201": "Zivilrecht",
204
+ "202": "Zivilschutz und Bevölkerungsschutz/Zivildienst",
205
+ "203": "Zoll",
206
+ "204": "erneuerbare Energie",
207
+ "205": "innere Sicherheit",
208
+ "206": "internationale Beziehungen",
209
+ "207": "internationale Organisation",
210
+ "208": "internationale Politik",
211
+ "209": "internationale Rechtshilfe",
212
+ "210": "internationale Strafjustiz",
213
+ "211": "internationale Zusammenarbeit",
214
+ "212": "internationaler Konflikt",
215
+ "213": "internationales Abkommen",
216
+ "214": "internationales Privatrecht",
217
+ "215": "internationales Recht",
218
+ "216": "internationales humanitäres Recht",
219
+ "217": "kantonales Parlament",
220
+ "218": "politische Partei",
221
+ "219": "politische Rechte",
222
+ "220": "politisches Leben",
223
+ "221": "politisches System",
224
+ "222": "öffentliche Finanzen",
225
+ "223": "öffentliche Verwaltung",
226
+ "224": "öffentlicher Verkehr"
227
+ }
requirements.txt ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Requests==2.32.2
2
+ annif
3
+ beautifulsoup4==4.12.3
4
+ datasets==2.14.5
5
+ fasttext==0.9.2
6
+ gradio
7
+ iterative_stratification==0.1.7
8
+ nltk==3.8.1
9
+ numpy==1.24.4
10
+ omikuji==0.5.1
11
+ openpyxl
12
+ pandas==2.2.2
13
+ pytz==2023.3.post1
14
+ scikit_learn==1.3.2
15
+ sentence_transformers==2.2.2
16
+ swissparlpy==0.3.0
17
+ tqdm==4.66.1
18
+ transformers==4.39.3
19
+ spacy==3.7.4
20
+ huggingface_hub