Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
import streamlit as st
|
2 |
-
from streamlit.components.v1 import
|
3 |
from pathlib import Path
|
4 |
import json
|
5 |
import time
|
@@ -7,322 +7,232 @@ from datetime import datetime
|
|
7 |
import re
|
8 |
import pandas as pd
|
9 |
import yaml
|
10 |
-
from io import StringIO
|
11 |
import openpyxl
|
12 |
import csv
|
13 |
import base64
|
14 |
import glob
|
15 |
import os
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
|
|
|
|
59 |
|
60 |
-
st.
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
"content": encoded_content
|
65 |
-
})
|
66 |
|
67 |
-
if
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
st.session_state.md_versions[filename].append({
|
72 |
-
"timestamp": timestamp,
|
73 |
-
"content": encoded_content,
|
74 |
-
"action": action
|
75 |
-
})
|
76 |
-
|
77 |
-
if filename not in [f["filename"] for f in st.session_state.md_files_history]:
|
78 |
-
st.session_state.md_files_history.append({
|
79 |
-
"filename": filename,
|
80 |
-
"timestamp": timestamp,
|
81 |
-
"content": encoded_content
|
82 |
-
})
|
83 |
-
|
84 |
-
st.session_state.combined_markdown = combine_markdown_files()
|
85 |
-
|
86 |
-
def combine_markdown_files():
|
87 |
-
"""Combine markdown files into a single document"""
|
88 |
-
return "".join([f"# {md_file['filename']}\n\n{decode_content(md_file['content'])}\n\n---\n\n"
|
89 |
-
for md_file in sorted(st.session_state.md_files_history,
|
90 |
-
key=lambda x: x["filename"])])
|
91 |
-
|
92 |
-
def scan_and_load_files():
|
93 |
-
"""Scan directory for supported files and load them"""
|
94 |
-
loaded_files = []
|
95 |
-
for ext in FILE_TYPES.keys():
|
96 |
-
for filepath in glob.glob(f"*.{ext}"):
|
97 |
-
try:
|
98 |
-
with open(filepath, 'r', encoding='utf-8') as f:
|
99 |
-
content = f.read()
|
100 |
-
file_type = filepath.split('.')[-1].lower()
|
101 |
-
|
102 |
-
st.session_state.file_data[filepath] = content
|
103 |
-
st.session_state.file_types[filepath] = file_type
|
104 |
-
|
105 |
-
if file_type == 'md':
|
106 |
-
st.session_state.md_outline[filepath] = parse_markdown_outline(content)
|
107 |
-
st.session_state.rendered_content[filepath] = content
|
108 |
-
if filepath not in [f["filename"] for f in st.session_state.md_files_history]:
|
109 |
-
add_to_history(filepath, content, "auto-loaded")
|
110 |
-
|
111 |
-
loaded_files.append(filepath)
|
112 |
-
except Exception as e:
|
113 |
-
st.error(f"π¨ Error loading {filepath}: {str(e)}")
|
114 |
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
"""Display previous versions of a markdown file"""
|
119 |
-
if filename in st.session_state.md_versions and len(st.session_state.md_versions[filename]) > 1:
|
120 |
-
st.markdown("### π Previous Versions")
|
121 |
-
version_idx = st.selectbox(
|
122 |
-
"Select version to view",
|
123 |
-
range(len(st.session_state.md_versions[filename])-1),
|
124 |
-
format_func=lambda x: f"Version {len(st.session_state.md_versions[filename])-1-x} - {st.session_state.md_versions[filename][x]['timestamp']}"
|
125 |
-
)
|
126 |
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
|
|
|
|
|
|
|
|
137 |
st.rerun()
|
138 |
|
139 |
-
def
|
140 |
-
"""
|
141 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
142 |
|
143 |
with tab1:
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
st.
|
148 |
-
st.session_state.md_outline[filename] = parse_markdown_outline(edited_content)
|
149 |
-
add_to_history(filename, edited_content, "edited")
|
150 |
-
content = edited_content
|
151 |
|
152 |
with tab2:
|
153 |
-
st.
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
|
|
|
|
|
|
159 |
|
160 |
-
|
161 |
-
|
|
|
162 |
|
163 |
-
|
164 |
-
|
165 |
-
def
|
166 |
-
"""
|
167 |
-
st.
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
for md_file in st.session_state.md_files_history:
|
184 |
-
col1, col2, col3 = st.sidebar.columns([2, 1, 1])
|
185 |
-
with col1:
|
186 |
-
st.markdown(f"**{md_file['filename']}**")
|
187 |
with col2:
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
st.
|
193 |
-
|
|
|
|
|
|
|
|
|
|
|
194 |
with col3:
|
195 |
-
st.
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
def read_file_content(uploaded_file):
|
211 |
-
"""Smart file reader with enhanced markdown handling"""
|
212 |
-
file_type = uploaded_file.name.split('.')[-1].lower()
|
213 |
-
try:
|
214 |
-
if file_type == 'md':
|
215 |
-
content = uploaded_file.getvalue().decode()
|
216 |
-
st.session_state.md_outline[uploaded_file.name] = parse_markdown_outline(content)
|
217 |
-
st.session_state.rendered_content[uploaded_file.name] = content
|
218 |
-
add_to_history(uploaded_file.name, content)
|
219 |
-
return content, "md"
|
220 |
-
elif file_type in ['csv', 'xlsx']:
|
221 |
-
df = pd.read_csv(uploaded_file) if file_type == 'csv' else pd.read_excel(uploaded_file)
|
222 |
-
return df.to_string(), file_type
|
223 |
-
elif file_type == 'json':
|
224 |
-
return json.dumps(json.load(uploaded_file), indent=2), "json"
|
225 |
-
elif file_type == 'yaml':
|
226 |
-
return yaml.dump(yaml.safe_load(uploaded_file)), "yaml"
|
227 |
-
else:
|
228 |
-
return uploaded_file.getvalue().decode(), "txt"
|
229 |
-
except Exception as e:
|
230 |
-
st.error(f"π¨ Error reading {uploaded_file.name}: {str(e)}")
|
231 |
-
return None, None
|
232 |
-
|
233 |
-
def save_file_content(content, filename, file_type):
|
234 |
-
"""Smart file saver with enhanced markdown handling"""
|
235 |
-
try:
|
236 |
-
if file_type == "md":
|
237 |
-
with open(filename, 'w') as f:
|
238 |
-
f.write(content)
|
239 |
-
st.session_state.rendered_content[filename] = content
|
240 |
-
add_to_history(filename, content, "saved")
|
241 |
-
elif file_type in ["csv", "xlsx"]:
|
242 |
-
df = pd.read_csv(StringIO(content)) if file_type == "csv" else pd.read_excel(StringIO(content))
|
243 |
-
df.to_csv(filename, index=False) if file_type == "csv" else df.to_excel(filename, index=False)
|
244 |
-
elif file_type == "json":
|
245 |
-
with open(filename, 'w') as f:
|
246 |
-
json.dump(json.loads(content), f, indent=2)
|
247 |
-
elif file_type == "yaml":
|
248 |
-
with open(filename, 'w') as f:
|
249 |
-
yaml.dump(yaml.safe_load(content), f)
|
250 |
-
else:
|
251 |
-
with open(filename, 'w') as f:
|
252 |
-
f.write(content)
|
253 |
-
return True
|
254 |
-
except Exception as e:
|
255 |
-
st.error(f"π¨ Error saving {filename}: {str(e)}")
|
256 |
-
return False
|
257 |
|
258 |
def main():
|
259 |
-
|
260 |
-
loaded_files = scan_and_load_files()
|
261 |
|
262 |
-
|
263 |
-
|
264 |
|
265 |
-
|
|
|
|
|
|
|
|
|
266 |
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
with col2:
|
278 |
-
multiple_uploaded_files = st.file_uploader(
|
279 |
-
"π Upload multiple files",
|
280 |
-
type=list(FILE_TYPES.keys()),
|
281 |
-
accept_multiple_files=True,
|
282 |
-
help="Upload multiple files to view as a book",
|
283 |
-
key="multiple_uploader"
|
284 |
-
)
|
285 |
-
|
286 |
-
if single_uploaded_file:
|
287 |
-
content, file_type = read_file_content(single_uploaded_file)
|
288 |
-
if content is not None:
|
289 |
-
st.session_state.file_data[single_uploaded_file.name] = content
|
290 |
-
st.session_state.file_types[single_uploaded_file.name] = file_type
|
291 |
-
st.success(f"π Loaded {FILE_TYPES.get(file_type, 'π')} file: {single_uploaded_file.name}")
|
292 |
-
|
293 |
-
if multiple_uploaded_files:
|
294 |
-
for uploaded_file in multiple_uploaded_files:
|
295 |
-
content, file_type = read_file_content(uploaded_file)
|
296 |
-
if content is not None:
|
297 |
-
st.session_state.file_data[uploaded_file.name] = content
|
298 |
-
st.session_state.file_types[uploaded_file.name] = file_type
|
299 |
-
st.success(f"π Loaded {len(multiple_uploaded_files)} files")
|
300 |
-
st.rerun()
|
301 |
-
|
302 |
-
show_file_history()
|
303 |
|
304 |
-
if
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
if st.button(f"πΎ Save {filename}"):
|
319 |
-
if save_file_content(content, filename, file_type):
|
320 |
-
st.success(f"β¨ Saved {filename} successfully!")
|
321 |
-
|
322 |
-
with book_tab:
|
323 |
-
if st.session_state.combined_markdown:
|
324 |
-
st.markdown("## π Book View")
|
325 |
-
st.markdown(st.session_state.combined_markdown)
|
326 |
|
327 |
if __name__ == "__main__":
|
328 |
main()
|
|
|
1 |
import streamlit as st
|
2 |
+
from streamlit.components.v1 import components
|
3 |
from pathlib import Path
|
4 |
import json
|
5 |
import time
|
|
|
7 |
import re
|
8 |
import pandas as pd
|
9 |
import yaml
|
10 |
+
from io import StringIO, BytesIO
|
11 |
import openpyxl
|
12 |
import csv
|
13 |
import base64
|
14 |
import glob
|
15 |
import os
|
16 |
+
import zipfile
|
17 |
+
|
18 |
+
# Initialize session state for chat history if not exists
|
19 |
+
if 'chat_history' not in st.session_state:
|
20 |
+
st.session_state.chat_history = []
|
21 |
+
if 'messages' not in st.session_state:
|
22 |
+
st.session_state.messages = []
|
23 |
+
if 'current_file' not in st.session_state:
|
24 |
+
st.session_state.current_file = None
|
25 |
+
if 'file_content' not in st.session_state:
|
26 |
+
st.session_state.file_content = None
|
27 |
+
|
28 |
+
def create_zip_of_files(files):
|
29 |
+
"""Create a zip file containing all markdown files"""
|
30 |
+
zip_buffer = BytesIO()
|
31 |
+
with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file:
|
32 |
+
for file in files:
|
33 |
+
with open(file, 'r', encoding='utf-8') as f:
|
34 |
+
zip_file.writestr(file, f.read())
|
35 |
+
return zip_buffer.getvalue()
|
36 |
+
|
37 |
+
def get_download_link(file_path):
|
38 |
+
"""Create a download link for a file"""
|
39 |
+
if isinstance(file_path, bytes): # For zip files
|
40 |
+
b64 = base64.b64encode(file_path).decode()
|
41 |
+
href = f'data:application/zip;base64,{b64}'
|
42 |
+
filename = 'all_files.zip'
|
43 |
+
else: # For individual files
|
44 |
+
with open(file_path, 'r', encoding='utf-8') as f:
|
45 |
+
content = f.read()
|
46 |
+
b64 = base64.b64encode(content.encode()).decode()
|
47 |
+
href = f'data:text/markdown;base64,{b64}'
|
48 |
+
filename = os.path.basename(file_path)
|
49 |
+
return f'<a href="{href}" download="{filename}">{filename}</a>'
|
50 |
+
|
51 |
+
def load_file(filepath):
|
52 |
+
"""Load file content"""
|
53 |
+
with open(filepath, 'r', encoding='utf-8') as f:
|
54 |
+
return f.read()
|
55 |
+
|
56 |
+
def display_file_manager():
|
57 |
+
"""Display file management sidebar with guaranteed unique button keys."""
|
58 |
+
st.sidebar.title("π File Management")
|
59 |
+
all_files = glob.glob("*.md")
|
60 |
+
all_files.sort(reverse=True)
|
61 |
|
62 |
+
if st.sidebar.button("π Delete All", key="delete_all_files_button"):
|
63 |
+
for file in all_files:
|
64 |
+
os.remove(file)
|
65 |
+
st.rerun()
|
|
|
|
|
66 |
|
67 |
+
if st.sidebar.button("β¬οΈ Download All", key="download_all_files_button"):
|
68 |
+
zip_file = create_zip_of_files(all_files)
|
69 |
+
st.sidebar.markdown(get_download_link(zip_file), unsafe_allow_html=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
|
71 |
+
for idx, file in enumerate(all_files):
|
72 |
+
file_stat = os.stat(file)
|
73 |
+
unique_id = f"{idx}_{file_stat.st_size}_{file_stat.st_mtime}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
|
75 |
+
col1, col2, col3, col4 = st.sidebar.columns([1,3,1,1])
|
76 |
+
with col1:
|
77 |
+
if st.button("π", key=f"view_{unique_id}"):
|
78 |
+
st.session_state.current_file = file
|
79 |
+
st.session_state.file_content = load_file(file)
|
80 |
+
with col2:
|
81 |
+
st.markdown(get_download_link(file), unsafe_allow_html=True)
|
82 |
+
with col3:
|
83 |
+
if st.button("π", key=f"edit_{unique_id}"):
|
84 |
+
st.session_state.current_file = file
|
85 |
+
st.session_state.file_content = load_file(file)
|
86 |
+
with col4:
|
87 |
+
if st.button("π", key=f"delete_{unique_id}"):
|
88 |
+
os.remove(file)
|
89 |
st.rerun()
|
90 |
|
91 |
+
def process_with_gpt(user_input):
|
92 |
+
"""Process input with GPT-4"""
|
93 |
+
# Add your GPT processing logic here
|
94 |
+
response = f"GPT-4 Response to: {user_input}"
|
95 |
+
st.session_state.messages.append({"role": "user", "content": user_input})
|
96 |
+
st.session_state.messages.append({"role": "assistant", "content": response})
|
97 |
+
return response
|
98 |
+
|
99 |
+
def process_with_claude(user_input):
|
100 |
+
"""Process input with Claude"""
|
101 |
+
# Add your Claude processing logic here
|
102 |
+
response = f"Claude Response to: {user_input}"
|
103 |
+
st.session_state.chat_history.append({
|
104 |
+
"user": user_input,
|
105 |
+
"claude": response
|
106 |
+
})
|
107 |
+
return response
|
108 |
+
|
109 |
+
def perform_ai_lookup(query):
|
110 |
+
"""Perform AI lookup with ArXiv"""
|
111 |
+
# Add your ArXiv lookup logic here
|
112 |
+
return f"ArXiv results for: {query}"
|
113 |
+
|
114 |
+
def search_arxiv(query):
|
115 |
+
"""Search ArXiv papers"""
|
116 |
+
# Add your ArXiv search logic here
|
117 |
+
return f"ArXiv search results for: {query}"
|
118 |
+
|
119 |
+
def create_media_gallery():
|
120 |
+
"""Create media gallery interface"""
|
121 |
+
st.subheader("Media Gallery")
|
122 |
+
st.write("Media gallery functionality goes here")
|
123 |
+
|
124 |
+
def show_chat_history():
|
125 |
+
"""Display chat history for both models"""
|
126 |
+
st.subheader("Chat History π")
|
127 |
+
tab1, tab2 = st.tabs(["Claude History", "GPT-4o History"])
|
128 |
|
129 |
with tab1:
|
130 |
+
for chat in st.session_state.chat_history:
|
131 |
+
st.text_area("You:", chat["user"], height=100)
|
132 |
+
st.text_area("Claude:", chat["claude"], height=200)
|
133 |
+
st.markdown(chat["claude"])
|
|
|
|
|
|
|
134 |
|
135 |
with tab2:
|
136 |
+
for message in st.session_state.messages:
|
137 |
+
with st.chat_message(message["role"]):
|
138 |
+
st.markdown(message["content"])
|
139 |
+
|
140 |
+
def handle_voice_input(model_choice):
|
141 |
+
"""Handle voice input tab logic"""
|
142 |
+
st.subheader("Voice Recognition")
|
143 |
+
if 'voice_transcript' not in st.session_state:
|
144 |
+
st.session_state.voice_transcript = ""
|
145 |
|
146 |
+
user_input = st.text_area("Message:", height=100)
|
147 |
+
if st.button("Send π¨") and user_input:
|
148 |
+
process_ai_input(user_input, model_choice)
|
149 |
|
150 |
+
show_chat_history()
|
151 |
+
|
152 |
+
def handle_file_editor():
|
153 |
+
"""Handle file editor tab logic"""
|
154 |
+
if st.session_state.current_file:
|
155 |
+
st.subheader(f"Editing: {st.session_state.current_file}")
|
156 |
+
new_content = st.text_area("Content:", st.session_state.file_content, height=300)
|
157 |
+
if st.button("Save Changes"):
|
158 |
+
with open(st.session_state.current_file, 'w', encoding='utf-8') as file:
|
159 |
+
file.write(new_content)
|
160 |
+
st.success("File updated successfully!")
|
161 |
+
|
162 |
+
def process_ai_input(user_input, model_choice):
|
163 |
+
"""Handle AI processing based on model choice"""
|
164 |
+
if model_choice == "GPT-4o":
|
165 |
+
gpt_response = process_with_gpt(user_input)
|
166 |
+
elif model_choice == "Claude-3":
|
167 |
+
claude_response = process_with_claude(user_input)
|
168 |
+
else: # All Three AIs
|
169 |
+
col1, col2, col3 = st.columns(3)
|
|
|
|
|
|
|
|
|
170 |
with col2:
|
171 |
+
st.subheader("Claude-3.5 Sonnet:")
|
172 |
+
try:
|
173 |
+
claude_response = process_with_claude(user_input)
|
174 |
+
except:
|
175 |
+
st.write('Claude 3.5 Sonnet out of tokens.')
|
176 |
+
with col1:
|
177 |
+
st.subheader("GPT-4o Omni:")
|
178 |
+
try:
|
179 |
+
gpt_response = process_with_gpt(user_input)
|
180 |
+
except:
|
181 |
+
st.write('GPT 4o out of tokens')
|
182 |
with col3:
|
183 |
+
st.subheader("Arxiv and Mistral Research:")
|
184 |
+
with st.spinner("Searching ArXiv..."):
|
185 |
+
try:
|
186 |
+
results = perform_ai_lookup(user_input)
|
187 |
+
st.markdown(results)
|
188 |
+
except:
|
189 |
+
st.write("Arxiv Mistral too busy - try again.")
|
190 |
+
|
191 |
+
def handle_arxiv_search():
|
192 |
+
"""Handle ArXiv search tab logic"""
|
193 |
+
query = st.text_input("Enter your research query:")
|
194 |
+
if query:
|
195 |
+
with st.spinner("Searching ArXiv..."):
|
196 |
+
results = search_arxiv(query)
|
197 |
+
st.markdown(results)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
198 |
|
199 |
def main():
|
200 |
+
st.sidebar.markdown("### π²BikeAIπ Claude and GPT Multi-Agent Research AI")
|
|
|
201 |
|
202 |
+
# Display file manager in sidebar first
|
203 |
+
display_file_manager()
|
204 |
|
205 |
+
# Model Selection
|
206 |
+
model_choice = st.sidebar.radio(
|
207 |
+
"Choose AI Model:",
|
208 |
+
["GPT+Claude+Arxiv", "GPT-4o", "Claude-3"]
|
209 |
+
)
|
210 |
|
211 |
+
# Main navigation
|
212 |
+
tab_main = st.radio("Choose Action:",
|
213 |
+
["π€ Voice Input", "πΈ Media Gallery", "π Search ArXiv", "π File Editor"],
|
214 |
+
horizontal=True)
|
215 |
+
|
216 |
+
try:
|
217 |
+
# Component Magic section - wrapped in try/except in case component isn't available
|
218 |
+
mycomponent = components.declare_component("mycomponent", path="mycomponent")
|
219 |
+
value = mycomponent(my_input_value="hello there")
|
220 |
+
st.write("Received", value)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
221 |
|
222 |
+
if value is not None:
|
223 |
+
process_ai_input(value, model_choice)
|
224 |
+
except:
|
225 |
+
st.warning("Voice component not available")
|
226 |
+
|
227 |
+
# Handle main tab navigation
|
228 |
+
if tab_main == "π€ Voice Input":
|
229 |
+
handle_voice_input(model_choice)
|
230 |
+
elif tab_main == "πΈ Media Gallery":
|
231 |
+
create_media_gallery()
|
232 |
+
elif tab_main == "π Search ArXiv":
|
233 |
+
handle_arxiv_search()
|
234 |
+
elif tab_main == "π File Editor":
|
235 |
+
handle_file_editor()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
236 |
|
237 |
if __name__ == "__main__":
|
238 |
main()
|