LoloSemper commited on
Commit
ec2c52a
·
verified ·
1 Parent(s): 07d2518

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +120 -39
app.py CHANGED
@@ -2,7 +2,7 @@ import json, re, os
2
  from typing import Dict
3
  import gradio as gr
4
 
5
- # ===== Archivos de léxico (generados en Colab) =====
6
  MINI_JSON = "lexicon_minimax.json" # ES -> code (Minimax)
7
  KOMI_JSON = "lexicon_komin.json" # ES -> code (Kōmín)
8
  MAST_JSON = "lexicon_master.json" # opcional: [{'lemma_es','lemma_en','minimax','komin'}, ...]
@@ -39,7 +39,7 @@ def norm_es(w: str) -> str:
39
  def norm_en(w: str) -> str:
40
  return re.sub(r"[^a-z]", "", w.lower())
41
 
42
- # ===== Lematización (spaCy si está; si no, reglas simples) =====
43
  USE_SPACY = False
44
  try:
45
  import spacy
@@ -52,11 +52,12 @@ try:
52
  except Exception:
53
  nlp_es = nlp_en = None
54
 
 
55
  IRREG_ES = {
56
  # estar
57
- "estoy":"estar","estas":"estar","está":"estar","esta":"estar","estamos":"estar","estan":"estar","están":"estar",
58
  "estuve":"estar","estuviste":"estar","estuvo":"estar","estuvimos":"estar","estuvieron":"estar",
59
- "estaria":"estar","estaría":"estar","estarias":"estar","estaría":"estar","estaré":"estar","estare":"estar",
60
  # ser
61
  "soy":"ser","eres":"ser","es":"ser","somos":"ser","son":"ser",
62
  "fui":"ser","fuiste":"ser","fue":"ser","fuimos":"ser","fueron":"ser",
@@ -65,11 +66,11 @@ IRREG_ES = {
65
  "tuve":"tener","tuviste":"tener","tuvo":"tener","tuvimos":"tener","tuvieron":"tener",
66
  # ir
67
  "voy":"ir","vas":"ir","va":"ir","vamos":"ir","van":"ir",
68
- "iba":"ir","ibas":"ir","ibamos":"ir","íbamos":"ir","iban":"ir",
69
  # haber (aux)
70
  "he":"haber","has":"haber","ha":"haber","hemos":"haber","han":"haber",
71
- "habia":"haber","había":"haber","habias":"haber","habías":"haber","habian":"haber","habían":"haber",
72
- # hacer/decir/poder/poner/querer/venir/ver/dar/saber
73
  "hago":"hacer","haces":"hacer","hace":"hacer","hacemos":"hacer","hacen":"hacer",
74
  "digo":"decir","dices":"decir","dice":"decir","decimos":"decir","dicen":"decir",
75
  "puedo":"poder","puedes":"poder","puede":"poder","podemos":"poder","pueden":"poder",
@@ -78,40 +79,61 @@ IRREG_ES = {
78
  "vengo":"venir","vienes":"venir","viene":"venir","venimos":"venir","vienen":"venir",
79
  "veo":"ver","ves":"ver","ve":"ver","vemos":"ver","ven":"ver",
80
  "doy":"dar","das":"dar","da":"dar","damos":"dar","dan":"dar",
81
- "se":"saber","sé":"saber","sabes":"saber","sabe":"saber","sabemos":"saber","saben":"saber",
 
 
 
 
 
 
 
 
 
82
  }
83
 
84
  def lemma_es(token: str) -> str:
85
- tok = norm_es(token)
 
86
  if not tok:
87
  return tok
88
- # irregular primero
 
 
 
 
 
 
89
  if tok in IRREG_ES:
90
  return IRREG_ES[tok]
 
 
91
  if USE_SPACY and nlp_es:
92
  doc = nlp_es(tok)
93
  for t in doc:
94
  if t.is_alpha:
95
  lem = norm_es(t.lemma_)
96
- return lem if lem else tok
97
- # heurística ligera para verbos regulares
98
- for suf, inf in [("ando","ar"),("iendo","er"),("yendo","ir"),
99
- ("aré","ar"),("eré","er"),("iré","ir"),("aria","ar"),("aría","ar"),
100
- ("erias","er"),("erías","er"),("iria","ir"),("iría","ir"),
101
- ("aste","ar"),("asteis","ar"),("aron","ar"),("amos","ar"),
102
- ("iste","er"),("isteis","er"),("ieron","er"),("imos","er"),
103
- ("iste","ir"),("isteis","ir"),("ieron","ir"),("imos","ir"),
104
- ("aba","ar"),("abas","ar"),("aban","ar"),
105
- ("ia","er"),("ía","er"),("ias","er"),("ías","er"),("ian","er"),("ían","er"),
106
- ("ia","ir"),("ía","ir"),("ias","ir"),("ías","ir"),("ian","ir"),("ían","ir"),
107
- ("o","ar"),("as","ar"),("a","ar"),("an","ar"),
108
- ("o","er"),("es","er"),("e","er"),("en","er"),
109
- ("o","ir"),("es","ir"),("e","ir"),("en","ir")]:
110
- if tok.endswith(suf):
 
 
 
111
  base = tok[:-len(suf)]
112
- if len(base) >= 2:
113
- return base + inf
114
- return tok
115
 
116
  def lemma_en(token: str) -> str:
117
  tok = norm_en(token)
@@ -122,9 +144,10 @@ def lemma_en(token: str) -> str:
122
  for t in doc:
123
  if t.is_alpha:
124
  lem = norm_en(t.lemma_)
125
- return lem if lem else tok
126
- # heurística mínima: plurales y gerundio/participio
127
- for suf, rep in [("ies","y"),("s",""),("ing",""),("ed","")]:
 
128
  if tok.endswith(suf) and len(tok) > len(suf)+1:
129
  return tok[:-len(suf)] + rep
130
  return tok
@@ -144,7 +167,6 @@ def build_dicts():
144
  es2mini: Dict[str, str] = (mm.get("mapping") or {})
145
  es2komi: Dict[str, str] = (kk.get("mapping") or {})
146
 
147
- # EN directo desde master si existe
148
  en2mini: Dict[str, str] = {}
149
  en2komi: Dict[str, str] = {}
150
  if isinstance(master, dict) and "entries" in master:
@@ -166,6 +188,60 @@ def build_dicts():
166
 
167
  ES2MINI, ES2KOMI, EN2MINI, EN2KOMI, MINI2ES, KOMI2ES, MINI2EN, KOMI2EN = build_dicts()
168
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169
  # ===== Codificar ES/EN → conlang (con lematización) =====
170
  def encode_text(text: str, src_lang: str, target: str) -> str:
171
  if not text.strip():
@@ -177,7 +253,7 @@ def encode_text(text: str, src_lang: str, target: str) -> str:
177
  def repl(m):
178
  tok = m.group(0)
179
  if src_lang == "Español":
180
- key = lemma_es(tok) # <— lematiza para casar con el léxico
181
  return lex_es.get(key, tok)
182
  else:
183
  key = lemma_en(tok)
@@ -191,7 +267,7 @@ def encode_text(text: str, src_lang: str, target: str) -> str:
191
  return WORD_RE.sub(repl, text)
192
 
193
  # ===== Decodificar conlang → ES/EN =====
194
- SPLIT_CODE_RE = re.compile(r"([^\w\s]+)") # separa signos
195
 
196
  def decode_text(text: str, source: str, tgt_lang: str) -> str:
197
  if not text.strip():
@@ -226,15 +302,19 @@ def decode_text(text: str, source: str, tgt_lang: str) -> str:
226
  out.append(p)
227
  return "".join(out)
228
 
229
- # ===== Ayuda UI =====
230
  HELP_ES = """
231
- **Consejo:** Si tu léxico de Colab se creó con `LEMMATIZE=True`, esta app **lematiza** la entrada para que
232
- formen (p.ej., *“estás” “estar”*) y **todo case**. Si prefieres no lematizar, regenera el léxico con `LEMMATIZE=False`.
 
 
233
  """
234
 
235
  HELP_EN = """
236
- **Tip:** If your Colab lexicon was built with `LEMMATIZE=True`, this app **lemmatizes** inputs (e.g., *“running” → “run”*)
237
- so entries match. If you prefer surface forms, rebuild the lexicon with `LEMMATIZE=False`.
 
 
238
  """
239
 
240
  # ===== UI =====
@@ -268,3 +348,4 @@ if __name__ == "__main__":
268
 
269
 
270
 
 
 
2
  from typing import Dict
3
  import gradio as gr
4
 
5
+ # ===== Archivos del léxico (generados en Colab) =====
6
  MINI_JSON = "lexicon_minimax.json" # ES -> code (Minimax)
7
  KOMI_JSON = "lexicon_komin.json" # ES -> code (Kōmín)
8
  MAST_JSON = "lexicon_master.json" # opcional: [{'lemma_es','lemma_en','minimax','komin'}, ...]
 
39
  def norm_en(w: str) -> str:
40
  return re.sub(r"[^a-z]", "", w.lower())
41
 
42
+ # ===== Lematización (spaCy si está; si no, reglas + irregulares) =====
43
  USE_SPACY = False
44
  try:
45
  import spacy
 
52
  except Exception:
53
  nlp_es = nlp_en = None
54
 
55
+ # Irregulares frecuentes (clave normalizada sin tildes)
56
  IRREG_ES = {
57
  # estar
58
+ "estoy":"estar","estas":"estar","esta":"estar","estamos":"estar","estan":"estar",
59
  "estuve":"estar","estuviste":"estar","estuvo":"estar","estuvimos":"estar","estuvieron":"estar",
60
+ "estare":"estar","estaria":"estar",
61
  # ser
62
  "soy":"ser","eres":"ser","es":"ser","somos":"ser","son":"ser",
63
  "fui":"ser","fuiste":"ser","fue":"ser","fuimos":"ser","fueron":"ser",
 
66
  "tuve":"tener","tuviste":"tener","tuvo":"tener","tuvimos":"tener","tuvieron":"tener",
67
  # ir
68
  "voy":"ir","vas":"ir","va":"ir","vamos":"ir","van":"ir",
69
+ "iba":"ir","ibas":"ir","ibamos":"ir","iban":"ir",
70
  # haber (aux)
71
  "he":"haber","has":"haber","ha":"haber","hemos":"haber","han":"haber",
72
+ "habia":"haber","habias":"haber","habian":"haber",
73
+ # otros comunes
74
  "hago":"hacer","haces":"hacer","hace":"hacer","hacemos":"hacer","hacen":"hacer",
75
  "digo":"decir","dices":"decir","dice":"decir","decimos":"decir","dicen":"decir",
76
  "puedo":"poder","puedes":"poder","puede":"poder","podemos":"poder","pueden":"poder",
 
79
  "vengo":"venir","vienes":"venir","viene":"venir","venimos":"venir","vienen":"venir",
80
  "veo":"ver","ves":"ver","ve":"ver","vemos":"ver","ven":"ver",
81
  "doy":"dar","das":"dar","da":"dar","damos":"dar","dan":"dar",
82
+ "se":"saber","sabes":"saber","sabe":"saber","sabemos":"saber","saben":"saber",
83
+ }
84
+
85
+ INTERROG_ES = {
86
+ "como":"cómo","cómo":"cómo","que":"qué","qué":"qué",
87
+ "quien":"quién","quién":"quién","cuando":"cuándo","cuándo":"cuándo",
88
+ "donde":"dónde","dónde":"dónde","cual":"cuál","cuál":"cuál",
89
+ "cuanto":"cuánto","cuánto":"cuánto","cuanta":"cuánta","cuánta":"cuánta",
90
+ "cuantos":"cuántos","cuántos":"cuántos","cuantas":"cuántas","cuántas":"cuántas",
91
+ "porque":"porque","porqué":"porqué"
92
  }
93
 
94
  def lemma_es(token: str) -> str:
95
+ tok_raw = token.strip()
96
+ tok = norm_es(tok_raw)
97
  if not tok:
98
  return tok
99
+
100
+ # Interrogativos y afines: conservar como “lema” propio (con o sin acento)
101
+ if tok_raw.lower() in INTERROG_ES or tok in INTERROG_ES:
102
+ base = INTERROG_ES.get(tok_raw.lower(), INTERROG_ES.get(tok, tok))
103
+ return base
104
+
105
+ # Irregulares más comunes
106
  if tok in IRREG_ES:
107
  return IRREG_ES[tok]
108
+
109
+ # spaCy si está disponible
110
  if USE_SPACY and nlp_es:
111
  doc = nlp_es(tok)
112
  for t in doc:
113
  if t.is_alpha:
114
  lem = norm_es(t.lemma_)
115
+ if lem:
116
+ return lem
117
+
118
+ # Heurística conservadora (evita confundir “como”→“comer”):
119
+ rules = [
120
+ ("ando","ar"),("iendo","er"),("yendo","ir"), # gerundios
121
+ ("abamos","ar"),("ábamos","ar"),("iamos","er"),("íamos","er"),("iamos","ir"),("íamos","ir"),
122
+ ("aste","ar"),("asteis","ar"),("aron","ar"),
123
+ ("iste","er"),("isteis","er"),("ieron","er"),("imos","er"),
124
+ ("iste","ir"),("isteis","ir"),("ieron","ir"),("imos","ir"),
125
+ ("aba","ar"),("abas","ar"),("aban","ar"),
126
+ ("ia","er"),("ía","er"),("ias","er"),("ías","er"),("ian","er"),("ían","er"),
127
+ ("ia","ir"),("ía","ir"),("ias","ir"),("ías","ir"),("ian","ir"),("ían","ir"),
128
+ ("are","ar"),("aré","ar"),("ere","er"),("eré","er"),("ire","ir"),("iré","ir"),
129
+ ("aria","ar"),("aría","ar"),("eria","er"),("ería","er"),("iria","ir"),("iría","ir"),
130
+ ]
131
+ for suf, inf in rules:
132
+ if tok.endswith(suf) and len(tok) > len(suf)+1:
133
  base = tok[:-len(suf)]
134
+ return base + inf
135
+
136
+ return tok # por defecto no tocar
137
 
138
  def lemma_en(token: str) -> str:
139
  tok = norm_en(token)
 
144
  for t in doc:
145
  if t.is_alpha:
146
  lem = norm_en(t.lemma_)
147
+ if lem:
148
+ return lem
149
+ # Heurística mínima: plurales y sufijos comunes
150
+ for suf, rep in [("ies","y"),("ing",""),("ed",""),("s","")]:
151
  if tok.endswith(suf) and len(tok) > len(suf)+1:
152
  return tok[:-len(suf)] + rep
153
  return tok
 
167
  es2mini: Dict[str, str] = (mm.get("mapping") or {})
168
  es2komi: Dict[str, str] = (kk.get("mapping") or {})
169
 
 
170
  en2mini: Dict[str, str] = {}
171
  en2komi: Dict[str, str] = {}
172
  if isinstance(master, dict) and "entries" in master:
 
188
 
189
  ES2MINI, ES2KOMI, EN2MINI, EN2KOMI, MINI2ES, KOMI2ES, MINI2EN, KOMI2EN = build_dicts()
190
 
191
+ # ===== Refuerzo: asigna códigos cortos a “básicos” si faltan =====
192
+ ALPHA_MINI = "@ptkmnslraeiouy0123456789><=:/!?.+-_*#bcdfghjvqwxzACEGHIJKLMNOPRS"[:64]
193
+ CJK_BASE = (
194
+ "天地人日月山川雨風星火水木土金石光影花草鳥犬猫魚"
195
+ "東西南北中外上下午夜明暗手口目耳心言書家道路門"
196
+ "大小長短早晚高低新古青紅白黒金銀銅玉米茶酒米"
197
+ "文学楽音画体気電海空森林雪雲砂島橋城村国自由静"
198
+ )
199
+ ALPHA_CJK = (CJK_BASE * 10)[:256]
200
+
201
+ def shortest_unused(prefix_list, used: set, alphabet: str, max_len: int = 3):
202
+ for L in range(1, max_len+1):
203
+ for p in prefix_list:
204
+ if len(p) == L and p not in used:
205
+ return p
206
+ def gen(L):
207
+ if L == 1:
208
+ for ch in alphabet:
209
+ yield ch
210
+ else:
211
+ for prev in gen(L-1):
212
+ for ch in alphabet:
213
+ yield prev + ch
214
+ for cand in gen(L):
215
+ if cand not in used:
216
+ return cand
217
+ # fallback
218
+ i = 1
219
+ while True:
220
+ cand = prefix_list[0] + alphabet[0]*i
221
+ if cand not in used:
222
+ return cand
223
+ i += 1
224
+
225
+ def augment_basics():
226
+ global ES2MINI, ES2KOMI, MINI2ES, KOMI2ES
227
+ basics = [
228
+ "hola","adios","gracias","por","favor","si","no",
229
+ "que","qué","quien","quién","como","cómo",
230
+ "cuando","cuándo","donde","dónde","cual","cuál"
231
+ ]
232
+ used_mini = set(ES2MINI.values())
233
+ used_komi = set(ES2KOMI.values())
234
+ for w in basics:
235
+ k = norm_es(w)
236
+ if k not in ES2MINI:
237
+ code = shortest_unused([w[:1].lower()], used_mini, ALPHA_MINI, max_len=3)
238
+ ES2MINI[k] = code; MINI2ES[code] = k; used_mini.add(code)
239
+ if k not in ES2KOMI:
240
+ code = shortest_unused([w[:1]], used_komi, ALPHA_CJK, max_len=2)
241
+ ES2KOMI[k] = code; KOMI2ES[code] = k; used_komi.add(code)
242
+
243
+ augment_basics()
244
+
245
  # ===== Codificar ES/EN → conlang (con lematización) =====
246
  def encode_text(text: str, src_lang: str, target: str) -> str:
247
  if not text.strip():
 
253
  def repl(m):
254
  tok = m.group(0)
255
  if src_lang == "Español":
256
+ key = lemma_es(tok)
257
  return lex_es.get(key, tok)
258
  else:
259
  key = lemma_en(tok)
 
267
  return WORD_RE.sub(repl, text)
268
 
269
  # ===== Decodificar conlang → ES/EN =====
270
+ SPLIT_CODE_RE = re.compile(r"([^\w\s]+)")
271
 
272
  def decode_text(text: str, source: str, tgt_lang: str) -> str:
273
  if not text.strip():
 
302
  out.append(p)
303
  return "".join(out)
304
 
305
+ # ===== Ayudas UI =====
306
  HELP_ES = """
307
+ **Consejos:**
308
+ - Este Space **lematiza** la entrada (spaCy si está disponible; si no, reglas + irregulares), así “estás”→“estar” y casa con tu léxico.
309
+ - Añadimos una pequeña **capa de básicos** (hola, gracias, sí, no, interrogativos) si faltan en los JSON, con códigos cortos sin colisiones.
310
+ - Si prefieres trabajar por **formas superficiales** (sin lemas), regenera los JSON en Colab con `LEMMATIZE=False`.
311
  """
312
 
313
  HELP_EN = """
314
+ **Tips:**
315
+ - Input is **lemmatized** (spaCy if available; otherwise rules + irregulars), so “running”→“run” and matches your lexicon.
316
+ - A small set of **basic words** (hello/thanks/yes/no/interrogatives) gets short codes if missing from JSONs.
317
+ - Prefer surface forms? Rebuild the lexicon in Colab with `LEMMATIZE=False`.
318
  """
319
 
320
  # ===== UI =====
 
348
 
349
 
350
 
351
+