Improve logging and url fetching
Browse files- app.py +35 -10
- requirements.txt +1 -0
- src/streamlit_app.py +35 -10
app.py
CHANGED
|
@@ -4,6 +4,10 @@ from huggingface_hub import HfApi
|
|
| 4 |
import requests
|
| 5 |
import re
|
| 6 |
import concurrent.futures
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
|
| 8 |
# Configure the Streamlit page
|
| 9 |
st.set_page_config(page_title="Heretic Models Explorer", page_icon="🔥", layout="wide")
|
|
@@ -16,6 +20,18 @@ st.markdown(
|
|
| 16 |
"allowing you to sort and compare them easily. Click on any column header to sort!"
|
| 17 |
)
|
| 18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
# Fetch model's readme.md file and attempt to parse refusal and KL divergence data.
|
| 20 |
def fetch_model_info(model):
|
| 21 |
"""Fetches the README.md for a given model and dynamically extracts metrics."""
|
|
@@ -28,7 +44,7 @@ def fetch_model_info(model):
|
|
| 28 |
# Download the README.md via raw URL for high-speed fetching
|
| 29 |
url = f"https://huggingface.co/{model_id}/raw/main/README.md"
|
| 30 |
try:
|
| 31 |
-
response =
|
| 32 |
if response.status_code == 200:
|
| 33 |
readme_text = response.text
|
| 34 |
|
|
@@ -38,8 +54,8 @@ def fetch_model_info(model):
|
|
| 38 |
if kl_match:
|
| 39 |
try:
|
| 40 |
kl_div = float(kl_match.group(1))
|
| 41 |
-
except ValueError:
|
| 42 |
-
|
| 43 |
|
| 44 |
# Extract Refusals using Regex
|
| 45 |
# Matches formats like: "Refusals | 15/100" or "15 / 100"
|
|
@@ -54,13 +70,18 @@ def fetch_model_info(model):
|
|
| 54 |
initial_refusals_str = f"{fractions[0][0]}/{fractions[0][1]}"
|
| 55 |
elif 'initial' not in line_lower and refusals_str is None:
|
| 56 |
refusals_str = f"{fractions[0][0]}/{fractions[0][1]}"
|
| 57 |
-
|
| 58 |
-
|
|
|
|
|
|
|
|
|
|
| 59 |
if len(fractions) >= 2 and initial_refusals_str is None:
|
| 60 |
initial_refusals_str = f"{fractions[1][0]}/{fractions[1][1]}"
|
| 61 |
|
| 62 |
-
except
|
| 63 |
-
|
|
|
|
|
|
|
| 64 |
|
| 65 |
# Skip models without explicitly stated KL divergence or refusal data
|
| 66 |
if kl_div is None or refusals_str is None:
|
|
@@ -82,7 +103,7 @@ def get_model_data(model):
|
|
| 82 |
model_id = model.id
|
| 83 |
url = f"https://huggingface.co/{model_id}/raw/main/reproduce/reproduce.json"
|
| 84 |
try:
|
| 85 |
-
response =
|
| 86 |
if response.status_code == 200:
|
| 87 |
data = response.json()
|
| 88 |
metrics = data.get("metrics")
|
|
@@ -105,8 +126,12 @@ def get_model_data(model):
|
|
| 105 |
"Downloads": getattr(model, 'downloads', 0),
|
| 106 |
"URL": f"https://huggingface.co/{model_id}"
|
| 107 |
}
|
| 108 |
-
except
|
| 109 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 110 |
return fetch_model_info(model)
|
| 111 |
|
| 112 |
@st.cache_data(ttl=3600, show_spinner=False) # Cache for 1 hour
|
|
|
|
| 4 |
import requests
|
| 5 |
import re
|
| 6 |
import concurrent.futures
|
| 7 |
+
import logging
|
| 8 |
+
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
|
| 9 |
+
|
| 10 |
+
logging.basicConfig(level=logging.WARNING, format="%(asctime)s - %(levelname)s - %(message)s")
|
| 11 |
|
| 12 |
# Configure the Streamlit page
|
| 13 |
st.set_page_config(page_title="Heretic Models Explorer", page_icon="🔥", layout="wide")
|
|
|
|
| 20 |
"allowing you to sort and compare them easily. Click on any column header to sort!"
|
| 21 |
)
|
| 22 |
|
| 23 |
+
@retry(
|
| 24 |
+
retry=retry_if_exception_type((requests.exceptions.ConnectionError, requests.exceptions.Timeout, requests.exceptions.HTTPError)),
|
| 25 |
+
stop=stop_after_attempt(3),
|
| 26 |
+
wait=wait_exponential(multiplier=1, min=2, max=10)
|
| 27 |
+
)
|
| 28 |
+
def fetch_url(url):
|
| 29 |
+
response = requests.get(url, timeout=5)
|
| 30 |
+
# Raise HTTPError for rate limits (429) or server errors (5xx) to trigger a retry
|
| 31 |
+
if response.status_code in (429, 500, 502, 503, 504):
|
| 32 |
+
response.raise_for_status()
|
| 33 |
+
return response
|
| 34 |
+
|
| 35 |
# Fetch model's readme.md file and attempt to parse refusal and KL divergence data.
|
| 36 |
def fetch_model_info(model):
|
| 37 |
"""Fetches the README.md for a given model and dynamically extracts metrics."""
|
|
|
|
| 44 |
# Download the README.md via raw URL for high-speed fetching
|
| 45 |
url = f"https://huggingface.co/{model_id}/raw/main/README.md"
|
| 46 |
try:
|
| 47 |
+
response = fetch_url(url)
|
| 48 |
if response.status_code == 200:
|
| 49 |
readme_text = response.text
|
| 50 |
|
|
|
|
| 54 |
if kl_match:
|
| 55 |
try:
|
| 56 |
kl_div = float(kl_match.group(1))
|
| 57 |
+
except ValueError as e:
|
| 58 |
+
logging.warning(f"Could not parse KL divergence for {model_id}: {e}")
|
| 59 |
|
| 60 |
# Extract Refusals using Regex
|
| 61 |
# Matches formats like: "Refusals | 15/100" or "15 / 100"
|
|
|
|
| 70 |
initial_refusals_str = f"{fractions[0][0]}/{fractions[0][1]}"
|
| 71 |
elif 'initial' not in line_lower and refusals_str is None:
|
| 72 |
refusals_str = f"{fractions[0][0]}/{fractions[0][1]}"
|
| 73 |
+
try:
|
| 74 |
+
refusal_rate = (int(fractions[0][0]) / int(fractions[0][1])) * 100
|
| 75 |
+
except (ValueError, ZeroDivisionError) as e:
|
| 76 |
+
logging.warning(f"Could not parse refusals for {model_id}: {e}")
|
| 77 |
+
continue
|
| 78 |
if len(fractions) >= 2 and initial_refusals_str is None:
|
| 79 |
initial_refusals_str = f"{fractions[1][0]}/{fractions[1][1]}"
|
| 80 |
|
| 81 |
+
except requests.exceptions.RequestException as e:
|
| 82 |
+
logging.warning(f"Error fetching README for {model_id}: {e}")
|
| 83 |
+
except Exception as e:
|
| 84 |
+
logging.error(f"Unexpected error parsing README for {model_id}: {e}")
|
| 85 |
|
| 86 |
# Skip models without explicitly stated KL divergence or refusal data
|
| 87 |
if kl_div is None or refusals_str is None:
|
|
|
|
| 103 |
model_id = model.id
|
| 104 |
url = f"https://huggingface.co/{model_id}/raw/main/reproduce/reproduce.json"
|
| 105 |
try:
|
| 106 |
+
response = fetch_url(url)
|
| 107 |
if response.status_code == 200:
|
| 108 |
data = response.json()
|
| 109 |
metrics = data.get("metrics")
|
|
|
|
| 126 |
"Downloads": getattr(model, 'downloads', 0),
|
| 127 |
"URL": f"https://huggingface.co/{model_id}"
|
| 128 |
}
|
| 129 |
+
except requests.exceptions.RequestException as e:
|
| 130 |
+
logging.warning(f"Error fetching JSON for {model_id}: {e}")
|
| 131 |
+
except (ValueError, KeyError, TypeError) as e:
|
| 132 |
+
logging.warning(f"Formatting error in JSON for {model_id}: {e}")
|
| 133 |
+
except Exception as e:
|
| 134 |
+
logging.error(f"Unexpected error processing JSON for {model_id}: {e}")
|
| 135 |
return fetch_model_info(model)
|
| 136 |
|
| 137 |
@st.cache_data(ttl=3600, show_spinner=False) # Cache for 1 hour
|
requirements.txt
CHANGED
|
@@ -3,3 +3,4 @@ streamlit
|
|
| 3 |
huggingface_hub
|
| 4 |
pandas
|
| 5 |
requests
|
|
|
|
|
|
| 3 |
huggingface_hub
|
| 4 |
pandas
|
| 5 |
requests
|
| 6 |
+
tenacity
|
src/streamlit_app.py
CHANGED
|
@@ -4,6 +4,10 @@ from huggingface_hub import HfApi
|
|
| 4 |
import requests
|
| 5 |
import re
|
| 6 |
import concurrent.futures
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
|
| 8 |
# Configure the Streamlit page
|
| 9 |
st.set_page_config(page_title="Heretic Models Explorer", page_icon="🔥", layout="wide")
|
|
@@ -16,6 +20,18 @@ st.markdown(
|
|
| 16 |
"allowing you to sort and compare them easily. Click on any column header to sort!"
|
| 17 |
)
|
| 18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
# Fetch model's readme.md file and attempt to parse refusal and KL divergence data.
|
| 20 |
def fetch_model_info(model):
|
| 21 |
"""Fetches the README.md for a given model and dynamically extracts metrics."""
|
|
@@ -28,7 +44,7 @@ def fetch_model_info(model):
|
|
| 28 |
# Download the README.md via raw URL for high-speed fetching
|
| 29 |
url = f"https://huggingface.co/{model_id}/raw/main/README.md"
|
| 30 |
try:
|
| 31 |
-
response =
|
| 32 |
if response.status_code == 200:
|
| 33 |
readme_text = response.text
|
| 34 |
|
|
@@ -38,8 +54,8 @@ def fetch_model_info(model):
|
|
| 38 |
if kl_match:
|
| 39 |
try:
|
| 40 |
kl_div = float(kl_match.group(1))
|
| 41 |
-
except ValueError:
|
| 42 |
-
|
| 43 |
|
| 44 |
# Extract Refusals using Regex
|
| 45 |
# Matches formats like: "Refusals | 15/100" or "15 / 100"
|
|
@@ -54,13 +70,18 @@ def fetch_model_info(model):
|
|
| 54 |
initial_refusals_str = f"{fractions[0][0]}/{fractions[0][1]}"
|
| 55 |
elif 'initial' not in line_lower and refusals_str is None:
|
| 56 |
refusals_str = f"{fractions[0][0]}/{fractions[0][1]}"
|
| 57 |
-
|
| 58 |
-
|
|
|
|
|
|
|
|
|
|
| 59 |
if len(fractions) >= 2 and initial_refusals_str is None:
|
| 60 |
initial_refusals_str = f"{fractions[1][0]}/{fractions[1][1]}"
|
| 61 |
|
| 62 |
-
except
|
| 63 |
-
|
|
|
|
|
|
|
| 64 |
|
| 65 |
# Skip models without explicitly stated KL divergence or refusal data
|
| 66 |
if kl_div is None or refusals_str is None:
|
|
@@ -82,7 +103,7 @@ def get_model_data(model):
|
|
| 82 |
model_id = model.id
|
| 83 |
url = f"https://huggingface.co/{model_id}/raw/main/reproduce/reproduce.json"
|
| 84 |
try:
|
| 85 |
-
response =
|
| 86 |
if response.status_code == 200:
|
| 87 |
data = response.json()
|
| 88 |
metrics = data.get("metrics")
|
|
@@ -105,8 +126,12 @@ def get_model_data(model):
|
|
| 105 |
"Downloads": getattr(model, 'downloads', 0),
|
| 106 |
"URL": f"https://huggingface.co/{model_id}"
|
| 107 |
}
|
| 108 |
-
except
|
| 109 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 110 |
return fetch_model_info(model)
|
| 111 |
|
| 112 |
@st.cache_data(ttl=3600, show_spinner=False) # Cache for 1 hour
|
|
|
|
| 4 |
import requests
|
| 5 |
import re
|
| 6 |
import concurrent.futures
|
| 7 |
+
import logging
|
| 8 |
+
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
|
| 9 |
+
|
| 10 |
+
logging.basicConfig(level=logging.WARNING, format="%(asctime)s - %(levelname)s - %(message)s")
|
| 11 |
|
| 12 |
# Configure the Streamlit page
|
| 13 |
st.set_page_config(page_title="Heretic Models Explorer", page_icon="🔥", layout="wide")
|
|
|
|
| 20 |
"allowing you to sort and compare them easily. Click on any column header to sort!"
|
| 21 |
)
|
| 22 |
|
| 23 |
+
@retry(
|
| 24 |
+
retry=retry_if_exception_type((requests.exceptions.ConnectionError, requests.exceptions.Timeout, requests.exceptions.HTTPError)),
|
| 25 |
+
stop=stop_after_attempt(3),
|
| 26 |
+
wait=wait_exponential(multiplier=1, min=2, max=10)
|
| 27 |
+
)
|
| 28 |
+
def fetch_url(url):
|
| 29 |
+
response = requests.get(url, timeout=5)
|
| 30 |
+
# Raise HTTPError for rate limits (429) or server errors (5xx) to trigger a retry
|
| 31 |
+
if response.status_code in (429, 500, 502, 503, 504):
|
| 32 |
+
response.raise_for_status()
|
| 33 |
+
return response
|
| 34 |
+
|
| 35 |
# Fetch model's readme.md file and attempt to parse refusal and KL divergence data.
|
| 36 |
def fetch_model_info(model):
|
| 37 |
"""Fetches the README.md for a given model and dynamically extracts metrics."""
|
|
|
|
| 44 |
# Download the README.md via raw URL for high-speed fetching
|
| 45 |
url = f"https://huggingface.co/{model_id}/raw/main/README.md"
|
| 46 |
try:
|
| 47 |
+
response = fetch_url(url)
|
| 48 |
if response.status_code == 200:
|
| 49 |
readme_text = response.text
|
| 50 |
|
|
|
|
| 54 |
if kl_match:
|
| 55 |
try:
|
| 56 |
kl_div = float(kl_match.group(1))
|
| 57 |
+
except ValueError as e:
|
| 58 |
+
logging.warning(f"Could not parse KL divergence for {model_id}: {e}")
|
| 59 |
|
| 60 |
# Extract Refusals using Regex
|
| 61 |
# Matches formats like: "Refusals | 15/100" or "15 / 100"
|
|
|
|
| 70 |
initial_refusals_str = f"{fractions[0][0]}/{fractions[0][1]}"
|
| 71 |
elif 'initial' not in line_lower and refusals_str is None:
|
| 72 |
refusals_str = f"{fractions[0][0]}/{fractions[0][1]}"
|
| 73 |
+
try:
|
| 74 |
+
refusal_rate = (int(fractions[0][0]) / int(fractions[0][1])) * 100
|
| 75 |
+
except (ValueError, ZeroDivisionError) as e:
|
| 76 |
+
logging.warning(f"Could not parse refusals for {model_id}: {e}")
|
| 77 |
+
continue
|
| 78 |
if len(fractions) >= 2 and initial_refusals_str is None:
|
| 79 |
initial_refusals_str = f"{fractions[1][0]}/{fractions[1][1]}"
|
| 80 |
|
| 81 |
+
except requests.exceptions.RequestException as e:
|
| 82 |
+
logging.warning(f"Error fetching README for {model_id}: {e}")
|
| 83 |
+
except Exception as e:
|
| 84 |
+
logging.error(f"Unexpected error parsing README for {model_id}: {e}")
|
| 85 |
|
| 86 |
# Skip models without explicitly stated KL divergence or refusal data
|
| 87 |
if kl_div is None or refusals_str is None:
|
|
|
|
| 103 |
model_id = model.id
|
| 104 |
url = f"https://huggingface.co/{model_id}/raw/main/reproduce/reproduce.json"
|
| 105 |
try:
|
| 106 |
+
response = fetch_url(url)
|
| 107 |
if response.status_code == 200:
|
| 108 |
data = response.json()
|
| 109 |
metrics = data.get("metrics")
|
|
|
|
| 126 |
"Downloads": getattr(model, 'downloads', 0),
|
| 127 |
"URL": f"https://huggingface.co/{model_id}"
|
| 128 |
}
|
| 129 |
+
except requests.exceptions.RequestException as e:
|
| 130 |
+
logging.warning(f"Error fetching JSON for {model_id}: {e}")
|
| 131 |
+
except (ValueError, KeyError, TypeError) as e:
|
| 132 |
+
logging.warning(f"Formatting error in JSON for {model_id}: {e}")
|
| 133 |
+
except Exception as e:
|
| 134 |
+
logging.error(f"Unexpected error processing JSON for {model_id}: {e}")
|
| 135 |
return fetch_model_info(model)
|
| 136 |
|
| 137 |
@st.cache_data(ttl=3600, show_spinner=False) # Cache for 1 hour
|