awacke1 commited on
Commit
110ed23
β€’
1 Parent(s): e5e0dd6

Create backup10.app.py

Browse files
Files changed (1) hide show
  1. backup10.app.py +1054 -0
backup10.app.py ADDED
@@ -0,0 +1,1054 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import streamlit.components.v1 as components
3
+ import anthropic
4
+ import openai
5
+ import base64
6
+ from datetime import datetime
7
+ import plotly.graph_objects as go
8
+ import cv2
9
+ import glob
10
+ import json
11
+ import math
12
+ import os
13
+ import pytz
14
+ import random
15
+ import re
16
+ import requests
17
+ import textract
18
+ import time
19
+ import zipfile
20
+ from audio_recorder_streamlit import audio_recorder
21
+ from bs4 import BeautifulSoup
22
+ from collections import deque
23
+ from dotenv import load_dotenv
24
+ from gradio_client import Client
25
+ from huggingface_hub import InferenceClient
26
+ from io import BytesIO
27
+ from PIL import Image
28
+ from PyPDF2 import PdfReader
29
+ from urllib.parse import quote
30
+ from xml.etree import ElementTree as ET
31
+ from openai import OpenAI
32
+ import extra_streamlit_components as stx
33
+ from streamlit.runtime.scriptrunner import get_script_run_ctx
34
+ import extra_streamlit_components as stx
35
+
36
+
37
+ # 1. 🚲BikeAIπŸ† Configuration and Setup
38
+ Site_Name = '🚲BikeAIπŸ† Claude and GPT Multi-Agent Research AI'
39
+ title = "🚲BikeAIπŸ† Claude and GPT Multi-Agent Research AI"
40
+ helpURL = 'https://huggingface.co/awacke1'
41
+ bugURL = 'https://huggingface.co/spaces/awacke1'
42
+ icons = 'πŸš²πŸ†'
43
+
44
+ st.set_page_config(
45
+ page_title=title,
46
+ page_icon=icons,
47
+ layout="wide",
48
+ initial_sidebar_state="auto",
49
+ menu_items={
50
+ 'Get Help': helpURL,
51
+ 'Report a bug': bugURL,
52
+ 'About': title
53
+ }
54
+ )
55
+
56
+
57
+
58
+ def create_speech_component():
59
+ """Create speech recognition component using postMessage for communication."""
60
+
61
+ speech_recognition_html = """
62
+ <div style="padding: 20px;">
63
+ <div class="controls">
64
+ <button id="start">Start Listening</button>
65
+ <button id="stop" disabled>Stop Listening</button>
66
+ <button id="clear">Clear Text</button>
67
+ </div>
68
+ <div id="status" style="margin: 10px 0; padding: 10px; background: #e8f5e9;">Ready</div>
69
+ <div id="output" style="white-space: pre-wrap; padding: 15px; background: #f5f5f5; min-height: 100px; max-height: 400px; overflow-y: auto;"></div>
70
+ <div id="debug" style="margin-top: 10px; color: #666;"></div>
71
+
72
+ <script>
73
+ let currentTranscript = '';
74
+ const debug = document.getElementById('debug');
75
+
76
+ function sendTranscriptUpdate() {
77
+ // Send transcript to parent (Streamlit)
78
+ window.parent.postMessage({
79
+ type: 'transcript_update',
80
+ data: currentTranscript
81
+ }, '*');
82
+ debug.textContent = `Last update: ${new Date().toLocaleTimeString()} - Length: ${currentTranscript.length}`;
83
+ }
84
+
85
+ // Set up periodic updates
86
+ setInterval(sendTranscriptUpdate, 3000); // Send update every 3 seconds
87
+
88
+ const recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
89
+ const startButton = document.getElementById('start');
90
+ const stopButton = document.getElementById('stop');
91
+ const clearButton = document.getElementById('clear');
92
+ const status = document.getElementById('status');
93
+ const output = document.getElementById('output');
94
+
95
+ recognition.continuous = true;
96
+ recognition.interimResults = true;
97
+
98
+ startButton.onclick = () => {
99
+ recognition.start();
100
+ status.textContent = '🎀 Listening...';
101
+ startButton.disabled = true;
102
+ stopButton.disabled = false;
103
+ };
104
+
105
+ stopButton.onclick = () => {
106
+ recognition.stop();
107
+ status.textContent = 'Stopped';
108
+ startButton.disabled = false;
109
+ stopButton.disabled = true;
110
+ sendTranscriptUpdate(); // Send final update when stopped
111
+ };
112
+
113
+ clearButton.onclick = () => {
114
+ currentTranscript = '';
115
+ output.textContent = '';
116
+ sendTranscriptUpdate(); // Send empty transcript
117
+ };
118
+
119
+ recognition.onresult = (event) => {
120
+ let interimTranscript = '';
121
+ let finalTranscript = '';
122
+
123
+ for (let i = event.resultIndex; i < event.results.length; i++) {
124
+ const transcript = event.results[i][0].transcript;
125
+ if (event.results[i].isFinal) {
126
+ finalTranscript += transcript + ' ';
127
+ currentTranscript += transcript + ' ';
128
+ } else {
129
+ interimTranscript += transcript;
130
+ }
131
+ }
132
+
133
+ output.textContent = currentTranscript + (interimTranscript ? '... ' + interimTranscript : '');
134
+ output.scrollTop = output.scrollHeight;
135
+
136
+ if (finalTranscript) {
137
+ sendTranscriptUpdate(); // Send update when we have final transcript
138
+ }
139
+ };
140
+
141
+ recognition.onend = () => {
142
+ if (!stopButton.disabled) {
143
+ recognition.start();
144
+ }
145
+ };
146
+
147
+ // Auto-start on load
148
+ window.addEventListener('load', () => {
149
+ setTimeout(() => startButton.click(), 1000);
150
+ });
151
+ </script>
152
+ </div>
153
+ """
154
+
155
+ # Return both the component value
156
+ return components.html(
157
+ speech_recognition_html,
158
+ height=400,
159
+ )
160
+
161
+ def integrate_speech_component():
162
+ """Integrate speech component with session state management."""
163
+ if "voice_transcript" not in st.session_state:
164
+ st.session_state.voice_transcript = ""
165
+ if "last_update" not in st.session_state:
166
+ st.session_state.last_update = time.time()
167
+
168
+ # Create placeholders for display
169
+ transcript_container = st.empty()
170
+ status_container = st.empty()
171
+
172
+ # Create component
173
+ component_val = create_speech_component()
174
+
175
+ # Display current transcript
176
+ current_transcript = st.session_state.voice_transcript
177
+ transcript_container.text_area(
178
+ "Voice Transcript:",
179
+ value=current_transcript,
180
+ height=100,
181
+ key=f"transcript_display_{int(time.time())}"
182
+ )
183
+
184
+ # Show status
185
+ status_container.text(
186
+ f"Last updated: {datetime.fromtimestamp(st.session_state.last_update).strftime('%H:%M:%S')}"
187
+ )
188
+
189
+ return current_transcript
190
+
191
+
192
+
193
+
194
+
195
+
196
+ # 2. 🚲BikeAIπŸ† Load environment variables and initialize clients
197
+ load_dotenv()
198
+
199
+ # OpenAI setup
200
+ openai.api_key = os.getenv('OPENAI_API_KEY')
201
+ if openai.api_key == None:
202
+ openai.api_key = st.secrets['OPENAI_API_KEY']
203
+
204
+ openai_client = OpenAI(
205
+ api_key=os.getenv('OPENAI_API_KEY'),
206
+ organization=os.getenv('OPENAI_ORG_ID')
207
+ )
208
+
209
+ # 3.🚲BikeAIπŸ† Claude setup
210
+ anthropic_key = os.getenv("ANTHROPIC_API_KEY_3")
211
+ if anthropic_key == None:
212
+ anthropic_key = st.secrets["ANTHROPIC_API_KEY"]
213
+ claude_client = anthropic.Anthropic(api_key=anthropic_key)
214
+
215
+ # 4.🚲BikeAIπŸ† Initialize session states
216
+ if 'transcript_history' not in st.session_state:
217
+ st.session_state.transcript_history = []
218
+ if "chat_history" not in st.session_state:
219
+ st.session_state.chat_history = []
220
+ if "openai_model" not in st.session_state:
221
+ st.session_state["openai_model"] = "gpt-4o-2024-05-13"
222
+ if "messages" not in st.session_state:
223
+ st.session_state.messages = []
224
+ if 'last_voice_input' not in st.session_state:
225
+ st.session_state.last_voice_input = ""
226
+
227
+ # 5. 🚲BikeAIπŸ† HuggingFace AI setup
228
+ API_URL = os.getenv('API_URL')
229
+ HF_KEY = os.getenv('HF_KEY')
230
+ MODEL1 = "meta-llama/Llama-2-7b-chat-hf"
231
+ MODEL2 = "openai/whisper-small.en"
232
+ headers = {
233
+ "Authorization": f"Bearer {HF_KEY}",
234
+ "Content-Type": "application/json"
235
+ }
236
+
237
+ # 6. 🚲BikeAIπŸ† Custom CSS
238
+ st.markdown("""
239
+ <style>
240
+ .main {
241
+ background: linear-gradient(to right, #1a1a1a, #2d2d2d);
242
+ color: #ffffff;
243
+ }
244
+ .stMarkdown {
245
+ font-family: 'Helvetica Neue', sans-serif;
246
+ }
247
+ .category-header {
248
+ background: linear-gradient(45deg, #2b5876, #4e4376);
249
+ padding: 20px;
250
+ border-radius: 10px;
251
+ margin: 10px 0;
252
+ }
253
+ .scene-card {
254
+ background: rgba(0,0,0,0.3);
255
+ padding: 15px;
256
+ border-radius: 8px;
257
+ margin: 10px 0;
258
+ border: 1px solid rgba(255,255,255,0.1);
259
+ }
260
+ .media-gallery {
261
+ display: grid;
262
+ gap: 1rem;
263
+ padding: 1rem;
264
+ }
265
+ .bike-card {
266
+ background: rgba(255,255,255,0.05);
267
+ border-radius: 10px;
268
+ padding: 15px;
269
+ transition: transform 0.3s;
270
+ }
271
+ .bike-card:hover {
272
+ transform: scale(1.02);
273
+ }
274
+ </style>
275
+ """, unsafe_allow_html=True)
276
+
277
+
278
+ # 7. Helper Functions
279
+ def generate_filename(prompt, file_type):
280
+ """Generate a safe filename using the prompt and file type."""
281
+ central = pytz.timezone('US/Central')
282
+ safe_date_time = datetime.now(central).strftime("%m%d_%H%M")
283
+ replaced_prompt = re.sub(r'[<>:"/\\|?*\n]', ' ', prompt)
284
+ safe_prompt = re.sub(r'\s+', ' ', replaced_prompt).strip()[:230]
285
+ return f"{safe_date_time}_{safe_prompt}.{file_type}"
286
+
287
+
288
+
289
+
290
+ # 8. Function to create and save a file (and avoid the black hole of lost data πŸ•³)
291
+ def create_file(filename, prompt, response, should_save=True):
292
+ if not should_save:
293
+ return
294
+ with open(filename, 'w', encoding='utf-8') as file:
295
+ file.write(prompt + "\n\n" + response)
296
+ def create_and_save_file(content, file_type="md", prompt=None, is_image=False, should_save=True):
297
+ """Create and save file with proper handling of different types."""
298
+ if not should_save:
299
+ return None
300
+ filename = generate_filename(prompt if prompt else content, file_type)
301
+ with open(filename, "w", encoding="utf-8") as f:
302
+ if is_image:
303
+ f.write(content)
304
+ else:
305
+ f.write(prompt + "\n\n" + content if prompt else content)
306
+ return filename
307
+
308
+
309
+ def get_download_link(file_path):
310
+ """Create download link for file."""
311
+ with open(file_path, "rb") as file:
312
+ contents = file.read()
313
+ b64 = base64.b64encode(contents).decode()
314
+ return f'<a href="data:file/txt;base64,{b64}" download="{os.path.basename(file_path)}">Download {os.path.basename(file_path)}πŸ“‚</a>'
315
+
316
+ @st.cache_resource
317
+ def SpeechSynthesis(result):
318
+ """HTML5 Speech Synthesis."""
319
+ documentHTML5 = f'''
320
+ <!DOCTYPE html>
321
+ <html>
322
+ <head>
323
+ <title>Read It Aloud</title>
324
+ <script type="text/javascript">
325
+ function readAloud() {{
326
+ const text = document.getElementById("textArea").value;
327
+ const speech = new SpeechSynthesisUtterance(text);
328
+ window.speechSynthesis.speak(speech);
329
+ }}
330
+ </script>
331
+ </head>
332
+ <body>
333
+ <h1>πŸ”Š Read It Aloud</h1>
334
+ <textarea id="textArea" rows="10" cols="80">{result}</textarea>
335
+ <br>
336
+ <button onclick="readAloud()">πŸ”Š Read Aloud</button>
337
+ </body>
338
+ </html>
339
+ '''
340
+ components.html(documentHTML5, width=1280, height=300)
341
+
342
+ # Media Processing Functions
343
+ def process_image(image_input, user_prompt):
344
+ """Process image with GPT-4o vision."""
345
+ if isinstance(image_input, str):
346
+ with open(image_input, "rb") as image_file:
347
+ image_input = image_file.read()
348
+
349
+ base64_image = base64.b64encode(image_input).decode("utf-8")
350
+
351
+ response = openai_client.chat.completions.create(
352
+ model=st.session_state["openai_model"],
353
+ messages=[
354
+ {"role": "system", "content": "You are a helpful assistant that responds in Markdown."},
355
+ {"role": "user", "content": [
356
+ {"type": "text", "text": user_prompt},
357
+ {"type": "image_url", "image_url": {
358
+ "url": f"data:image/png;base64,{base64_image}"
359
+ }}
360
+ ]}
361
+ ],
362
+ temperature=0.0,
363
+ )
364
+
365
+ return response.choices[0].message.content
366
+
367
+ def process_audio(audio_input, text_input=''):
368
+ """Process audio with Whisper and GPT."""
369
+ if isinstance(audio_input, str):
370
+ with open(audio_input, "rb") as file:
371
+ audio_input = file.read()
372
+
373
+ transcription = openai_client.audio.transcriptions.create(
374
+ model="whisper-1",
375
+ file=audio_input,
376
+ )
377
+
378
+ st.session_state.messages.append({"role": "user", "content": transcription.text})
379
+
380
+ with st.chat_message("assistant"):
381
+ st.markdown(transcription.text)
382
+ SpeechSynthesis(transcription.text)
383
+
384
+ filename = generate_filename(transcription.text, "wav")
385
+ create_and_save_file(audio_input, "wav", transcription.text, True)
386
+
387
+ # Modified video processing function without moviepy dependency
388
+ def process_video(video_path, seconds_per_frame=1):
389
+ """Process video files for frame extraction."""
390
+ base64Frames = []
391
+ video = cv2.VideoCapture(video_path)
392
+ total_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
393
+ fps = video.get(cv2.CAP_PROP_FPS)
394
+ frames_to_skip = int(fps * seconds_per_frame)
395
+
396
+ for frame_idx in range(0, total_frames, frames_to_skip):
397
+ video.set(cv2.CAP_PROP_POS_FRAMES, frame_idx)
398
+ success, frame = video.read()
399
+ if not success:
400
+ break
401
+ _, buffer = cv2.imencode(".jpg", frame)
402
+ base64Frames.append(base64.b64encode(buffer).decode("utf-8"))
403
+
404
+ video.release()
405
+ return base64Frames, None
406
+
407
+ def process_video_with_gpt(video_input, user_prompt):
408
+ """Process video with GPT-4 vision."""
409
+ base64Frames, _ = process_video(video_input)
410
+
411
+ response = openai_client.chat.completions.create(
412
+ model=st.session_state["openai_model"],
413
+ messages=[
414
+ {"role": "system", "content": "Analyze the video frames and provide a detailed description."},
415
+ {"role": "user", "content": [
416
+ {"type": "text", "text": user_prompt},
417
+ *[{"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{frame}"}}
418
+ for frame in base64Frames]
419
+ ]}
420
+ ]
421
+ )
422
+ return response.choices[0].message.content
423
+
424
+
425
+ def extract_urls(text):
426
+ try:
427
+ date_pattern = re.compile(r'### (\d{2} \w{3} \d{4})')
428
+ abs_link_pattern = re.compile(r'\[(.*?)\]\((https://arxiv\.org/abs/\d+\.\d+)\)')
429
+ pdf_link_pattern = re.compile(r'\[⬇️\]\((https://arxiv\.org/pdf/\d+\.\d+)\)')
430
+ title_pattern = re.compile(r'### \d{2} \w{3} \d{4} \| \[(.*?)\]')
431
+ date_matches = date_pattern.findall(text)
432
+ abs_link_matches = abs_link_pattern.findall(text)
433
+ pdf_link_matches = pdf_link_pattern.findall(text)
434
+ title_matches = title_pattern.findall(text)
435
+
436
+ # markdown with the extracted fields
437
+ markdown_text = ""
438
+ for i in range(len(date_matches)):
439
+ date = date_matches[i]
440
+ title = title_matches[i]
441
+ abs_link = abs_link_matches[i][1]
442
+ pdf_link = pdf_link_matches[i]
443
+ markdown_text += f"**Date:** {date}\n\n"
444
+ markdown_text += f"**Title:** {title}\n\n"
445
+ markdown_text += f"**Abstract Link:** [{abs_link}]({abs_link})\n\n"
446
+ markdown_text += f"**PDF Link:** [{pdf_link}]({pdf_link})\n\n"
447
+ markdown_text += "---\n\n"
448
+ return markdown_text
449
+
450
+ except:
451
+ st.write('.')
452
+ return ''
453
+
454
+
455
+ def search_arxiv(query):
456
+
457
+ st.write("Performing AI Lookup...")
458
+ client = Client("awacke1/Arxiv-Paper-Search-And-QA-RAG-Pattern")
459
+
460
+ result1 = client.predict(
461
+ prompt=query,
462
+ llm_model_picked="mistralai/Mixtral-8x7B-Instruct-v0.1",
463
+ stream_outputs=True,
464
+ api_name="/ask_llm"
465
+ )
466
+ st.markdown("### Mixtral-8x7B-Instruct-v0.1 Result")
467
+ st.markdown(result1)
468
+
469
+ result2 = client.predict(
470
+ prompt=query,
471
+ llm_model_picked="mistralai/Mistral-7B-Instruct-v0.2",
472
+ stream_outputs=True,
473
+ api_name="/ask_llm"
474
+ )
475
+ st.markdown("### Mistral-7B-Instruct-v0.2 Result")
476
+ st.markdown(result2)
477
+ combined_result = f"{result1}\n\n{result2}"
478
+ return combined_result
479
+
480
+ #return responseall
481
+
482
+
483
+ # Function to generate a filename based on prompt and time (because names matter πŸ•’)
484
+ def generate_filename(prompt, file_type):
485
+ central = pytz.timezone('US/Central')
486
+ safe_date_time = datetime.now(central).strftime("%m%d_%H%M")
487
+ safe_prompt = re.sub(r'\W+', '_', prompt)[:90]
488
+ return f"{safe_date_time}_{safe_prompt}.{file_type}"
489
+
490
+ # Function to create and save a file (and avoid the black hole of lost data πŸ•³)
491
+ def create_file(filename, prompt, response):
492
+ with open(filename, 'w', encoding='utf-8') as file:
493
+ file.write(prompt + "\n\n" + response)
494
+
495
+
496
+ def perform_ai_lookup(query):
497
+ start_time = time.strftime("%Y-%m-%d %H:%M:%S")
498
+ client = Client("awacke1/Arxiv-Paper-Search-And-QA-RAG-Pattern")
499
+ response1 = client.predict(
500
+ query,
501
+ 20,
502
+ "Semantic Search",
503
+ "mistralai/Mixtral-8x7B-Instruct-v0.1",
504
+ api_name="/update_with_rag_md"
505
+ )
506
+ Question = '### πŸ”Ž ' + query + '\r\n' # Format for markdown display with links
507
+ References = response1[0]
508
+ ReferenceLinks = extract_urls(References)
509
+
510
+ RunSecondQuery = True
511
+ results=''
512
+ if RunSecondQuery:
513
+ # Search 2 - Retrieve the Summary with Papers Context and Original Query
514
+ response2 = client.predict(
515
+ query,
516
+ "mistralai/Mixtral-8x7B-Instruct-v0.1",
517
+ True,
518
+ api_name="/ask_llm"
519
+ )
520
+ if len(response2) > 10:
521
+ Answer = response2
522
+ SpeechSynthesis(Answer)
523
+ # Restructure results to follow format of Question, Answer, References, ReferenceLinks
524
+ results = Question + '\r\n' + Answer + '\r\n' + References + '\r\n' + ReferenceLinks
525
+ st.markdown(results)
526
+
527
+ st.write('πŸ”Run of Multi-Agent System Paper Summary Spec is Complete')
528
+ end_time = time.strftime("%Y-%m-%d %H:%M:%S")
529
+ start_timestamp = time.mktime(time.strptime(start_time, "%Y-%m-%d %H:%M:%S"))
530
+ end_timestamp = time.mktime(time.strptime(end_time, "%Y-%m-%d %H:%M:%S"))
531
+ elapsed_seconds = end_timestamp - start_timestamp
532
+ st.write(f"Start time: {start_time}")
533
+ st.write(f"Finish time: {end_time}")
534
+ st.write(f"Elapsed time: {elapsed_seconds:.2f} seconds")
535
+
536
+
537
+ filename = generate_filename(query, "md")
538
+ create_file(filename, query, results)
539
+ return results
540
+
541
+ # Chat Processing Functions
542
+ def process_with_gpt(text_input):
543
+ """Process text with GPT-4o."""
544
+ if text_input:
545
+ st.session_state.messages.append({"role": "user", "content": text_input})
546
+
547
+ with st.chat_message("user"):
548
+ st.markdown(text_input)
549
+
550
+ with st.chat_message("assistant"):
551
+ completion = openai_client.chat.completions.create(
552
+ model=st.session_state["openai_model"],
553
+ messages=[
554
+ {"role": m["role"], "content": m["content"]}
555
+ for m in st.session_state.messages
556
+ ],
557
+ stream=False
558
+ )
559
+ return_text = completion.choices[0].message.content
560
+ st.write("GPT-4o: " + return_text)
561
+
562
+ #filename = generate_filename(text_input, "md")
563
+ filename = generate_filename("GPT-4o: " + return_text, "md")
564
+ create_file(filename, text_input, return_text)
565
+ st.session_state.messages.append({"role": "assistant", "content": return_text})
566
+ return return_text
567
+
568
+ def process_with_claude(text_input):
569
+ """Process text with Claude."""
570
+ if text_input:
571
+
572
+ with st.chat_message("user"):
573
+ st.markdown(text_input)
574
+
575
+ with st.chat_message("assistant"):
576
+ response = claude_client.messages.create(
577
+ model="claude-3-sonnet-20240229",
578
+ max_tokens=1000,
579
+ messages=[
580
+ {"role": "user", "content": text_input}
581
+ ]
582
+ )
583
+ response_text = response.content[0].text
584
+ st.write("Claude: " + response_text)
585
+
586
+ #filename = generate_filename(text_input, "md")
587
+ filename = generate_filename("Claude: " + response_text, "md")
588
+ create_file(filename, text_input, response_text)
589
+
590
+ st.session_state.chat_history.append({
591
+ "user": text_input,
592
+ "claude": response_text
593
+ })
594
+ return response_text
595
+
596
+ # File Management Functions
597
+ def load_file(file_name):
598
+ """Load file content."""
599
+ with open(file_name, "r", encoding='utf-8') as file:
600
+ content = file.read()
601
+ return content
602
+
603
+ def create_zip_of_files(files):
604
+ """Create zip archive of files."""
605
+ zip_name = "all_files.zip"
606
+ with zipfile.ZipFile(zip_name, 'w') as zipf:
607
+ for file in files:
608
+ zipf.write(file)
609
+ return zip_name
610
+
611
+
612
+
613
+ def get_media_html(media_path, media_type="video", width="100%"):
614
+ """Generate HTML for media player."""
615
+ media_data = base64.b64encode(open(media_path, 'rb').read()).decode()
616
+ if media_type == "video":
617
+ return f'''
618
+ <video width="{width}" controls autoplay muted loop>
619
+ <source src="data:video/mp4;base64,{media_data}" type="video/mp4">
620
+ Your browser does not support the video tag.
621
+ </video>
622
+ '''
623
+ else: # audio
624
+ return f'''
625
+ <audio controls style="width: {width};">
626
+ <source src="data:audio/mpeg;base64,{media_data}" type="audio/mpeg">
627
+ Your browser does not support the audio element.
628
+ </audio>
629
+ '''
630
+
631
+ def create_media_gallery():
632
+ """Create the media gallery interface."""
633
+ st.header("🎬 Media Gallery")
634
+
635
+ tabs = st.tabs(["πŸ–ΌοΈ Images", "🎡 Audio", "πŸŽ₯ Video"])
636
+
637
+ with tabs[0]:
638
+ image_files = glob.glob("*.png") + glob.glob("*.jpg")
639
+ if image_files:
640
+ num_cols = st.slider("Number of columns", 1, 5, 3)
641
+ cols = st.columns(num_cols)
642
+ for idx, image_file in enumerate(image_files):
643
+ with cols[idx % num_cols]:
644
+ img = Image.open(image_file)
645
+ st.image(img, use_container_width=True)
646
+
647
+ # Add GPT vision analysis option
648
+ if st.button(f"Analyze {os.path.basename(image_file)}"):
649
+ analysis = process_image(image_file,
650
+ "Describe this image in detail and identify key elements.")
651
+ st.markdown(analysis)
652
+
653
+ with tabs[1]:
654
+ audio_files = glob.glob("*.mp3") + glob.glob("*.wav")
655
+ for audio_file in audio_files:
656
+ with st.expander(f"🎡 {os.path.basename(audio_file)}"):
657
+ st.markdown(get_media_html(audio_file, "audio"), unsafe_allow_html=True)
658
+ if st.button(f"Transcribe {os.path.basename(audio_file)}"):
659
+ with open(audio_file, "rb") as f:
660
+ transcription = process_audio(f)
661
+ st.write(transcription)
662
+
663
+ with tabs[2]:
664
+ video_files = glob.glob("*.mp4")
665
+ for video_file in video_files:
666
+ with st.expander(f"πŸŽ₯ {os.path.basename(video_file)}"):
667
+ st.markdown(get_media_html(video_file, "video"), unsafe_allow_html=True)
668
+ if st.button(f"Analyze {os.path.basename(video_file)}"):
669
+ analysis = process_video_with_gpt(video_file,
670
+ "Describe what's happening in this video.")
671
+ st.markdown(analysis)
672
+
673
+
674
+
675
+ def display_file_manager():
676
+ """Display file management sidebar with guaranteed unique button keys."""
677
+ st.sidebar.title("πŸ“ File Management")
678
+
679
+ all_files = glob.glob("*.md")
680
+ all_files.sort(reverse=True)
681
+
682
+ if st.sidebar.button("πŸ—‘ Delete All", key="delete_all_files_button"):
683
+ for file in all_files:
684
+ os.remove(file)
685
+ st.rerun()
686
+
687
+ if st.sidebar.button("⬇️ Download All", key="download_all_files_button"):
688
+ zip_file = create_zip_of_files(all_files)
689
+ st.sidebar.markdown(get_download_link(zip_file), unsafe_allow_html=True)
690
+
691
+ # Create unique keys using file attributes
692
+ for idx, file in enumerate(all_files):
693
+ # Get file stats for unique identification
694
+ file_stat = os.stat(file)
695
+ unique_id = f"{idx}_{file_stat.st_size}_{file_stat.st_mtime}"
696
+
697
+ col1, col2, col3, col4 = st.sidebar.columns([1,3,1,1])
698
+ with col1:
699
+ if st.button("🌐", key=f"view_{unique_id}"):
700
+ st.session_state.current_file = file
701
+ st.session_state.file_content = load_file(file)
702
+ with col2:
703
+ st.markdown(get_download_link(file), unsafe_allow_html=True)
704
+ with col3:
705
+ if st.button("πŸ“‚", key=f"edit_{unique_id}"):
706
+ st.session_state.current_file = file
707
+ st.session_state.file_content = load_file(file)
708
+ with col4:
709
+ if st.button("πŸ—‘", key=f"delete_{unique_id}"):
710
+ os.remove(file)
711
+ st.rerun()
712
+
713
+
714
+
715
+
716
+ # Speech Recognition HTML Component
717
+ speech_recognition_html = """
718
+ <!DOCTYPE html>
719
+ <html>
720
+ <head>
721
+ <title>Continuous Speech Demo</title>
722
+ <style>
723
+ body {
724
+ font-family: sans-serif;
725
+ padding: 20px;
726
+ max-width: 800px;
727
+ margin: 0 auto;
728
+ }
729
+ button {
730
+ padding: 10px 20px;
731
+ margin: 10px 5px;
732
+ font-size: 16px;
733
+ }
734
+ #status {
735
+ margin: 10px 0;
736
+ padding: 10px;
737
+ background: #e8f5e9;
738
+ border-radius: 4px;
739
+ }
740
+ #output {
741
+ white-space: pre-wrap;
742
+ padding: 15px;
743
+ background: #f5f5f5;
744
+ border-radius: 4px;
745
+ margin: 10px 0;
746
+ min-height: 100px;
747
+ max-height: 400px;
748
+ overflow-y: auto;
749
+ }
750
+ .controls {
751
+ margin: 10px 0;
752
+ }
753
+ </style>
754
+ </head>
755
+ <body>
756
+ <div class="controls">
757
+ <button id="start">Start Listening</button>
758
+ <button id="stop" disabled>Stop Listening</button>
759
+ <button id="clear">Clear Text</button>
760
+ </div>
761
+ <div id="status">Ready</div>
762
+ <div id="output"></div>
763
+
764
+ <!-- Add the hidden input here -->
765
+ <input type="hidden" id="streamlit-data" value="">
766
+
767
+ <script>
768
+ if (!('webkitSpeechRecognition' in window)) {
769
+ alert('Speech recognition not supported');
770
+ } else {
771
+ const recognition = new webkitSpeechRecognition();
772
+ const startButton = document.getElementById('start');
773
+ const stopButton = document.getElementById('stop');
774
+ const clearButton = document.getElementById('clear');
775
+ const status = document.getElementById('status');
776
+ const output = document.getElementById('output');
777
+ let fullTranscript = '';
778
+ let lastUpdateTime = Date.now();
779
+
780
+ // Configure recognition
781
+ recognition.continuous = true;
782
+ recognition.interimResults = true;
783
+
784
+ // Function to start recognition
785
+ const startRecognition = () => {
786
+ try {
787
+ recognition.start();
788
+ status.textContent = 'Listening...';
789
+ startButton.disabled = true;
790
+ stopButton.disabled = false;
791
+ } catch (e) {
792
+ console.error(e);
793
+ status.textContent = 'Error: ' + e.message;
794
+ }
795
+ };
796
+
797
+ // Auto-start on load
798
+ window.addEventListener('load', () => {
799
+ setTimeout(startRecognition, 1000);
800
+ });
801
+
802
+ startButton.onclick = startRecognition;
803
+
804
+ stopButton.onclick = () => {
805
+ recognition.stop();
806
+ status.textContent = 'Stopped';
807
+ startButton.disabled = false;
808
+ stopButton.disabled = true;
809
+ };
810
+
811
+ clearButton.onclick = () => {
812
+ fullTranscript = '';
813
+ output.textContent = '';
814
+ window.parent.postMessage({
815
+ type: 'clear_transcript',
816
+ }, '*');
817
+ };
818
+
819
+ recognition.onresult = (event) => {
820
+ let interimTranscript = '';
821
+ let finalTranscript = '';
822
+
823
+ for (let i = event.resultIndex; i < event.results.length; i++) {
824
+ const transcript = event.results[i][0].transcript;
825
+ if (event.results[i].isFinal) {
826
+ finalTranscript += transcript + '\\n';
827
+ } else {
828
+ interimTranscript += transcript;
829
+ }
830
+ }
831
+
832
+ if (finalTranscript || (Date.now() - lastUpdateTime > 5000)) {
833
+ if (finalTranscript) {
834
+ fullTranscript += finalTranscript;
835
+
836
+ // Update the hidden input value
837
+ document.getElementById('streamlit-data').value = fullTranscript;
838
+ }
839
+ lastUpdateTime = Date.now();
840
+ }
841
+
842
+ output.textContent = fullTranscript + (interimTranscript ? '... ' + interimTranscript : '');
843
+ output.scrollTop = output.scrollHeight;
844
+
845
+ document.getElementById('streamlit-data').value = fullTranscript;
846
+
847
+ };
848
+
849
+ recognition.onend = () => {
850
+ if (!stopButton.disabled) {
851
+ try {
852
+ recognition.start();
853
+ console.log('Restarted recognition');
854
+ } catch (e) {
855
+ console.error('Failed to restart recognition:', e);
856
+ status.textContent = 'Error restarting: ' + e.message;
857
+ startButton.disabled = false;
858
+ stopButton.disabled = true;
859
+ }
860
+ }
861
+ };
862
+
863
+ recognition.onerror = (event) => {
864
+ console.error('Recognition error:', event.error);
865
+ status.textContent = 'Error: ' + event.error;
866
+
867
+ if (event.error === 'not-allowed' || event.error === 'service-not-allowed') {
868
+ startButton.disabled = false;
869
+ stopButton.disabled = true;
870
+ }
871
+ };
872
+ }
873
+ </script>
874
+ </body>
875
+ </html>
876
+ """
877
+
878
+ # Helper Functions
879
+ def generate_filename(prompt, file_type):
880
+ central = pytz.timezone('US/Central')
881
+ safe_date_time = datetime.now(central).strftime("%m%d_%H%M")
882
+ replaced_prompt = re.sub(r'[<>:"/\\|?*\n]', ' ', prompt)
883
+ safe_prompt = re.sub(r'\s+', ' ', replaced_prompt).strip()[:230]
884
+ return f"{safe_date_time}_{safe_prompt}.{file_type}"
885
+
886
+ # File Management Functions
887
+ def load_file(file_name):
888
+ """Load file content."""
889
+ with open(file_name, "r", encoding='utf-8') as file:
890
+ content = file.read()
891
+ return content
892
+
893
+ def create_zip_of_files(files):
894
+ """Create zip archive of files."""
895
+ zip_name = "all_files.zip"
896
+ with zipfile.ZipFile(zip_name, 'w') as zipf:
897
+ for file in files:
898
+ zipf.write(file)
899
+ return zip_name
900
+
901
+ def get_download_link(file):
902
+ """Create download link for file."""
903
+ with open(file, "rb") as f:
904
+ contents = f.read()
905
+ b64 = base64.b64encode(contents).decode()
906
+ return f'<a href="data:file/txt;base64,{b64}" download="{os.path.basename(file)}">Download {os.path.basename(file)}πŸ“‚</a>'
907
+
908
+ def display_file_manager():
909
+ """Display file management sidebar."""
910
+ st.sidebar.title("πŸ“ File Management")
911
+
912
+ all_files = glob.glob("*.md")
913
+ all_files.sort(reverse=True)
914
+
915
+ if st.sidebar.button("πŸ—‘ Delete All"):
916
+ for file in all_files:
917
+ os.remove(file)
918
+ st.rerun()
919
+
920
+ if st.sidebar.button("⬇️ Download All"):
921
+ zip_file = create_zip_of_files(all_files)
922
+ st.sidebar.markdown(get_download_link(zip_file), unsafe_allow_html=True)
923
+
924
+ for file in all_files:
925
+ col1, col2, col3, col4 = st.sidebar.columns([1,3,1,1])
926
+ with col1:
927
+ if st.button("🌐", key="view_"+file):
928
+ st.session_state.current_file = file
929
+ st.session_state.file_content = load_file(file)
930
+ with col2:
931
+ st.markdown(get_download_link(file), unsafe_allow_html=True)
932
+ with col3:
933
+ if st.button("πŸ“‚", key="edit_"+file):
934
+ st.session_state.current_file = file
935
+ st.session_state.file_content = load_file(file)
936
+ with col4:
937
+ if st.button("πŸ—‘", key="delete_"+file):
938
+ os.remove(file)
939
+ st.rerun()
940
+
941
+ def create_media_gallery():
942
+ """Create the media gallery interface."""
943
+ st.header("🎬 Media Gallery")
944
+
945
+ tabs = st.tabs(["πŸ–ΌοΈ Images", "🎡 Audio", "πŸŽ₯ Video"])
946
+
947
+ with tabs[0]:
948
+ image_files = glob.glob("*.png") + glob.glob("*.jpg")
949
+ if image_files:
950
+ num_cols = st.slider("Number of columns", 1, 5, 3)
951
+ cols = st.columns(num_cols)
952
+ for idx, image_file in enumerate(image_files):
953
+ with cols[idx % num_cols]:
954
+ img = Image.open(image_file)
955
+ st.image(img, use_container_width=True)
956
+
957
+ # Add GPT vision analysis option
958
+ if st.button(f"Analyze {os.path.basename(image_file)}"):
959
+ analysis = process_image(image_file,
960
+ "Describe this image in detail and identify key elements.")
961
+ st.markdown(analysis)
962
+
963
+ with tabs[1]:
964
+ audio_files = glob.glob("*.mp3") + glob.glob("*.wav")
965
+ for audio_file in audio_files:
966
+ with st.expander(f"🎡 {os.path.basename(audio_file)}"):
967
+ st.markdown(get_media_html(audio_file, "audio"), unsafe_allow_html=True)
968
+ if st.button(f"Transcribe {os.path.basename(audio_file)}"):
969
+ with open(audio_file, "rb") as f:
970
+ transcription = process_audio(f)
971
+ st.write(transcription)
972
+
973
+ with tabs[2]:
974
+ video_files = glob.glob("*.mp4")
975
+ for video_file in video_files:
976
+ with st.expander(f"πŸŽ₯ {os.path.basename(video_file)}"):
977
+ st.markdown(get_media_html(video_file, "video"), unsafe_allow_html=True)
978
+ if st.button(f"Analyze {os.path.basename(video_file)}"):
979
+ analysis = process_video_with_gpt(video_file,
980
+ "Describe what's happening in this video.")
981
+ st.markdown(analysis)
982
+
983
+
984
+
985
+ def get_media_html(media_path, media_type="video", width="100%"):
986
+ """Generate HTML for media player."""
987
+ media_data = base64.b64encode(open(media_path, 'rb').read()).decode()
988
+ if media_type == "video":
989
+ return f'''
990
+ <video width="{width}" controls autoplay muted loop>
991
+ <source src="data:video/mp4;base64,{media_data}" type="video/mp4">
992
+ Your browser does not support the video tag.
993
+ </video>
994
+ '''
995
+ else: # audio
996
+ return f'''
997
+ <audio controls style="width: {width};">
998
+ <source src="data:audio/mpeg;base64,{media_data}" type="audio/mpeg">
999
+ Your browser does not support the audio element.
1000
+ </audio>
1001
+ '''
1002
+
1003
+ @st.cache_resource
1004
+ def set_transcript(text):
1005
+ """Set transcript in session state."""
1006
+ st.session_state.voice_transcript = text
1007
+ def main():
1008
+ st.sidebar.markdown("### 🚲BikeAIπŸ† Claude and GPT Multi-Agent Research AI")
1009
+
1010
+ tab_main = st.radio("Choose Action:",
1011
+ ["🎀 Voice Input", "πŸ’¬ Chat", "πŸ“Έ Media Gallery", "πŸ” Search ArXiv", "πŸ“ File Editor"],
1012
+ horizontal=True)
1013
+
1014
+ if tab_main == "🎀 Voice Input":
1015
+ st.subheader("Voice Recognition")
1016
+
1017
+ try:
1018
+ # Initialize speech component
1019
+ current_transcript = integrate_speech_component()
1020
+
1021
+ # Show last update time
1022
+ st.text(f"Last updated: {datetime.fromtimestamp(st.session_state.last_update).strftime('%H:%M:%S')}")
1023
+
1024
+ # Process buttons if we have a transcript
1025
+ if current_transcript:
1026
+ col1, col2, col3 = st.columns(3)
1027
+
1028
+ with col1:
1029
+ if st.button("Process with GPT"):
1030
+ with st.spinner("Processing with GPT..."):
1031
+ response = process_with_gpt(current_transcript)
1032
+ st.markdown(response)
1033
+
1034
+ with col2:
1035
+ if st.button("Process with Claude"):
1036
+ with st.spinner("Processing with Claude..."):
1037
+ response = process_with_claude(current_transcript)
1038
+ st.markdown(response)
1039
+
1040
+ with col3:
1041
+ if st.button("Search ArXiv"):
1042
+ with st.spinner("Searching ArXiv..."):
1043
+ results = perform_ai_lookup(current_transcript)
1044
+ st.markdown(results)
1045
+
1046
+ except Exception as e:
1047
+ st.error(f"Error in voice input: {str(e)}")
1048
+
1049
+
1050
+ # Always show file manager in sidebar
1051
+ display_file_manager()
1052
+
1053
+ if __name__ == "__main__":
1054
+ main()