Alibrown commited on
Commit
1e94a79
·
verified ·
1 Parent(s): 6705130

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +41 -20
app.py CHANGED
@@ -10,7 +10,7 @@ import PyPDF2
10
  import os
11
 
12
  # --- Konfiguration ---
13
- st.set_page_config(page_title="OpenRouter + Gemini AI Chat", layout="wide", initial_sidebar_state="expanded")
14
 
15
  OPENROUTER_API_BASE = "https://openrouter.ai/api/v1"
16
 
@@ -25,6 +25,8 @@ if "messages" not in st.session_state:
25
  st.session_state.messages = []
26
  if "uploaded_content" not in st.session_state:
27
  st.session_state.uploaded_content = None
 
 
28
 
29
  # --- Utilities ---
30
 
@@ -63,6 +65,7 @@ def process_file(uploaded_file):
63
  try:
64
  with zipfile.ZipFile(uploaded_file) as z:
65
  content = "ZIP Contents:\n"
 
66
  for f in z.infolist():
67
  if not f.is_dir() and f.filename.lower().endswith(text_exts):
68
  content += f"\n📄 {f.filename}:\n"
@@ -73,9 +76,9 @@ def process_file(uploaded_file):
73
 
74
  return {"type": "error", "content": "Nicht unterstütztes Dateiformat."}
75
 
76
- @st.cache_data(show_spinner=False, ttl=3600) # Caching für 1 Stunde, um Rate Limits zu schonen
77
  def fetch_model_contexts(api_key):
78
- """Fetches Context Lengths and Price for models from OpenRouter API."""
79
  if not api_key:
80
  return {}
81
 
@@ -89,7 +92,7 @@ def fetch_model_contexts(api_key):
89
  if m.get("pricing", {}).get("prompt", 1) == 0:
90
  contexts[m.get("id")] = m.get("context_length", 4096)
91
 
92
- # Füge die gefilterten Modelle zur Session hinzu
93
  st.session_state.free_models = list(contexts.keys())
94
  return contexts
95
 
@@ -137,9 +140,8 @@ with st.sidebar:
137
  model_contexts = fetch_model_contexts(api_key)
138
 
139
  # 2. Liste der kostenlosen Modelle definieren/aktualisieren
140
- # Fallback, falls API-Key fehlt oder Fehler auftritt
141
  FREE_MODEL_LIST = st.session_state.get("free_models", [
142
- "cognitivecomputations/dolphin-mistral-24b-venice-edition", # :free Suffix entfernt
143
  "deepseek/deepseek-chat-v3",
144
  "google/gemma-2-9b-it",
145
  "mistralai/mistral-7b-instruct-v0.2",
@@ -155,23 +157,36 @@ with st.sidebar:
155
  max_tokens = st.slider(
156
  f"Max Output Tokens (Total Context: {default_ctx})",
157
  min_value=1,
158
- max_value=min(default_ctx, 32768), # Begrenzung nach oben
159
- value=min(1024, default_ctx), # Realistischer Standard-Output (1024 Tokens)
160
  step=256
161
  )
162
 
163
  temperature = st.slider("Temperature", 0.0, 1.0, 0.7)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
 
165
- if st.button("🔄 Reset Chat"):
 
166
  st.session_state.messages = []
167
  st.session_state.uploaded_content = None
168
- st.experimental_rerun() # Refresh, um den file_uploader zu resetten
169
- st.success("Chat und Anhang gelöscht!")
170
-
171
- st.markdown("""
172
- ---
173
- 💡 **Hinweis:** Der Context Window (`Total Context`) beinhaltet sowohl Ihre Eingabe (Chat-Verlauf + Anhang) als auch die Ausgabe (`Max Output Tokens`).
174
- """)
175
 
176
 
177
  # --- File Upload & Preview ---
@@ -179,6 +194,9 @@ uploaded_file = st.file_uploader("Upload File (optional)",
179
  type=["jpg", "jpeg", "png", "txt", "pdf", "zip", "csv", "xlsx", "html", "css", "js", "py"])
180
  if uploaded_file and st.session_state.uploaded_content is None:
181
  st.session_state.uploaded_content = process_file(uploaded_file)
 
 
 
182
 
183
  if st.session_state.uploaded_content:
184
  processed = st.session_state.uploaded_content
@@ -189,6 +207,7 @@ if st.session_state.uploaded_content:
189
  st.text_area("File Preview", processed["content"], height=150)
190
  elif processed["type"] == "error":
191
  st.error(processed["content"])
 
192
  if st.button("❌ Anhang entfernen"):
193
  st.session_state.uploaded_content = None
194
  st.experimental_rerun()
@@ -206,7 +225,7 @@ if prompt := st.chat_input("Deine Nachricht..."):
206
  st.warning("Bitte trage deinen OpenRouter API Key in der Sidebar ein.")
207
  st.stop()
208
 
209
- # 1. Nachricht hinzufügen
210
  st.session_state.messages.append({"role": "user", "content": prompt})
211
  with st.chat_message("user"):
212
  st.markdown(prompt)
@@ -238,12 +257,14 @@ if prompt := st.chat_input("Deine Nachricht..."):
238
  # Antwort anzeigen
239
  st.markdown(reply)
240
 
241
- # Antwort speichern
242
  st.session_state.messages.append({"role": "assistant", "content": reply})
 
243
 
244
- # NEU: Copy Button (kleine, saubere JS-Lösung als Teil des Chat-Bereichs)
245
- st.button("📋 Copy Response", key=f"copy_{len(st.session_state.messages)}", help="Kopiert die gesamte Antwort in die Zwischenablage.")
246
 
247
  except Exception as e:
248
  st.error(str(e))
 
249
  st.session_state.messages.append({"role": "assistant", "content": f"❌ {str(e)}"})
 
10
  import os
11
 
12
  # --- Konfiguration ---
13
+ st.set_page_config(page_title="OpenRouter Free-Tier Hub", layout="wide", initial_sidebar_state="expanded")
14
 
15
  OPENROUTER_API_BASE = "https://openrouter.ai/api/v1"
16
 
 
25
  st.session_state.messages = []
26
  if "uploaded_content" not in st.session_state:
27
  st.session_state.uploaded_content = None
28
+ if "last_response" not in st.session_state:
29
+ st.session_state.last_response = "" # NEU: Speichert die letzte Antwort zum Kopieren
30
 
31
  # --- Utilities ---
32
 
 
65
  try:
66
  with zipfile.ZipFile(uploaded_file) as z:
67
  content = "ZIP Contents:\n"
68
+ # Verbesserte Filterung für Textdateien in ZIP
69
  for f in z.infolist():
70
  if not f.is_dir() and f.filename.lower().endswith(text_exts):
71
  content += f"\n📄 {f.filename}:\n"
 
76
 
77
  return {"type": "error", "content": "Nicht unterstütztes Dateiformat."}
78
 
79
+ @st.cache_data(show_spinner=False, ttl=3600)
80
  def fetch_model_contexts(api_key):
81
+ """Fetches Context Lengths and Price for models from OpenRouter API (Cached)."""
82
  if not api_key:
83
  return {}
84
 
 
92
  if m.get("pricing", {}).get("prompt", 1) == 0:
93
  contexts[m.get("id")] = m.get("context_length", 4096)
94
 
95
+ # Speichere die kostenlosen Modelle
96
  st.session_state.free_models = list(contexts.keys())
97
  return contexts
98
 
 
140
  model_contexts = fetch_model_contexts(api_key)
141
 
142
  # 2. Liste der kostenlosen Modelle definieren/aktualisieren
 
143
  FREE_MODEL_LIST = st.session_state.get("free_models", [
144
+ "cognitivecomputations/dolphin-mistral-24b-venice-edition",
145
  "deepseek/deepseek-chat-v3",
146
  "google/gemma-2-9b-it",
147
  "mistralai/mistral-7b-instruct-v0.2",
 
157
  max_tokens = st.slider(
158
  f"Max Output Tokens (Total Context: {default_ctx})",
159
  min_value=1,
160
+ max_value=min(default_ctx, 32768),
161
+ value=min(1024, default_ctx),
162
  step=256
163
  )
164
 
165
  temperature = st.slider("Temperature", 0.0, 1.0, 0.7)
166
+
167
+ st.markdown("---")
168
+
169
+ # NEU: Kopier-Funktion
170
+ st.subheader("📋 Letzte Antwort kopieren")
171
+ # Textfeld, das die letzte Antwort zum einfachen Kopieren anzeigt
172
+ st.text_area(
173
+ "Response Text",
174
+ st.session_state.last_response,
175
+ height=200,
176
+ key="copy_area_key",
177
+ help="Markiere den Text im Feld und kopiere ihn (Strg+C)."
178
+ )
179
+
180
+ st.markdown("---")
181
 
182
+ # Verbesserter Reset-Button
183
+ if st.button("🔄 Reset Chat & Attachment"):
184
  st.session_state.messages = []
185
  st.session_state.uploaded_content = None
186
+ st.session_state.last_response = "" # Auch die letzte Antwort löschen
187
+ # Da st.file_uploader nicht einfach im Code resettet wird, muss die App neu starten:
188
+ st.experimental_rerun()
189
+ # Hinweis: st.success wird wegen Rerun nicht angezeigt, aber der Reset ist effektiv.
 
 
 
190
 
191
 
192
  # --- File Upload & Preview ---
 
194
  type=["jpg", "jpeg", "png", "txt", "pdf", "zip", "csv", "xlsx", "html", "css", "js", "py"])
195
  if uploaded_file and st.session_state.uploaded_content is None:
196
  st.session_state.uploaded_content = process_file(uploaded_file)
197
+ # Wenn eine neue Datei hochgeladen wird, das Interface neu rendern, um die Vorschau anzuzeigen.
198
+ st.experimental_rerun()
199
+
200
 
201
  if st.session_state.uploaded_content:
202
  processed = st.session_state.uploaded_content
 
207
  st.text_area("File Preview", processed["content"], height=150)
208
  elif processed["type"] == "error":
209
  st.error(processed["content"])
210
+
211
  if st.button("❌ Anhang entfernen"):
212
  st.session_state.uploaded_content = None
213
  st.experimental_rerun()
 
225
  st.warning("Bitte trage deinen OpenRouter API Key in der Sidebar ein.")
226
  st.stop()
227
 
228
+ # 1. Benutzer-Nachricht hinzufügen und sofort anzeigen
229
  st.session_state.messages.append({"role": "user", "content": prompt})
230
  with st.chat_message("user"):
231
  st.markdown(prompt)
 
257
  # Antwort anzeigen
258
  st.markdown(reply)
259
 
260
+ # Antwort speichern und Copy-Feld aktualisieren
261
  st.session_state.messages.append({"role": "assistant", "content": reply})
262
+ st.session_state.last_response = reply
263
 
264
+ # Nach erfolgreicher Antwort neu rendern, um das Copy-Feld zu aktualisieren
265
+ st.experimental_rerun()
266
 
267
  except Exception as e:
268
  st.error(str(e))
269
+ # Fehler zur Historie hinzufügen
270
  st.session_state.messages.append({"role": "assistant", "content": f"❌ {str(e)}"})