1 / app.py
R3dparrot1's picture
Update app.py
63d9eed verified
import os
from groq import Groq
import gradio as gr
import pypdf,numpy as np
from docx import Document
from pptx import Presentation
from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
from reportlab.platypus import SimpleDocTemplate,Paragraph,Spacer,Table,TableStyle
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import inch
from reportlab.lib import colors
from io import BytesIO
os.environ["HF_HOME"] = "/tmp/huggingface"
client = Groq(api_key=os.environ.get("GROQ_API_KEY"))
embed = SentenceTransformer("all-MiniLM-L6-v2","cpu")
MODELS = ["llama-3.3-70b-versatile","gpt-oss-120b","gpt-oss-20b","llama-3.1-8b-instant"]
ECB_RENTE = "**ECB depositorente 2026**\nHuidig: **2,00 %** (feb 2026)\nVerwachting: geen verandering in 2026 (85–90 %)\nStabiel tot eind 2026 / begin 2027\nEerste verhoging waarschijnlijk 2027"
ECB_INFLATIE = "**Eurozone inflatie 2026**\nECB staff: **1,9 %** headline\nSPF/Reuters: **1,8–1,9 %**\nCore: **2,0–2,2 %**\nLanger termijn: stabiel ~2,0 %"
def read(f):
t=""
for x in f or []:
try:
e=os.path.splitext(x.name)[1].lower()
if e==".pdf":t+="".join(p.extract_text()or""for p in pypdf.PdfReader(x.name).pages)
elif e==".docx":t+="\n".join(p.text for p in Document(x.name).paragraphs)
elif e==".pptx":t+="\n".join(sh.text for s in Presentation(x.name).slides for sh in s.shapes if hasattr(sh,"text"))
elif e in(".txt",".md"):t+=open(x.name,"r",encoding="utf-8",errors="ignore").read()
except:pass
return t.strip()
def analyse(q,f,l,m):
if not q.strip()or not f:return "Vraag + bestanden verplicht.",None,gr.update(visible=False)
if not client.api_key:return "GROQ_API_KEY ontbreekt.",None,gr.update(visible=False)
txt=read(f)
if len(txt)<50:return "Te weinig tekst.",None,gr.update(visible=False)
ch=[txt[i:i+600].strip()for i in range(0,len(txt),450)if len(txt[i:i+600].strip())>30]
if not ch:return "Geen bruikbare tekst.",None,gr.update(visible=False)
sc=cosine_similarity(embed.encode([q]),embed.encode(ch)).flatten()
idx=np.argsort(sc)[-3:][::-1]
ctx="\n\n".join(ch[i]for i in idx)
msgs=[{"role":"system","content":f"Strategische analist. Antwoord alleen in {l}."},
{"role":"user","content":f"Context:\n{ctx}\n\nVraag: {q}"}]
s=client.chat.completions.create(model=m,messages=msgs,temperature=0.65,max_tokens=4500,stream=True)
u=m
if isinstance(s,str):
for fb in[m for m in MODELS if m!=m]:
s=client.chat.completions.create(model=fb,messages=msgs,temperature=0.65,max_tokens=4500,stream=True)
if not isinstance(s,str):u=fb;break
else:return f"Alle modellen faalden.\n\n{s}",None,gr.update(visible=False)
a=""
for c in s:a+=c.choices[0].delta.content or ""
pdf=BytesIO()
try:
doc=SimpleDocTemplate(pdf,pagesize=A4)
st=getSampleStyleSheet()
d=[["Match","Tekst"]]+[[f"{sc[i]:.1%}",Paragraph(ch[i].replace("\n","<br/>"),st["BodyText"])]for i in idx]
t=Table(d,colWidths=[0.6*inch,6.7*inch])
t.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,0),colors.HexColor("#004080")),
("GRID",(0,0),(-1,-1),0.3,colors.grey),
("VALIGN",(0,0),(-1,-1),"TOP"),
("FONTSIZE",(0,0),(-1,-1),6.5)]))
story=[Paragraph("RAPPORT",st["Title"]),Spacer(1,0.08*inch),
Paragraph(f"{q}{u}",st["Heading2"]),Spacer(1,0.08*inch),
Paragraph(a.replace("\n","<br/>"),st["Normal"]),Spacer(1,0.15*inch),t]
doc.build(story)
pdf.seek(0)
return f"<div style='white-space:pre-wrap;line-height:1.7;font-size:17px;color:#00f0ff;text-shadow:0 0 10px #00f0ff;user-select:text;'>{a.replace('\n','<br>')}</div>", \
{"value": pdf.getvalue(), "orig_name": "rapport.pdf", "mime_type": "application/pdf"}, \
gr.update(visible=True)
except Exception as e:
print("PDF-fout:",e)
return f"<div style='white-space:pre-wrap;line-height:1.7;font-size:17px;color:#00f0ff;text-shadow:0 0 10px #00f0ff;user-select:text;'>{a.replace('\n','<br>')}</div>", None, gr.update(visible=False)
css="""
.gradio-container{background:#001122;color:#00f0ff;font-family:system-ui,sans-serif;max-width:1400px;margin:1.5rem auto;border:1px solid #00408088;border-radius:12px;}
h1,h2,h3{color:#00f0ff !important;text-shadow:0 0 16px #00f0ffcc;font-weight:700;}
.gr-markdown,.gr-markdown *{color:#00f0ff !important;text-shadow:0 0 14px #00f0ffaa !important;}
.gr-file-label,.gr-file-description,.gr-label,.gr-input-label,.gr-dropdown-label,.gr-file-upload-text{color:#00f0ff !important;text-shadow:0 0 10px #00f0ff;font-weight:bold;}
.gr-dropdown,.gr-dropdown *{color:#00f0ff !important;}
button{background:linear-gradient(135deg,#00aaff,#004080) !important;color:#000 !important;font-weight:600;border:none;border-radius:8px;box-shadow:0 4px 15px #004080aa;}
button:hover{box-shadow:0 8px 25px #00aaffdd;}
input,textarea{background:#002244 !important;border:1px solid #004080 !important;color:#00f0ff !important;border-radius:8px;}
.gr-html{background:#0a1421;padding:1.5rem;border-radius:8px;border:1px solid #00408088;}
footer{display:none;}
"""
with gr.Blocks(title="Strategische Analyse")as d:
with gr.Tabs():
with gr.Tab("Document Analyse"):
with gr.Row():
with gr.Column(scale=1,min_width=320):
f=gr.File(file_count="multiple",file_types=[".pdf",".docx",".pptx",".txt",".md"],label="Bestanden")
l=gr.Dropdown(["Nederlands","English","Español","Deutsch"],value="Nederlands",label="Taal")
gr.Markdown("**Model suggesties** \n• Diep/vergelijken → gpt-oss-120b \n• Snel samenvatten → gpt-oss-20b \n• Strategisch → llama-3.3-70b-versatile \n• Testen → llama-3.1-8b-instant")
m=gr.Dropdown(MODELS,value=MODELS[0],label="Kies een model...",interactive=True)
q=gr.Textbox(label="Vraag",lines=3,placeholder="Wat wil je weten?")
with gr.Row():r=gr.Button("Analyseren",variant="primary");c=gr.Button("Reset")
dl=gr.DownloadButton("Opslaan als PDF",visible=False)
with gr.Column(scale=2):
o=gr.HTML("<div style='padding:1rem;color:#00f0ff;text-shadow:0 0 10px #00f0ff;'>Klaar…</div>")
def rst():return None,"Nederlands",MODELS[0],"","<div style='padding:1rem;color:#00f0ff;text-shadow:0 0 10px #00f0ff;'>Klaar…</div>",gr.update(visible=False)
c.click(rst,outputs=[f,l,m,q,o,dl])
r.click(analyse,inputs=[q,f,l,m],outputs=[o,dl])
with gr.Tab("Dashboard (ECB 2026)"):
gr.Markdown("### Actuele ECB Verwachtingen – Februari 2026")
gr.Markdown(ECB_RENTE)
gr.Markdown(ECB_INFLATIE)
gr.Markdown("**Bron:** ECB projections, SPF Q1 2026, Reuters-poll. Data-dependent beleid.")
d.launch(css=css)