Spaces:
Sleeping
Sleeping
Update app.py
#2
app.py
CHANGED
|
@@ -825,6 +825,101 @@ def extract_causal_signals(
|
|
| 825 |
|
| 826 |
return signals
|
| 827 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 828 |
# ============================================================
|
| 829 |
# CHATBOT + RSNN DETECTION
|
| 830 |
# ============================================================
|
|
@@ -922,7 +1017,8 @@ def respond(
|
|
| 922 |
|
| 923 |
return (
|
| 924 |
"The model produced "
|
| 925 |
-
"no scoreable response."
|
|
|
|
| 926 |
)
|
| 927 |
|
| 928 |
|
|
@@ -1061,6 +1157,25 @@ def respond(
|
|
| 1061 |
)
|
| 1062 |
|
| 1063 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1064 |
flagged_preview = [
|
| 1065 |
|
| 1066 |
f"{i}:{token_strings[i]}"
|
|
@@ -1179,7 +1294,8 @@ def respond(
|
|
| 1179 |
+
|
| 1180 |
"\n\n"
|
| 1181 |
+
|
| 1182 |
-
report
|
|
|
|
| 1183 |
)
|
| 1184 |
|
| 1185 |
|
|
@@ -1201,7 +1317,7 @@ with gr.Blocks() as demo:
|
|
| 1201 |
"""
|
| 1202 |
# LatticeSpike Hallucination-Aware Chatbot
|
| 1203 |
|
| 1204 |
-
**LLM:** Meta Llama 3.2 1B Instruct
|
| 1205 |
**Detector:** LatticeSpike RSNN
|
| 1206 |
|
| 1207 |
The LLM generates an answer, then LatticeSpike analyzes
|
|
@@ -1212,6 +1328,16 @@ For this first version, each message is evaluated independently.
|
|
| 1212 |
)
|
| 1213 |
|
| 1214 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1215 |
chatbot = gr.ChatInterface(
|
| 1216 |
|
| 1217 |
fn=respond,
|
|
@@ -1242,6 +1368,8 @@ For this first version, each message is evaluated independently.
|
|
| 1242 |
label="Top-p",
|
| 1243 |
),
|
| 1244 |
],
|
|
|
|
|
|
|
| 1245 |
)
|
| 1246 |
|
| 1247 |
|
|
|
|
| 825 |
|
| 826 |
return signals
|
| 827 |
|
| 828 |
+
# ============================================================
|
| 829 |
+
# TOKEN-LEVEL HALLUCINATION HTML BUILDER
|
| 830 |
+
# ============================================================
|
| 831 |
+
|
| 832 |
+
def build_highlight_html(token_strings, flagged_set, burst_set, anomaly_scores):
|
| 833 |
+
"""
|
| 834 |
+
Build an inline HTML token map.
|
| 835 |
+
Red = anomaly above threshold (hallucinated)
|
| 836 |
+
Amber = RSNN burst spike
|
| 837 |
+
Hover tooltip shows token index and anomaly score.
|
| 838 |
+
"""
|
| 839 |
+
|
| 840 |
+
legend = (
|
| 841 |
+
'<div style="font-family:sans-serif;font-size:12px;'
|
| 842 |
+
'margin-bottom:8px;display:flex;gap:14px;flex-wrap:wrap;">'
|
| 843 |
+
'<span>'
|
| 844 |
+
'<span style="background:#ffd8d7;color:#82071e;border-radius:3px;'
|
| 845 |
+
'padding:1px 6px;font-weight:700;">H</span>'
|
| 846 |
+
' Hallucinated (anomaly > threshold)'
|
| 847 |
+
'</span>'
|
| 848 |
+
'<span>'
|
| 849 |
+
'<span style="background:#fff3cd;color:#7d4e00;border-radius:3px;'
|
| 850 |
+
'padding:1px 6px;font-weight:700;">B</span>'
|
| 851 |
+
' RSNN burst spike'
|
| 852 |
+
'</span>'
|
| 853 |
+
'</div>'
|
| 854 |
+
)
|
| 855 |
+
|
| 856 |
+
parts = []
|
| 857 |
+
|
| 858 |
+
for i, raw in enumerate(token_strings):
|
| 859 |
+
|
| 860 |
+
# Humanise the token string
|
| 861 |
+
display = raw
|
| 862 |
+
for src, dst in [
|
| 863 |
+
('\u0120', ' '), # Ġ → space (GPT-2/Llama BPE)
|
| 864 |
+
('\u2581', ' '), # ▁ → space (SentencePiece)
|
| 865 |
+
('\u010a', '\n'), # Ċ → newline
|
| 866 |
+
('<0x0A>', '\n'), # literal newline token
|
| 867 |
+
]:
|
| 868 |
+
display = display.replace(src, dst)
|
| 869 |
+
|
| 870 |
+
# HTML-escape, then convert newlines to <br>
|
| 871 |
+
display = (
|
| 872 |
+
display
|
| 873 |
+
.replace('&', '&')
|
| 874 |
+
.replace('<', '<')
|
| 875 |
+
.replace('>', '>')
|
| 876 |
+
.replace('\n', '<br>')
|
| 877 |
+
)
|
| 878 |
+
|
| 879 |
+
if display.strip() == '':
|
| 880 |
+
display = ' '
|
| 881 |
+
|
| 882 |
+
score = (
|
| 883 |
+
float(anomaly_scores[i])
|
| 884 |
+
if i < len(anomaly_scores)
|
| 885 |
+
else 0.0
|
| 886 |
+
)
|
| 887 |
+
|
| 888 |
+
title = f"[{i}] {raw} | anomaly={score:.4f}"
|
| 889 |
+
|
| 890 |
+
if i in flagged_set:
|
| 891 |
+
style = (
|
| 892 |
+
"background:#ffd8d7;color:#82071e;"
|
| 893 |
+
"border-radius:3px;padding:1px 3px;cursor:default;"
|
| 894 |
+
)
|
| 895 |
+
elif i in burst_set:
|
| 896 |
+
style = (
|
| 897 |
+
"background:#fff3cd;color:#7d4e00;"
|
| 898 |
+
"border-radius:3px;padding:1px 3px;cursor:default;"
|
| 899 |
+
)
|
| 900 |
+
else:
|
| 901 |
+
style = "cursor:default;"
|
| 902 |
+
|
| 903 |
+
parts.append(
|
| 904 |
+
f'<span style="{style}" title="{title}">{display}</span>'
|
| 905 |
+
)
|
| 906 |
+
|
| 907 |
+
text_html = (
|
| 908 |
+
'<div style="font-family:sans-serif;font-size:14px;'
|
| 909 |
+
'line-height:1.9;background:#fff;border:1px solid #d0d7de;'
|
| 910 |
+
'border-radius:8px;padding:12px 16px;word-break:break-word;">'
|
| 911 |
+
+ ''.join(parts)
|
| 912 |
+
+ '</div>'
|
| 913 |
+
)
|
| 914 |
+
|
| 915 |
+
heading = (
|
| 916 |
+
'<h4 style="font-family:sans-serif;margin-bottom:6px;'
|
| 917 |
+
'color:#1f2328;">Token-level Hallucination Map</h4>'
|
| 918 |
+
)
|
| 919 |
+
|
| 920 |
+
return heading + legend + text_html
|
| 921 |
+
|
| 922 |
+
|
| 923 |
# ============================================================
|
| 924 |
# CHATBOT + RSNN DETECTION
|
| 925 |
# ============================================================
|
|
|
|
| 1017 |
|
| 1018 |
return (
|
| 1019 |
"The model produced "
|
| 1020 |
+
"no scoreable response.",
|
| 1021 |
+
"<p><em>No tokens to visualize.</em></p>",
|
| 1022 |
)
|
| 1023 |
|
| 1024 |
|
|
|
|
| 1157 |
)
|
| 1158 |
|
| 1159 |
|
| 1160 |
+
# ----------------------------------------------------
|
| 1161 |
+
# BUILD TOKEN-LEVEL HTML VISUALIZATION
|
| 1162 |
+
# ----------------------------------------------------
|
| 1163 |
+
|
| 1164 |
+
anomaly_list = (
|
| 1165 |
+
anomaly
|
| 1166 |
+
.detach()
|
| 1167 |
+
.cpu()
|
| 1168 |
+
.tolist()
|
| 1169 |
+
)
|
| 1170 |
+
|
| 1171 |
+
hallu_html = build_highlight_html(
|
| 1172 |
+
token_strings,
|
| 1173 |
+
flagged_set=set(flagged_indices),
|
| 1174 |
+
burst_set=set(burst_indices),
|
| 1175 |
+
anomaly_scores=anomaly_list,
|
| 1176 |
+
)
|
| 1177 |
+
|
| 1178 |
+
|
| 1179 |
flagged_preview = [
|
| 1180 |
|
| 1181 |
f"{i}:{token_strings[i]}"
|
|
|
|
| 1294 |
+
|
| 1295 |
"\n\n"
|
| 1296 |
+
|
| 1297 |
+
report,
|
| 1298 |
+
hallu_html,
|
| 1299 |
)
|
| 1300 |
|
| 1301 |
|
|
|
|
| 1317 |
"""
|
| 1318 |
# LatticeSpike Hallucination-Aware Chatbot
|
| 1319 |
|
| 1320 |
+
**LLM:** Meta Llama 3.2 1B Instruct
|
| 1321 |
**Detector:** LatticeSpike RSNN
|
| 1322 |
|
| 1323 |
The LLM generates an answer, then LatticeSpike analyzes
|
|
|
|
| 1328 |
)
|
| 1329 |
|
| 1330 |
|
| 1331 |
+
hallu_viz = gr.HTML(
|
| 1332 |
+
value=(
|
| 1333 |
+
"<p style='font-family:sans-serif;color:#57606a;font-size:13px;'>"
|
| 1334 |
+
"<em>Submit a question to see the token-level hallucination map.</em>"
|
| 1335 |
+
"</p>"
|
| 1336 |
+
),
|
| 1337 |
+
label="Token-level Hallucination Visualization",
|
| 1338 |
+
)
|
| 1339 |
+
|
| 1340 |
+
|
| 1341 |
chatbot = gr.ChatInterface(
|
| 1342 |
|
| 1343 |
fn=respond,
|
|
|
|
| 1368 |
label="Top-p",
|
| 1369 |
),
|
| 1370 |
],
|
| 1371 |
+
|
| 1372 |
+
additional_outputs=[hallu_viz],
|
| 1373 |
)
|
| 1374 |
|
| 1375 |
|