-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
131 lines (97 loc) · 3.76 KB
/
app.py
File metadata and controls
131 lines (97 loc) · 3.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
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
# app.py – versión final estable (diciembre 2025)
import os
import streamlit as st
import pandas as pd
from io import BytesIO
from openpyxl.styles import Alignment
from langchain_community.document_loaders import PyPDFLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_openai import ChatOpenAI
from langchain_core.prompts import PromptTemplate
# ===============================
# API KEY
# ===============================
if "OPENAI_API_KEY" not in os.environ:
api_key = st.sidebar.text_input("OpenAI API Key", type="password")
if api_key:
os.environ["OPENAI_API_KEY"] = api_key
st.success("Key cargada!")
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
st.title("Contract Review Agent – Expatriados Argentina")
# ===============================
# CARGA PDF
# ===============================
uploaded_file = st.file_uploader("Subí el Assignment Letter (PDF)", type=["pdf"])
if uploaded_file:
# Guardar temporalmente
with open("temp.pdf", "wb") as f:
f.write(uploaded_file.getbuffer())
loader = PyPDFLoader("temp.pdf")
docs = loader.load()
# Splitter actualizado (DEC 2025)
splitter = RecursiveCharacterTextSplitter(chunk_size=4000, chunk_overlap=200)
chunks = splitter.split_documents(docs)
# ===============================
# PROMPT
# ===============================
template = """Sos experto en Global Mobility y Tax Argentina.
Revisá SOLO el contrato y respondé claro y en español.
Contrato:
{context}
Pregunta: {question}
Respuesta:
"""
prompt = PromptTemplate.from_template(template)
# ===============================
# PREGUNTAS
# ===============================
preguntas = [
"Fecha exacta de inicio y fin",
"País home y país host",
"Tipo de política (tax equalization, protection, etc.)",
"Cláusula de repatriación anticipada",
"Riesgo de Permanent Establishment en Argentina (explicar)",
"Obligación de shadow payroll o inscripción AFIP",
"Beneficios de vivienda, educación y mudanza"
]
resultados = {}
bar = st.progress(0)
for i, q in enumerate(preguntas):
# Usamos primer chunk grande (sobra contexto)
context = "\n\n".join([c.page_content for c in chunks[:4]])
answer = llm.invoke(prompt.format(context=context, question=q))
resultados[q] = answer.content
bar.progress((i + 1) / len(preguntas))
# ===============================
# RESULTADOS EN PANTALLA
# ===============================
st.balloons()
st.success("¡Listo, rey!")
for q, r in resultados.items():
st.write(f"**{q}**")
st.write(r)
st.divider()
# ===============================
# EXPORTAR A EXCEL (PRO)
# ===============================
df = pd.DataFrame(list(resultados.items()), columns=["Campo", "Resultado"])
output = BytesIO()
with pd.ExcelWriter(output, engine='openpyxl') as writer:
df.to_excel(writer, index=False, sheet_name='Revisión Contrato')
workbook = writer.book
worksheet = writer.sheets['Revisión Contrato']
# Columnas anchas
worksheet.column_dimensions['A'].width = 40
worksheet.column_dimensions['B'].width = 80
# Con wrap + alineación vertical
align = Alignment(wrap_text=True, vertical='top')
for row in worksheet.iter_rows(min_row=1, max_row=worksheet.max_row):
for cell in row:
cell.alignment = align
output.seek(0)
st.download_button(
label="📊 Descargar Excel",
data=output,
file_name="revision_expatriado_PRO.xlsx",
mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
)