tymbos commited on
Commit
f94c5ea
·
verified ·
1 Parent(s): e022de9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +127 -78
app.py CHANGED
@@ -1,15 +1,18 @@
1
  # -*- coding: utf-8 -*-
 
 
2
  import gradio as gr
3
  import requests
4
- import json
5
- import re
6
  from io import BytesIO
7
  import matplotlib.pyplot as plt
8
- from train_tokenizer import train_tokenizer
9
  from datasets import load_dataset
 
10
  from tokenizers import Tokenizer
11
- import tempfile
12
- import os
 
 
13
 
14
  def fetch_splits(dataset_name):
15
  try:
@@ -42,7 +45,6 @@ def update_components(dataset_name):
42
  try:
43
  splits_data = fetch_splits(dataset_name)
44
  config_choices = list(splits_data['splits'].keys())
45
-
46
  first_config = config_choices[0] if config_choices else None
47
  iframe_html = f"""
48
  <iframe
@@ -53,30 +55,30 @@ def update_components(dataset_name):
53
  ></iframe>
54
  """ if first_config else "Δεν βρέθηκαν διαθέσιμα δεδομένα"
55
 
56
- # Επιστρέφουμε ένα νέο πεδίο όπου ο χρήστης μπορεί να εισάγει πολλαπλά configs (π.χ. "20231101.el,20231101.en")
 
57
  return [
58
- gr.Textbox.update(value=f"{first_config},20231101.en" if first_config and "el" in first_config else first_config),
59
  gr.Dropdown.update(choices=splits_data['splits'].get(first_config, [])),
60
  gr.HTML.update(value=iframe_html)
61
  ]
62
  except Exception as e:
63
  raise gr.Error(f"Σφάλμα: {str(e)}")
64
 
65
- def update_split_choices(dataset_name, config):
66
- # Εδώ παραμένει για το πρώτο config (μπορείτε να το τροποποιήσετε αν χρειαστεί)
67
- if not dataset_name or not config:
68
  return gr.Dropdown.update(choices=[])
69
-
70
  try:
71
  splits_data = fetch_splits(dataset_name)
72
- return gr.Dropdown.update(choices=splits_data['splits'].get(config.split(",")[0].strip(), []))
 
 
73
  except:
74
  return gr.Dropdown.update(choices=[])
75
 
76
  def create_iterator(dataset_name, configs, split):
77
  """
78
- Δέχεται τη μεταβλητή configs ως string με λίστα από config χωρισμένα με κόμμα.
79
- Για κάθε config φορτώνει το αντίστοιχο streaming dataset και επιστρέφει τα κείμενα.
80
  """
81
  configs_list = [c.strip() for c in configs.split(",") if c.strip()]
82
  for config in configs_list:
@@ -94,62 +96,112 @@ def create_iterator(dataset_name, configs, split):
94
  except Exception as e:
95
  print(f"Σφάλμα φόρτωσης dataset για config {config}: {e}")
96
 
97
- def train_and_test(dataset_name, configs, split, vocab_size, min_freq, test_text, custom_files):
98
- try:
99
- dataset_iterator = create_iterator(dataset_name, configs, split)
100
-
101
- # Συνδυασμός iterator από τα streaming datasets και τα custom αρχεία
102
- def combined_iterator():
103
- # Δεδομένα από τα streaming datasets
104
- for text in dataset_iterator:
105
- yield text
106
- # Δεδομένα από τα custom αρχεία (αναμένεται λίστα με file paths)
107
- if custom_files:
108
- for file_path in custom_files:
109
- try:
110
- with open(file_path, 'r', encoding='utf-8') as f:
111
- content = f.read()
112
- if content:
113
- yield content
114
- except Exception as file_error:
115
- print(f"Σφάλμα ανάγνωσης αρχείου {file_path}: {file_error}")
116
-
117
- # Δημιουργία tokenizer χωρίς progress bar (αφαιρέσαμε το gr.Progress)
118
- tokenizer = train_tokenizer(combined_iterator(), vocab_size, min_freq)
119
-
120
- # Αποθήκευση και φόρτωση του εκπαι��ευμένου tokenizer
121
- with tempfile.NamedTemporaryFile(delete=False, suffix=".json") as f:
122
- tokenizer.save(f.name)
123
- trained_tokenizer = Tokenizer.from_file(f.name)
124
- os.unlink(f.name)
125
-
126
- # Validation: κωδικοποίηση και αποκωδικοποίηση του test κειμένου
127
- encoded = trained_tokenizer.encode(test_text)
128
- decoded = trained_tokenizer.decode(encoded.ids)
129
-
130
- # Δημιουργία γραφήματος για την κατανομή των μηκών των tokens
131
- token_lengths = [len(t) for t in encoded.tokens]
132
- fig = plt.figure()
133
- plt.hist(token_lengths, bins=20)
134
- plt.xlabel('Μήκος Token')
135
- plt.ylabel('Συχνότητα')
136
- img_buffer = BytesIO()
137
- plt.savefig(img_buffer, format='png')
138
- plt.close()
139
-
140
- return {
141
- "Πρωτότυπο Κείμενο": test_text,
142
- "Αποκωδικοποιημένο": decoded,
143
- "Αριθμός Tokens": len(encoded.tokens),
144
- "Αγνώστων Tokens": sum(1 for t in encoded.tokens if t == "<unk>")
145
- }, img_buffer.getvalue()
146
-
147
- except Exception as e:
148
- raise gr.Error(f"Σφάλμα εκπαίδευσης: {str(e)}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
 
150
  # Gradio Interface
151
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
152
- gr.Markdown("## Wikipedia Tokenizer Trainer")
153
 
154
  with gr.Row():
155
  with gr.Column():
@@ -158,7 +210,6 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
158
  value="wikimedia/wikipedia",
159
  placeholder="π.χ. 'wikimedia/wikipedia'"
160
  )
161
- # Νέο πεδίο για εισαγωγή πολλαπλών configs ως λίστα, χωρισμένα με κόμμα.
162
  configs = gr.Textbox(
163
  label="Configs (π.χ. '20231101.el,20231101.en' για ελληνικά και αγγλικά)",
164
  value="20231101.el,20231101.en",
@@ -173,7 +224,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
173
  vocab_size = gr.Slider(20000, 100000, value=50000, label="Μέγεθος Λεξιλογίου")
174
  min_freq = gr.Slider(1, 100, value=3, label="Ελάχιστη Συχνότητα")
175
  test_text = gr.Textbox(
176
- value='Η Ακρόπολη είναι σύμβολο της αρχαίας ελληνικής πολιτισμικής κληρονομιάς.',
177
  label="Test Text"
178
  )
179
  custom_files = gr.File(
@@ -182,29 +233,27 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
182
  type="filepath"
183
  )
184
  train_btn = gr.Button("Εκπαίδευση", variant="primary")
185
-
186
  with gr.Column():
187
- preview = gr.HTML(label="Dataset Preview")
188
  results_json = gr.JSON(label="Αποτελέσματα")
189
  results_plot = gr.Image(label="Κατανομή Μηκών Tokens")
190
-
191
  # Event handlers
192
  dataset_name.change(
193
  fn=update_components,
194
  inputs=dataset_name,
195
- outputs=[configs, split, preview]
196
  )
197
-
198
  split.change(
199
  fn=update_split_choices,
200
  inputs=[dataset_name, configs],
201
  outputs=split
202
  )
203
-
204
  train_btn.click(
205
- fn=train_and_test,
206
  inputs=[dataset_name, configs, split, vocab_size, min_freq, test_text, custom_files],
207
- outputs=[results_json, results_plot]
 
208
  )
209
 
210
  if __name__ == "__main__":
 
1
  # -*- coding: utf-8 -*-
2
+ import os
3
+ import time
4
  import gradio as gr
5
  import requests
 
 
6
  from io import BytesIO
7
  import matplotlib.pyplot as plt
8
+ import tempfile
9
  from datasets import load_dataset
10
+ from train_tokenizer import train_tokenizer
11
  from tokenizers import Tokenizer
12
+
13
+ # Ρυθμίσεις checkpointing
14
+ CHECKPOINT_FILE = "checkpoint.txt" # αρχείο που αποθηκεύει όλα τα επεξεργασμένα κείμενα
15
+ CHUNK_SIZE = 1000 # αριθμός δειγμάτων που θα επεξεργάζονται πριν την αποθήκευση checkpoint
16
 
17
  def fetch_splits(dataset_name):
18
  try:
 
45
  try:
46
  splits_data = fetch_splits(dataset_name)
47
  config_choices = list(splits_data['splits'].keys())
 
48
  first_config = config_choices[0] if config_choices else None
49
  iframe_html = f"""
50
  <iframe
 
55
  ></iframe>
56
  """ if first_config else "Δεν βρέθηκαν διαθέσιμα δεδομένα"
57
 
58
+ # Προτείνουμε ως προεπιλογή για πολλαπλά configs τα ελληνικά και αγγλικά
59
+ default_configs = "20231101.el,20231101.en" if first_config and "el" in first_config else first_config
60
  return [
61
+ gr.Textbox.update(value=default_configs),
62
  gr.Dropdown.update(choices=splits_data['splits'].get(first_config, [])),
63
  gr.HTML.update(value=iframe_html)
64
  ]
65
  except Exception as e:
66
  raise gr.Error(f"Σφάλμα: {str(e)}")
67
 
68
+ def update_split_choices(dataset_name, configs):
69
+ if not dataset_name or not configs:
 
70
  return gr.Dropdown.update(choices=[])
 
71
  try:
72
  splits_data = fetch_splits(dataset_name)
73
+ # Χρησιμοποιούμε το πρώτο config της λίστας για τις επιλογές του split
74
+ first_config = configs.split(",")[0].strip()
75
+ return gr.Dropdown.update(choices=splits_data['splits'].get(first_config, []))
76
  except:
77
  return gr.Dropdown.update(choices=[])
78
 
79
  def create_iterator(dataset_name, configs, split):
80
  """
81
+ Για κάθε config στη λίστα (χωρισμένα με κόμμα) φορτώνει το αντίστοιχο streaming dataset και παράγει τα κείμενα.
 
82
  """
83
  configs_list = [c.strip() for c in configs.split(",") if c.strip()]
84
  for config in configs_list:
 
96
  except Exception as e:
97
  print(f"Σφάλμα φόρτωσης dataset για config {config}: {e}")
98
 
99
+ def append_to_checkpoint(texts, checkpoint_file):
100
+ """
101
+ Αποθηκεύει τα κείμενα στο αρχείο checkpoint.
102
+ """
103
+ with open(checkpoint_file, "a", encoding="utf-8") as f:
104
+ for t in texts:
105
+ f.write(t + "\n")
106
+
107
+ def load_checkpoint(checkpoint_file):
108
+ """
109
+ Διαβάζει και επιστρέφει τα κείμενα από το checkpoint (αν υπάρχει).
110
+ """
111
+ if os.path.exists(checkpoint_file):
112
+ with open(checkpoint_file, "r", encoding="utf-8") as f:
113
+ return f.read().splitlines()
114
+ return []
115
+
116
+ def train_and_test_streaming(dataset_name, configs, split, vocab_size, min_freq, test_text, custom_files):
117
+ """
118
+ Generator που εκπαιδεύει τον tokenizer σε chunks, αποθηκεύοντας τα δεδομένα σε checkpoint.
119
+ Επίσης, ενημερώνει την πρόοδο μέσω streaming στην Gradio διεπαφή.
120
+
121
+ Αν υπάρχει ήδη checkpoint, συνεχίζει από εκεί.
122
+ """
123
+ # Φόρτωση ήδη επεξεργασμένων δεδομένων από checkpoint (αν υπάρχουν)
124
+ all_texts = load_checkpoint(CHECKPOINT_FILE)
125
+ total_processed = len(all_texts)
126
+ yield {"progress": f"Έχετε {total_processed} δείγματα ήδη αποθηκευμένα στο checkpoint.\n"}
127
+
128
+ # Δημιουργία iterator από τα streaming datasets
129
+ dataset_iterator = create_iterator(dataset_name, configs, split)
130
+
131
+ new_texts = []
132
+ chunk_count = 0
133
+ # Διατρέχουμε τα νέα δεδομένα σε chunks
134
+ for text in dataset_iterator:
135
+ new_texts.append(text)
136
+ total_processed += 1
137
+ # Κάθε CHUNK_SIZE δείγματα αποθηκεύουμε στο checkpoint και ενημερώνουμε την πρόοδο
138
+ if len(new_texts) >= CHUNK_SIZE:
139
+ append_to_checkpoint(new_texts, CHECKPOINT_FILE)
140
+ chunk_count += 1
141
+ yield {"progress": f"Επεξεργάστηκαν {total_processed} δείγματα (chunk {chunk_count}).\n"}
142
+ new_texts = [] # καθαρίζουμε το chunk
143
+
144
+ # Αποθήκευση τυχόν υπολειπόμενων νέων δεδομένων
145
+ if new_texts:
146
+ append_to_checkpoint(new_texts, CHECKPOINT_FILE)
147
+ total_processed += len(new_texts)
148
+ chunk_count += 1
149
+ yield {"progress": f"Τελικό chunk: συνολικά {total_processed} δείγματα αποθηκεύτηκαν.\n"}
150
+
151
+ # Ενσωματώνουμε επίσης τα custom files (αν υπάρχουν)
152
+ if custom_files:
153
+ custom_texts = []
154
+ for file_path in custom_files:
155
+ try:
156
+ with open(file_path, 'r', encoding='utf-8') as f:
157
+ content = f.read()
158
+ if content:
159
+ custom_texts.append(content)
160
+ except Exception as file_error:
161
+ print(f"Σφάλμα ανάγνωσης αρχείου {file_path}: {file_error}")
162
+ if custom_texts:
163
+ append_to_checkpoint(custom_texts, CHECKPOINT_FILE)
164
+ total_processed += len(custom_texts)
165
+ yield {"progress": f"Προστέθηκαν {len(custom_texts)} δείγματα από custom αρχεία.\n"}
166
+
167
+ # Συνολικά δεδομένα για εκπαίδευση: checkpoint + νέα δεδομένα
168
+ all_texts = load_checkpoint(CHECKPOINT_FILE)
169
+ yield {"progress": f"Ξεκινάει η εκπαίδευση του tokenizer σε {len(all_texts)} δείγματα...\n"}
170
+
171
+ # Εκπαίδευση του tokenizer πάνω στα συσσωρευμένα δεδομένα
172
+ tokenizer = train_tokenizer(all_texts, vocab_size, min_freq)
173
+
174
+ # Αποθήκευση και φόρτωση του εκπαιδευμένου tokenizer
175
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".json") as f:
176
+ tokenizer.save(f.name)
177
+ trained_tokenizer = Tokenizer.from_file(f.name)
178
+ os.unlink(f.name)
179
+
180
+ # Validation: κωδικοποίηση και αποκωδικοποίηση του test κειμένου
181
+ encoded = trained_tokenizer.encode(test_text)
182
+ decoded = trained_tokenizer.decode(encoded.ids)
183
+
184
+ # Δημιουργία γραφήματος για την κατανομή των μηκών των tokens
185
+ token_lengths = [len(t) for t in encoded.tokens]
186
+ fig = plt.figure()
187
+ plt.hist(token_lengths, bins=20)
188
+ plt.xlabel('Μήκος Token')
189
+ plt.ylabel('Συχνότητα')
190
+ img_buffer = BytesIO()
191
+ plt.savefig(img_buffer, format='png')
192
+ plt.close()
193
+
194
+ results = {
195
+ "Πρωτότυπο Κείμενο": test_text,
196
+ "Αποκωδικοποιημένο": decoded,
197
+ "Αριθμός Tokens": len(encoded.tokens),
198
+ "Αγνώστων Tokens": sum(1 for t in encoded.tokens if t == "<unk>")
199
+ }
200
+ yield {"progress": "Η εκπαίδευση ολοκληρώθηκε!\n", "results": results, "plot": img_buffer.getvalue()}
201
 
202
  # Gradio Interface
203
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
204
+ gr.Markdown("## Wikipedia Tokenizer Trainer with Checkpointing and Streaming")
205
 
206
  with gr.Row():
207
  with gr.Column():
 
210
  value="wikimedia/wikipedia",
211
  placeholder="π.χ. 'wikimedia/wikipedia'"
212
  )
 
213
  configs = gr.Textbox(
214
  label="Configs (π.χ. '20231101.el,20231101.en' για ελληνικά και αγγλικά)",
215
  value="20231101.el,20231101.en",
 
224
  vocab_size = gr.Slider(20000, 100000, value=50000, label="Μέγεθος Λεξιλογίου")
225
  min_freq = gr.Slider(1, 100, value=3, label="Ελάχιστη Συχνότητα")
226
  test_text = gr.Textbox(
227
+ value="Η Ακρόπολη είναι σύμβολο της αρχαίας ελληνικής πολιτισμικής κληρονομιάς.",
228
  label="Test Text"
229
  )
230
  custom_files = gr.File(
 
233
  type="filepath"
234
  )
235
  train_btn = gr.Button("Εκπαίδευση", variant="primary")
 
236
  with gr.Column():
237
+ progress_box = gr.Textbox(label="Πρόοδος", interactive=False)
238
  results_json = gr.JSON(label="Αποτελέσματα")
239
  results_plot = gr.Image(label="Κατανομή Μηκών Tokens")
240
+
241
  # Event handlers
242
  dataset_name.change(
243
  fn=update_components,
244
  inputs=dataset_name,
245
+ outputs=[configs, split, gr.HTML(label="Dataset Preview")]
246
  )
 
247
  split.change(
248
  fn=update_split_choices,
249
  inputs=[dataset_name, configs],
250
  outputs=split
251
  )
 
252
  train_btn.click(
253
+ fn=train_and_test_streaming,
254
  inputs=[dataset_name, configs, split, vocab_size, min_freq, test_text, custom_files],
255
+ outputs=[progress_box, results_json, results_plot],
256
+ stream=True
257
  )
258
 
259
  if __name__ == "__main__":