angelsg213 commited on
Commit
c142c28
·
verified ·
1 Parent(s): 4bbc0ce

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +118 -54
app.py CHANGED
@@ -1,79 +1,143 @@
1
- # ==========================================
2
- # 2. CONSULTA AL LLM (CORREGIDO)
3
- # ==========================================
4
- def consultar_llm(texto_factura):
5
- # CORRECCIÓN 1: Asegúrate de que esto coincida con el nombre en tus Secrets
6
- token = os.getenv("aa")
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
 
8
  if not token:
9
- return {"error": "Falta configurar HF_TOKEN en Settings -> Secrets"}
10
-
11
- texto_limpio = texto_factura[:6000]
12
 
13
- # CORRECCIÓN 2: Usamos la URL estándar y la versión v0.2 que es más estable
14
- API_URL = "https://api-inference.huggingface.co/models/mistralai/Mistral-7B-Instruct-v0.2"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
  headers = {
17
  "Content-Type": "application/json",
18
  "Authorization": f"Bearer {token}"
19
  }
20
-
21
- prompt = f"""
22
- [INST] Eres un experto en extracción de datos. Tu tarea es convertir esta factura en JSON.
23
-
24
- TEXTO DE LA FACTURA:
25
- {texto_limpio}
26
-
27
- INSTRUCCIONES:
28
- 1. Extrae: numero_factura, fecha, emisor, cliente, total.
29
- 2. Extrae la lista de items (descripcion, cantidad, precio).
30
- 3. Responde ÚNICAMENTE con el JSON válido. No saludes, no expliques.
31
-
32
- FORMATO JSON ESPERADO:
33
- {{
34
- "numero_factura": "string",
35
- "fecha": "DD/MM/YYYY",
36
- "emisor": "string",
37
- "cliente": "string",
38
- "items": [
39
- {{ "descripcion": "string", "cantidad": number, "total": number }}
40
- ],
41
- "total_factura": number
42
- }}
43
- [/INST]
44
- """
45
-
46
  payload = {
47
  "inputs": prompt,
48
  "parameters": {
49
- "max_new_tokens": 1500,
50
- "temperature": 0.1,
51
  "return_full_text": False
52
  },
53
  "options": {
54
- "wait_for_model": True # Esperar si el modelo está cargando
55
  }
56
  }
57
-
58
  try:
59
- response = requests.post(API_URL, headers=headers, json=payload)
 
 
 
60
 
61
  if response.status_code != 200:
62
- return {"error": f"Error API ({response.status_code})", "detalle": response.text}
63
-
64
  resultado = response.json()
65
 
66
- texto_generado = ""
67
  if isinstance(resultado, list) and len(resultado) > 0:
68
- texto_generado = resultado[0].get('generated_text', '')
69
  elif isinstance(resultado, dict):
70
- texto_generado = resultado.get('generated_text', '')
 
 
 
 
 
71
 
72
- match = re.search(r'\{.*\}', texto_generado, re.DOTALL)
73
- if match:
74
- return json.loads(match.group(0))
75
- else:
76
- return {"error": "El modelo no generó un JSON válido", "respuesta_cruda": texto_generado}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
 
78
- except Exception as e:
79
- return {"error": f"Error interno: {str(e)}"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import PyPDF2
3
+ import requests
4
+ import os
5
+
6
+ # ============= EXTRAER TEXTO DEL PDF =============
7
+ def extraer_texto_pdf(pdf_file):
8
+ try:
9
+ pdf_reader = PyPDF2.PdfReader(pdf_file)
10
+ texto = ""
11
+ for pagina in pdf_reader.pages:
12
+ texto += pagina.extract_text() + "\n"
13
+ return texto
14
+ except Exception as e:
15
+ return f"Error: {str(e)}"
16
+
17
+ # ============= ANALIZAR CON LLM =============
18
+ def analizar_con_llm(texto):
19
+ """El LLM analiza la factura y devuelve un resumen en un párrafo"""
20
 
21
+ token = os.getenv("aa")
22
  if not token:
23
+ return "❌ Error: Falta configurar HF_TOKEN en Settings Secrets"
 
 
24
 
25
+ # Limitar texto
26
+ texto_limpio = texto[:8000]
27
+
28
+ # Prompt simple
29
+ prompt = f"""Analiza esta factura y dame un resumen en UN SOLO PÁRRAFO con:
30
+ - Número de factura
31
+ - Fecha
32
+ - Emisor y cliente
33
+ - Productos/servicios
34
+ - Total a pagar
35
+
36
+ TEXTO DE LA FACTURA:
37
+ {texto_limpio}
38
+
39
+ Responde en un solo párrafo claro y conciso:"""
40
+
41
+ # Modelo LLM (el más potente gratis)
42
+ API_URL = "https://api-inference.huggingface.co/models/Qwen/Qwen2.5-72B-Instruct"
43
 
44
  headers = {
45
  "Content-Type": "application/json",
46
  "Authorization": f"Bearer {token}"
47
  }
48
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  payload = {
50
  "inputs": prompt,
51
  "parameters": {
52
+ "max_new_tokens": 500,
53
+ "temperature": 0.3,
54
  "return_full_text": False
55
  },
56
  "options": {
57
+ "wait_for_model": True
58
  }
59
  }
60
+
61
  try:
62
+ response = requests.post(API_URL, headers=headers, json=payload, timeout=60)
63
+
64
+ if response.status_code == 503:
65
+ return "⏳ El modelo está cargando, intenta en 20 segundos..."
66
 
67
  if response.status_code != 200:
68
+ return f" Error {response.status_code}: {response.text[:200]}"
69
+
70
  resultado = response.json()
71
 
72
+ # Extraer respuesta
73
  if isinstance(resultado, list) and len(resultado) > 0:
74
+ return resultado[0].get('generated_text', 'Sin respuesta')
75
  elif isinstance(resultado, dict):
76
+ return resultado.get('generated_text', 'Sin respuesta')
77
+
78
+ return "❌ No se pudo obtener respuesta del modelo"
79
+
80
+ except Exception as e:
81
+ return f"❌ Error: {str(e)}"
82
 
83
+ # ============= FUNCIÓN PRINCIPAL =============
84
+ def procesar_factura(pdf_file):
85
+ if pdf_file is None:
86
+ return "", "⚠️ Sube un PDF primero"
87
+
88
+ # Extraer texto
89
+ texto = extraer_texto_pdf(pdf_file)
90
+
91
+ if texto.startswith("Error"):
92
+ return "", f"❌ {texto}"
93
+
94
+ # Mostrar texto extraído
95
+ texto_preview = f"**Texto extraído ({len(texto)} caracteres):**\n\n{texto[:1000]}..."
96
+
97
+ # Analizar con LLM
98
+ analisis = analizar_con_llm(texto)
99
+
100
+ # Resultado final
101
+ resultado = f"""## 📄 Análisis de la Factura
102
 
103
+ {analisis}
104
+
105
+ ---
106
+
107
+ ### 📝 Texto Original:
108
+ {texto_preview}
109
+ """
110
+
111
+ return texto, resultado
112
+
113
+ # ============= INTERFAZ GRADIO =============
114
+ with gr.Blocks(title="Analizador de Facturas con IA") as demo:
115
+ gr.Markdown("""
116
+ # 🤖 Analizador de Facturas con IA
117
+ ### Sube un PDF y el LLM lo analizará en un párrafo
118
+ """)
119
+
120
+ with gr.Row():
121
+ with gr.Column():
122
+ pdf_input = gr.File(label="📎 Subir PDF de Factura", file_types=[".pdf"])
123
+ btn = gr.Button("🚀 Analizar", variant="primary", size="lg")
124
+
125
+ with gr.Column():
126
+ texto_salida = gr.Textbox(label="📝 Texto Extraído", lines=10, max_lines=15)
127
+ resultado = gr.Markdown(label="🤖 Análisis del LLM")
128
+
129
+ btn.click(
130
+ fn=procesar_factura,
131
+ inputs=[pdf_input],
132
+ outputs=[texto_salida, resultado]
133
+ )
134
+
135
+ gr.Markdown("""
136
+ ---
137
+ **Configuración necesaria:**
138
+ 1. Ve a Settings → Secrets
139
+ 2. Crea: `HF_TOKEN` = tu token de https://huggingface.co/settings/tokens
140
+ """)
141
+
142
+ if __name__ == "__main__":
143
+ demo.launch()