Spaces:
Sleeping
Sleeping
Fredrik Sitje
commited on
Commit
·
47ec288
1
Parent(s):
abc33c8
Include tooltips to the answers.
Browse files- src/streamlit_app.py +88 -0
src/streamlit_app.py
CHANGED
|
@@ -75,10 +75,95 @@ ASSESSMENT_TO_SCORE = {
|
|
| 75 |
"Irrelevant / NA": "NA"
|
| 76 |
}
|
| 77 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
def format_snake_case(text):
|
| 79 |
"""Convert snake_case to Title Case"""
|
| 80 |
return ' '.join(word.capitalize() for word in text.split('_'))
|
| 81 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
def hash_password(password):
|
| 83 |
"""Hash a password using SHA256"""
|
| 84 |
return hashlib.sha256(password.encode()).hexdigest()
|
|
@@ -762,6 +847,9 @@ elif st.session_state.logged_in:
|
|
| 762 |
changes_info = [] # Store info about changes for display
|
| 763 |
selected_values = {} # Store all selected values for validation
|
| 764 |
|
|
|
|
|
|
|
|
|
|
| 765 |
for i, subcat in enumerate(category.subcategories):
|
| 766 |
st.markdown(f"**Subcategory: {subcat.formatted_name}**")
|
| 767 |
|
|
|
|
| 75 |
"Irrelevant / NA": "NA"
|
| 76 |
}
|
| 77 |
|
| 78 |
+
# Score explanations from annotation guide
|
| 79 |
+
SCORE_EXPLANATIONS = {
|
| 80 |
+
"Perfect": "Only when truly flawless. The answer is legally accurate, well-stated, and appropriate for legal education. It correctly explains the legal principle, rule, or concept without any discernible errors or misleading statements.",
|
| 81 |
+
"Mostly correct": "One very small issue or slightly awkward phrasing. The answer is generally accurate but contains minor inaccuracies, imprecise language, or could be more precise. The core legal content is correct, but there are small issues that could be improved for educational purposes.",
|
| 82 |
+
"Noticeably flawed": "Clear error but main idea still ok. The answer contains significant errors that substantially affect its accuracy. While not completely wrong, there are important mistakes in legal reasoning, application of law, or factual statements that would confuse or mislead students.",
|
| 83 |
+
"Seriously wrong": "Hallucination, wrong format, meaningless, etc. The answer contains fundamental legal errors that completely misrepresent the law, legal principle, or legal concept. The answer would mislead a student and is factually wrong at its core.",
|
| 84 |
+
"Irrelevant / NA": "The answer explicitly indicates that the information is unknown, unavailable, or not relevant to the question. This is appropriate when the AI correctly identifies that it cannot provide an answer."
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
def format_snake_case(text):
|
| 88 |
"""Convert snake_case to Title Case"""
|
| 89 |
return ' '.join(word.capitalize() for word in text.split('_'))
|
| 90 |
|
| 91 |
+
def inject_tooltip_css():
|
| 92 |
+
"""Inject CSS and JavaScript to add tooltips to radio button labels"""
|
| 93 |
+
tooltip_css_js = f"""
|
| 94 |
+
<style>
|
| 95 |
+
/* Tooltip container */
|
| 96 |
+
.stRadio > div > label {{
|
| 97 |
+
position: relative;
|
| 98 |
+
cursor: help;
|
| 99 |
+
}}
|
| 100 |
+
|
| 101 |
+
/* Tooltip text */
|
| 102 |
+
.stRadio > div > label[data-tooltip]:hover::after {{
|
| 103 |
+
content: attr(data-tooltip);
|
| 104 |
+
position: absolute;
|
| 105 |
+
left: 100%;
|
| 106 |
+
top: 50%;
|
| 107 |
+
transform: translateY(-50%);
|
| 108 |
+
margin-left: 10px;
|
| 109 |
+
padding: 8px 12px;
|
| 110 |
+
background-color: #333;
|
| 111 |
+
color: #fff;
|
| 112 |
+
border-radius: 4px;
|
| 113 |
+
white-space: normal;
|
| 114 |
+
width: 300px;
|
| 115 |
+
z-index: 1000;
|
| 116 |
+
font-size: 12px;
|
| 117 |
+
line-height: 1.4;
|
| 118 |
+
box-shadow: 0 2px 8px rgba(0,0,0,0.2);
|
| 119 |
+
pointer-events: none;
|
| 120 |
+
}}
|
| 121 |
+
|
| 122 |
+
/* Tooltip arrow */
|
| 123 |
+
.stRadio > div > label[data-tooltip]:hover::before {{
|
| 124 |
+
content: '';
|
| 125 |
+
position: absolute;
|
| 126 |
+
left: 100%;
|
| 127 |
+
top: 50%;
|
| 128 |
+
transform: translateY(-50%);
|
| 129 |
+
margin-left: 4px;
|
| 130 |
+
border: 6px solid transparent;
|
| 131 |
+
border-right-color: #333;
|
| 132 |
+
z-index: 1001;
|
| 133 |
+
pointer-events: none;
|
| 134 |
+
}}
|
| 135 |
+
</style>
|
| 136 |
+
<script>
|
| 137 |
+
(function() {{
|
| 138 |
+
// Wait for Streamlit to render radio buttons
|
| 139 |
+
function addTooltips() {{
|
| 140 |
+
const scoreExplanations = {json.dumps(SCORE_EXPLANATIONS)};
|
| 141 |
+
const radioLabels = document.querySelectorAll('.stRadio > div > label');
|
| 142 |
+
|
| 143 |
+
radioLabels.forEach(label => {{
|
| 144 |
+
const labelText = label.textContent.trim();
|
| 145 |
+
if (scoreExplanations[labelText]) {{
|
| 146 |
+
label.setAttribute('data-tooltip', scoreExplanations[labelText]);
|
| 147 |
+
label.style.cursor = 'help';
|
| 148 |
+
}}
|
| 149 |
+
}});
|
| 150 |
+
}}
|
| 151 |
+
|
| 152 |
+
// Run on page load
|
| 153 |
+
if (document.readyState === 'loading') {{
|
| 154 |
+
document.addEventListener('DOMContentLoaded', addTooltips);
|
| 155 |
+
}} else {{
|
| 156 |
+
addTooltips();
|
| 157 |
+
}}
|
| 158 |
+
|
| 159 |
+
// Also run after Streamlit reruns (using MutationObserver)
|
| 160 |
+
const observer = new MutationObserver(addTooltips);
|
| 161 |
+
observer.observe(document.body, {{ childList: true, subtree: true }});
|
| 162 |
+
}})();
|
| 163 |
+
</script>
|
| 164 |
+
"""
|
| 165 |
+
st.markdown(tooltip_css_js, unsafe_allow_html=True)
|
| 166 |
+
|
| 167 |
def hash_password(password):
|
| 168 |
"""Hash a password using SHA256"""
|
| 169 |
return hashlib.sha256(password.encode()).hexdigest()
|
|
|
|
| 847 |
changes_info = [] # Store info about changes for display
|
| 848 |
selected_values = {} # Store all selected values for validation
|
| 849 |
|
| 850 |
+
# Inject tooltip CSS and JavaScript for score explanations
|
| 851 |
+
inject_tooltip_css()
|
| 852 |
+
|
| 853 |
for i, subcat in enumerate(category.subcategories):
|
| 854 |
st.markdown(f"**Subcategory: {subcat.formatted_name}**")
|
| 855 |
|