Sheller commited on
Commit
6f00807
·
verified ·
1 Parent(s): f2af70d

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +211 -38
src/streamlit_app.py CHANGED
@@ -1,40 +1,213 @@
1
- import altair as alt
2
- import numpy as np
3
- import pandas as pd
4
  import streamlit as st
 
5
 
6
- """
7
- # Welcome to Streamlit!
8
-
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
12
-
13
- In the meantime, below is an example of what you can do with just a few lines of code:
14
- """
15
-
16
- num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
17
- num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
18
-
19
- indices = np.linspace(0, 1, num_points)
20
- theta = 2 * np.pi * num_turns * indices
21
- radius = indices
22
-
23
- x = radius * np.cos(theta)
24
- y = radius * np.sin(theta)
25
-
26
- df = pd.DataFrame({
27
- "x": x,
28
- "y": y,
29
- "idx": indices,
30
- "rand": np.random.randn(num_points),
31
- })
32
-
33
- st.altair_chart(alt.Chart(df, height=700, width=700)
34
- .mark_point(filled=True)
35
- .encode(
36
- x=alt.X("x", axis=None),
37
- y=alt.Y("y", axis=None),
38
- color=alt.Color("idx", legend=None, scale=alt.Scale()),
39
- size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
40
- ))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import streamlit as st
2
+ import time
3
 
4
+ # --- CONFIGURATION & CONTENT ---
5
+ st.set_page_config(page_title="Elf-OS Agent Simulator", page_icon="🤖")
6
+
7
+ # Content Dictionary for Multi-Language Support
8
+ CONTENT = {
9
+ "Deutsch": {
10
+ "title": "🤖 Elf-OS: Agenten Simulation",
11
+ "intro": "Ein **KI-Agent** ist wie ein kluger Elf: Er rät nicht einfach, sondern benutzt **Werkzeuge** (Tools), um Aufgaben zu lösen. Deine Aufgabe ist es, dem Agenten zu sagen, in welcher REIHENFOLGE er die Werkzeuge nutzen soll.",
12
+ "sidebar_title": "Wähle eine Mission",
13
+ "tools_header": "🧰 Verfügbare Werkzeuge",
14
+ "chain_header": "🔗 Deine Gedanken-Kette",
15
+ "empty_chain": "*Noch keine Werkzeuge gewählt...*",
16
+ "btn_add": "➕",
17
+ "btn_clear": "🗑️ Kette löschen",
18
+ "btn_run": "🚀 Agent starten",
19
+ "spinner": "Der Agent denkt nach...",
20
+ "feedback_spotify": "❌ <strong>Fehler:</strong> Warum Musik hören? Das löst das Problem nicht! (Agenten sollten keine unnötigen Tools nutzen).",
21
+ "feedback_order": "⚠️ <strong>Reihenfolge falsch!</strong> Du hast die richtigen Tools, aber in der falschen Reihenfolge. (Man kann nichts buchen, bevor man weiß wo!)",
22
+ "feedback_fail": "❌ <strong>Das reicht nicht.</strong> Der Agent wusste nicht weiter oder hat falsche Informationen. Überdenke die Logik.",
23
+ "feedback_success": "✅ <strong>Erfolg!</strong> Der Agent hat das Problem gelöst.",
24
+ "missions": {
25
+ "L1": {
26
+ "name": "Level 1: Das vergessene Geschenk",
27
+ "briefing": "Santa hat vergessen, was die kleine Mia sich gewünscht hat! Er steht auf ihrem Dach. Finde heraus, was sie will, und ob es im Sack ist.",
28
+ "solution_ids": ["db", "inv"],
29
+ "explanation": "Der Agent muss erst WISSEN, was gesucht ist (Datenbank), bevor er PRÜFEN kann, ob er es hat (Inventar)."
30
+ },
31
+ "L2": {
32
+ "name": "Level 2: Die Routen-Planung",
33
+ "briefing": "Wir müssen nach Berlin fliegen. Aber wir dürfen nur starten, wenn das Wetter gut ist UND wir genug Rentiermoos für den Rückweg haben.",
34
+ "solution_ids": ["weather", "fuel", "nav"],
35
+ "explanation": "Ein Agent muss erst die 'Blocker' prüfen (Wetter & Tank), bevor er die Aktion (Navigation/Flug) startet."
36
+ },
37
+ "L3": {
38
+ "name": "Level 3: Der Notfall (Advanced)",
39
+ "briefing": "Rudolph hat Schnupfen! Der Agent muss einen Tierarzt in der Nähe finden, der JETZT offen hat, und dort einen Termin buchen.",
40
+ "solution_ids": ["gps", "maps", "cal", "book"],
41
+ "explanation": "Eine klassische 'Agent Chain': Wo bin ich? -> Wer ist hier? -> Haben die Zeit? -> Buche es."
42
+ }
43
+ },
44
+ "tools": {
45
+ "weather": "Wetter_Radar",
46
+ "db": "Wunschzettel_Datenbank",
47
+ "inv": "Geschenksack_Inventar",
48
+ "nav": "Navigations_System",
49
+ "fuel": "Tankanzeige_Rentiere",
50
+ "gps": "GPS_Ortung",
51
+ "maps": "Google_Maps_Suche",
52
+ "cal": "Kalender_Bot",
53
+ "book": "Buchungs_Tool",
54
+ "spotify": "Spotify_Weihnachtsplaylist"
55
+ }
56
+ },
57
+ "English": {
58
+ "title": "🤖 Elf-OS: Agent Simulator",
59
+ "intro": "An **AI Agent** is like a smart Elf: It doesn't just guess; it uses **Tools** to solve tasks. Your job is to tell the Agent in which ORDER to use the tools.",
60
+ "sidebar_title": "Choose a Mission",
61
+ "tools_header": "🧰 Available Tools",
62
+ "chain_header": "🔗 Your Thought Chain",
63
+ "empty_chain": "*No tools selected yet...*",
64
+ "btn_add": "➕",
65
+ "btn_clear": "🗑️ Clear Chain",
66
+ "btn_run": "🚀 Run Agent",
67
+ "spinner": "The Agent is thinking...",
68
+ "feedback_spotify": "❌ <strong>Error:</strong> Why listen to music? That doesn't solve the problem! (Agents shouldn't use unnecessary tools).",
69
+ "feedback_order": "⚠️ <strong>Wrong Order!</strong> You have the right tools, but in the wrong sequence. (You can't book something before you know where!)",
70
+ "feedback_fail": "❌ <strong>Not enough.</strong> The Agent got stuck or lacks information. Rethink the logic.",
71
+ "feedback_success": "✅ <strong>Success!</strong> The Agent solved the problem.",
72
+ "missions": {
73
+ "L1": {
74
+ "name": "Level 1: The Forgotten Gift",
75
+ "briefing": "Santa forgot what little Mia wanted! He is on her roof. Find out what she wants, and check if it's in the sack.",
76
+ "solution_ids": ["db", "inv"],
77
+ "explanation": "The Agent must KNOW what is needed (Database) before it can CHECK if it has it (Inventory)."
78
+ },
79
+ "L2": {
80
+ "name": "Level 2: Route Planning",
81
+ "briefing": "We need to fly to Berlin. But we can only take off if the weather is good AND we have enough reindeer moss for the return trip.",
82
+ "solution_ids": ["weather", "fuel", "nav"],
83
+ "explanation": "An Agent must check 'Blockers' (Weather & Fuel) before executing the Action (Navigation/Flight)."
84
+ },
85
+ "L3": {
86
+ "name": "Level 3: The Emergency (Advanced)",
87
+ "briefing": "Rudolph has a cold! The Agent needs to find a vet nearby who is open NOW, and book an appointment.",
88
+ "solution_ids": ["gps", "maps", "cal", "book"],
89
+ "explanation": "A classic 'Agent Chain': Where am I? -> Who is here? -> Are they free? -> Book it."
90
+ }
91
+ },
92
+ "tools": {
93
+ "weather": "Weather_Radar",
94
+ "db": "Wishlist_Database",
95
+ "inv": "Giftbag_Inventory",
96
+ "nav": "Navigation_System",
97
+ "fuel": "Fuel_Gauge_Reindeer",
98
+ "gps": "GPS_Location",
99
+ "maps": "Google_Maps_Search",
100
+ "cal": "Calendar_Bot",
101
+ "book": "Booking_Tool",
102
+ "spotify": "Spotify_ChristmasPlaylist"
103
+ }
104
+ }
105
+ }
106
+
107
+ # --- CUSTOM CSS ---
108
+ st.markdown("""
109
+ <style>
110
+ .stButton>button {
111
+ width: 100%;
112
+ border-radius: 10px;
113
+ height: 50px;
114
+ font-weight: 500;
115
+ }
116
+ .success-box {
117
+ padding: 20px;
118
+ background-color: #d4edda;
119
+ color: #155724;
120
+ border-radius: 10px;
121
+ margin-bottom: 10px;
122
+ border: 1px solid #c3e6cb;
123
+ }
124
+ .fail-box {
125
+ padding: 20px;
126
+ background-color: #f8d7da;
127
+ color: #721c24;
128
+ border-radius: 10px;
129
+ margin-bottom: 10px;
130
+ border: 1px solid #f5c6cb;
131
+ }
132
+ div[data-testid="stExpander"] {
133
+ background-color: #f0f2f6;
134
+ border-radius: 10px;
135
+ }
136
+ </style>
137
+ """, unsafe_allow_html=True)
138
+
139
+ # --- APP LOGIC ---
140
+
141
+ # 1. Language Selection
142
+ lang_key = st.sidebar.radio("Language / Sprache", ["Deutsch", "English"])
143
+ text = CONTENT[lang_key]
144
+
145
+ st.title(text["title"])
146
+ st.markdown(text["intro"])
147
+
148
+ # 2. Mission Selection
149
+ # We use keys (L1, L2, L3) to track missions, but display names
150
+ mission_options = {m_data["name"]: m_key for m_key, m_data in text["missions"].items()}
151
+ selected_mission_name = st.sidebar.selectbox(text["sidebar_title"], list(mission_options.keys()))
152
+ selected_mission_key = mission_options[selected_mission_name]
153
+ mission_data = text["missions"][selected_mission_key]
154
+
155
+ # 3. Session State Management
156
+ if 'chain' not in st.session_state:
157
+ st.session_state.chain = [] # Stores Tool IDs (e.g., 'db', 'inv')
158
+
159
+ # Reset chain if mission changes
160
+ if 'current_mission' not in st.session_state or st.session_state.current_mission != selected_mission_key:
161
+ st.session_state.chain = []
162
+ st.session_state.current_mission = selected_mission_key
163
+
164
+ # 4. Display Mission
165
+ st.info(f"📋 **MISSION:** {mission_data['briefing']}")
166
+
167
+ col1, col2 = st.columns([1, 1])
168
+
169
+ with col1:
170
+ st.subheader(text["tools_header"])
171
+ # Tool Buttons
172
+ for tool_id, tool_name in text["tools"].items():
173
+ if st.button(f"{text['btn_add']} {tool_name}", key=f"btn_{tool_id}"):
174
+ st.session_state.chain.append(tool_id)
175
+
176
+ with col2:
177
+ st.subheader(text["chain_header"])
178
+ if len(st.session_state.chain) == 0:
179
+ st.markdown(text["empty_chain"])
180
+ else:
181
+ for i, tool_id in enumerate(st.session_state.chain):
182
+ tool_name = text["tools"][tool_id]
183
+ st.markdown(f"**{i+1}.** `{tool_name}`")
184
+
185
+ if st.button(text["btn_clear"], type="secondary"):
186
+ st.session_state.chain = []
187
+
188
+ st.write("---")
189
+
190
+ # 5. Execution Logic
191
+ if st.button(text["btn_run"], type="primary"):
192
+ with st.spinner(text["spinner"]):
193
+ time.sleep(1.0) # Simulation delay
194
+
195
+ user_chain_ids = st.session_state.chain
196
+ correct_ids = mission_data['solution_ids']
197
+
198
+ # Check 1: Spotify (Hallucination/Distraction)
199
+ if "spotify" in user_chain_ids:
200
+ st.markdown(f'<div class="fail-box">{text["feedback_spotify"]}</div>', unsafe_allow_html=True)
201
+
202
+ # Check 2: Exact Match
203
+ elif user_chain_ids == correct_ids:
204
+ st.balloons()
205
+ st.markdown(f'<div class="success-box">{text["feedback_success"]}<br><br><em>💡 {mission_data["explanation"]}</em></div>', unsafe_allow_html=True)
206
+
207
+ # Check 3: Right Tools, Wrong Order (Set comparison)
208
+ elif set(user_chain_ids) == set(correct_ids) and len(user_chain_ids) == len(correct_ids):
209
+ st.markdown(f'<div class="fail-box">{text["feedback_order"]}</div>', unsafe_allow_html=True)
210
+
211
+ # Check 4: Wrong
212
+ else:
213
+ st.markdown(f'<div class="fail-box">{text["feedback_fail"]}</div>', unsafe_allow_html=True)