sha6th commited on
Commit
b94533c
·
1 Parent(s): 5e1c5e3

Update LLM evaluation dashboard

Browse files
Files changed (1) hide show
  1. app.py +173 -89
app.py CHANGED
@@ -2,6 +2,11 @@ import streamlit as st
2
  import requests
3
  import pandas as pd
4
 
 
 
 
 
 
5
  st.set_page_config(
6
  page_title="LLM Hallucination Detector",
7
  layout="wide"
@@ -11,80 +16,126 @@ st.title("🔍 LLM Evaluation & Hallucination Detection Framework")
11
 
12
  API_URL = "https://sha6th-llm-eval-ap.hf.space"
13
 
14
- # ---------------------------------------------------------
 
15
  # Tabs
16
- # ---------------------------------------------------------
17
 
18
- tab1, tab2 = st.tabs(["Evaluate New Response", "History"])
 
 
19
 
20
 
21
  # =========================================================
22
- # TAB 1: Evaluate
23
  # =========================================================
24
 
25
  with tab1:
26
 
27
  st.subheader("Evaluate an LLM Response")
28
 
29
- st.info("Enter each context chunk on a new line")
 
 
 
 
 
 
30
 
31
  contexts_input = st.text_area(
32
  "Retrieved Contexts (one chunk per line)",
33
  height=150
34
  )
35
 
36
- question = st.text_input("Question")
 
 
 
 
 
 
 
 
 
 
37
 
38
  llm_response = st.text_area(
39
  "LLM Response",
40
  height=100
41
  )
42
 
 
 
 
 
43
  if st.button("Evaluate"):
44
 
 
45
  retrieved_contexts = [
46
  c.strip()
47
  for c in contexts_input.split("\n")
48
  if c.strip()
49
  ]
50
 
51
- # Validate input
 
 
 
52
  if (
53
  not retrieved_contexts
54
  or not question.strip()
55
  or not llm_response.strip()
56
  ):
57
- st.error("All fields are required.")
 
 
 
58
 
59
  else:
60
 
61
- with st.spinner("Running evaluation..."):
 
 
 
 
 
 
 
 
 
 
62
 
63
  try:
64
 
 
 
 
 
65
  response = requests.post(
66
  f"{API_URL}/evaluate-llm",
67
  json={
68
- "retrieved_contexts": retrieved_contexts,
69
  "question": question,
70
  "llm_response": llm_response
71
  },
72
  timeout=120
73
  )
74
 
75
- # -------------------------------------------------
76
- # Successful response
77
- # -------------------------------------------------
78
 
79
  if response.status_code == 200:
80
 
81
  result = response.json()
82
 
83
- # -----------------------------
84
  # Final Verdict
85
- # -----------------------------
86
 
87
- verdict = result["final_verdict"]
 
 
88
 
89
  if verdict == "Hallucinated":
90
 
@@ -104,59 +155,23 @@ with tab1:
104
  f"**Verdict: {verdict}**"
105
  )
106
 
107
- # -----------------------------
108
- # Retrieval Evaluation
109
- # -----------------------------
110
-
111
- st.subheader("Retrieval Evaluation")
112
-
113
- col1, col2 = st.columns(2)
114
 
115
- col1.metric(
116
- "Context Relevance",
117
- result[
118
- "retrieval_evaluation"
119
- ][
120
- "context_relevance"
121
- ][
122
- "average_score"
123
- ],
124
- result[
125
- "retrieval_evaluation"
126
- ][
127
- "context_relevance"
128
- ][
129
- "verdict"
130
- ]
131
  )
132
 
133
- col2.metric(
134
- "Context Recall",
135
- result[
136
- "retrieval_evaluation"
137
- ][
138
- "context_recall"
139
- ][
140
- "score"
141
- ],
142
- result[
143
- "retrieval_evaluation"
144
- ][
145
- "context_recall"
146
- ][
147
- "verdict"
148
- ]
149
  )
150
 
151
- # -----------------------------
152
- # Generation Evaluation
153
- # -----------------------------
154
-
155
- st.subheader("Generation Evaluation")
156
-
157
- col3, col4, col5, col6 = st.columns(4)
158
 
159
- col3.metric(
160
  "Cosine",
161
  result[
162
  "generation_evaluation"
@@ -174,7 +189,11 @@ with tab1:
174
  ]
175
  )
176
 
177
- col4.metric(
 
 
 
 
178
  "BERTScore",
179
  result[
180
  "generation_evaluation"
@@ -192,7 +211,11 @@ with tab1:
192
  ]
193
  )
194
 
195
- col5.metric(
 
 
 
 
196
  "NLI",
197
  result[
198
  "generation_evaluation"
@@ -210,7 +233,11 @@ with tab1:
210
  ]
211
  )
212
 
213
- col6.metric(
 
 
 
 
214
  "Fluency",
215
  "-",
216
  result[
@@ -222,17 +249,19 @@ with tab1:
222
  ]
223
  )
224
 
225
- # -----------------------------
226
- # Detailed Result
227
- # -----------------------------
228
 
229
- with st.expander("View Detailed Evaluation"):
 
 
230
 
231
  st.json(result)
232
 
233
- # -------------------------------------------------
234
- # API error
235
- # -------------------------------------------------
236
 
237
  else:
238
 
@@ -242,17 +271,26 @@ with tab1:
242
  )
243
 
244
  try:
245
- error_data = response.json()
246
 
247
- with st.expander("View Error Details"):
248
- st.json(error_data)
 
 
 
 
 
 
 
 
 
249
 
250
  except Exception:
 
251
  pass
252
 
253
- # -----------------------------------------------------
254
- # Connection / timeout error
255
- # -----------------------------------------------------
256
 
257
  except requests.exceptions.Timeout:
258
 
@@ -261,10 +299,15 @@ with tab1:
261
  "Please try again."
262
  )
263
 
 
 
 
 
264
  except requests.exceptions.RequestException as e:
265
 
266
  st.error(
267
- f"Could not connect to the evaluation API: {e}"
 
268
  )
269
 
270
 
@@ -274,9 +317,17 @@ with tab1:
274
 
275
  with tab2:
276
 
277
- st.subheader("Past Evaluations")
 
 
 
 
 
 
278
 
279
- if st.button("Refresh History"):
 
 
280
 
281
  st.rerun()
282
 
@@ -287,20 +338,38 @@ with tab2:
287
  timeout=30
288
  )
289
 
 
 
 
 
290
  if response.status_code == 200:
291
 
292
  data = response.json()
293
 
 
 
 
 
294
  if data["total"] == 0:
295
 
296
- st.info("No evaluations yet.")
 
 
297
 
298
  else:
299
 
 
 
 
 
300
  df = pd.DataFrame(
301
  data["evaluations"]
302
  )
303
 
 
 
 
 
304
  df = df[
305
  [
306
  "id",
@@ -311,23 +380,37 @@ with tab2:
311
  ]
312
  ]
313
 
 
 
 
 
314
  st.dataframe(
315
  df,
316
  use_container_width=True
317
  )
318
 
319
- # -----------------------------
320
  # Verdict Distribution
321
- # -----------------------------
322
 
323
- st.subheader("Verdict Distribution")
 
 
324
 
325
  verdict_counts = (
326
- df["final_verdict"]
 
 
327
  .value_counts()
328
  )
329
 
330
- st.bar_chart(verdict_counts)
 
 
 
 
 
 
331
 
332
  else:
333
 
@@ -339,5 +422,6 @@ with tab2:
339
  except requests.exceptions.RequestException as e:
340
 
341
  st.error(
342
- f"Could not connect to the evaluation API: {e}"
 
343
  )
 
2
  import requests
3
  import pandas as pd
4
 
5
+
6
+ # =========================================================
7
+ # Page Configuration
8
+ # =========================================================
9
+
10
  st.set_page_config(
11
  page_title="LLM Hallucination Detector",
12
  layout="wide"
 
16
 
17
  API_URL = "https://sha6th-llm-eval-ap.hf.space"
18
 
19
+
20
+ # =========================================================
21
  # Tabs
22
+ # =========================================================
23
 
24
+ tab1, tab2 = st.tabs(
25
+ ["Evaluate New Response", "History"]
26
+ )
27
 
28
 
29
  # =========================================================
30
+ # TAB 1: LLM Evaluation
31
  # =========================================================
32
 
33
  with tab1:
34
 
35
  st.subheader("Evaluate an LLM Response")
36
 
37
+ st.info(
38
+ "Enter each context chunk on a new line"
39
+ )
40
+
41
+ # -----------------------------------------------------
42
+ # Input: Context
43
+ # -----------------------------------------------------
44
 
45
  contexts_input = st.text_area(
46
  "Retrieved Contexts (one chunk per line)",
47
  height=150
48
  )
49
 
50
+ # -----------------------------------------------------
51
+ # Input: Question
52
+ # -----------------------------------------------------
53
+
54
+ question = st.text_input(
55
+ "Question"
56
+ )
57
+
58
+ # -----------------------------------------------------
59
+ # Input: LLM Response
60
+ # -----------------------------------------------------
61
 
62
  llm_response = st.text_area(
63
  "LLM Response",
64
  height=100
65
  )
66
 
67
+ # -----------------------------------------------------
68
+ # Evaluate Button
69
+ # -----------------------------------------------------
70
+
71
  if st.button("Evaluate"):
72
 
73
+ # Convert the context input into a list
74
  retrieved_contexts = [
75
  c.strip()
76
  for c in contexts_input.split("\n")
77
  if c.strip()
78
  ]
79
 
80
+ # -------------------------------------------------
81
+ # Validate Input
82
+ # -------------------------------------------------
83
+
84
  if (
85
  not retrieved_contexts
86
  or not question.strip()
87
  or not llm_response.strip()
88
  ):
89
+
90
+ st.error(
91
+ "All fields are required."
92
+ )
93
 
94
  else:
95
 
96
+ # -------------------------------------------------
97
+ # Convert context chunks into ONE string
98
+ # -------------------------------------------------
99
+
100
+ context = "\n".join(
101
+ retrieved_contexts
102
+ )
103
+
104
+ with st.spinner(
105
+ "Running LLM evaluation..."
106
+ ):
107
 
108
  try:
109
 
110
+ # -------------------------------------------------
111
+ # Call LLM-only evaluation endpoint
112
+ # -------------------------------------------------
113
+
114
  response = requests.post(
115
  f"{API_URL}/evaluate-llm",
116
  json={
117
+ "context": context,
118
  "question": question,
119
  "llm_response": llm_response
120
  },
121
  timeout=120
122
  )
123
 
124
+ # =================================================
125
+ # Successful Response
126
+ # =================================================
127
 
128
  if response.status_code == 200:
129
 
130
  result = response.json()
131
 
132
+ # -------------------------------------------------
133
  # Final Verdict
134
+ # -------------------------------------------------
135
 
136
+ verdict = result[
137
+ "final_verdict"
138
+ ]
139
 
140
  if verdict == "Hallucinated":
141
 
 
155
  f"**Verdict: {verdict}**"
156
  )
157
 
158
+ # =================================================
159
+ # Generation Evaluation
160
+ # =================================================
 
 
 
 
161
 
162
+ st.subheader(
163
+ "Generation Evaluation"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  )
165
 
166
+ col1, col2, col3, col4 = (
167
+ st.columns(4)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
  )
169
 
170
+ # -------------------------------------------------
171
+ # Cosine
172
+ # -------------------------------------------------
 
 
 
 
173
 
174
+ col1.metric(
175
  "Cosine",
176
  result[
177
  "generation_evaluation"
 
189
  ]
190
  )
191
 
192
+ # -------------------------------------------------
193
+ # BERTScore
194
+ # -------------------------------------------------
195
+
196
+ col2.metric(
197
  "BERTScore",
198
  result[
199
  "generation_evaluation"
 
211
  ]
212
  )
213
 
214
+ # -------------------------------------------------
215
+ # NLI
216
+ # -------------------------------------------------
217
+
218
+ col3.metric(
219
  "NLI",
220
  result[
221
  "generation_evaluation"
 
233
  ]
234
  )
235
 
236
+ # -------------------------------------------------
237
+ # Fluency
238
+ # -------------------------------------------------
239
+
240
+ col4.metric(
241
  "Fluency",
242
  "-",
243
  result[
 
249
  ]
250
  )
251
 
252
+ # =================================================
253
+ # Detailed Evaluation
254
+ # =================================================
255
 
256
+ with st.expander(
257
+ "View Detailed Evaluation"
258
+ ):
259
 
260
  st.json(result)
261
 
262
+ # =================================================
263
+ # API Error
264
+ # =================================================
265
 
266
  else:
267
 
 
271
  )
272
 
273
  try:
 
274
 
275
+ error_data = (
276
+ response.json()
277
+ )
278
+
279
+ with st.expander(
280
+ "View Error Details"
281
+ ):
282
+
283
+ st.json(
284
+ error_data
285
+ )
286
 
287
  except Exception:
288
+
289
  pass
290
 
291
+ # =====================================================
292
+ # Timeout Error
293
+ # =====================================================
294
 
295
  except requests.exceptions.Timeout:
296
 
 
299
  "Please try again."
300
  )
301
 
302
+ # =====================================================
303
+ # Connection Error
304
+ # =====================================================
305
+
306
  except requests.exceptions.RequestException as e:
307
 
308
  st.error(
309
+ f"Could not connect to the "
310
+ f"evaluation API: {e}"
311
  )
312
 
313
 
 
317
 
318
  with tab2:
319
 
320
+ st.subheader(
321
+ "Past Evaluations"
322
+ )
323
+
324
+ # -----------------------------------------------------
325
+ # Refresh History
326
+ # -----------------------------------------------------
327
 
328
+ if st.button(
329
+ "Refresh History"
330
+ ):
331
 
332
  st.rerun()
333
 
 
338
  timeout=30
339
  )
340
 
341
+ # =================================================
342
+ # Successful History Response
343
+ # =================================================
344
+
345
  if response.status_code == 200:
346
 
347
  data = response.json()
348
 
349
+ # -------------------------------------------------
350
+ # No evaluations
351
+ # -------------------------------------------------
352
+
353
  if data["total"] == 0:
354
 
355
+ st.info(
356
+ "No evaluations yet."
357
+ )
358
 
359
  else:
360
 
361
+ # -------------------------------------------------
362
+ # Create DataFrame
363
+ # -------------------------------------------------
364
+
365
  df = pd.DataFrame(
366
  data["evaluations"]
367
  )
368
 
369
+ # -------------------------------------------------
370
+ # Select columns
371
+ # -------------------------------------------------
372
+
373
  df = df[
374
  [
375
  "id",
 
380
  ]
381
  ]
382
 
383
+ # -------------------------------------------------
384
+ # Display History
385
+ # -------------------------------------------------
386
+
387
  st.dataframe(
388
  df,
389
  use_container_width=True
390
  )
391
 
392
+ # =================================================
393
  # Verdict Distribution
394
+ # =================================================
395
 
396
+ st.subheader(
397
+ "Verdict Distribution"
398
+ )
399
 
400
  verdict_counts = (
401
+ df[
402
+ "final_verdict"
403
+ ]
404
  .value_counts()
405
  )
406
 
407
+ st.bar_chart(
408
+ verdict_counts
409
+ )
410
+
411
+ # =================================================
412
+ # History API Error
413
+ # =================================================
414
 
415
  else:
416
 
 
422
  except requests.exceptions.RequestException as e:
423
 
424
  st.error(
425
+ f"Could not connect to the "
426
+ f"evaluation API: {e}"
427
  )