valegro's picture
Update app.py
ca7ea29 verified
raw
history blame
7.87 kB
import streamlit as st
import torch
import torch.nn as nn
import torch.nn.functional as F
import pandas as pd
import numpy as np
from PIL import Image
# =========================
# 1) LIBRERIA OUTPUT: possibili nuovi usi
# Ognuno ha un "mini embedding" e un'immagine di esempio
# =========================
output_libreria = {
"ArmadioAnta": {
"embedding": [1.0, 0.0], # fittizio
"descrizione": "Riutilizzo come anta armadio",
"img": "armadio.jpg" # se ce l'hai, o lascialo vuoto
},
"DockRigenerato": {
"embedding": [0.5, 0.5],
"descrizione": "Base dock con componenti EoL",
"img": "dock.jpg"
},
"OggettoVetrina": {
"embedding": [0.0, 1.0],
"descrizione": "Pannello estetico o vetrina",
"img": "vetrina.jpg"
}
}
# In un caso reale potresti mettere molte voci, con embeddings più ricchi
# e parametri più precisi
# =========================
# 2) MODELLO AI: un MLP
# Input: [volume, area, lunghezza, spessore, usura, (materiale cod?), + output_embedding(2)]
# Output: punteggio compatibilità (float)
# =========================
class SimpleMLP(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(8, 16)
self.fc2 = nn.Linear(16, 8)
self.fc3 = nn.Linear(8, 1)
def forward(self, x):
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = torch.sigmoid(self.fc3(x)) # punteggio tra 0 e 1
return x
# =========================
# Salviamo il modello in session_state per poterlo usare da più sezioni
# =========================
if "model" not in st.session_state:
st.session_state["model"] = SimpleMLP()
if "trained" not in st.session_state:
st.session_state["trained"] = False
# Ottimizziamo i param in session
optimizer = torch.optim.Adam(st.session_state["model"].parameters(), lr=1e-3)
# ============== FUNZIONE DI TRAIN FAKE ================
def train_fake_model(epochs=20, batch_size=32):
"""
Genera un dataset fittizio di EoL + output => score
e allena un MLP in session_state["model"].
"""
# Generiamo un dataset random con 1000 esempi
# EoL -> (vol, area, lunghezza, spessore, usura, materialeCod)
# Output -> 2D embedding
# Score -> random 0..1 ma correlato un po' a "logica" fittizia
n = 1000
rng = np.random.default_rng(42)
vol = rng.normal(50,15,n)
area = rng.normal(20,5,n)
lung = rng.normal(100,30,n)
spess = rng.uniform(0.5,5,n)
usura = rng.uniform(0,1,n)
materiale = rng.integers(0,3,n).astype(float)
# Scegli output a caso
out_keys = list(output_libreria.keys())
output_idx = rng.integers(0,len(out_keys),n)
# costruiamo embedding 2D
out_emb = []
for i in output_idx:
key = out_keys[i]
out_emb.append(output_libreria[key]["embedding"])
out_emb = np.array(out_emb)
# Score fittizio
# Esempio: se volume < 200 e usura < 0.5 => punteggio +
# + un offset se output = "ArmadioAnta" e spess < 3 => punteggio alto
base_score = 0.5 * np.ones(n)
base_score -= (usura * 0.3)
base_score -= ((vol - 200)/400)
# se spess < 3 e out=Armadio => +0.2
# se out=DockRigenerato => +0.1 random
for i in range(n):
if out_keys[output_idx[i]]=="ArmadioAnta" and spess[i]<3:
base_score[i]+=0.2
if out_keys[output_idx[i]]=="DockRigenerato":
base_score[i]+=rng.uniform(0,0.1)
# bounding punteggio
base_score = np.clip(base_score,0,1)
X = np.column_stack([vol,area,lung,spess,usura,materiale,out_emb])
y = base_score.reshape(-1,1)
# Torch
X_t = torch.tensor(X, dtype=torch.float32)
y_t = torch.tensor(y, dtype=torch.float32)
dataset = torch.utils.data.TensorDataset(X_t, y_t)
loader = torch.utils.data.DataLoader(dataset, batch_size=batch_size, shuffle=True)
model = st.session_state["model"]
# reinit param
def weights_init(m):
if isinstance(m, nn.Linear):
nn.init.xavier_uniform_(m.weight)
nn.init.zeros_(m.bias)
model.apply(weights_init)
lossf = nn.MSELoss()
for ep in range(epochs):
totloss=0
for xb,yb in loader:
optimizer.zero_grad()
pred = model(xb)
loss=lossf(pred,yb)
loss.backward()
optimizer.step()
totloss+=loss.item()
st.session_state["trained"] = True
return totloss
# ============== UI Streamlit ================
st.title("WEEKO – Flusso: EoL + Output-libreria + AI + Overlay Estetico")
# TAB: Train AI + Avanzamento
tab1, tab2, tab3 = st.tabs(["1) Train AI (finto)","2) Valuta EoL + Output","3) Overlay Estetico"])
with tab1:
st.subheader("Fase 1: Train fittizio del modello AI")
st.write("Generiamo un dataset casuale simulando molte componenti EoL e possibili output.")
if st.button("🏋️ Esegui training fittizio"):
final_loss = train_fake_model(epochs=20)
st.success(f"Training completato, loss={final_loss:.4f}")
if st.session_state["trained"]:
st.info("Modello AI pronto all'uso.")
else:
st.warning("Non hai ancora addestrato il modello fittizio, i punteggi saranno casuali.")
with tab2:
st.subheader("Fase 2: Inserisci EoL e scegli un Output")
# Carico eventuale foto EoL
file_eol = st.file_uploader("Foto EoL (opzionale)", type=["jpg","png"], key="eolFile2")
if file_eol:
st.image(file_eol, caption="Componente EoL", use_column_width=True)
# Dati EoL
vol_in = st.number_input("Volume (cm³)", 0.0, 1000.0, 100.0)
area_in = st.number_input("Area (cm²)", 0.0, 500.0, 30.0)
lung_in = st.number_input("Lunghezza (mm)", 0.0, 2000.0, 120.0)
spess_in = st.number_input("Spessore (mm)", 0.5, 10.0, 2.0)
usura_in = st.slider("Usura (0=nuovo,1=molto usurato)", 0.0,1.0,0.3)
mat_in = st.selectbox("Materiale", ["Plastica","Metallo","PCB"])
mat_code = {"Plastica":0.0,"Metallo":1.0,"PCB":2.0}[mat_in]
# Scegli un output
scelte = list(output_libreria.keys())
out_sel = st.selectbox("Scegli l'output-libreria", scelte)
if st.button("Calcola punteggio AI"):
model = st.session_state["model"]
embed = output_libreria[out_sel]["embedding"] # 2D
x_np = np.array([[vol_in, area_in, lung_in, spess_in, usura_in, mat_code, embed[0], embed[1]]], dtype=np.float32)
x_t = torch.from_numpy(x_np)
with torch.no_grad():
pred = model(x_t).item()
st.info(f"Punteggio di compatibilità con '{out_sel}': {pred:.3f}")
if pred>0.7:
st.success("Ottima compatibilità! Procedi con la rigenerazione.")
elif pred>0.4:
st.warning("Compatibilità media: valuta modifiche/manuale rifinitura.")
else:
st.error("Compatibilità bassa, meglio cambiare output o scartare.")
with tab3:
st.subheader("Fase 3: Overlay Estetico")
st.write("Carica la foto EoL e la foto dell'Output finale per un effetto wow. (Puramente estetico)")
col1, col2 = st.columns(2)
with col1:
file_eol_3 = st.file_uploader("Foto EoL", type=["jpg","png"], key="uplEol3")
with col2:
file_out_3 = st.file_uploader("Foto Oggetto Finale (es. Armadio?)", type=["jpg","png"], key="uplOut3")
alpha_val = st.slider("Trasparenza EoL", 0.0,1.0,0.5)
if file_eol_3 and file_out_3:
eol_img = Image.open(file_eol_3).convert("RGBA")
out_img = Image.open(file_out_3).convert("RGBA")
# ridimensioniamo la EoL all'immagine dell'oggetto
eol_img = eol_img.resize(out_img.size)
blend = Image.blend(out_img, eol_img, alpha_val)
st.image(blend, caption="Overlay EoL + Oggetto Finale", use_column_width=True)
else:
st.info("Attendi di caricare entrambe le immagini per vedere l'overlay.")