StepWise / src /streamlit_app.py
Fatser's picture
Update src/streamlit_app.py
4635488 verified
import streamlit as st
import requests
import json
import os
import graphviz
import time
from dotenv import load_dotenv
from prompts import SYSTEM_INSTRUCTIONS
st.set_page_config(page_title="StepWise: Algorithmic Thinking Mentor", layout="wide")
load_dotenv()
api_key = os.getenv("API_KEY")
def call_gemini(messages):
url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-lite:generateContent?key={api_key}"
headers = {'Content-Type': 'application/json'}
contents = []
for m in messages:
role = "model" if m["role"] == "assistant" else "user"
contents.append({"role": role, "parts": [{"text": m["content"]}]})
payload = {"contents": contents}
for attempt in range(3):
try:
response = requests.post(url, headers=headers, json=payload)
if response.status_code == 200:
return response.json()['candidates'][0]['content']['parts'][0]['text']
elif response.status_code in [429, 503]:
time.sleep(5)
continue
else:
return f"🚨 API Hatası: {response.status_code}"
except:
time.sleep(2)
continue
return "🚨 Sunucu yoğun, lütfen tekrar dene."
if "messages" not in st.session_state: st.session_state.messages = []
if "flow_nodes" not in st.session_state: st.session_state.flow_nodes = []
if "flow_edges" not in st.session_state: st.session_state.flow_edges = []
if "mode" not in st.session_state: st.session_state.mode = "chat"
with st.sidebar:
st.title("🚀 StepWise Paneli")
st.divider()
if st.button("📚 Konu Tekrarı", use_container_width=True):
st.session_state.mode = "chat"
st.session_state.messages = [{"role": "user", "content": f"SİSTEM: {SYSTEM_INSTRUCTIONS}\n\nGÖREV: Merhaba! Lütfen öğrenciye konuyu en baştan anlatmaya başla."}]
with st.spinner("Öğretmen hazırlanıyor..."):
res = call_gemini(st.session_state.messages)
st.session_state.messages.append({"role": "assistant", "content": res})
st.rerun()
if st.button("📐 Akış Şeması İnşası", use_container_width=True):
st.session_state.mode = "flowchart"
st.session_state.flow_nodes, st.session_state.flow_edges = [], []
st.session_state.messages = [{"role": "user", "content": f"SİSTEM: {SYSTEM_INSTRUCTIONS}\n\nGÖREV: Akış Şeması modundayız. Lütfen öğrenciye içinde mutlaka bir KARAR yapısı olan orta zorlukta bir problem ver ve çizmesini iste."}]
with st.spinner("Senaryo oluşturuluyor..."):
res = call_gemini(st.session_state.messages)
st.session_state.messages.append({"role": "assistant", "content": res})
st.rerun()
if st.button("🎁 Girdi-Çıktı Kutusu", use_container_width=True):
st.session_state.mode = "blackbox"
st.session_state.messages = [{"role": "user", "content": f"SİSTEM: {SYSTEM_INSTRUCTIONS}\n\nGÖREV: Girdi-Çıktı oyun modundayız. Gizli bir kural belirle, kategoriyi söyle ve ilk Girdi: X, Çıktı: Y örneğini ver."}]
with st.spinner("Kutu hazırlanıyor..."):
res = call_gemini(st.session_state.messages)
st.session_state.messages.append({"role": "assistant", "content": res})
st.rerun()
if st.button("🔧 Algoritma Tamirhanesi", use_container_width=True):
st.session_state.mode = "repair"
st.session_state.messages = [{"role": "user", "content": f"SİSTEM: {SYSTEM_INSTRUCTIONS}\n\nGÖREV: Tamirhane modundayız. Lütfen adımları birbirine karışmış bozuk bir senaryo ver ve öğrenciden doğru sıralamayı (A-B-C gibi) iste."}]
with st.spinner("Arıza tespit ediliyor..."):
res = call_gemini(st.session_state.messages)
st.session_state.messages.append({"role": "assistant", "content": res})
st.rerun()
st.divider()
if st.button("🗑️ Her Şeyi Sıfırla", use_container_width=True):
st.session_state.messages, st.session_state.flow_nodes, st.session_state.flow_edges, st.session_state.mode = [], [], [], "chat"
st.rerun()
st.title("🤖 StepWise: Algoritmik Düşünme Mentoru")
if st.session_state.mode == "repair":
st.info("🔧 **Tamirhane Modu:** Aşağıdaki adımları mantıklı bir sıraya dizebilir misin? Tahminini aşağıya yaz!")
elif st.session_state.mode == "flowchart":
with st.container(border=True):
st.subheader("🛠️ Akış Şeması Tasarım Alanı")
c1, c2, c3 = st.columns([2, 3, 1])
with c1:
shape_type = st.selectbox("Şekil:", ["Elips (Başla/Bitir)", "Dikdörtgen (İşlem)", "Eşkenar Dörtgen (Karar)", "Paralelkenar (Bilgi Girişi)"])
with c2:
node_text = st.text_input("Metin:", key="node_input")
with c3:
st.write("")
if st.button("➕ Ekle", use_container_width=True):
if node_text:
st.session_state.flow_nodes.append({"id": str(len(st.session_state.flow_nodes)), "text": node_text, "type": shape_type})
st.rerun()
if st.session_state.flow_nodes:
bc1, bc2, bc3, bc4 = st.columns([2, 2, 2, 1])
with bc1:
source = st.selectbox("Kaynak:", options=st.session_state.flow_nodes, format_func=lambda x: f"{x['id']}: {x['text']}")
with bc2:
target = st.selectbox("Hedef:", options=st.session_state.flow_nodes, format_func=lambda x: f"{x['id']}: {x['text']}")
with bc3:
label = st.selectbox("Yol:", ["", "Evet", "Hayır"]) if "Eşkenar" in source["type"] else ""
with bc4:
st.write("")
if st.button("🔗 Bağla", use_container_width=True):
st.session_state.flow_edges.append({"from": source["id"], "to": target["id"], "label": label})
st.rerun()
dot = graphviz.Digraph()
for node in st.session_state.flow_nodes:
shape = "ellipse" if "Elips" in node["type"] else "box" if "Dikdörtgen" in node["type"] else "diamond" if "Eşkenar" in node["type"] else "parallelogram"
dot.node(node["id"], node["text"], shape=shape, color="blue", style="filled", fillcolor="white")
for edge in st.session_state.flow_edges:
dot.edge(edge["from"], edge["to"], label=edge["label"])
st.graphviz_chart(dot)
b1, b2 = st.columns(2)
if b1.button("🗑️ Şemayı Temizle"):
st.session_state.flow_nodes, st.session_state.flow_edges = [], []
st.rerun()
if b2.button("✅ Bitti ve Kontrol Et"):
node_map = {n['id']: n['text'] for n in st.session_state.flow_nodes}
schema_desc = " | ".join([f"{node_map[e['from']]} -> {node_map[e['to']]} ({e['label']})" for e in st.session_state.flow_edges])
st.session_state.messages.append({"role": "user", "content": f"SİSTEM: Öğrenci şemayı bitirdi. Yapı şu şekilde: {schema_desc}. Lütfen analiz et ve geri bildirim ver."})
with st.spinner("Kontrol ediliyor..."):
res = call_gemini(st.session_state.messages)
st.session_state.messages.append({"role": "assistant", "content": res})
st.rerun()
elif st.session_state.mode == "blackbox":
with st.container(border=True):
st.subheader("🎁 Sihirli Kara Kutu")
box_viz = graphviz.Digraph()
box_viz.attr(rankdir='LR')
box_viz.node("IN", "Girdi", shape="parallelogram", style="filled", fillcolor="#E1BEE7")
box_viz.node("BOX", "???", shape="box", style="filled", fillcolor="#212121", fontcolor="white")
box_viz.node("OUT", "Çıktı", shape="parallelogram", style="filled", fillcolor="#C8E6C9")
box_viz.edge("IN", "BOX"); box_viz.edge("BOX", "OUT")
st.graphviz_chart(box_viz)
st.divider()
for message in st.session_state.messages:
if not message["content"].startswith("SİSTEM"):
with st.chat_message(message["role"]):
st.markdown(message["content"])
if prompt := st.chat_input("Mesajını yaz..."):
st.session_state.messages.append({"role": "user", "content": prompt})
with st.chat_message("user"): st.markdown(prompt)
with st.chat_message("assistant"):
res = call_gemini(st.session_state.messages)
st.markdown(res)
st.session_state.messages.append({"role": "assistant", "content": res})