Moibe commited on
Commit
435164a
·
1 Parent(s): 8972247

DNI Panamá Listo

Browse files
Files changed (12) hide show
  1. app.py +11 -59
  2. cloudfunction.py +0 -64
  3. conexion_firebase.py +0 -44
  4. config.json +0 -13
  5. default.png +0 -0
  6. documentos.py +10 -0
  7. espacios.py +0 -41
  8. funciones.py +57 -0
  9. herramientas.py +26 -197
  10. ia.py +96 -0
  11. obtenCampo.py +12 -0
  12. requirements.txt +6 -1
app.py CHANGED
@@ -1,15 +1,13 @@
1
- import herramientas
2
  from io import BytesIO
3
- import funciones, globales
4
  from fastapi import FastAPI, Form
5
  from fastapi import FastAPI, File, UploadFile
6
  from fastapi.responses import StreamingResponse, FileResponse, JSONResponse
7
 
8
  app = FastAPI()
9
 
10
- # Nuevo endpoint para Health Check
11
  @app.get("/health",
12
- tags=["Health Check"],
13
  description="Verifica el estado de salud de la API.",
14
  summary="Health Check"
15
  )
@@ -20,8 +18,9 @@ async def health_check():
20
  return JSONResponse(content={"status": "ok"}, status_code=200)
21
 
22
  @app.post("/echo-image/",
23
- description="Test endpoint que recibe y regresa la misma imagen, para probar envío, recepción y problemas con api o red.",
24
- summary="Summary"
 
25
  )
26
  async def echo_image(image: UploadFile = File(...)):
27
  if not image.content_type.startswith("image/"):
@@ -30,60 +29,13 @@ async def echo_image(image: UploadFile = File(...)):
30
  return StreamingResponse(BytesIO(contents), media_type=image.content_type)
31
 
32
  @app.post("/procesa-dni/",
33
- description="Procesa DNI.",
34
- summary="Summary"
 
35
  )
36
  async def echo_image(image: UploadFile = File(...)):
37
  if not image.content_type.startswith("image/"):
38
  return {"error": "El archivo no es una imagen"}
39
- contents = await image.read()
40
- return StreamingResponse(BytesIO(contents), media_type=image.content_type)
41
-
42
- @app.post("/genera-imagen/")
43
- async def genera_imagen(platillo: str = Form(...)):
44
-
45
- seconds_available = herramientas.obtenSegundosDisponibles() #Ahora los segundos disponible son independientes. Por server no hay diferencia, pero si por cuenta (y ahora tenemos 3 PRO), es importante que no quede ese distintivo en código para que la sincronización sea fácil y rápida. Local es Moibe, las demás su respectivo server. Todos manejados en bridges y en hf variables.
46
-
47
- print(herramientas.imprimeTimeNow())
48
-
49
- if seconds_available > globales.work_cost:
50
- print("Usando GPU (capa gratuita)...")
51
- resultado = funciones.genera_platillo_gpu(platillo)
52
- if "Error" in resultado:
53
- return resultado
54
- else:
55
- return FileResponse(resultado, media_type="image/png", filename="imagen.png")
56
- else:
57
-
58
- print("Usando Inference...")
59
- resultado = funciones.genera_platillo_inference(platillo)
60
- print("El resultado de inference es: ", resultado)
61
- if type(resultado) is str:
62
- return resultado
63
- else:
64
- return StreamingResponse(content=resultado, media_type="image/png")
65
-
66
- # @app.post("/procesador-lotes/")
67
- # async def procesa_lote(platillo: str = Form(...)):
68
-
69
- # print("Servicio Secundario de Procesamiento de Lotes")
70
- # seconds_available = herramientas.obtenSegundosDisponibles()
71
- # #seconds_available = 0
72
- # print(herramientas.imprimeTimeNow())
73
-
74
- # if seconds_available > globales.work_cost:
75
- # print("Usando GPU (capa gratuita)...")
76
- # resultado = funciones.genera_platillo_gpu(platillo)
77
- # if "Error" in resultado:
78
- # return resultado
79
- # else:
80
- # return FileResponse(resultado, media_type="image/png", filename="imagen.png")
81
- # else:
82
-
83
- # print("Usando Inference...")
84
- # resultado = funciones.genera_platillo_inference(platillo)
85
- # print("El resultado de inference es: ", resultado)
86
- # if type(resultado) is str:
87
- # return resultado
88
- # else:
89
- # return StreamingResponse(content=resultado, media_type="image/png")
 
1
+ import ia
2
  from io import BytesIO
 
3
  from fastapi import FastAPI, Form
4
  from fastapi import FastAPI, File, UploadFile
5
  from fastapi.responses import StreamingResponse, FileResponse, JSONResponse
6
 
7
  app = FastAPI()
8
 
 
9
  @app.get("/health",
10
+ tags=["Monitoreo Server"],
11
  description="Verifica el estado de salud de la API.",
12
  summary="Health Check"
13
  )
 
18
  return JSONResponse(content={"status": "ok"}, status_code=200)
19
 
20
  @app.post("/echo-image/",
21
+ tags=["Monitoreo Server"],
22
+ description="Test endpoint para prueba de envío de imagenes.",
23
+ summary="Mirror test para envío de imagenes"
24
  )
25
  async def echo_image(image: UploadFile = File(...)):
26
  if not image.content_type.startswith("image/"):
 
29
  return StreamingResponse(BytesIO(contents), media_type=image.content_type)
30
 
31
  @app.post("/procesa-dni/",
32
+ tags=["Rapicash"],
33
+ description="Procesa DNI de Panamá obteniendo los datos deseados.",
34
+ summary="Identificación de DNI con IA"
35
  )
36
  async def echo_image(image: UploadFile = File(...)):
37
  if not image.content_type.startswith("image/"):
38
  return {"error": "El archivo no es una imagen"}
39
+ contents = await image.read()
40
+ # return StreamingResponse(BytesIO(contents), media_type=image.content_type)
41
+ return ia.inference(contents, 'en')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cloudfunction.py DELETED
@@ -1,64 +0,0 @@
1
- # main.py o donde definas tus funciones
2
-
3
- import firebase_admin
4
- from firebase_functions import pubsub_fn, options
5
- from firebase_admin import firestore, exceptions # Import exceptions for better error handling
6
-
7
- # Inicializa Firebase Admin si no lo has hecho ya en tu proyecto
8
- # Esto generalmente se hace una vez en el punto de entrada de tus funciones (ej. en __init__.py o al inicio de tu main.py)
9
- # Puedes usar un bloque try/except para evitar reinicializar si ya está inicializado.
10
- # try:
11
- # firebase_admin.get_app()
12
- # except ValueError:
13
- # firebase_admin.initialize_app()
14
-
15
- # Obtén una referencia a la base de datos de Firestore con el nombre 'nowme'
16
- # Asegúrate de que firebase_admin.initializeApp() se haya ejecutado antes de obtener esta referencia.
17
- # firestore.client() obtiene el cliente para la app por defecto,
18
- # y luego .instance('nowme') especifica la base de datos con nombre.
19
- db = firestore.client().instance('nowme')
20
-
21
- @pubsub_fn.on_message_published(
22
- # Puedes dar un nombre lógico al trabajo programado (Cloud Scheduler job) si quieres
23
- # topic="increment-segundos-job", # Este parámetro no es necesario para schedule, Firebase lo gestiona
24
- schedule="every 24 hours at 16:00",
25
- timezone="America/Mexico_City", # Establece la zona horaria a Ciudad de México
26
- # Opcional: puedes añadir opciones de runtime aquí si lo necesitas
27
- # memory=options.MemoryOption.GB_1, # Ejemplo: 1 GB de memoria
28
- # timeout_sec=300, # Ejemplo: 5 minutos de timeout
29
- )
30
- def incrementar_segundos_python(event: pubsub_fn.CloudEvent) -> None:
31
- """
32
- Cloud Function en Python activada por un programador
33
- para incrementar el campo 'segundos' en un documento de Firestore.
34
- """
35
- print(f"Function incrementar_segundos_python activada a las {event.time} por mensaje ID: {event.id}")
36
- # Para este caso, no necesitamos los datos específicos del evento Pub/Sub
37
-
38
- # Referencia al documento específico: colección 'nowme', documento 'sosa'
39
- doc_ref = db.collection('nowme').document('sosa')
40
-
41
- try:
42
- # Usa update con FieldValue.increment para una actualización atómica segura
43
- # Esto es especialmente bueno para valores numéricos que pueden ser
44
- # modificados por múltiples fuentes al mismo tiempo.
45
- doc_ref.update({
46
- "segundos": firestore.FieldValue.increment(1500)
47
- })
48
- print("Campo 'segundos' actualizado con éxito (+1500) en el documento 'nowme/sosa'.")
49
-
50
- except exceptions.NotFound:
51
- print("Error: Documento nowme/sosa no encontrado. No se pudo actualizar.")
52
- # Puedes decidir si quieres crear el documento si no existe,
53
- # pero update() solo funciona si el documento ya existe.
54
- # Si quieres crearlo si no existe, usarías set(..., merge=True).
55
- # doc_ref.set({"segundos": 1500}, merge=True) # Ejemplo de cómo crear/actualizar
56
-
57
- except Exception as e:
58
- print(f"Error al actualizar el documento nowme/sosa: {e}")
59
- # Puedes lanzar la excepción si quieres que Cloud Functions lo reporte como un fallo.
60
- # raise e
61
- pass # O simplemente pasar para que la Function no se marque como fallo en este caso
62
-
63
- print("Fin de la ejecución de la Function.")
64
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
conexion_firebase.py DELETED
@@ -1,44 +0,0 @@
1
- import firebase_admin
2
- from firebase_admin import firestore
3
- from firebase_admin import auth
4
- from firebase_admin import credentials
5
- import time
6
-
7
-
8
- firebase_cred = credentials.Certificate('config.json')
9
- firebase_admin.initialize_app(firebase_cred)
10
-
11
- db = firestore.client(database_id='nowme')
12
- #dato es el dato que traes como el nombre del user.
13
- #info es la info de ese dato que estás buscando, como token.
14
- def obtenDato(coleccion, dato, info):
15
- #Future: Tentativamente ésta parte podría solo hacerse una vez y vivir en la app para ser reutilizado.
16
-
17
- #Primero debemos definir la referencia al documento, o sea a la hoja de usuario.
18
- doc_ref = db.collection(coleccion).document(dato)
19
- #Éste es el documento que tiene los datos de ella.
20
- documento = doc_ref.get()
21
-
22
- #Recuerda la conversión a diccionario.
23
- documento = doc_ref.get()
24
- diccionario = documento.to_dict()
25
- return diccionario.get(info)
26
-
27
- def editaDato(coleccion, dato, info, contenido):
28
-
29
- #Primero debemos definir la referencia al documento, o sea a la hoja de usuario.
30
- doc_ref = db.collection(coleccion).document(dato)
31
-
32
- doc_ref.update({
33
- # 'quote': quote,
34
- info: contenido,
35
- })
36
-
37
- def creaDato(coleccion, dato, info, contenido):
38
-
39
- #Primero debemos definir la referencia al documento, o sea a la hoja de usuario.
40
- doc_ref = db.collection(coleccion).document(dato)
41
-
42
- doc_ref.set({
43
- info: contenido,
44
- })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
config.json DELETED
@@ -1,13 +0,0 @@
1
- {
2
- "type": "service_account",
3
- "project_id": "nowme-images-dea8a",
4
- "private_key_id": "5b80469ffe674a059beba453312ed588c2e6406f",
5
- "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC8WoI+b+BJ1Lo5\nIxiNJ/q7Za1nKaHaScxTvEM12Qa2+roVJnTxJqh0wBeoF+ylWWUdVckSKPwTOC40\nLm1ezb71Wl+EAav+5RRXdiaQbx2PGBGDjn+4pLFvzm/22cH3Sn2N9JzgHvjOgBCP\nTuXm8lSrvE2AeKrJupwXUzebin0/2W7lG2j5aKaWd5AOrOORTU2FHtBsS7mxs+IF\nsY9S29YKxtGZ/yzhG3c/6zprEZPUJXlwjr3otOZJfFObMv7VNmvR9d1D9IgN7CjN\nL3jkcbX9z7+VVMfEEybdQrr05mSoe3Shvo3EwtYIW8Gt7jSCpsZcHRRy8WnGjCHC\nqf/NB4QJAgMBAAECggEAEnfN5jUWQOr7pOtO5pVFUX9NVqyHdwWuJAY1MVgRn1qb\naQQ7qmL72LG2iBfrb0WCA3O0OsR7vd8v8ZQdS3LBPuGg9KqszHn16gL20kng1DVc\nD0IHPimgz7mGMyYkDX0XbTYvNQ74XpgCN6j45BF98ZZNo5OBTHUQhb12Ofkk4YAD\nAEYX0anGgThA5AlBMG6NaztVP1oufxv4k18gMJfA1qRQJLx984VBoqlCOuVRXmT9\npilyFQLnR9a/ucXDhKzVO1/1mjLhZhTCIok9V4LICeE/TXvb+PhsHJoS/eFlty6f\nKHSIB5i/jfhBsdx8jpqN3DmjpBWu42JUi79ZHwOo0QKBgQD6RUbKLjNOQijXEZYd\naa93feLAyafjSQKGE1BqF/DRvympFo/FIssiYTkbbdaLKmcbevwmaFwZQvcNTYFk\nSmhH7ZqVrWWlTgUx1D56+lIji/449DZJOzT4NkKNpO5oeBufUTFERAYLvWUqrfVn\n+jYLHdS4katxLwpe+7SFXWjIUQKBgQDAql0799RGmKGF/4nKPummh2gGL6SLtFA5\nd61whFu/rpUskzS8JYxRWPId3hbvKF4Hn0mlnvlAIWLEPQ0tRDYrGDbZDHeWBr6Y\nJN+vy5ycC1nunqSE59uqBIKcZSR8gcqsNnb85cDAzW7tPxlx+v9tCxRmOqs/aGdQ\nyPHyorPKOQKBgGmZs5350pIx3lOpSwMMJgqwZm5caGfB1bvHCIZLpcSK+cQsDevr\nm3TdOyB0vzMnaCwzP5PhMwNBu0a0rmUn9EptWm3PpXUTr6Nv4BE58FCpcFKN0R4j\nSl11X62uqx4Pl/AobTZV0YtAliBlGIiQDh+wraJXbNSsOZ8MbAZd/KmRAoGAP5o+\nKyTWU/PhJr5EO5rnQU1kHt6tgF0nOsFyZTmcnDvDDTMPbqkqmFQ3oXqGsa7u069W\n/bDscapT05qf9fiVtUZKHP8Ln2BcnRdXLM6Xxb/NkYOXpjRwhMD2aTDOibfDM3TL\ndRNXvY5T90gkW0dT+Sh2NIVbsRQDP10G2mWx2qkCgYBnLTMhcyuh/7HBHyKQsiZz\nzVaLnjf9pOiKdLE6ETERQH0q/LpOxY68iPRkvpTUDdHb8Y5/AK2aYeJ6MKBhE4S1\n4RlIwm80xS7G//GA47FZHFiHI+XEN+gnNzZcHR6vmg1707VkXLTF+I+01+A+mKdf\ncBgEwYp4liDawuNjz8tgSw==\n-----END PRIVATE KEY-----\n",
6
- "client_email": "firebase-adminsdk-fbsvc@nowme-images-dea8a.iam.gserviceaccount.com",
7
- "client_id": "107709451350786325129",
8
- "auth_uri": "https://accounts.google.com/o/oauth2/auth",
9
- "token_uri": "https://oauth2.googleapis.com/token",
10
- "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
11
- "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-fbsvc%40nowme-images-dea8a.iam.gserviceaccount.com",
12
- "universe_domain": "googleapis.com"
13
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
default.png DELETED
Binary file (62.5 kB)
 
documentos.py ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ import obtenCampo
2
+
3
+ def dni(textos_extraidos):
4
+ textos_extraidos_simplificados = [texto.lower().replace(" ", "") for texto in textos_extraidos]
5
+
6
+ #Campos Buscados
7
+ nombre, apellido = obtenCampo.Nombre(textos_extraidos, textos_extraidos_simplificados)
8
+ identificacion = obtenCampo.Identificacion(textos_extraidos, textos_extraidos_simplificados)
9
+
10
+ return nombre, apellido, identificacion
espacios.py DELETED
@@ -1,41 +0,0 @@
1
- import herramientas
2
-
3
- # server = herramientas.getFluxServer()
4
- # print("Server elegido: ", server)
5
- # print("El type es: ", type(server))
6
-
7
- espacio = [
8
- {
9
- "id": "black-forest-labs/FLUX.1-dev",
10
- "static_kwargs": {
11
- "api_name": "/infer",
12
- }
13
- },
14
- # {
15
- # "id": "black-forest-labs/FLUX.1-schnell",
16
- # "static_kwargs": {
17
- # "api_name": "/infer",
18
- # }
19
- # },
20
- # {
21
- # "id": "NihalGazi/FLUX-Pro-Unlimited",
22
- # "static_kwargs": {
23
- # "api_name": "/generate_image",
24
- # "server_choice": server,
25
- # }
26
- # },
27
- # {
28
- # "id": "HiDream-ai/HiDream-I1-Dev",
29
- # "static_kwargs": {
30
- # "api_name": "/infer",
31
- #
32
- # }
33
- # },
34
- # {
35
- # "id": "stabilityai/stable-diffusion",
36
- # "static_kwargs": {
37
- # "api_name": "/generate",
38
- #
39
- # }
40
- # }
41
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
funciones.py CHANGED
@@ -11,6 +11,63 @@ from huggingface_hub import InferenceClient
11
 
12
  servidor = globales.servidor
13
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  def genera_platillo_gpu(platillo):
15
 
16
  prompt = globales.previo + platillo
 
11
 
12
  servidor = globales.servidor
13
 
14
+ def procesa_dni(platillo):
15
+
16
+ print("Estoy en procesa DNI...")
17
+
18
+ print("Y esto es contents: ", platillo)
19
+
20
+ time.sleep(18)
21
+
22
+ prompt = globales.previo + platillo
23
+ print("Platillo enviado:", platillo)
24
+
25
+ try:
26
+
27
+ dict_espacios = conexion_firebase.obtenDato('nowme', servidor, 'espacios')
28
+
29
+ espacios_habilitados = [
30
+ nombre for nombre, config in dict_espacios.items()
31
+ if config.get("habilitado", False) # Usamos .get() para evitar KeyError si 'habilitado' no existe
32
+ ]
33
+
34
+ print(f"Espacios habilitados: {espacios_habilitados}")
35
+
36
+ espacio_aleatorio_elegido = random.choice(espacios_habilitados)
37
+ configuracion_espacio = dict_espacios[espacio_aleatorio_elegido]
38
+ print(f"La configuración completa para '{espacio_aleatorio_elegido}' es: {configuracion_espacio}")
39
+
40
+ client = gradio_client.Client(configuracion_espacio['ruta'], hf_token=globales.llave)
41
+ #kwargs = selected_space_config['static_kwargs']
42
+
43
+ result = client.predict(
44
+ #**kwargs,
45
+ prompt=prompt,
46
+ #negative_prompt="live animals",
47
+ # seed=42,
48
+ # randomize_seed=True,
49
+ width=786,
50
+ height=568,
51
+ # guidance_scale=3.5,
52
+ # num_inference_steps=28,
53
+ api_name=configuracion_espacio['api_name']
54
+ )
55
+
56
+ #Cuando es GPU, debe de restar segundos disponibles de HF
57
+ herramientas.restaSegundosGPU(globales.work_cost)
58
+
59
+ print("Platillo generado:", platillo)
60
+ return result[0]
61
+
62
+ except Exception as e:
63
+ print("Excepción: ", e)
64
+ # Opción para regresar imagen genérica. (ya no porque se envía desde backend.)
65
+ # return "default.png"
66
+ raise HTTPException(
67
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
68
+ detail=e
69
+ )
70
+
71
  def genera_platillo_gpu(platillo):
72
 
73
  prompt = globales.previo + platillo
herramientas.py CHANGED
@@ -1,197 +1,26 @@
1
- import conexion_firebase
2
- import globales
3
- import pytz
4
- import random
5
- from datetime import datetime
6
-
7
- servidor = globales.servidor
8
-
9
- # segundos = server_configs[globales.servidor]["segundos_var"]
10
-
11
- def obtenUltimoTimestamp():
12
- """
13
- Obtiene el último timestamp de renovación guardado.
14
- """
15
- resultado = conexion_firebase.obtenDato('nowme', servidor, 'timestamp')
16
- print("Obten último timestamp obtenido: ", resultado)
17
-
18
- return resultado
19
-
20
- def obtenSegundosDisponibles():
21
-
22
- if esDiaSiguiente() == True:
23
- renuevaSegundosDisponibles()
24
- renuevaModeloPrincipal()
25
-
26
- #Finalmente obten los segundos disponibles después de las operaciones.
27
- return conexion_firebase.obtenDato('nowme', servidor, 'segundos')
28
-
29
- def obtenSegundosDisponiblesInference():
30
-
31
- # if esDiaSiguiente() == True:
32
- # renuevaSegundosDisponibles()
33
- # renuevaModeloPrincipal()
34
-
35
- #Finalmente obten los segundos disponibles después de las operaciones.
36
- return conexion_firebase.obtenDato('nowme', servidor, 'inferencias')
37
-
38
-
39
- def renuevaSegundosDisponibles():
40
-
41
- #Segundos de cuota total gratuita disponibles al momento.
42
- conexion_firebase.editaDato('nowme', servidor, 'segundos', globales.quota)
43
- renuevaTimestampActual()
44
-
45
- def renuevaTimestampActual():
46
-
47
- timestamp_actual = imprimeTimeNowFixed16h()
48
- print("Ésto es el timestamp now de la renovación...: ", timestamp_actual)
49
- conexion_firebase.editaDato('nowme', servidor, 'timestamp', timestamp_actual)
50
-
51
- def restaSegundosGPU(cuantos_segundos):
52
- """
53
- Lee el número de segundos disponibles,
54
- resta los segundos dados como parámetro y guarda el nuevo valor en el archivo.
55
- """
56
-
57
- segundos_disponibles = obtenSegundosDisponibles()
58
- print("Segundos disponibles: ", segundos_disponibles)
59
-
60
- # Restar los segundos
61
- nuevos_segundos_disponibles = segundos_disponibles - cuantos_segundos
62
- print("Segundos disponibles ahora: ", nuevos_segundos_disponibles)
63
- conexion_firebase.editaDato('nowme', servidor, 'segundos', nuevos_segundos_disponibles)
64
-
65
- def restaSegundosInference(cuantos_segundos):
66
- """
67
- Lee el número de segundos disponibles desde seconds_available.txt,
68
- resta los segundos dados como parámetro y guarda el nuevo valor en el archivo.
69
- """
70
-
71
- segundos_disponibles = obtenSegundosDisponiblesInference()
72
- print("Segundos disponibles Inference: ", segundos_disponibles)
73
-
74
- # Restar los segundos
75
- nuevos_segundos_disponibles = segundos_disponibles - cuantos_segundos
76
- print("Segundos disponibles ahora en restaSegundosInference: ", nuevos_segundos_disponibles)
77
- conexion_firebase.editaDato('nowme', servidor, 'inferencias', nuevos_segundos_disponibles)
78
-
79
- def modificaModeloActual(nuevo_modelo):
80
- """
81
- Actualiza el archivo archivos/modelo_actual.txt con el modelo funcional en caso de
82
- problemas con el actual.
83
- """
84
-
85
- modelo_actual = conexion_firebase.obtenDato('nowme', servidor, 'modelo_actual')
86
- conexion_firebase.editaDato('nowme', servidor, 'modelo_actual', nuevo_modelo)
87
- print(f"Se actualizó el modelo actual: {modelo_actual} por {nuevo_modelo}.")
88
-
89
- def renuevaModeloPrincipal():
90
- #Obten el modelo principal (default).
91
- modelo_principal = conexion_firebase.obtenDato('nowme', servidor, 'modelo_principal')
92
- #Asignalo como modelo actual.
93
- conexion_firebase.editaDato('nowme', servidor, 'modelo_actual', modelo_principal)
94
-
95
- def imprimeTimeNow():
96
- """
97
- Devuelve la fecha y hora actual en la zona horaria de la Ciudad de México (GMT-6).
98
- """
99
- # 1. Definir la zona horaria de la Ciudad de México
100
- # Puedes usar 'America/Mexico_City' para que pytz maneje el horario de verano automáticamente.
101
- mexico_city_tz = pytz.timezone('America/Mexico_City')
102
-
103
- # 2. Obtener la hora actual en UTC
104
- utc_now = datetime.now(pytz.utc)
105
-
106
- # 3. Convertir la hora UTC a la zona horaria deseada
107
- mexico_city_now = utc_now.astimezone(mexico_city_tz)
108
-
109
- # 4. Formatear la fecha y hora
110
- # El formato que deseas es "YYYY-MM-DD HH:MM:SS"
111
- formatted_time = mexico_city_now.strftime("%Y-%m-%d %H:%M:%S")
112
-
113
- return formatted_time
114
-
115
- def imprimeTimeNowFixed16h():
116
- """
117
- Devuelve la fecha actual con la hora fijada a las 16:00:00 (4 PM)
118
- en la zona horaria de la Ciudad de México (GMT-6).
119
- """
120
- # 1. Definir la zona horaria de la Ciudad de México
121
- mexico_city_tz = pytz.timezone('America/Mexico_City')
122
-
123
- # 2. Obtener la fecha y hora actual en UTC
124
- utc_now = datetime.now(pytz.utc)
125
-
126
- # 3. Convertir la hora UTC a la zona horaria de la Ciudad de México
127
- # Esto nos da la fecha correcta (año, mes, día) para esa zona.
128
- mexico_city_aware_dt = utc_now.astimezone(mexico_city_tz)
129
-
130
- # 4. Crear un nuevo objeto datetime con la fecha obtenida
131
- # pero con la hora fijada a las 16:00:00
132
- fixed_time_dt = mexico_city_tz.localize(
133
- datetime(
134
- mexico_city_aware_dt.year,
135
- mexico_city_aware_dt.month,
136
- mexico_city_aware_dt.day,
137
- 16, # Hora fijada a las 16 (4 PM)
138
- 0, # Minutos fijados a 0
139
- 0 # Segundos fijados a 0
140
- )
141
- )
142
-
143
- # 5. Formatear la fecha y hora
144
- formatted_time = fixed_time_dt.strftime("%Y-%m-%d %H:%M:%S")
145
-
146
- return formatted_time
147
-
148
- def esDiaSiguiente():
149
- """
150
- Compara dos timestamps Unix y devuelve True si el día de timestamp_actual
151
- es diferente al día de timestamp_registro.
152
-
153
- Args:
154
- timestamp_registro (int): Timestamp Unix del registro original (en segundos).
155
- timestamp_actual (int): Timestamp Unix actual (en segundos).
156
-
157
- Returns:
158
- bool: True si el día de timestamp_actual es diferente al día de
159
- timestamp_registro, False si es el mismo día.
160
- """
161
-
162
- #Obtiene el último registro de fecha de la base de firestore.
163
- fecha_registro_dt = obtenUltimoTimestamp()
164
-
165
- print("Primero, el último timestamp obtenido de base es: ", fecha_registro_dt)
166
- print("Y su tipo es: ", type(fecha_registro_dt))
167
-
168
- #Timestamp actual
169
- fecha_actual_dt = imprimeTimeNow()
170
- print("Segundo, la fecha_actual_dt quedó como: ", fecha_actual_dt)
171
- print("Y su tipo es: ", type(fecha_actual_dt))
172
-
173
-
174
- formato = "%Y-%m-%d %H:%M:%S"
175
- datetime_obj_1 = datetime.strptime(fecha_registro_dt, formato)
176
- datetime_obj_2 = datetime.strptime(fecha_actual_dt, formato)
177
-
178
- # Extraer solo la fecha de los objetos datetime
179
- fecha_registro = datetime_obj_1.date()
180
- #print("Primera extracción: ", fecha_registro)
181
- fecha_actual = datetime_obj_2.date()
182
- #print("Segunda extracción: ", fecha_actual)
183
-
184
-
185
- # Verificar si las fechas son diferentes
186
- resultado = fecha_actual > fecha_registro
187
- print("Resultado de resta de fechas: ", resultado)
188
-
189
- return resultado
190
-
191
- def getFluxServer():
192
- print("In getFluxServer...")
193
- server_keys = list(globales.SERVER_NAMES.values())
194
- random_value = random.choice(server_keys)
195
- print("Random key: ", random_value)
196
-
197
- return random_value
 
1
+ #Herramientas Generales
2
+
3
+ def listaTextosExtraidos(result):
4
+
5
+ textos_extraidos = []
6
+ print("Líneas encontradas con modelo IA:")
7
+ for item in result:
8
+ texto = item[1][0]
9
+ print(texto)
10
+ textos_extraidos.append(texto)
11
+ return textos_extraidos
12
+
13
+ #Herramientas para DNI Panamá.
14
+
15
+ def buscaIndexPalabra(arreglo, palabra):
16
+ palabra_limpia = palabra.lower().replace(" ", "")
17
+ for i, texto_limpio in enumerate(arreglo):
18
+ if palabra_limpia in texto_limpio:
19
+ return i
20
+ return 'error'
21
+
22
+ def buscarPatronCedula(lista_textos):
23
+ for i, texto in enumerate(lista_textos):
24
+ if texto and texto[0].isdigit() and '-' in texto:
25
+ return i
26
+ return 'error'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ia.py ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import atexit
2
+ import functools
3
+ from queue import Queue
4
+ from threading import Event, Thread
5
+ from paddleocr import PaddleOCR
6
+ import documentos
7
+ import herramientas
8
+
9
+ LANG_CONFIG = {
10
+ "ch": {"num_workers": 2},
11
+ "en": {"num_workers": 2},
12
+ "fr": {"num_workers": 1},
13
+ "german": {"num_workers": 1},
14
+ "korean": {"num_workers": 1},
15
+ "japan": {"num_workers": 1},
16
+ }
17
+ CONCURRENCY_LIMIT = 8
18
+
19
+ class PaddleOCRModelManager(object):
20
+ def __init__(self,
21
+ num_workers,
22
+ model_factory):
23
+ super().__init__()
24
+ self._model_factory = model_factory
25
+ self._queue = Queue()
26
+ self._workers = []
27
+ self._model_initialized_event = Event()
28
+ for _ in range(num_workers):
29
+ worker = Thread(target=self._worker, daemon=False)
30
+ worker.start()
31
+ self._model_initialized_event.wait()
32
+ self._model_initialized_event.clear()
33
+ self._workers.append(worker)
34
+
35
+ def infer(self, *args, **kwargs):
36
+ # XXX: Should I use a more lightweight data structure, say, a future?
37
+ result_queue = Queue(maxsize=1)
38
+ self._queue.put((args, kwargs, result_queue))
39
+ success, payload = result_queue.get()
40
+ if success:
41
+ return payload
42
+ else:
43
+ raise payload
44
+
45
+ def close(self):
46
+ for _ in self._workers:
47
+ self._queue.put(None)
48
+ for worker in self._workers:
49
+ worker.join()
50
+
51
+ def _worker(self):
52
+ model = self._model_factory()
53
+ self._model_initialized_event.set()
54
+ while True:
55
+ item = self._queue.get()
56
+ if item is None:
57
+ break
58
+ args, kwargs, result_queue = item
59
+ try:
60
+ result = model.ocr(*args, **kwargs)
61
+ result_queue.put((True, result))
62
+ except Exception as e:
63
+ result_queue.put((False, e))
64
+ finally:
65
+ self._queue.task_done()
66
+
67
+ def create_model(lang):
68
+ return PaddleOCR(lang=lang, use_angle_cls=True, use_gpu=False)
69
+
70
+ model_managers = {}
71
+ for lang, config in LANG_CONFIG.items():
72
+ model_manager = PaddleOCRModelManager(config["num_workers"], functools.partial(create_model, lang=lang))
73
+ model_managers[lang] = model_manager
74
+
75
+ def close_model_managers():
76
+ for manager in model_managers.values():
77
+ manager.close()
78
+
79
+ # XXX: Not sure if gradio allows adding custom teardown logic
80
+ atexit.register(close_model_managers)
81
+
82
+ def inference(img, lang):
83
+ ocr = model_managers[lang]
84
+ result = ocr.infer(img, cls=True)[0]
85
+ textos_extraidos = herramientas.listaTextosExtraidos(result)
86
+
87
+ #Campos DNI Panamá.
88
+ nombre, apellido, identificacion = documentos.dni(textos_extraidos)
89
+
90
+ print(f"Hola: {nombre}, {apellido} con identificación: {identificacion}")
91
+
92
+ return {
93
+ "nombre": nombre,
94
+ "apellido": apellido,
95
+ "identificacion": identificacion
96
+ }
obtenCampo.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import herramientas
2
+
3
+ def Nombre(textos_extraidos, textos_extraidos_limpios):
4
+ indice = herramientas.buscaIndexPalabra(textos_extraidos_limpios, 'usual')
5
+ nombre = textos_extraidos[indice-2]
6
+ apellido = textos_extraidos[indice-1]
7
+ return nombre, apellido
8
+
9
+ def Identificacion(textos_extraidos, textos_extraidos_limpios):
10
+ indice = herramientas.buscarPatronCedula(textos_extraidos_limpios)
11
+ identificacion = textos_extraidos[indice]
12
+ return identificacion
requirements.txt CHANGED
@@ -4,4 +4,9 @@ huggingface_hub
4
  gradio_client
5
  Pillow
6
  firebase_admin
7
- pytz
 
 
 
 
 
 
4
  gradio_client
5
  Pillow
6
  firebase_admin
7
+ pytz
8
+ #OCR
9
+ Pillow
10
+ requests
11
+ paddlepaddle
12
+ paddleocr==2.10.0