MotionS / app.py
TamerTokgoz's picture
Update app.py
3aa0a7e verified
import streamlit as st
import pandas as pd
import numpy as np
import faiss
import matplotlib.pyplot as plt
import seaborn as sns
from sentence_transformers import SentenceTransformer
# --- SAYFA AYARLARI ---
st.set_page_config(
page_title="Motion-S: Text-to-Motion",
page_icon="🕺",
layout="wide"
)
# --- CSS İLE GÖRSELLEŞTİRME ---
st.markdown("""
<style>
.main { background-color: #f5f7f9; }
.stTextInput > div > div > input { background-color: #ffffff; }
.token-box {
background-color: #262730;
color: #00ff41;
padding: 15px;
border-radius: 10px;
font-family: monospace;
border-left: 5px solid #00ff41;
}
</style>
""", unsafe_allow_html=True)
# --- MODEL VE VERİ YÜKLEME ---
@st.cache_resource
def load_assets():
# Modeli HF sunucularından çeker
model = SentenceTransformer('all-mpnet-base-v2')
# Senin yerelde/Kaggle'da kaydettiğin dosyaları okur
# Dosya isimlerinin tam olarak bunlar olduğundan emin ol
index = faiss.read_index("faiss_index.bin")
df = pd.read_csv("train_data_final.csv")
return model, index, df
try:
model, index, df = load_assets()
except Exception as e:
st.error(f"Dosyalar yüklenirken hata oluştu! Lütfen 'faiss_index.bin' ve 'train_data_final.csv' dosyalarının yüklendiğinden emin olun. Hata: {e}")
st.stop()
# --- YARDIMCI FONKSİYONLAR ---
def plot_motion_density(token_string):
"""Token dizisini ısı haritasına dönüştürür."""
tokens = [int(t) for t in str(token_string).split()]
data = np.array(tokens[:100]) # İlk 100 token yeterli
# 10x10'luk bir matris oluştur
if len(data) < 100:
data = np.pad(data, (0, 100 - len(data)), mode='constant')
matrix = data.reshape(10, 10)
fig, ax = plt.subplots(figsize=(5, 4))
sns.heatmap(matrix, annot=False, cmap="viridis", cbar=True, ax=ax)
ax.set_title("Hareket Yoğunluk Haritası (İlk 100 Token)")
ax.axis('off')
return fig
# --- ARAYÜZ ---
st.title("🕺 Motion-S: Hierarchical Motion Synthesis")
st.markdown("Doğal dil girişini hiyerarşik hareket tokenlarına dönüştüren yapay zeka arayüzü.")
query = st.text_input("Bir hareket cümlesi veya Gloss girin:", placeholder="Örn: a person walking slowly or 'WALK SLOW'")
if query:
with st.spinner('En yakın hareket hesaplanıyor...'):
# 1. Arama (Retrieval)
q_emb = model.encode([query], normalize_embeddings=True)
D, I = index.search(q_emb, 1)
best_idx = I[0][0]
match_score = D[0][0]
res_row = df.iloc[best_idx]
# --- SONUÇLARI GÖSTER ---
st.divider()
col1, col2 = st.columns([1, 1.2])
with col1:
st.subheader("🎯 Eşleşme Bilgileri")
st.write(f"**Eşleşen Cümle:** {res_row['sentence']}")
st.write(f"**Gloss:** `{res_row['gloss']}`")
st.metric("Benzerlik Skoru", f"{match_score:.4f}")
st.write("---")
st.write("**Görsel Analiz:**")
fig = plot_motion_density(res_row['base_tokens'])
st.pyplot(fig)
with col2:
st.subheader("🔢 Hiyerarşik Token Karşılıkları")
tab_base, tab_res = st.tabs(["Ana Hareket (Base)", "Residual Katmanlar"])
with tab_base:
st.markdown('<p style="color: grey;">Base tokens (Ana iskelet)</p>', unsafe_allow_html=True)
st.markdown(f'<div class="token-box">{res_row["base_tokens"]}</div>', unsafe_allow_html=True)
with tab_res:
st.write("Residual katmanlar hareketin detaylarını (fine-grained) içerir.")
selected_layer = st.selectbox("Katman Seç:", ["residual_1", "residual_2", "residual_3", "residual_4", "residual_5"])
st.markdown(f'<div class="token-box">{res_row[selected_layer]}</div>', unsafe_allow_html=True)
st.success("Hareket başarıyla sentezlendi! Bu tokenlar animasyon motoruna gönderilmeye hazırdır.")
else:
st.info("Lütfen yukarıdaki kutuya bir metin girerek analizi başlatın.")
# Alt Bilgi
st.markdown("---")
st.caption("Motion-S Project | SBERT + FAISS + Streamlit Deployment")