Spaces:
Build error
Build error
Update app.py
Browse files
app.py
CHANGED
|
@@ -9,7 +9,6 @@ from io import BytesIO
|
|
| 9 |
from md2pdf.core import md2pdf
|
| 10 |
from dotenv import load_dotenv
|
| 11 |
from datetime import datetime
|
| 12 |
-
import backoff
|
| 13 |
import requests
|
| 14 |
from requests.exceptions import RequestException
|
| 15 |
from typing import Optional, Dict, Any
|
|
@@ -20,7 +19,7 @@ from st_audiorec import st_audiorec # Import the audio recorder component
|
|
| 20 |
MAX_FILE_SIZE = 41943040 # 40MB
|
| 21 |
FILE_TOO_LARGE_MESSAGE = "File too large. Maximum size is 40MB."
|
| 22 |
|
| 23 |
-
# Load environment variables
|
| 24 |
load_dotenv()
|
| 25 |
|
| 26 |
# Initialize session states
|
|
@@ -48,7 +47,7 @@ st.set_page_config(
|
|
| 48 |
LLM_MODEL = "deepseek-r1-distill-llama-70b"
|
| 49 |
TRANSCRIPTION_MODEL = "distil-whisper-large-v3-en"
|
| 50 |
|
| 51 |
-
# Configure
|
| 52 |
MAX_RETRIES = 5
|
| 53 |
INITIAL_WAIT = 0.5
|
| 54 |
MAX_WAIT = 30
|
|
@@ -192,16 +191,39 @@ class NoteSection:
|
|
| 192 |
markdown_content += self.get_markdown_content(content, level + 1)
|
| 193 |
return markdown_content
|
| 194 |
|
| 195 |
-
#
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 205 |
def transcribe_audio_with_groq(audio_data) -> str:
|
| 206 |
"""
|
| 207 |
Transcribe audio file using Groq's transcription API with retry capability
|
|
@@ -462,56 +484,21 @@ def main():
|
|
| 462 |
st.title("π§ββοΈ ScribeWizard")
|
| 463 |
st.markdown("Transform speech into highly structured notes with AI magic")
|
| 464 |
|
| 465 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
| 466 |
with st.sidebar:
|
| 467 |
-
st.header("Configuration")
|
| 468 |
-
|
| 469 |
-
# Improved API key handling
|
| 470 |
-
api_key_input = st.text_input(
|
| 471 |
-
"Groq API Key",
|
| 472 |
-
value=st.session_state.api_key,
|
| 473 |
-
type="password",
|
| 474 |
-
help="Enter your Groq API key. Get one at https://console.groq.com/keys"
|
| 475 |
-
)
|
| 476 |
-
|
| 477 |
-
# Only update if changed
|
| 478 |
-
if api_key_input != st.session_state.api_key:
|
| 479 |
-
st.session_state.api_key = api_key_input
|
| 480 |
-
# Reinitialize client with new key
|
| 481 |
-
st.session_state.groq_client = initialize_groq_client(api_key_input)
|
| 482 |
-
|
| 483 |
-
if st.session_state.groq_client:
|
| 484 |
-
st.success("β
API key validated!")
|
| 485 |
-
|
| 486 |
-
# Initialize client if not done already
|
| 487 |
-
if st.session_state.api_key and not st.session_state.groq_client:
|
| 488 |
-
st.session_state.groq_client = initialize_groq_client(st.session_state.api_key)
|
| 489 |
-
|
| 490 |
-
# API key instructions
|
| 491 |
-
with st.expander("How to get a Groq API key"):
|
| 492 |
-
st.markdown("""
|
| 493 |
-
1. Visit [Groq Cloud Console](https://console.groq.com/)
|
| 494 |
-
2. Sign up or log in to your account
|
| 495 |
-
3. Navigate to API Keys in the sidebar
|
| 496 |
-
4. Click "Create API Key" and give it a name
|
| 497 |
-
5. Copy the generated key (you won't see it again!)
|
| 498 |
-
|
| 499 |
-
**Security tip**: For production use, store your API key as an environment variable:
|
| 500 |
-
```bash
|
| 501 |
-
export GROQ_API_KEY="your-api-key-here"
|
| 502 |
-
```
|
| 503 |
-
""")
|
| 504 |
-
|
| 505 |
-
st.markdown("---")
|
| 506 |
st.info("Using DeepSeek-R1-Distill-Llama-70B model for note generation and Distil Whisper for transcription")
|
| 507 |
|
| 508 |
# Check if API key is valid before proceeding
|
| 509 |
if not st.session_state.api_key:
|
| 510 |
-
st.
|
| 511 |
st.stop()
|
| 512 |
|
| 513 |
if not st.session_state.groq_client:
|
| 514 |
-
st.error("β Failed to initialize Groq client. Please check your API key.")
|
| 515 |
st.stop()
|
| 516 |
|
| 517 |
# Input methods tabs
|
|
@@ -618,7 +605,7 @@ def main():
|
|
| 618 |
if "Audio file too large" in str(e) or "exceeds" in str(e):
|
| 619 |
st.info("π‘ Try trimming your audio file or uploading a shorter segment.")
|
| 620 |
elif "API key" in str(e) or "Authentication" in str(e):
|
| 621 |
-
st.info("π‘ Check that your Groq API key is correct
|
| 622 |
elif "Rate limit" in str(e):
|
| 623 |
st.info("π‘ You've hit Groq's rate limits. Please wait a few minutes before trying again.")
|
| 624 |
|
|
|
|
| 9 |
from md2pdf.core import md2pdf
|
| 10 |
from dotenv import load_dotenv
|
| 11 |
from datetime import datetime
|
|
|
|
| 12 |
import requests
|
| 13 |
from requests.exceptions import RequestException
|
| 14 |
from typing import Optional, Dict, Any
|
|
|
|
| 19 |
MAX_FILE_SIZE = 41943040 # 40MB
|
| 20 |
FILE_TOO_LARGE_MESSAGE = "File too large. Maximum size is 40MB."
|
| 21 |
|
| 22 |
+
# Load environment variables - will also load from Hugging Face secrets
|
| 23 |
load_dotenv()
|
| 24 |
|
| 25 |
# Initialize session states
|
|
|
|
| 47 |
LLM_MODEL = "deepseek-r1-distill-llama-70b"
|
| 48 |
TRANSCRIPTION_MODEL = "distil-whisper-large-v3-en"
|
| 49 |
|
| 50 |
+
# Configure retry parameters without backoff library
|
| 51 |
MAX_RETRIES = 5
|
| 52 |
INITIAL_WAIT = 0.5
|
| 53 |
MAX_WAIT = 30
|
|
|
|
| 191 |
markdown_content += self.get_markdown_content(content, level + 1)
|
| 192 |
return markdown_content
|
| 193 |
|
| 194 |
+
# Manual implementation of retry logic (replacing backoff library)
|
| 195 |
+
def retry_with_exponential_backoff(max_tries=MAX_RETRIES, initial_wait=INITIAL_WAIT, max_wait=MAX_WAIT):
|
| 196 |
+
"""
|
| 197 |
+
Custom retry decorator with exponential backoff
|
| 198 |
+
"""
|
| 199 |
+
def decorator(func):
|
| 200 |
+
def wrapper(*args, **kwargs):
|
| 201 |
+
wait = initial_wait
|
| 202 |
+
tries = 0
|
| 203 |
+
|
| 204 |
+
while tries < max_tries:
|
| 205 |
+
try:
|
| 206 |
+
return func(*args, **kwargs)
|
| 207 |
+
except (RequestException, GroqAPIError) as e:
|
| 208 |
+
tries += 1
|
| 209 |
+
if tries == max_tries:
|
| 210 |
+
raise
|
| 211 |
+
|
| 212 |
+
# Calculate next wait time with exponential backoff
|
| 213 |
+
wait = min(wait * 2, max_wait)
|
| 214 |
+
|
| 215 |
+
# Add some jitter (Β±20%)
|
| 216 |
+
jitter = wait * 0.4 * (np.random.random() - 0.5)
|
| 217 |
+
wait_with_jitter = wait + jitter
|
| 218 |
+
|
| 219 |
+
# Inform user of retry attempt
|
| 220 |
+
st.info(f"Retrying transcription... (Attempt {tries}/{max_tries})")
|
| 221 |
+
time.sleep(wait_with_jitter)
|
| 222 |
+
|
| 223 |
+
return wrapper
|
| 224 |
+
return decorator
|
| 225 |
+
|
| 226 |
+
@retry_with_exponential_backoff()
|
| 227 |
def transcribe_audio_with_groq(audio_data) -> str:
|
| 228 |
"""
|
| 229 |
Transcribe audio file using Groq's transcription API with retry capability
|
|
|
|
| 484 |
st.title("π§ββοΈ ScribeWizard")
|
| 485 |
st.markdown("Transform speech into highly structured notes with AI magic")
|
| 486 |
|
| 487 |
+
# Initialize API key from environment (Hugging Face secrets)
|
| 488 |
+
if st.session_state.api_key and not st.session_state.groq_client:
|
| 489 |
+
st.session_state.groq_client = initialize_groq_client(st.session_state.api_key)
|
| 490 |
+
|
| 491 |
+
# Display model info in the sidebar
|
| 492 |
with st.sidebar:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 493 |
st.info("Using DeepSeek-R1-Distill-Llama-70B model for note generation and Distil Whisper for transcription")
|
| 494 |
|
| 495 |
# Check if API key is valid before proceeding
|
| 496 |
if not st.session_state.api_key:
|
| 497 |
+
st.error("β No API key found. Please set the GROQ_API_KEY secret in your Hugging Face Space settings.")
|
| 498 |
st.stop()
|
| 499 |
|
| 500 |
if not st.session_state.groq_client:
|
| 501 |
+
st.error("β Failed to initialize Groq client. Please check your API key secret in Hugging Face Space settings.")
|
| 502 |
st.stop()
|
| 503 |
|
| 504 |
# Input methods tabs
|
|
|
|
| 605 |
if "Audio file too large" in str(e) or "exceeds" in str(e):
|
| 606 |
st.info("π‘ Try trimming your audio file or uploading a shorter segment.")
|
| 607 |
elif "API key" in str(e) or "Authentication" in str(e):
|
| 608 |
+
st.info("π‘ Check that your Groq API key is correct in your Hugging Face Space settings.")
|
| 609 |
elif "Rate limit" in str(e):
|
| 610 |
st.info("π‘ You've hit Groq's rate limits. Please wait a few minutes before trying again.")
|
| 611 |
|