Cristobal299 commited on
Commit
6ba37ce
·
verified ·
1 Parent(s): ef0f8e1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +62 -8
app.py CHANGED
@@ -5,6 +5,7 @@ Leer hebreo real + español fluido con exégesis de Groq y audio optimizado
5
  """
6
  import os, glob, json, tempfile, html, asyncio, subprocess, shutil, re
7
  import urllib.request
 
8
  import gradio as gr
9
  import edge_tts
10
  try:
@@ -57,8 +58,10 @@ def traducir_capitulo_con_groq(pares):
57
  Si Groq no está disponible o falla, cae al literal español (o al hebreo).
58
  """
59
  fallback = {n: (es or he) for (n, he, es) in pares}
60
- if not GROQ_KEY or not pares:
61
- return fallback
 
 
62
 
63
  # Bloque de entrada numerado: el hebreo es la fuente; el literal español,
64
  # si existe, va solo como ayuda.
@@ -96,9 +99,22 @@ def traducir_capitulo_con_groq(pares):
96
  with urllib.request.urlopen(req, timeout=120) as r:
97
  d = json.load(r)
98
  salida = (d["choices"][0]["message"]["content"] or "").strip()
 
 
 
 
 
 
 
 
 
99
  except Exception as e:
100
- print(f"Error traduciendo con Groq: {e}")
101
- return fallback
 
 
 
 
102
 
103
  # Parseamos las líneas '[N] texto' a un diccionario por versículo.
104
  res = {}
@@ -107,8 +123,14 @@ def traducir_capitulo_con_groq(pares):
107
  if m:
108
  res[int(m.group(1))] = m.group(2).strip()
109
 
 
 
 
110
  # Si Groq se saltó algún versículo, se completa con el fallback.
111
- return {n: res.get(n, fallback[n]) for (n, he, es) in pares}
 
 
 
112
 
113
 
114
  # --- PROCESAMIENTO ACÚSTICO FFMPEG ---
@@ -390,10 +412,17 @@ def render(nombre, cap):
390
 
391
  # Groq da SENTIDO a las palabras ANTES de mostrarlas: traduce el capítulo
392
  # desde el hebreo, versículo por versículo.
393
- es_por_verso = traducir_capitulo_con_groq(pares)
394
 
395
  # Interfaz: hebreo intacto arriba y, debajo, la traducción con sentido.
396
- filas = [f"<div class='cab'><span class='h'>{html.escape(_limpiar_entidades(d.get('heb','')))}</span><br>"
 
 
 
 
 
 
 
397
  f"{html.escape(d.get('es',''))} {cap}</div>"]
398
 
399
  partes_es = []
@@ -496,6 +525,31 @@ with gr.Blocks(theme=fenix_theme(), css=FENIX_CSS, title="Centralita Torá") as
496
 
497
  q_btn.click(buscar, q, q_out)
498
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
499
  with gr.Tab("Estudiar"):
500
  gr.Markdown("La IA usa el capítulo abierto en **Leer** como contexto.")
501
  chat = gr.Chatbot(type="messages", height=360)
@@ -528,4 +582,4 @@ with gr.Blocks(theme=fenix_theme(), css=FENIX_CSS, title="Centralita Torá") as
528
  )
529
 
530
  if __name__ == "__main__":
531
- demo.launch(ssr_mode=False)
 
5
  """
6
  import os, glob, json, tempfile, html, asyncio, subprocess, shutil, re
7
  import urllib.request
8
+ import urllib.error
9
  import gradio as gr
10
  import edge_tts
11
  try:
 
58
  Si Groq no está disponible o falla, cae al literal español (o al hebreo).
59
  """
60
  fallback = {n: (es or he) for (n, he, es) in pares}
61
+ if not pares:
62
+ return fallback, "sin_pares"
63
+ if not GROQ_KEY:
64
+ return fallback, "sin_key"
65
 
66
  # Bloque de entrada numerado: el hebreo es la fuente; el literal español,
67
  # si existe, va solo como ayuda.
 
99
  with urllib.request.urlopen(req, timeout=120) as r:
100
  d = json.load(r)
101
  salida = (d["choices"][0]["message"]["content"] or "").strip()
102
+ except urllib.error.HTTPError as e:
103
+ cuerpo_error = ""
104
+ try:
105
+ cuerpo_error = e.read().decode("utf-8", errors="replace")[:300]
106
+ except Exception:
107
+ pass
108
+ motivo = f"error HTTP {e.code}: {cuerpo_error or e.reason}"
109
+ print(f"Error traduciendo con Groq: {motivo}")
110
+ return fallback, motivo
111
  except Exception as e:
112
+ motivo = f"error: {type(e).__name__}: {e}"
113
+ print(f"Error traduciendo con Groq: {motivo}")
114
+ return fallback, motivo
115
+
116
+ if not salida:
117
+ return fallback, "respuesta vacía de Groq"
118
 
119
  # Parseamos las líneas '[N] texto' a un diccionario por versículo.
120
  res = {}
 
123
  if m:
124
  res[int(m.group(1))] = m.group(2).strip()
125
 
126
+ if not res:
127
+ return fallback, "no se pudo interpretar la respuesta de Groq"
128
+
129
  # Si Groq se saltó algún versículo, se completa con el fallback.
130
+ final = {n: res.get(n, fallback[n]) for (n, he, es) in pares}
131
+ faltantes = sum(1 for (n, he, es) in pares if n not in res)
132
+ estado = "ok" if faltantes == 0 else f"ok (Groq omitió {faltantes} versículo(s), se completó con literal)"
133
+ return final, estado
134
 
135
 
136
  # --- PROCESAMIENTO ACÚSTICO FFMPEG ---
 
412
 
413
  # Groq da SENTIDO a las palabras ANTES de mostrarlas: traduce el capítulo
414
  # desde el hebreo, versículo por versículo.
415
+ es_por_verso, estado_groq = traducir_capitulo_con_groq(pares)
416
 
417
  # Interfaz: hebreo intacto arriba y, debajo, la traducción con sentido.
418
+ if estado_groq == "ok" or estado_groq.startswith("ok ("):
419
+ aviso = f"<div class='aviso-groq' style='color:#2a7a2a'>✅ Traducción con sentido (Groq) — {estado_groq}</div>" if estado_groq != "ok" else ""
420
+ elif estado_groq == "sin_key":
421
+ aviso = "<div class='aviso-groq' style='color:#b00'>⚠️ Mostrando literal: falta el Secret GROQ_API_KEY.</div>"
422
+ else:
423
+ aviso = f"<div class='aviso-groq' style='color:#b00'>⚠️ Mostrando literal: falló Groq ({html.escape(estado_groq)}).</div>"
424
+
425
+ filas = [aviso, f"<div class='cab'><span class='h'>{html.escape(_limpiar_entidades(d.get('heb','')))}</span><br>"
426
  f"{html.escape(d.get('es',''))} {cap}</div>"]
427
 
428
  partes_es = []
 
525
 
526
  q_btn.click(buscar, q, q_out)
527
 
528
+ with gr.Tab("Buscar"):
529
+ q = gr.Textbox(label="Palabra o frase (hebreo o español)", placeholder="ej. luz / אור")
530
+ q_btn = gr.Button("Buscar", variant="primary")
531
+ q_out = gr.HTML()
532
+
533
+ def buscar(texto):
534
+ t = (texto or "").strip().lower()
535
+ if not t:
536
+ return "<p>Escribe algo para buscar.</p>"
537
+ filas = []
538
+ for lid in IDS:
539
+ d = LIBROS[lid]
540
+ for c, vs in d.get("capitulos", {}).items():
541
+ for v in vs:
542
+ campos = " ".join(filter(None, [v.get("es"), v.get("he")])).lower()
543
+ if t in campos:
544
+ ref = f"{d.get('es', lid)} {c}:{v.get('n')}"
545
+ txt = html.escape(_limpiar_entidades(v.get("es") or v.get("he") or ""))
546
+ filas.append(f"<div class='resultado'><span class='ref'>{ref}</span> — {txt}</div>")
547
+ if len(filas) >= 120:
548
+ return "".join(filas)
549
+ return "".join(filas) if filas else "<p>Sin resultados en los libros cargados.</p>"
550
+
551
+ q_btn.click(buscar, q, q_out)
552
+
553
  with gr.Tab("Estudiar"):
554
  gr.Markdown("La IA usa el capítulo abierto en **Leer** como contexto.")
555
  chat = gr.Chatbot(type="messages", height=360)
 
582
  )
583
 
584
  if __name__ == "__main__":
585
+ demo.launch(ssr_mode=False)