Alibrown commited on
Commit
322738b
·
verified ·
1 Parent(s): 65be34d

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +231 -0
app.py ADDED
@@ -0,0 +1,231 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import google.generativeai as genai
3
+ from PIL import Image
4
+ import io
5
+ import base64
6
+ import pandas as pd
7
+ import zipfile
8
+ import PyPDF2
9
+
10
+ # Konfiguration der Seite
11
+ st.set_page_config(page_title="Gemini AI Chat", layout="wide")
12
+
13
+ st.title("🤖 Gemini AI Chat Interface")
14
+ st.markdown("""
15
+ **Welcome to the Gemini AI Chat Interface!**
16
+ Chat seamlessly with Google's advanced Gemini AI models, supporting multiple input types.
17
+ 🔗 [GitHub Profile](https://github.com/volkansah) |
18
+ 📂 [Project Repository](https://github.com/volkansah/gemini-ai-chat) |
19
+ 💬 [Soon](https://aicodecraft.io)
20
+ """)
21
+
22
+ # Session State Management
23
+ if "messages" not in st.session_state:
24
+ st.session_state.messages = []
25
+ if "uploaded_content" not in st.session_state:
26
+ st.session_state.uploaded_content = None
27
+
28
+ # Funktionen zur Dateiverarbeitung
29
+ def encode_image(image):
30
+ buffered = io.BytesIO()
31
+ image.save(buffered, format="JPEG")
32
+ return base64.b64encode(buffered.getvalue()).decode('utf-8')
33
+
34
+ def process_file(uploaded_file):
35
+ """Verarbeitet die hochgeladene Datei und extrahiert den Inhalt."""
36
+ file_type = uploaded_file.name.split('.')[-1].lower()
37
+
38
+ # Text-basierte Erweiterungen für ZIP-Verarbeitung
39
+ text_extensions = ('.txt', '.csv', '.py', '.html', '.js', '.css',
40
+ '.php', '.json', '.xml', '.c', '.cpp', '.java',
41
+ '.cs', '.rb', '.go', '.ts', '.swift', '.kt', '.rs', '.sh', '.sql', '.xlsx')
42
+
43
+ if file_type in ["jpg", "jpeg", "png"]:
44
+ return {"type": "image", "content": Image.open(uploaded_file).convert('RGB')}
45
+
46
+ if file_type in ["txt"] + [ext.strip('.') for ext in text_extensions if ext not in ('.csv', '.xlsx')]:
47
+ return {"type": "text", "content": uploaded_file.read().decode("utf-8", errors='ignore')}
48
+
49
+ if file_type in ["csv", "xlsx"]:
50
+ try:
51
+ # Versuch, Datei als CSV oder Excel zu lesen
52
+ if file_type == "csv":
53
+ df = pd.read_csv(uploaded_file)
54
+ else: # xlsx
55
+ df = pd.read_excel(uploaded_file)
56
+ return {"type": "text", "content": df.to_string()}
57
+ except Exception as e:
58
+ return {"type": "error", "content": f"Failed to read tabular data: {e}"}
59
+
60
+ if file_type == "pdf":
61
+ try:
62
+ reader = PyPDF2.PdfReader(uploaded_file)
63
+ return {"type": "text", "content": "".join(page.extract_text() for page in reader.pages if page.extract_text())}
64
+ except Exception as e:
65
+ return {"type": "error", "content": f"Failed to read PDF: {e}"}
66
+
67
+ if file_type == "zip":
68
+ try:
69
+ with zipfile.ZipFile(uploaded_file) as z:
70
+ newline = "\n"
71
+ content = f"ZIP Contents (Processing text files only):{newline}"
72
+
73
+ for file_info in z.infolist():
74
+ if not file_info.is_dir():
75
+ try:
76
+ # Prüfen, ob die Datei eine Text-Erweiterung hat
77
+ if file_info.filename.lower().endswith(text_extensions):
78
+ with z.open(file_info.filename) as file:
79
+ # Decode mit 'ignore', falls es Probleme gibt
80
+ file_content = file.read().decode('utf-8', errors='ignore')
81
+ content += f"{newline}📄 {file_info.filename}:{newline}{file_content}{newline}"
82
+ else:
83
+ content += f"{newline}⚠️ Binärdatei/Unbekannte Datei ignoriert: {file_info.filename}{newline}"
84
+ except Exception as e:
85
+ content += f"{newline}❌ Fehler beim Lesen von {file_info.filename}: {str(e)}{newline}"
86
+
87
+ return {"type": "text", "content": content}
88
+ except Exception as e:
89
+ return {"type": "error", "content": f"Failed to process ZIP: {e}"}
90
+
91
+ return {"type": "error", "content": "Unsupported file format"}
92
+
93
+ # Sidebar für Einstellungen
94
+ with st.sidebar:
95
+ api_key = st.text_input("Google AI API Key", type="password")
96
+
97
+ # Modell-Liste bereinigt und Vision hervorgehoben
98
+ model_list = [
99
+ "gemini-1.5-flash",
100
+ "gemini-1.5-pro",
101
+ "gemini-1.5-pro-vision-latest", # Vision-Modell für Bilder
102
+ "gemini-1.0-pro-vision-latest",
103
+ "gemini-2.0-flash",
104
+ "gemini-2.0-flash-lite",
105
+ "gemini-2.0-pro-exp-02-05",
106
+ ]
107
+ model = st.selectbox("Model", model_list)
108
+ st.caption("❗ Für Bildanalyse **(Vision)**-Modell wählen.")
109
+
110
+ temperature = st.slider("Temperature", 0.0, 1.0, 0.7)
111
+ max_tokens = st.slider("Max Tokens", 1, 100000, 1000)
112
+
113
+ # Datei-Upload-Kontrolle
114
+ uploaded_file = st.file_uploader("Upload File (Image/Text/PDF/ZIP)",
115
+ type=["jpg", "jpeg", "png", "txt", "pdf", "zip",
116
+ "csv", "xlsx", "html", "css", "php", "js", "py"])
117
+
118
+ # Logik zur Dateiverarbeitung und Vorschau
119
+ if uploaded_file and st.session_state.uploaded_content is None:
120
+ # Nur verarbeiten, wenn eine neue Datei hochgeladen wird und kein Inhalt im State ist
121
+ processed = process_file(uploaded_file)
122
+ st.session_state.uploaded_content = processed
123
+
124
+ # Vorschau anzeigen, wenn Inhalt vorhanden
125
+ if st.session_state.uploaded_content:
126
+ processed = st.session_state.uploaded_content
127
+
128
+ st.subheader("Current File Attachment:")
129
+
130
+ if processed["type"] == "image":
131
+ st.image(processed["content"], caption="Attached Image", use_container_width=False, width=300)
132
+ elif processed["type"] == "text":
133
+ st.text_area("File Preview", processed["content"], height=150)
134
+ elif processed["type"] == "error":
135
+ st.error(f"Error processing file: {processed['content']}")
136
+
137
+ # NEU: Clear Button
138
+ if st.button("❌ Clear Uploaded File Attachment"):
139
+ st.session_state.uploaded_content = None
140
+ # Da st.file_uploader selbst nicht einfach resettet,
141
+ # informieren wir den Nutzer, dass der Zustand gelöscht ist.
142
+ st.info("Attachment cleared! Reload the page to reset the upload field completely.")
143
+
144
+
145
+ # Chat-Historie anzeigen
146
+ for message in st.session_state.messages:
147
+ with st.chat_message(message["role"]):
148
+ st.markdown(message["content"])
149
+
150
+ # Chat-Eingabe verarbeiten
151
+ if prompt := st.chat_input("Your message..."):
152
+ if not api_key:
153
+ st.warning("API Key benötigt!")
154
+ st.stop()
155
+
156
+ # NEU: Spinner hinzugefügt
157
+ with st.spinner("Gemini is thinking..."):
158
+ try:
159
+ # API konfigurieren
160
+ genai.configure(api_key=api_key)
161
+
162
+ # Modell auswählen
163
+ model_instance = genai.GenerativeModel(model)
164
+
165
+ # Inhalt vorbereiten
166
+ content = [{"text": prompt}]
167
+
168
+ # Dateiinhalt hinzufügen
169
+ if st.session_state.uploaded_content:
170
+ if st.session_state.uploaded_content["type"] == "image":
171
+ # Überprüfung, ob ein Vision-Modell ausgewählt ist
172
+ if "vision" not in model.lower() and "pro" not in model.lower():
173
+ st.error("Bitte ein Vision- oder Pro-Modell für Bilder auswählen!")
174
+ st.stop()
175
+
176
+ content.append({
177
+ "inline_data": {
178
+ "mime_type": "image/jpeg",
179
+ "data": encode_image(st.session_state.uploaded_content["content"])
180
+ }
181
+ })
182
+ elif st.session_state.uploaded_content["type"] == "text":
183
+ # Text-Inhalt dem Prompt hinzufügen
184
+ content[0]["text"] += f"\n\n[Attached File Content]\n{st.session_state.uploaded_content['content']}"
185
+
186
+ # Nachricht zur Historie hinzufügen und anzeigen
187
+ st.session_state.messages.append({"role": "user", "content": prompt})
188
+ with st.chat_message("user"):
189
+ st.markdown(prompt)
190
+
191
+ # Antwort generieren
192
+ response = model_instance.generate_content(
193
+ content,
194
+ generation_config=genai.types.GenerationConfig(
195
+ temperature=temperature,
196
+ max_output_tokens=max_tokens
197
+ )
198
+ )
199
+
200
+ # Überprüfen, ob die Antwort gültig ist
201
+ if not response.candidates:
202
+ st.error("API Error: Keine gültige Antwort erhalten. Überprüfe die Eingabe oder das Modell.")
203
+ else:
204
+ # Antwort anzeigen und zur Historie hinzufügen
205
+ response_text = response.text
206
+ with st.chat_message("assistant"):
207
+ st.markdown(response_text)
208
+ st.session_state.messages.append({"role": "assistant", "content": response_text})
209
+
210
+ except Exception as e:
211
+ st.error(f"API Error: {str(e)}")
212
+ # Zusätzliche Überprüfung für Visionsfehler
213
+ if st.session_state.uploaded_content and st.session_state.uploaded_content["type"] == "image" and "vision" not in model.lower() and "pro" not in model.lower():
214
+ st.error("Detail-Fehler: Für Bilder MUSS ein Vision-fähiger Modell (z.B. 1.5 Pro) ausgewählt werden.")
215
+
216
+ # Instructions in the sidebar
217
+ with st.sidebar:
218
+ st.markdown("""
219
+ ---
220
+ ## 📝 Instructions:
221
+ 1. Enter your Google AI API key
222
+ 2. Select a model (use **Pro/Vision** models for image analysis)
223
+ 3. Adjust parameters (Temperature/Tokens)
224
+ 4. Upload a file (optional, supports **Image, Text, PDF, ZIP, CSV/XLSX**)
225
+ 5. Type your message and press Enter
226
+
227
+ ### About
228
+ 🔗 [GitHub Profile](https://github.com/volkansah) |
229
+ 📂 [Project Repository](https://github.com/volkansah/gemini-ai-chat) |
230
+ 💬 [Soon](https://aicodecraft.io)
231
+ """)