Update app.py
Browse files
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 |
-
|
9 |
from datasets import load_dataset
|
|
|
10 |
from tokenizers import Tokenizer
|
11 |
-
|
12 |
-
|
|
|
|
|
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 |
-
#
|
|
|
57 |
return [
|
58 |
-
gr.Textbox.update(value=
|
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,
|
66 |
-
|
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 |
-
|
|
|
|
|
73 |
except:
|
74 |
return gr.Dropdown.update(choices=[])
|
75 |
|
76 |
def create_iterator(dataset_name, configs, split):
|
77 |
"""
|
78 |
-
|
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
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
-
|
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,
|
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=
|
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__":
|